MediaWiki  master
Message.php
Go to the documentation of this file.
1 <?php
26 
138 class Message implements MessageSpecifier, Serializable {
140  public const FORMAT_PLAIN = 'plain';
142  public const FORMAT_BLOCK_PARSE = 'block-parse';
144  public const FORMAT_PARSE = 'parse';
146  public const FORMAT_TEXT = 'text';
148  public const FORMAT_ESCAPED = 'escaped';
149 
154  protected static $listTypeMap = [
155  'comma' => 'commaList',
156  'semicolon' => 'semicolonList',
157  'pipe' => 'pipeList',
158  'text' => 'listToText',
159  ];
160 
167  protected $interface = true;
168 
174  protected $language = false;
175 
180  protected $key;
181 
185  protected $keysToTry;
186 
190  protected $parameters = [];
191 
196  protected $format = 'parse';
197 
201  protected $useDatabase = true;
202 
206  protected $contextPage = null;
207 
211  protected $content = null;
212 
216  protected $message;
217 
228  public function __construct( $key, $params = [], Language $language = null ) {
229  if ( $key instanceof MessageSpecifier ) {
230  if ( $params ) {
231  throw new InvalidArgumentException(
232  '$params must be empty if $key is a MessageSpecifier'
233  );
234  }
235  $params = $key->getParams();
236  $key = $key->getKey();
237  }
238 
239  if ( !is_string( $key ) && !is_array( $key ) ) {
240  throw new InvalidArgumentException( '$key must be a string or an array' );
241  }
242 
243  $this->keysToTry = (array)$key;
244 
245  if ( empty( $this->keysToTry ) ) {
246  throw new InvalidArgumentException( '$key must not be an empty list' );
247  }
248 
249  $this->key = reset( $this->keysToTry );
250 
251  $this->parameters = array_values( $params );
252  // User language is only resolved in getLanguage(). This helps preserve the
253  // semantic intent of "user language" across serialize() and unserialize().
254  $this->language = $language ?: false;
255  }
256 
262  public function serialize() {
263  return serialize( [
264  'interface' => $this->interface,
265  'language' => $this->language ? $this->language->getCode() : false,
266  'key' => $this->key,
267  'keysToTry' => $this->keysToTry,
268  'parameters' => $this->parameters,
269  'format' => $this->format,
270  'useDatabase' => $this->useDatabase,
271  // Optimisation: Avoid cost of TitleFormatter on serialize,
272  // and especially cost of TitleParser (via Title::newFromText)
273  // on retrieval.
274  'titlevalue' => ( $this->contextPage
275  ? [ 0 => $this->contextPage->getNamespace(), 1 => $this->contextPage->getDBkey() ]
276  : null
277  ),
278  ] );
279  }
280 
286  public function unserialize( $serialized ) {
287  $data = unserialize( $serialized );
288  if ( !is_array( $data ) ) {
289  throw new InvalidArgumentException( __METHOD__ . ': Invalid serialized data' );
290  }
291 
292  $this->interface = $data['interface'];
293  $this->key = $data['key'];
294  $this->keysToTry = $data['keysToTry'];
295  $this->parameters = $data['parameters'];
296  $this->format = $data['format'];
297  $this->useDatabase = $data['useDatabase'];
298  $this->language = $data['language']
299  ? MediaWikiServices::getInstance()->getLanguageFactory()
300  ->getLanguage( $data['language'] )
301  : false;
302 
303  // Since 1.35, the key 'titlevalue' is set, instead of 'titlestr'.
304  if ( isset( $data['titlevalue'] ) ) {
305  $this->contextPage = new PageReferenceValue(
306  $data['titlevalue'][0],
307  $data['titlevalue'][1],
308  PageReference::LOCAL
309  );
310  } elseif ( isset( $data['titlestr'] ) ) {
311  // TODO: figure out what's needed to remove this codepath
312  $this->contextPage = Title::newFromText( $data['titlestr'] );
313  } else {
314  $this->contextPage = null; // Explicit for sanity
315  }
316  }
317 
324  public function isMultiKey() {
325  return count( $this->keysToTry ) > 1;
326  }
327 
334  public function getKeysToTry() {
335  return $this->keysToTry;
336  }
337 
349  public function getKey() {
350  return $this->key;
351  }
352 
360  public function getParams() {
361  return $this->parameters;
362  }
363 
371  public function getLanguage() {
372  // Defaults to false which means current user language
373  return $this->language ?: RequestContext::getMain()->getLanguage();
374  }
375 
388  public static function newFromKey( $key, ...$params ) {
389  return new self( $key, $params );
390  }
391 
406  public static function newFromSpecifier( $value ) {
407  $params = [];
408  if ( is_array( $value ) ) {
409  $params = $value;
410  $value = array_shift( $params );
411  }
412 
413  if ( $value instanceof Message ) { // Message, RawMessage, ApiMessage, etc
414  $message = clone $value;
415  } elseif ( $value instanceof MessageSpecifier ) {
416  $message = new Message( $value );
417  } elseif ( is_string( $value ) ) {
418  $message = new Message( $value, $params );
419  } else {
420  throw new InvalidArgumentException( __METHOD__ . ': invalid argument type '
421  . gettype( $value ) );
422  }
423 
424  return $message;
425  }
426 
440  public static function newFallbackSequence( ...$keys ) {
441  if ( func_num_args() == 1 ) {
442  if ( is_array( $keys[0] ) ) {
443  // Allow an array to be passed as the first argument instead
444  $keys = array_values( $keys[0] );
445  } else {
446  // Optimize a single string to not need special fallback handling
447  $keys = $keys[0];
448  }
449  }
450  return new self( $keys );
451  }
452 
463  public function getTitle() {
465 
466  $contLang = MediaWikiServices::getInstance()->getContentLanguage();
467  $lang = $this->getLanguage();
468  $title = $this->key;
469  if (
470  !$lang->equals( $contLang )
471  && in_array( $this->key, (array)$wgForceUIMsgAsContentMsg )
472  ) {
473  $title .= '/' . $lang->getCode();
474  }
475 
476  return Title::makeTitle(
477  NS_MEDIAWIKI, $contLang->ucfirst( strtr( $title, ' ', '_' ) ) );
478  }
479 
490  public function params( ...$args ) {
491  // If $args has only one entry and it's an array, then it's either a
492  // non-varargs call or it happens to be a call with just a single
493  // "special" parameter. Since the "special" parameters don't have any
494  // numeric keys, we'll test that to differentiate the cases.
495  if ( count( $args ) === 1 && isset( $args[0] ) && is_array( $args[0] ) ) {
496  if ( $args[0] === [] ) {
497  $args = [];
498  } else {
499  foreach ( $args[0] as $key => $value ) {
500  if ( is_int( $key ) ) {
501  $args = $args[0];
502  break;
503  }
504  }
505  }
506  }
507 
508  $this->parameters = array_merge( $this->parameters, array_values( $args ) );
509  return $this;
510  }
511 
525  public function rawParams( ...$params ) {
526  if ( isset( $params[0] ) && is_array( $params[0] ) ) {
527  $params = $params[0];
528  }
529  foreach ( $params as $param ) {
530  $this->parameters[] = self::rawParam( $param );
531  }
532  return $this;
533  }
534 
546  public function numParams( ...$params ) {
547  if ( isset( $params[0] ) && is_array( $params[0] ) ) {
548  $params = $params[0];
549  }
550  foreach ( $params as $param ) {
551  $this->parameters[] = self::numParam( $param );
552  }
553  return $this;
554  }
555 
567  public function durationParams( ...$params ) {
568  if ( isset( $params[0] ) && is_array( $params[0] ) ) {
569  $params = $params[0];
570  }
571  foreach ( $params as $param ) {
572  $this->parameters[] = self::durationParam( $param );
573  }
574  return $this;
575  }
576 
588  public function expiryParams( ...$params ) {
589  if ( isset( $params[0] ) && is_array( $params[0] ) ) {
590  $params = $params[0];
591  }
592  foreach ( $params as $param ) {
593  $this->parameters[] = self::expiryParam( $param );
594  }
595  return $this;
596  }
597 
609  public function dateTimeParams( ...$params ) {
610  if ( isset( $params[0] ) && is_array( $params[0] ) ) {
611  $params = $params[0];
612  }
613  foreach ( $params as $param ) {
614  $this->parameters[] = self::dateTimeParam( $param );
615  }
616  return $this;
617  }
618 
630  public function dateParams( ...$params ) {
631  if ( isset( $params[0] ) && is_array( $params[0] ) ) {
632  $params = $params[0];
633  }
634  foreach ( $params as $param ) {
635  $this->parameters[] = self::dateParam( $param );
636  }
637  return $this;
638  }
639 
651  public function timeParams( ...$params ) {
652  if ( isset( $params[0] ) && is_array( $params[0] ) ) {
653  $params = $params[0];
654  }
655  foreach ( $params as $param ) {
656  $this->parameters[] = self::timeParam( $param );
657  }
658  return $this;
659  }
660 
672  public function timeperiodParams( ...$params ) {
673  if ( isset( $params[0] ) && is_array( $params[0] ) ) {
674  $params = $params[0];
675  }
676  foreach ( $params as $param ) {
677  $this->parameters[] = self::timeperiodParam( $param );
678  }
679  return $this;
680  }
681 
693  public function sizeParams( ...$params ) {
694  if ( isset( $params[0] ) && is_array( $params[0] ) ) {
695  $params = $params[0];
696  }
697  foreach ( $params as $param ) {
698  $this->parameters[] = self::sizeParam( $param );
699  }
700  return $this;
701  }
702 
714  public function bitrateParams( ...$params ) {
715  if ( isset( $params[0] ) && is_array( $params[0] ) ) {
716  $params = $params[0];
717  }
718  foreach ( $params as $param ) {
719  $this->parameters[] = self::bitrateParam( $param );
720  }
721  return $this;
722  }
723 
737  public function plaintextParams( ...$params ) {
738  if ( isset( $params[0] ) && is_array( $params[0] ) ) {
739  $params = $params[0];
740  }
741  foreach ( $params as $param ) {
742  $this->parameters[] = self::plaintextParam( $param );
743  }
744  return $this;
745  }
746 
756  public function setContext( IContextSource $context ) {
757  $this->inLanguage( $context->getLanguage() );
758  $this->page( $context->getTitle() );
759  $this->interface = true;
760 
761  return $this;
762  }
763 
775  public function inLanguage( $lang ) {
776  $previousLanguage = $this->language;
777 
778  if ( $lang instanceof Language ) {
779  $this->language = $lang;
780  } elseif ( is_string( $lang ) ) {
781  if ( !$this->language instanceof Language || $this->language->getCode() != $lang ) {
782  $this->language = MediaWikiServices::getInstance()->getLanguageFactory()
783  ->getLanguage( $lang );
784  }
785  } elseif ( $lang instanceof StubUserLang ) {
786  $this->language = false;
787  } else {
788  $type = gettype( $lang );
789  throw new MWException( __METHOD__ . " must be "
790  . "passed a String or Language object; $type given"
791  );
792  }
793 
794  if ( $this->language !== $previousLanguage ) {
795  // The language has changed. Clear the message cache.
796  $this->message = null;
797  }
798  $this->interface = false;
799  return $this;
800  }
801 
811  public function inContentLanguage() {
813  if ( in_array( $this->key, (array)$wgForceUIMsgAsContentMsg ) ) {
814  return $this;
815  }
816 
817  $this->inLanguage( MediaWikiServices::getInstance()->getContentLanguage() );
818  return $this;
819  }
820 
831  public function setInterfaceMessageFlag( $interface ) {
832  $this->interface = (bool)$interface;
833  return $this;
834  }
835 
845  public function useDatabase( $useDatabase ) {
846  $this->useDatabase = (bool)$useDatabase;
847  $this->message = null;
848  return $this;
849  }
850 
861  public function title( $title ) {
862  return $this->page( $title );
863  }
864 
874  public function page( ?PageReference $page ) {
875  $this->contextPage = $page;
876  return $this;
877  }
878 
884  public function content() {
885  if ( !$this->content ) {
886  $this->content = new MessageContent( $this );
887  }
888 
889  return $this->content;
890  }
891 
900  public function toString( $format = null ) {
901  if ( $format === null ) {
902  wfDeprecated( __METHOD__ . ' with implicit format', '1.36' );
904  }
905  return $this->format( $format );
906  }
907 
915  private function format( string $format ): string {
916  $string = $this->fetchMessage();
917 
918  if ( $string === false ) {
919  // Err on the side of safety, ensure that the output
920  // is always html safe in the event the message key is
921  // missing, since in that case its highly likely the
922  // message key is user-controlled.
923  // '⧼' is used instead of '<' to side-step any
924  // double-escaping issues.
925  // (Keep synchronised with mw.Message#toString in JS.)
926  return '⧼' . htmlspecialchars( $this->key ) . '⧽';
927  }
928 
929  # Replace $* with a list of parameters for &uselang=qqx.
930  if ( strpos( $string, '$*' ) !== false ) {
931  $paramlist = '';
932  if ( $this->parameters !== [] ) {
933  $paramlist = ': $' . implode( ', $', range( 1, count( $this->parameters ) ) );
934  }
935  $string = str_replace( '$*', $paramlist, $string );
936  }
937 
938  # Replace parameters before text parsing
939  $string = $this->replaceParameters( $string, 'before', $format );
940 
941  # Maybe transform using the full parser
942  if ( $format === self::FORMAT_PARSE ) {
943  $string = $this->parseText( $string );
944  $string = Parser::stripOuterParagraph( $string );
945  } elseif ( $format === self::FORMAT_BLOCK_PARSE ) {
946  $string = $this->parseText( $string );
947  } elseif ( $format === self::FORMAT_TEXT ) {
948  $string = $this->transformText( $string );
949  } elseif ( $format === self::FORMAT_ESCAPED ) {
950  $string = $this->transformText( $string );
951  $string = htmlspecialchars( $string, ENT_QUOTES, 'UTF-8', false );
952  }
953 
954  # Raw parameter replacement
955  $string = $this->replaceParameters( $string, 'after', $format );
956 
957  return $string;
958  }
959 
969  public function __toString() {
970  // PHP doesn't allow __toString to throw exceptions and will
971  // trigger a fatal error if it does. So, catch any exceptions.
972 
973  try {
974  return $this->format( self::FORMAT_PARSE );
975  } catch ( Exception $ex ) {
976  try {
977  trigger_error( "Exception caught in " . __METHOD__ . " (message " . $this->key . "): "
978  . $ex, E_USER_WARNING );
979  } catch ( Exception $ex ) {
980  // Doh! Cause a fatal error after all?
981  }
982 
983  return '⧼' . htmlspecialchars( $this->key ) . '⧽';
984  }
985  }
986 
994  public function parse() {
995  $this->format = self::FORMAT_PARSE;
996  return $this->format( self::FORMAT_PARSE );
997  }
998 
1006  public function text() {
1007  $this->format = self::FORMAT_TEXT;
1008  return $this->format( self::FORMAT_TEXT );
1009  }
1010 
1018  public function plain() {
1019  $this->format = self::FORMAT_PLAIN;
1020  return $this->format( self::FORMAT_PLAIN );
1021  }
1022 
1030  public function parseAsBlock() {
1032  return $this->format( self::FORMAT_BLOCK_PARSE );
1033  }
1034 
1043  public function escaped() {
1044  $this->format = self::FORMAT_ESCAPED;
1045  return $this->format( self::FORMAT_ESCAPED );
1046  }
1047 
1055  public function exists() {
1056  return $this->fetchMessage() !== false;
1057  }
1058 
1067  public function isBlank() {
1068  $message = $this->fetchMessage();
1069  return $message === false || $message === '';
1070  }
1071 
1079  public function isDisabled() {
1080  $message = $this->fetchMessage();
1081  return $message === false || $message === '' || $message === '-';
1082  }
1083 
1092  public static function rawParam( $raw ) {
1093  return [ 'raw' => $raw ];
1094  }
1095 
1103  public static function numParam( $num ) {
1104  return [ 'num' => $num ];
1105  }
1106 
1114  public static function durationParam( $duration ) {
1115  return [ 'duration' => $duration ];
1116  }
1117 
1125  public static function expiryParam( $expiry ) {
1126  return [ 'expiry' => $expiry ];
1127  }
1128 
1136  public static function dateTimeParam( string $dateTime ) {
1137  return [ 'datetime' => $dateTime ];
1138  }
1139 
1147  public static function dateParam( string $date ) {
1148  return [ 'date' => $date ];
1149  }
1150 
1158  public static function timeParam( string $time ) {
1159  return [ 'time' => $time ];
1160  }
1161 
1169  public static function timeperiodParam( $period ) {
1170  return [ 'period' => $period ];
1171  }
1172 
1180  public static function sizeParam( $size ) {
1181  return [ 'size' => $size ];
1182  }
1183 
1191  public static function bitrateParam( $bitrate ) {
1192  return [ 'bitrate' => $bitrate ];
1193  }
1194 
1202  public static function plaintextParam( $plaintext ) {
1203  return [ 'plaintext' => $plaintext ];
1204  }
1205 
1213  public static function listParam( array $list, $type = 'text' ) {
1214  if ( !isset( self::$listTypeMap[$type] ) ) {
1215  throw new InvalidArgumentException(
1216  "Invalid type '$type'. Known types are: " . implode( ', ', array_keys( self::$listTypeMap ) )
1217  );
1218  }
1219  return [ 'list' => $list, 'type' => $type ];
1220  }
1221 
1233  protected function replaceParameters( $message, $type, $format ) {
1234  // A temporary marker for $1 parameters that is only valid
1235  // in non-attribute contexts. However if the entire message is escaped
1236  // then we don't want to use it because it will be mangled in all contexts
1237  // and its unnessary as ->escaped() messages aren't html.
1238  $marker = $format === self::FORMAT_ESCAPED ? '$' : '$\'"';
1239  $replacementKeys = [];
1240  foreach ( $this->parameters as $n => $param ) {
1241  list( $paramType, $value ) = $this->extractParam( $param, $format );
1242  if ( $type === 'before' ) {
1243  if ( $paramType === 'before' ) {
1244  $replacementKeys['$' . ( $n + 1 )] = $value;
1245  } else /* $paramType === 'after' */ {
1246  // To protect against XSS from replacing parameters
1247  // inside html attributes, we convert $1 to $'"1.
1248  // In the event that one of the parameters ends up
1249  // in an attribute, either the ' or the " will be
1250  // escaped, breaking the replacement and avoiding XSS.
1251  $replacementKeys['$' . ( $n + 1 )] = $marker . ( $n + 1 );
1252  }
1253  } elseif ( $paramType === 'after' ) {
1254  $replacementKeys[$marker . ( $n + 1 )] = $value;
1255  }
1256  }
1257  return strtr( $message, $replacementKeys );
1258  }
1259 
1270  protected function extractParam( $param, $format ) {
1271  if ( is_array( $param ) ) {
1272  if ( isset( $param['raw'] ) ) {
1273  return [ 'after', $param['raw'] ];
1274  } elseif ( isset( $param['num'] ) ) {
1275  // Replace number params always in before step for now.
1276  // No support for combined raw and num params
1277  return [ 'before', $this->getLanguage()->formatNum( $param['num'] ) ];
1278  } elseif ( isset( $param['duration'] ) ) {
1279  return [ 'before', $this->getLanguage()->formatDuration( $param['duration'] ) ];
1280  } elseif ( isset( $param['expiry'] ) ) {
1281  return [ 'before', $this->getLanguage()->formatExpiry( $param['expiry'] ) ];
1282  } elseif ( isset( $param['datetime'] ) ) {
1283  return [ 'before', $this->getLanguage()->timeanddate( $param['datetime'] ) ];
1284  } elseif ( isset( $param['date'] ) ) {
1285  return [ 'before', $this->getLanguage()->date( $param['date'] ) ];
1286  } elseif ( isset( $param['time'] ) ) {
1287  return [ 'before', $this->getLanguage()->time( $param['time'] ) ];
1288  } elseif ( isset( $param['period'] ) ) {
1289  return [ 'before', $this->getLanguage()->formatTimePeriod( $param['period'] ) ];
1290  } elseif ( isset( $param['size'] ) ) {
1291  return [ 'before', $this->getLanguage()->formatSize( $param['size'] ) ];
1292  } elseif ( isset( $param['bitrate'] ) ) {
1293  return [ 'before', $this->getLanguage()->formatBitrate( $param['bitrate'] ) ];
1294  } elseif ( isset( $param['plaintext'] ) ) {
1295  return [ 'after', $this->formatPlaintext( $param['plaintext'], $format ) ];
1296  } elseif ( isset( $param['list'] ) ) {
1297  return $this->formatListParam( $param['list'], $param['type'], $format );
1298  } else {
1299  LoggerFactory::getInstance( 'Bug58676' )->warning(
1300  'Invalid parameter for message "{msgkey}": {param}',
1301  [
1302  'exception' => new Exception,
1303  'msgkey' => $this->getKey(),
1304  'param' => htmlspecialchars( serialize( $param ) ),
1305  ]
1306  );
1307 
1308  return [ 'before', '[INVALID]' ];
1309  }
1310  } elseif ( $param instanceof Message ) {
1311  // Match language, flags, etc. to the current message.
1312  $msg = clone $param;
1313  if ( $msg->language !== $this->language || $msg->useDatabase !== $this->useDatabase ) {
1314  // Cache depends on these parameters
1315  $msg->message = null;
1316  }
1317  $msg->interface = $this->interface;
1318  $msg->language = $this->language;
1319  $msg->useDatabase = $this->useDatabase;
1320  $msg->contextPage = $this->contextPage;
1321 
1322  // DWIM
1323  if ( $format === 'block-parse' ) {
1324  $format = 'parse';
1325  }
1326  $msg->format = $format;
1327 
1328  // Message objects should not be before parameters because
1329  // then they'll get double escaped. If the message needs to be
1330  // escaped, it'll happen right here when we call toString().
1331  return [ 'after', $msg->format( $format ) ];
1332  } else {
1333  return [ 'before', $param ];
1334  }
1335  }
1336 
1346  protected function parseText( $string ) {
1347  $out = MediaWikiServices::getInstance()->getMessageCache()->parse(
1348  $string,
1349  $this->contextPage,
1350  /*linestart*/true,
1351  $this->interface,
1352  $this->getLanguage()
1353  );
1354 
1355  return $out instanceof ParserOutput
1356  ? $out->getText( [
1357  'enableSectionEditLinks' => false,
1358  // Wrapping messages in an extra <div> is probably not expected. If
1359  // they're outside the content area they probably shouldn't be
1360  // targeted by CSS that's targeting the parser output, and if
1361  // they're inside they already are from the outer div.
1362  'unwrap' => true,
1363  ] )
1364  : $out;
1365  }
1366 
1376  protected function transformText( $string ) {
1377  return MediaWikiServices::getInstance()->getMessageCache()->transform(
1378  $string,
1379  $this->interface,
1380  $this->getLanguage(),
1381  $this->contextPage
1382  );
1383  }
1384 
1393  protected function fetchMessage() {
1394  if ( $this->message === null ) {
1395  $cache = MediaWikiServices::getInstance()->getMessageCache();
1396 
1397  foreach ( $this->keysToTry as $key ) {
1398  $message = $cache->get( $key, $this->useDatabase, $this->getLanguage() );
1399  if ( $message !== false && $message !== '' ) {
1400  break;
1401  }
1402  }
1403 
1404  // NOTE: The constructor makes sure keysToTry isn't empty,
1405  // so we know that $key and $message are initialized.
1406  $this->key = $key;
1407  $this->message = $message;
1408  }
1409  return $this->message;
1410  }
1411 
1424  protected function formatPlaintext( $plaintext, $format ) {
1425  switch ( $format ) {
1426  case self::FORMAT_TEXT:
1427  case self::FORMAT_PLAIN:
1428  return $plaintext;
1429 
1430  case self::FORMAT_PARSE:
1432  case self::FORMAT_ESCAPED:
1433  default:
1434  return htmlspecialchars( $plaintext, ENT_QUOTES );
1435  }
1436  }
1437 
1446  protected function formatListParam( array $params, $listType, $format ) {
1447  if ( !isset( self::$listTypeMap[$listType] ) ) {
1448  $warning = 'Invalid list type for message "' . $this->getKey() . '": '
1449  . htmlspecialchars( $listType )
1450  . ' (params are ' . htmlspecialchars( serialize( $params ) ) . ')';
1451  trigger_error( $warning, E_USER_WARNING );
1452  $e = new Exception;
1453  wfDebugLog( 'Bug58676', $warning . "\n" . $e->getTraceAsString() );
1454  return [ 'before', '[INVALID]' ];
1455  }
1456  $func = self::$listTypeMap[$listType];
1457 
1458  // Handle an empty list sensibly
1459  if ( !$params ) {
1460  return [ 'before', $this->getLanguage()->$func( [] ) ];
1461  }
1462 
1463  // First, determine what kinds of list items we have
1464  $types = [];
1465  $vars = [];
1466  $list = [];
1467  foreach ( $params as $n => $p ) {
1468  list( $type, $value ) = $this->extractParam( $p, $format );
1469  $types[$type] = true;
1470  $list[] = $value;
1471  $vars[] = '$' . ( $n + 1 );
1472  }
1473 
1474  // Easy case: all are 'before' or 'after', so just join the
1475  // values and use the same type.
1476  if ( count( $types ) === 1 ) {
1477  return [ key( $types ), $this->getLanguage()->$func( $list ) ];
1478  }
1479 
1480  // Hard case: We need to process each value per its type, then
1481  // return the concatenated values as 'after'. We handle this by turning
1482  // the list into a RawMessage and processing that as a parameter.
1483  $vars = $this->getLanguage()->$func( $vars );
1484  // @phan-suppress-next-line SecurityCheck-DoubleEscaped RawMessage is safe here
1485  return $this->extractParam( new RawMessage( $vars, $params ), $format );
1486  }
1487 }
Message\numParam
static numParam( $num)
Definition: Message.php:1103
Message\newFromSpecifier
static newFromSpecifier( $value)
Transform a MessageSpecifier or a primitive value used interchangeably with specifiers (a message key...
Definition: Message.php:406
Title\newFromText
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:415
Message\getParams
getParams()
Returns the message parameters.
Definition: Message.php:360
Message\exists
exists()
Check whether a message key has been defined currently.
Definition: Message.php:1055
Message\dateParam
static dateParam(string $date)
Definition: Message.php:1147
ParserOutput
Definition: ParserOutput.php:31
Message\$listTypeMap
static array $listTypeMap
Mapping from Message::listParam() types to Language methods.
Definition: Message.php:154
NS_MEDIAWIKI
const NS_MEDIAWIKI
Definition: Defines.php:72
Message\$message
string $message
Definition: Message.php:216
Message\toString
toString( $format=null)
Returns the message formatted a certain way.
Definition: Message.php:900
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:184
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:37
true
return true
Definition: router.php:90
Message\$contextPage
PageReference $contextPage
page object to use as context.
Definition: Message.php:206
MessageSpecifier
Definition: MessageSpecifier.php:24
Message\parseText
parseText( $string)
Wrapper for what ever method we use to parse wikitext.
Definition: Message.php:1346
Message\$keysToTry
string[] $keysToTry
List of keys to try when fetching the message.
Definition: Message.php:185
Message\timeperiodParam
static timeperiodParam( $period)
Definition: Message.php:1169
$serialized
foreach( $res as $row) $serialized
Definition: testCompression.php:88
Message\fetchMessage
fetchMessage()
Wrapper for what ever method we use to get message contents.
Definition: Message.php:1393
Message\format
format(string $format)
Returns the message formatted a certain way.
Definition: Message.php:915
Message\plain
plain()
Returns the message text as-is, only parameters are substituted.
Definition: Message.php:1018
Message\inContentLanguage
inContentLanguage()
Request the message in the wiki's content language, unless it is disabled for this message.
Definition: Message.php:811
Message\$content
Content $content
Content object representing the message.
Definition: Message.php:211
Message\isDisabled
isDisabled()
Check whether a message does not exist, is an empty string, or is "-".
Definition: Message.php:1079
Message\text
text()
Returns the message text.
Definition: Message.php:1006
Message\setInterfaceMessageFlag
setInterfaceMessageFlag( $interface)
Allows manipulating the interface message flag directly.
Definition: Message.php:831
wfDebugLog
wfDebugLog( $logGroup, $text, $dest='all', array $context=[])
Send a line to a supplementary debug log file, if configured, or main debug log if not.
Definition: GlobalFunctions.php:958
Page\PageReference
Interface for objects (potentially) representing a page that can be viewable and linked to on a wiki.
Definition: PageReference.php:49
Message\listParam
static listParam(array $list, $type='text')
Definition: Message.php:1213
Message\__toString
__toString()
Magic method implementation of the above (for PHP >= 5.2.0), so we can do, eg: $foo = new Message( $k...
Definition: Message.php:969
Message\$language
Language bool $language
In which language to get this message.
Definition: Message.php:174
Message\getKey
getKey()
Returns the message key.
Definition: Message.php:349
Message\getLanguage
getLanguage()
Returns the Language of the Message.
Definition: Message.php:371
Message\numParams
numParams(... $params)
Add parameters that are numeric and will be passed through Language::formatNum before substitution.
Definition: Message.php:546
Message\isBlank
isBlank()
Check whether a message does not exist, or is an empty string.
Definition: Message.php:1067
Message\FORMAT_BLOCK_PARSE
const FORMAT_BLOCK_PARSE
Use normal wikitext -> HTML parsing (the result will be wrapped in a block-level HTML tag)
Definition: Message.php:142
MWException
MediaWiki exception.
Definition: MWException.php:29
Message\isMultiKey
isMultiKey()
Definition: Message.php:324
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that $function is deprecated.
Definition: GlobalFunctions.php:996
MediaWiki\Logger\LoggerFactory
PSR-3 logger instance factory.
Definition: LoggerFactory.php:45
Message\useDatabase
useDatabase( $useDatabase)
Enable or disable database use.
Definition: Message.php:845
Message\FORMAT_TEXT
const FORMAT_TEXT
Transform {{..}} constructs but don't transform to HTML.
Definition: Message.php:146
Message\durationParams
durationParams(... $params)
Add parameters that are durations of time and will be passed through Language::formatDuration before ...
Definition: Message.php:567
Message\serialize
serialize()
Definition: Message.php:262
Message\$interface
bool $interface
In which language to get this message.
Definition: Message.php:167
$args
if( $line===false) $args
Definition: mcc.php:124
$title
$title
Definition: testCompression.php:38
Title\makeTitle
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:680
Message\rawParams
rawParams(... $params)
Add parameters that are substituted after parsing or escaping.
Definition: Message.php:525
Message\FORMAT_PARSE
const FORMAT_PARSE
Use normal wikitext -> HTML parsing but strip the block-level wrapper.
Definition: Message.php:144
Message\getKeysToTry
getKeysToTry()
Definition: Message.php:334
Message\parseAsBlock
parseAsBlock()
Returns the parsed message text which is always surrounded by a block element.
Definition: Message.php:1030
Message\sizeParam
static sizeParam( $size)
Definition: Message.php:1180
Language\getCode
getCode()
Get the internal language code for this language object.
Definition: Language.php:4393
Message\formatPlaintext
formatPlaintext( $plaintext, $format)
Formats a message parameter wrapped with 'plaintext'.
Definition: Message.php:1424
Message\plaintextParam
static plaintextParam( $plaintext)
Definition: Message.php:1202
Message\rawParam
static rawParam( $raw)
Definition: Message.php:1092
StubUserLang
Stub object for the user language.
Definition: StubUserLang.php:24
Message\expiryParam
static expiryParam( $expiry)
Definition: Message.php:1125
Message\parse
parse()
Fully parse the text from wikitext to HTML.
Definition: Message.php:994
Message\setContext
setContext(IContextSource $context)
Set the language and the title from a context object.
Definition: Message.php:756
Message\transformText
transformText( $string)
Wrapper for what ever method we use to {{-transform wikitext.
Definition: Message.php:1376
Message\timeParams
timeParams(... $params)
Add parameters that are times and will be passed through Language::time before substitution.
Definition: Message.php:651
RequestContext\getMain
static getMain()
Get the RequestContext object associated with the main request.
Definition: RequestContext.php:484
IContextSource\getTitle
getTitle()
Message\plaintextParams
plaintextParams(... $params)
Add parameters that are plaintext and will be passed through without the content being evaluated.
Definition: Message.php:737
$wgForceUIMsgAsContentMsg
$wgForceUIMsgAsContentMsg
When translating messages with wfMessage(), it is not always clear what should be considered UI messa...
Definition: DefaultSettings.php:3668
IContextSource
Interface for objects which can provide a MediaWiki context on request.
Definition: IContextSource.php:58
Message\extractParam
extractParam( $param, $format)
Extracts the parameter type and preprocessed the value if needed.
Definition: Message.php:1270
Message\escaped
escaped()
Returns the message text.
Definition: Message.php:1043
Content
Base interface for content objects.
Definition: Content.php:35
Message\params
params(... $args)
Adds parameters to the parameter list of this message.
Definition: Message.php:490
Message\$key
string $key
The message key.
Definition: Message.php:180
Parser\stripOuterParagraph
static stripOuterParagraph( $html)
Strip outer.
Definition: Parser.php:6310
Message\newFromKey
static newFromKey( $key,... $params)
Factory function that is just wrapper for the real constructor.
Definition: Message.php:388
Message\timeParam
static timeParam(string $time)
Definition: Message.php:1158
Message\formatListParam
formatListParam(array $params, $listType, $format)
Formats a list of parameters as a concatenated string.
Definition: Message.php:1446
$cache
$cache
Definition: mcc.php:33
MessageContent
Wrapper allowing us to handle a system message as a Content object.
Definition: MessageContent.php:36
Page\PageReferenceValue
Immutable value object representing a page reference.
Definition: PageReferenceValue.php:42
Message\dateTimeParam
static dateTimeParam(string $dateTime)
Definition: Message.php:1136
Message\getTitle
getTitle()
Get a title object for a mediawiki message, where it can be found in the mediawiki namespace.
Definition: Message.php:463
Message\title
title( $title)
Set the Title object to use as context when transforming the message.
Definition: Message.php:861
Message\bitrateParam
static bitrateParam( $bitrate)
Definition: Message.php:1191
Message\replaceParameters
replaceParameters( $message, $type, $format)
Substitutes any parameters into the message text.
Definition: Message.php:1233
Message\bitrateParams
bitrateParams(... $params)
Add parameters that are bitrates and will be passed through Language::formatBitrate before substituti...
Definition: Message.php:714
Message\unserialize
unserialize( $serialized)
Definition: Message.php:286
Message
The Message class deals with fetching and processing of interface message into a variety of formats.
Definition: Message.php:138
$keys
$keys
Definition: testCompression.php:72
Message\$parameters
array $parameters
List of parameters which will be substituted into the message.
Definition: Message.php:190
Message\content
content()
Returns the message as a Content object.
Definition: Message.php:884
Message\expiryParams
expiryParams(... $params)
Add parameters that are expiration times and will be passed through Language::formatExpiry before sub...
Definition: Message.php:588
ParserOutput\getText
getText( $options=[])
Get the output HTML.
Definition: ParserOutput.php:350
Message\$useDatabase
bool $useDatabase
Whether database can be used.
Definition: Message.php:201
Message\timeperiodParams
timeperiodParams(... $params)
Add parameters that are time periods and will be passed through Language::formatTimePeriod before sub...
Definition: Message.php:672
Message\FORMAT_ESCAPED
const FORMAT_ESCAPED
Transform {{..}} constructs, HTML-escape the result.
Definition: Message.php:148
RawMessage
Variant of the Message class.
Definition: RawMessage.php:35
Message\__construct
__construct( $key, $params=[], Language $language=null)
Definition: Message.php:228
Message\sizeParams
sizeParams(... $params)
Add parameters that are file sizes and will be passed through Language::formatSize before substitutio...
Definition: Message.php:693
Message\inLanguage
inLanguage( $lang)
Request the message in any language that is supported.
Definition: Message.php:775
Message\FORMAT_PLAIN
const FORMAT_PLAIN
Use message text as-is.
Definition: Message.php:140
Message\page
page(?PageReference $page)
Set the page object to use as context when transforming the message.
Definition: Message.php:874
Message\newFallbackSequence
static newFallbackSequence(... $keys)
Factory function accepting multiple message keys and returning a message instance for the first messa...
Definition: Message.php:440
Message\durationParam
static durationParam( $duration)
Definition: Message.php:1114
Language
Internationalisation code See https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation for more...
Definition: Language.php:42
Message\$format
string $format
Definition: Message.php:196
IContextSource\getLanguage
getLanguage()
Message\dateTimeParams
dateTimeParams(... $params)
Add parameters that are date-times and will be passed through Language::timeanddate before substituti...
Definition: Message.php:609
Message\dateParams
dateParams(... $params)
Add parameters that are dates and will be passed through Language::date before substitution.
Definition: Message.php:630
$type
$type
Definition: testCompression.php:52