Anomie has uploaded a new change for review.
https://gerrit.wikimedia.org/r/321404
Change subject: Add Message::listParam()
......................................................................
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
---
M includes/Message.php
M includes/api/ApiPageSet.php
M tests/phpunit/includes/MessageTest.php
3 files changed, 180 insertions(+), 7 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core
refs/changes/04/321404/1
diff --git a/includes/Message.php b/includes/Message.php
index 85c78d6..1337fe1 100644
--- a/includes/Message.php
+++ b/includes/Message.php
@@ -169,6 +169,17 @@
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.
*
@@ -1071,6 +1082,22 @@
}
/**
+ * @since 1.29
+ *
+ * @param array $list
+ * @param string $type 'comma', 'semicolon', 'pipe', 'text'
+ * @return string[] 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.
*
* @since 1.17
@@ -1123,6 +1150,8 @@
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 @@
}
}
+
+ /**
+ * 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 );
+ }
}
/**
diff --git a/includes/api/ApiPageSet.php b/includes/api/ApiPageSet.php
index 46c57b8..c41d348 100644
--- a/includes/api/ApiPageSet.php
+++ b/includes/api/ApiPageSet.php
@@ -1411,13 +1411,7 @@
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' ) ],
],
],
];
diff --git a/tests/phpunit/includes/MessageTest.php
b/tests/phpunit/includes/MessageTest.php
index 0294d37..774d94c 100644
--- a/tests/phpunit/includes/MessageTest.php
+++ b/tests/phpunit/includes/MessageTest.php
@@ -512,6 +512,108 @@
);
}
+ 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
*/
--
To view, visit https://gerrit.wikimedia.org/r/321404
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I66868c61832260870449998fef14c842f17753ee
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Anomie <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits