/** 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.
*
* @since 1.17
*
- * @param mixed ... Parameters as strings, or a single argument that is
- * an array of strings.
+ * @param mixed ... Parameters as strings or arrays from
+ * Message::numParam() and the like, or a single array of parameters.
*
* @return Message $this
*/
public function params( /*...*/ ) {
$args = func_get_args();
- if ( isset( $args[0] ) && is_array( $args[0] ) ) {
- $args = $args[0];
+
+ // If $args has only one entry and it's an array, then it's either a
+ // non-varargs call or it happens to be a call with just a single
+ // "special" parameter. Since the "special" parameters don't have any
+ // numeric keys, we'll test that to differentiate the cases.
+ if ( count( $args ) === 1 && isset( $args[0] ) && is_array( $args[0] ) ) {
+ if ( $args[0] === [] ) {
+ $args = [];
+ } else {
+ foreach ( $args[0] as $key => $value ) {
+ if ( is_int( $key ) ) {
+ $args = $args[0];
+ break;
+ }
+ }
+ }
}
- $args_values = array_values( $args );
- $this->parameters = array_merge( $this->parameters, $args_values );
+
+ $this->parameters = array_merge( $this->parameters, array_values( $args ) );
return $this;
}
/**
* @since 1.22
*
- * @param number $period
+ * @param int $period
*
- * @return number[] Array with a single "period" key.
+ * @return int[] Array with a single "period" key.
*/
public static function timeperiodParam( $period ) {
return [ 'period' => $period ];
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.
*
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 ) );
}
}
+
+ /**
+ * 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( $listType )
+ . ' (params are ' . htmlspecialchars( serialize( $params ) ) . ')';
+ 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 );
+ }
}
/**