Add Message::listParam()
This allows for passing a list of values that will be turned into a list in the context of the language for which the Message is being processed. For example, currently you'd have to do $msg = new Message( 'something', [ $language->commaList( $list ) ] ); which isn't going to give correct results if the message is later changed to a different language with a different value for 'comma-separator'. Now, you can do this instead $msg = new Message( 'something', [ Message::listParam( $list, 'comma' ) ] ); and it will be listified properly no matter what language is later used to parse $msg. Change-Id: I66868c61832260870449998fef14c842f17753ee
This commit is contained in:
parent
5a1104444f
commit
3041b5c038
3 changed files with 180 additions and 7 deletions
|
|
@ -168,6 +168,17 @@ class Message implements MessageSpecifier, Serializable {
|
|||
/** Transform {{..}} constructs, HTML-escape the result */
|
||||
const FORMAT_ESCAPED = 'escaped';
|
||||
|
||||
/**
|
||||
* Mapping from Message::listParam() types to Language methods.
|
||||
* @var array
|
||||
*/
|
||||
protected static $listTypeMap = [
|
||||
'comma' => 'commaList',
|
||||
'semicolon' => 'semicolonList',
|
||||
'pipe' => 'pipeList',
|
||||
'text' => 'listToText',
|
||||
];
|
||||
|
||||
/**
|
||||
* In which language to get this message. True, which is the default,
|
||||
* means the current user language, false content language.
|
||||
|
|
@ -1070,6 +1081,22 @@ class Message implements MessageSpecifier, Serializable {
|
|||
return [ 'plaintext' => $plaintext ];
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.29
|
||||
*
|
||||
* @param array $list
|
||||
* @param string $type 'comma', 'semicolon', 'pipe', 'text'
|
||||
* @return array Array with "list" and "type" keys.
|
||||
*/
|
||||
public static function listParam( array $list, $type = 'text' ) {
|
||||
if ( !isset( self::$listTypeMap[$type] ) ) {
|
||||
throw new InvalidArgumentException(
|
||||
"Invalid type '$type'. Known types are: " . join( ', ', array_keys( self::$listTypeMap ) )
|
||||
);
|
||||
}
|
||||
return [ 'list' => $list, 'type' => $type ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Substitutes any parameters into the message text.
|
||||
*
|
||||
|
|
@ -1123,6 +1150,8 @@ class Message implements MessageSpecifier, Serializable {
|
|||
return [ 'before', $this->getLanguage()->formatBitrate( $param['bitrate'] ) ];
|
||||
} elseif ( isset( $param['plaintext'] ) ) {
|
||||
return [ 'after', $this->formatPlaintext( $param['plaintext'], $format ) ];
|
||||
} elseif ( isset( $param['list'] ) ) {
|
||||
return $this->formatListParam( $param['list'], $param['type'], $format );
|
||||
} else {
|
||||
$warning = 'Invalid parameter for message "' . $this->getKey() . '": ' .
|
||||
htmlspecialchars( serialize( $param ) );
|
||||
|
|
@ -1251,6 +1280,54 @@ class Message implements MessageSpecifier, Serializable {
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a list of parameters as a concatenated string.
|
||||
* @since 1.29
|
||||
* @param array $params
|
||||
* @param string $listType
|
||||
* @param string $format One of the FORMAT_* constants.
|
||||
* @return array Array with the parameter type (either "before" or "after") and the value.
|
||||
*/
|
||||
protected function formatListParam( array $params, $listType, $format ) {
|
||||
if ( !isset( self::$listTypeMap[$listType] ) ) {
|
||||
$warning = 'Invalid list type for message "' . $this->getKey() . '": ' .
|
||||
htmlspecialchars( serialize( $param ) );
|
||||
trigger_error( $warning, E_USER_WARNING );
|
||||
$e = new Exception;
|
||||
wfDebugLog( 'Bug58676', $warning . "\n" . $e->getTraceAsString() );
|
||||
return [ 'before', '[INVALID]' ];
|
||||
}
|
||||
$func = self::$listTypeMap[$listType];
|
||||
|
||||
// Handle an empty list sensibly
|
||||
if ( !$params ) {
|
||||
return [ 'before', $this->getLanguage()->$func( [] ) ];
|
||||
}
|
||||
|
||||
// First, determine what kinds of list items we have
|
||||
$types = [];
|
||||
$vars = [];
|
||||
$list = [];
|
||||
foreach ( $params as $n => $p ) {
|
||||
list( $type, $value ) = $this->extractParam( $p, $format );
|
||||
$types[$type] = true;
|
||||
$list[] = $value;
|
||||
$vars[] = '$' . ( $n + 1 );
|
||||
}
|
||||
|
||||
// Easy case: all are 'before' or 'after', so just join the
|
||||
// values and use the same type.
|
||||
if ( count( $types ) === 1 ) {
|
||||
return [ key( $types ), $this->getLanguage()->$func( $list ) ];
|
||||
}
|
||||
|
||||
// Hard case: We need to process each value per its type, then
|
||||
// return the concatenated values as 'after'. We handle this by turning
|
||||
// the list into a RawMessage and processing that as a parameter.
|
||||
$vars = $this->getLanguage()->$func( $vars );
|
||||
return $this->extractParam( new RawMessage( $vars, $params ), $format );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1412,13 +1412,7 @@ class ApiPageSet extends ApiBase {
|
|||
ApiBase::PARAM_DFLT => false,
|
||||
ApiBase::PARAM_HELP_MSG => [
|
||||
'api-pageset-param-converttitles',
|
||||
new DeferredStringifier(
|
||||
function ( IContextSource $context ) {
|
||||
return $context->getLanguage()
|
||||
->commaList( LanguageConverter::$languagesWithVariants );
|
||||
},
|
||||
$this
|
||||
)
|
||||
[ Message::listParam( LanguageConverter::$languagesWithVariants, 'text' ) ],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -512,6 +512,108 @@ class MessageTest extends MediaWikiLangTestCase {
|
|||
);
|
||||
}
|
||||
|
||||
public static function provideListParam() {
|
||||
$lang = Language::factory( 'de' );
|
||||
$msg1 = new Message( 'mainpage', [], $lang );
|
||||
$msg2 = new RawMessage( "''link''", [], $lang );
|
||||
|
||||
return [
|
||||
'Simple comma list' => [
|
||||
[ 'a', 'b', 'c' ],
|
||||
'comma',
|
||||
'text',
|
||||
'a, b, c'
|
||||
],
|
||||
|
||||
'Simple semicolon list' => [
|
||||
[ 'a', 'b', 'c' ],
|
||||
'semicolon',
|
||||
'text',
|
||||
'a; b; c'
|
||||
],
|
||||
|
||||
'Simple pipe list' => [
|
||||
[ 'a', 'b', 'c' ],
|
||||
'pipe',
|
||||
'text',
|
||||
'a | b | c'
|
||||
],
|
||||
|
||||
'Simple text list' => [
|
||||
[ 'a', 'b', 'c' ],
|
||||
'text',
|
||||
'text',
|
||||
'a, b and c'
|
||||
],
|
||||
|
||||
'Empty list' => [
|
||||
[],
|
||||
'comma',
|
||||
'text',
|
||||
''
|
||||
],
|
||||
|
||||
'List with all "before" params, ->text()' => [
|
||||
[ "''link''", Message::numParam( 12345678 ) ],
|
||||
'semicolon',
|
||||
'text',
|
||||
'\'\'link\'\'; 12,345,678'
|
||||
],
|
||||
|
||||
'List with all "before" params, ->parse()' => [
|
||||
[ "''link''", Message::numParam( 12345678 ) ],
|
||||
'semicolon',
|
||||
'parse',
|
||||
'<i>link</i>; 12,345,678'
|
||||
],
|
||||
|
||||
'List with all "after" params, ->text()' => [
|
||||
[ $msg1, $msg2, Message::rawParam( '[[foo]]' ) ],
|
||||
'semicolon',
|
||||
'text',
|
||||
'Main Page; \'\'link\'\'; [[foo]]'
|
||||
],
|
||||
|
||||
'List with all "after" params, ->parse()' => [
|
||||
[ $msg1, $msg2, Message::rawParam( '[[foo]]' ) ],
|
||||
'semicolon',
|
||||
'parse',
|
||||
'Main Page; <i>link</i>; [[foo]]'
|
||||
],
|
||||
|
||||
'List with both "before" and "after" params, ->text()' => [
|
||||
[ $msg1, $msg2, Message::rawParam( '[[foo]]' ), "''link''", Message::numParam( 12345678 ) ],
|
||||
'semicolon',
|
||||
'text',
|
||||
'Main Page; \'\'link\'\'; [[foo]]; \'\'link\'\'; 12,345,678'
|
||||
],
|
||||
|
||||
'List with both "before" and "after" params, ->parse()' => [
|
||||
[ $msg1, $msg2, Message::rawParam( '[[foo]]' ), "''link''", Message::numParam( 12345678 ) ],
|
||||
'semicolon',
|
||||
'parse',
|
||||
'Main Page; <i>link</i>; [[foo]]; <i>link</i>; 12,345,678'
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Message::listParam
|
||||
* @covers Message::extractParam
|
||||
* @covers Message::formatListParam
|
||||
* @dataProvider provideListParam
|
||||
*/
|
||||
public function testListParam( $list, $type, $format, $expect ) {
|
||||
$lang = Language::factory( 'en' );
|
||||
|
||||
$msg = new RawMessage( '$1' );
|
||||
$msg->params( [ Message::listParam( $list, $type ) ] );
|
||||
$this->assertEquals(
|
||||
$expect,
|
||||
$msg->inLanguage( $lang )->$format()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Message::extractParam
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in a new issue