MediaWiki  master
CoreParserFunctions.php
Go to the documentation of this file.
1 <?php
30 use Wikimedia\RemexHtml\Tokenizer\Attributes;
31 use Wikimedia\RemexHtml\Tokenizer\PlainAttributes;
32 
38 
42  public const REGISTER_OPTIONS = [
43  // See documentation for the corresponding config options
44  MainConfigNames::AllowDisplayTitle,
45  MainConfigNames::AllowSlowParserFunctions,
46  ];
47 
56  public static function register( Parser $parser, ServiceOptions $options ) {
57  $options->assertRequiredOptions( self::REGISTER_OPTIONS );
58  $allowDisplayTitle = $options->get( MainConfigNames::AllowDisplayTitle );
59  $allowSlowParserFunctions = $options->get( MainConfigNames::AllowSlowParserFunctions );
60 
61  # Syntax for arguments (see Parser::setFunctionHook):
62  # "name for lookup in localized magic words array",
63  # function callback,
64  # optional Parser::SFH_NO_HASH to omit the hash from calls (e.g. {{int:...}}
65  # instead of {{#int:...}})
66  $noHashFunctions = [
67  'ns', 'nse', 'urlencode', 'lcfirst', 'ucfirst', 'lc', 'uc',
68  'localurl', 'localurle', 'fullurl', 'fullurle', 'canonicalurl',
69  'canonicalurle', 'formatnum', 'grammar', 'gender', 'plural', 'bidi',
70  'numberofpages', 'numberofusers', 'numberofactiveusers',
71  'numberofarticles', 'numberoffiles', 'numberofadmins',
72  'numberingroup', 'numberofedits', 'language',
73  'padleft', 'padright', 'anchorencode', 'defaultsort', 'filepath',
74  'pagesincategory', 'pagesize', 'protectionlevel', 'protectionexpiry',
75  'namespace',
76  'namespacee', 'namespacenumber', 'talkspace', 'talkspacee',
77  'subjectspace', 'subjectspacee', 'pagename', 'pagenamee',
78  'fullpagename', 'fullpagenamee', 'rootpagename', 'rootpagenamee',
79  'basepagename', 'basepagenamee', 'subpagename', 'subpagenamee',
80  'talkpagename', 'talkpagenamee', 'subjectpagename',
81  'subjectpagenamee', 'pageid', 'revisionid', 'revisionday',
82  'revisionday2', 'revisionmonth', 'revisionmonth1', 'revisionyear',
83  'revisiontimestamp', 'revisionuser', 'cascadingsources',
84  ];
85  foreach ( $noHashFunctions as $func ) {
86  $parser->setFunctionHook( $func, [ __CLASS__, $func ], Parser::SFH_NO_HASH );
87  }
88 
89  $parser->setFunctionHook( 'int', [ __CLASS__, 'intFunction' ], Parser::SFH_NO_HASH );
90  $parser->setFunctionHook( 'special', [ __CLASS__, 'special' ] );
91  $parser->setFunctionHook( 'speciale', [ __CLASS__, 'speciale' ] );
92  $parser->setFunctionHook( 'tag', [ __CLASS__, 'tagObj' ], Parser::SFH_OBJECT_ARGS );
93  $parser->setFunctionHook( 'formatdate', [ __CLASS__, 'formatDate' ] );
94 
95  if ( $allowDisplayTitle ) {
96  $parser->setFunctionHook(
97  'displaytitle',
98  [ __CLASS__, 'displaytitle' ],
100  );
101  }
102  if ( $allowSlowParserFunctions ) {
103  $parser->setFunctionHook(
104  'pagesinnamespace',
105  [ __CLASS__, 'pagesinnamespace' ],
107  );
108  }
109  }
110 
117  public static function intFunction( $parser, $part1 = '', ...$params ) {
118  if ( strval( $part1 ) !== '' ) {
119  $message = wfMessage( $part1, $params )
120  ->inLanguage( $parser->getOptions()->getUserLangObj() );
121  return [ $message->plain(), 'noparse' => false ];
122  } else {
123  return [ 'found' => false ];
124  }
125  }
126 
134  public static function formatDate( $parser, $date, $defaultPref = null ) {
135  $lang = $parser->getFunctionLang();
136  $df = MediaWikiServices::getInstance()->getDateFormatterFactory()->get( $lang );
137 
138  $date = trim( $date );
139 
140  $pref = $parser->getOptions()->getDateFormat();
141 
142  // Specify a different default date format other than the normal default
143  // if the user has 'default' for their setting
144  if ( $pref == 'default' && $defaultPref ) {
145  $pref = $defaultPref;
146  }
147 
148  $date = $df->reformat( $pref, $date, [ 'match-whole' ] );
149  return $date;
150  }
151 
152  public static function ns( $parser, $part1 = '' ) {
153  if ( intval( $part1 ) || $part1 == "0" ) {
154  $index = intval( $part1 );
155  } else {
156  $index = $parser->getContentLanguage()->getNsIndex( str_replace( ' ', '_', $part1 ) );
157  }
158  if ( $index !== false ) {
159  return $parser->getContentLanguage()->getFormattedNsText( $index );
160  } else {
161  return [ 'found' => false ];
162  }
163  }
164 
165  public static function nse( $parser, $part1 = '' ) {
166  $ret = self::ns( $parser, $part1 );
167  if ( is_string( $ret ) ) {
168  $ret = wfUrlencode( str_replace( ' ', '_', $ret ) );
169  }
170  return $ret;
171  }
172 
185  public static function urlencode( $parser, $s = '', $arg = null ) {
186  static $magicWords = null;
187  if ( $magicWords === null ) {
188  $magicWords =
189  $parser->getMagicWordFactory()->newArray( [ 'url_path', 'url_query', 'url_wiki' ] );
190  }
191  switch ( $magicWords->matchStartToEnd( $arg ?? '' ) ) {
192  // Encode as though it's a wiki page, '_' for ' '.
193  case 'url_wiki':
194  $func = 'wfUrlencode';
195  $s = str_replace( ' ', '_', $s );
196  break;
197 
198  // Encode for an HTTP Path, '%20' for ' '.
199  case 'url_path':
200  $func = 'rawurlencode';
201  break;
202 
203  // Encode for HTTP query, '+' for ' '.
204  case 'url_query':
205  default:
206  $func = 'urlencode';
207  }
208  // See T105242, where the choice to kill markers and various
209  // other options were discussed.
210  return $func( $parser->killMarkers( $s ) );
211  }
212 
213  public static function lcfirst( $parser, $s = '' ) {
214  return $parser->getContentLanguage()->lcfirst( $s );
215  }
216 
217  public static function ucfirst( $parser, $s = '' ) {
218  return $parser->getContentLanguage()->ucfirst( $s );
219  }
220 
226  public static function lc( $parser, $s = '' ) {
227  return $parser->markerSkipCallback( $s, [ $parser->getContentLanguage(), 'lc' ] );
228  }
229 
235  public static function uc( $parser, $s = '' ) {
236  return $parser->markerSkipCallback( $s, [ $parser->getContentLanguage(), 'uc' ] );
237  }
238 
239  public static function localurl( $parser, $s = '', $arg = null ) {
240  return self::urlFunction( 'getLocalURL', $s, $arg );
241  }
242 
243  public static function localurle( $parser, $s = '', $arg = null ) {
244  $temp = self::urlFunction( 'getLocalURL', $s, $arg );
245  if ( !is_string( $temp ) ) {
246  return $temp;
247  } else {
248  return htmlspecialchars( $temp, ENT_COMPAT );
249  }
250  }
251 
252  public static function fullurl( $parser, $s = '', $arg = null ) {
253  return self::urlFunction( 'getFullURL', $s, $arg );
254  }
255 
256  public static function fullurle( $parser, $s = '', $arg = null ) {
257  $temp = self::urlFunction( 'getFullURL', $s, $arg );
258  if ( !is_string( $temp ) ) {
259  return $temp;
260  } else {
261  return htmlspecialchars( $temp, ENT_COMPAT );
262  }
263  }
264 
265  public static function canonicalurl( $parser, $s = '', $arg = null ) {
266  return self::urlFunction( 'getCanonicalURL', $s, $arg );
267  }
268 
269  public static function canonicalurle( $parser, $s = '', $arg = null ) {
270  $temp = self::urlFunction( 'getCanonicalURL', $s, $arg );
271  if ( !is_string( $temp ) ) {
272  return $temp;
273  } else {
274  return htmlspecialchars( $temp, ENT_COMPAT );
275  }
276  }
277 
278  public static function urlFunction( $func, $s = '', $arg = null ) {
280  # Due to order of execution of a lot of bits, the values might be encoded
281  # before arriving here; if that's true, then the title can't be created
282  # and the variable will fail. If we can't get a decent title from the first
283  # attempt, url-decode and try for a second.
284  if ( $title === null ) {
285  $title = Title::newFromURL( urldecode( $s ) );
286  }
287  if ( $title !== null ) {
288  # Convert NS_MEDIA -> NS_FILE
289  if ( $title->inNamespace( NS_MEDIA ) ) {
290  $title = Title::makeTitle( NS_FILE, $title->getDBkey() );
291  }
292  if ( $arg !== null ) {
293  $text = $title->$func( $arg );
294  } else {
295  $text = $title->$func();
296  }
297  return $text;
298  } else {
299  return [ 'found' => false ];
300  }
301  }
302 
309  public static function formatnum( $parser, $num = '', $arg = null ) {
310  if ( self::matchAgainstMagicword( $parser->getMagicWordFactory(), 'rawsuffix', $arg ) ) {
311  $func = [ $parser->getFunctionLang(), 'parseFormattedNumber' ];
312  } elseif (
313  self::matchAgainstMagicword( $parser->getMagicWordFactory(), 'nocommafysuffix', $arg )
314  ) {
315  $func = [ $parser->getFunctionLang(), 'formatNumNoSeparators' ];
316  $func = self::getLegacyFormatNum( $parser, $func );
317  } else {
318  $func = [ $parser->getFunctionLang(), 'formatNum' ];
319  $func = self::getLegacyFormatNum( $parser, $func );
320  }
321  return $parser->markerSkipCallback( $num, $func );
322  }
323 
330  private static function getLegacyFormatNum( $parser, $callback ) {
331  // For historic reasons, the formatNum parser function will
332  // take arguments which are not actually formatted numbers,
333  // which then trigger deprecation warnings in Language::formatNum*.
334  // Instead emit a tracking category instead to allow linting.
335  return static function ( $number ) use ( $parser, $callback ) {
336  $validNumberRe = '(-(?=[\d\.]))?(\d+|(?=\.\d))(\.\d*)?([Ee][-+]?\d+)?';
337  if (
338  !is_numeric( $number ) &&
339  $number !== (string)NAN &&
340  $number !== (string)INF &&
341  $number !== (string)-INF
342  ) {
343  $parser->addTrackingCategory( 'nonnumeric-formatnum' );
344  // Don't split on NAN/INF in the legacy case since they are
345  // likely to be found embedded inside non-numeric text.
346  return preg_replace_callback( "/{$validNumberRe}/", static function ( $m ) use ( $callback ) {
347  return call_user_func( $callback, $m[0] );
348  }, $number );
349  }
350  return call_user_func( $callback, $number );
351  };
352  }
353 
360  public static function grammar( $parser, $case = '', $word = '' ) {
361  $word = $parser->killMarkers( $word );
362  return $parser->getFunctionLang()->convertGrammar( $word, $case );
363  }
364 
371  public static function gender( $parser, $username, ...$forms ) {
372  // Some shortcuts to avoid loading user data unnecessarily
373  if ( count( $forms ) === 0 ) {
374  return '';
375  } elseif ( count( $forms ) === 1 ) {
376  return $forms[0];
377  }
378 
379  $username = trim( $username );
380 
381  $userOptionsLookup = MediaWikiServices::getInstance()->getUserOptionsLookup();
382  $gender = $userOptionsLookup->getDefaultOption( 'gender' );
383 
384  // allow prefix and normalize (e.g. "&#42;foo" -> "*foo" ).
385  $title = Title::newFromText( $username, NS_USER );
386 
387  if ( $title && $title->inNamespace( NS_USER ) ) {
388  $username = $title->getText();
389  }
390 
391  // check parameter, or use the ParserOptions if in interface message
392  $user = User::newFromName( $username );
393  $genderCache = MediaWikiServices::getInstance()->getGenderCache();
394  if ( $user ) {
395  $gender = $genderCache->getGenderOf( $user, __METHOD__ );
396  } elseif ( $username === '' && $parser->getOptions()->getInterfaceMessage() ) {
397  $gender = $genderCache->getGenderOf( $parser->getOptions()->getUserIdentity(), __METHOD__ );
398  }
399  $ret = $parser->getFunctionLang()->gender( $gender, $forms );
400  return $ret;
401  }
402 
409  public static function plural( $parser, $text = '', ...$forms ) {
410  $text = $parser->getFunctionLang()->parseFormattedNumber( $text );
411  settype( $text, ctype_digit( $text ) ? 'int' : 'float' );
412  // @phan-suppress-next-line PhanTypeMismatchArgument Phan does not handle settype
413  return $parser->getFunctionLang()->convertPlural( $text, $forms );
414  }
415 
421  public static function bidi( $parser, $text = '' ) {
422  return $parser->getFunctionLang()->embedBidi( $text );
423  }
424 
434  public static function displaytitle( $parser, $text = '', $uarg = '' ) {
435  $restrictDisplayTitle = MediaWikiServices::getInstance()->getMainConfig()
436  ->get( MainConfigNames::RestrictDisplayTitle );
437 
438  static $magicWords = null;
439  if ( $magicWords === null ) {
440  $magicWords = $parser->getMagicWordFactory()->newArray(
441  [ 'displaytitle_noerror', 'displaytitle_noreplace' ] );
442  }
443  $arg = $magicWords->matchStartToEnd( $uarg );
444 
445  // parse a limited subset of wiki markup (just the single quote items)
446  $text = $parser->doQuotes( $text );
447 
448  // remove stripped text (e.g. the UNIQ-QINU stuff) that was generated by tag extensions/whatever
449  $text = $parser->killMarkers( $text );
450 
451  // See T28547 for rationale for this processing.
452  // list of disallowed tags for DISPLAYTITLE
453  // these will be escaped even though they are allowed in normal wiki text
454  $bad = [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'div', 'blockquote', 'ol', 'ul', 'li', 'hr',
455  'table', 'tr', 'th', 'td', 'dl', 'dd', 'caption', 'p', 'ruby', 'rb', 'rt', 'rtc', 'rp', 'br' ];
456 
457  // disallow some styles that could be used to bypass $wgRestrictDisplayTitle
458  if ( $restrictDisplayTitle ) {
459  // This code is tested with the cases marked T28547 in
460  // parserTests.txt
461  $htmlTagsCallback = static function ( Attributes $attr ): Attributes {
462  $decoded = $attr->getValues();
463 
464  if ( isset( $decoded['style'] ) ) {
465  // this is called later anyway, but we need it right now for the regexes below to be safe
466  // calling it twice doesn't hurt
467  $decoded['style'] = Sanitizer::checkCss( $decoded['style'] );
468 
469  if ( preg_match( '/(display|user-select|visibility)\s*:/i', $decoded['style'] ) ) {
470  $decoded['style'] = '/* attempt to bypass $wgRestrictDisplayTitle */';
471  }
472  }
473 
474  return new PlainAttributes( $decoded );
475  };
476  } else {
477  $htmlTagsCallback = null;
478  }
479 
480  // only requested titles that normalize to the actual title are allowed through
481  // if $wgRestrictDisplayTitle is true (it is by default)
482  // mimic the escaping process that occurs in OutputPage::setPageTitle
483  $text = Sanitizer::removeSomeTags( $text, [
484  'attrCallback' => $htmlTagsCallback,
485  'removeTags' => $bad,
486  ] );
488  // Decode entities in $text the same way that Title::newFromText does
489  $filteredText = Sanitizer::decodeCharReferencesAndNormalize( $text );
490 
491  if ( !$restrictDisplayTitle ||
492  ( $title instanceof Title
493  && !$title->hasFragment()
494  && $title->equals( $parser->getTitle() ) )
495  ) {
496  $old = $parser->getOutput()->getPageProperty( 'displaytitle' );
497  if ( $old === null || $arg !== 'displaytitle_noreplace' ) {
498  $parser->getOutput()->setDisplayTitle( $text );
499  }
500  if ( $old !== null && $old !== $text && !$arg ) {
501 
502  $converter = $parser->getTargetLanguageConverter();
503  return '<span class="error">' .
504  wfMessage( 'duplicate-displaytitle',
505  // Message should be parsed, but these params should only be escaped.
506  $converter->markNoConversion( wfEscapeWikiText( $old ) ),
507  // @phan-suppress-next-line SecurityCheck-DoubleEscaped we removed escaping above
508  $converter->markNoConversion( wfEscapeWikiText( $filteredText ) )
509  )->inContentLanguage()->text() .
510  '</span>';
511  } else {
512  return '';
513  }
514  } else {
515  $parser->getOutput()->addWarningMsg(
516  'restricted-displaytitle',
517  // Message should be parsed, but this param should only be escaped.
518  Message::plaintextParam( $filteredText )
519  );
520  $parser->addTrackingCategory( 'restricted-displaytitle-ignored' );
521  }
522  }
523 
533  private static function matchAgainstMagicword(
534  MagicWordFactory $magicWordFactory, $magicword, $value
535  ) {
536  $value = trim( strval( $value ) );
537  if ( $value === '' ) {
538  return false;
539  }
540  $mwObject = $magicWordFactory->get( $magicword );
541  return $mwObject->matchStartToEnd( $value );
542  }
543 
553  public static function formatRaw(
554  $num, $raw, $language, MagicWordFactory $magicWordFactory = null
555  ) {
556  if ( $raw !== null ) {
557  if ( !$magicWordFactory ) {
558  $magicWordFactory = MediaWikiServices::getInstance()->getMagicWordFactory();
559  }
560  if ( self::matchAgainstMagicword( $magicWordFactory, 'rawsuffix', $raw ) ) {
561  return (string)$num;
562  }
563  }
564  return $language->formatNum( $num );
565  }
566 
567  public static function numberofpages( $parser, $raw = null ) {
568  return self::formatRaw( SiteStats::pages(), $raw, $parser->getFunctionLang() );
569  }
570 
571  public static function numberofusers( $parser, $raw = null ) {
572  return self::formatRaw( SiteStats::users(), $raw, $parser->getFunctionLang() );
573  }
574 
575  public static function numberofactiveusers( $parser, $raw = null ) {
576  return self::formatRaw( SiteStats::activeUsers(), $raw, $parser->getFunctionLang() );
577  }
578 
579  public static function numberofarticles( $parser, $raw = null ) {
580  return self::formatRaw( SiteStats::articles(), $raw, $parser->getFunctionLang() );
581  }
582 
583  public static function numberoffiles( $parser, $raw = null ) {
584  return self::formatRaw( SiteStats::images(), $raw, $parser->getFunctionLang() );
585  }
586 
587  public static function numberofadmins( $parser, $raw = null ) {
588  return self::formatRaw(
589  SiteStats::numberingroup( 'sysop' ),
590  $raw,
591  $parser->getFunctionLang()
592  );
593  }
594 
595  public static function numberofedits( $parser, $raw = null ) {
596  return self::formatRaw( SiteStats::edits(), $raw, $parser->getFunctionLang() );
597  }
598 
599  public static function pagesinnamespace( $parser, $namespace = 0, $raw = null ) {
600  return self::formatRaw(
601  SiteStats::pagesInNs( intval( $namespace ) ),
602  $raw,
603  $parser->getFunctionLang()
604  );
605  }
606 
607  public static function numberingroup( $parser, $name = '', $raw = null ) {
608  return self::formatRaw(
609  SiteStats::numberingroup( strtolower( $name ) ),
610  $raw,
611  $parser->getFunctionLang()
612  );
613  }
614 
623  public static function namespace( $parser, $title = null ) {
625  if ( $t === null ) {
626  return '';
627  }
628  return str_replace( '_', ' ', $t->getNsText() );
629  }
630 
641  public static function mwnamespace( $parser, $title = null ) {
642  wfDeprecated( __METHOD__, '1.39' );
643  return self::namespace( $parser, $title );
644  }
645 
646  public static function namespacee( $parser, $title = null ) {
648  if ( $t === null ) {
649  return '';
650  }
651  return wfUrlencode( $t->getNsText() );
652  }
653 
654  public static function namespacenumber( $parser, $title = null ) {
656  if ( $t === null ) {
657  return '';
658  }
659  return $t->getNamespace();
660  }
661 
662  public static function talkspace( $parser, $title = null ) {
664  if ( $t === null || !$t->canHaveTalkPage() ) {
665  return '';
666  }
667  return str_replace( '_', ' ', $t->getTalkNsText() );
668  }
669 
670  public static function talkspacee( $parser, $title = null ) {
672  if ( $t === null || !$t->canHaveTalkPage() ) {
673  return '';
674  }
675  return wfUrlencode( $t->getTalkNsText() );
676  }
677 
678  public static function subjectspace( $parser, $title = null ) {
680  if ( $t === null ) {
681  return '';
682  }
683  return str_replace( '_', ' ', $t->getSubjectNsText() );
684  }
685 
686  public static function subjectspacee( $parser, $title = null ) {
688  if ( $t === null ) {
689  return '';
690  }
691  return wfUrlencode( $t->getSubjectNsText() );
692  }
693 
701  public static function pagename( $parser, $title = null ) {
703  if ( $t === null ) {
704  return '';
705  }
706  return wfEscapeWikiText( $t->getText() );
707  }
708 
709  public static function pagenamee( $parser, $title = null ) {
711  if ( $t === null ) {
712  return '';
713  }
714  return wfEscapeWikiText( $t->getPartialURL() );
715  }
716 
717  public static function fullpagename( $parser, $title = null ) {
719  if ( $t === null || !$t->canHaveTalkPage() ) {
720  return '';
721  }
722  return wfEscapeWikiText( $t->getPrefixedText() );
723  }
724 
725  public static function fullpagenamee( $parser, $title = null ) {
727  if ( $t === null || !$t->canHaveTalkPage() ) {
728  return '';
729  }
730  return wfEscapeWikiText( $t->getPrefixedURL() );
731  }
732 
733  public static function subpagename( $parser, $title = null ) {
735  if ( $t === null ) {
736  return '';
737  }
738  return wfEscapeWikiText( $t->getSubpageText() );
739  }
740 
741  public static function subpagenamee( $parser, $title = null ) {
743  if ( $t === null ) {
744  return '';
745  }
746  return wfEscapeWikiText( $t->getSubpageUrlForm() );
747  }
748 
749  public static function rootpagename( $parser, $title = null ) {
751  if ( $t === null ) {
752  return '';
753  }
754  return wfEscapeWikiText( $t->getRootText() );
755  }
756 
757  public static function rootpagenamee( $parser, $title = null ) {
759  if ( $t === null ) {
760  return '';
761  }
762  return wfEscapeWikiText( wfUrlencode( str_replace( ' ', '_', $t->getRootText() ) ) );
763  }
764 
765  public static function basepagename( $parser, $title = null ) {
767  if ( $t === null ) {
768  return '';
769  }
770  return wfEscapeWikiText( $t->getBaseText() );
771  }
772 
773  public static function basepagenamee( $parser, $title = null ) {
775  if ( $t === null ) {
776  return '';
777  }
778  return wfEscapeWikiText( wfUrlencode( str_replace( ' ', '_', $t->getBaseText() ) ) );
779  }
780 
781  public static function talkpagename( $parser, $title = null ) {
783  if ( $t === null || !$t->canHaveTalkPage() ) {
784  return '';
785  }
786  return wfEscapeWikiText( $t->getTalkPage()->getPrefixedText() );
787  }
788 
789  public static function talkpagenamee( $parser, $title = null ) {
791  if ( $t === null || !$t->canHaveTalkPage() ) {
792  return '';
793  }
794  return wfEscapeWikiText( $t->getTalkPage()->getPrefixedURL() );
795  }
796 
797  public static function subjectpagename( $parser, $title = null ) {
799  if ( $t === null ) {
800  return '';
801  }
802  return wfEscapeWikiText( $t->getSubjectPage()->getPrefixedText() );
803  }
804 
805  public static function subjectpagenamee( $parser, $title = null ) {
807  if ( $t === null ) {
808  return '';
809  }
810  return wfEscapeWikiText( $t->getSubjectPage()->getPrefixedURL() );
811  }
812 
823  public static function pagesincategory( $parser, $name = '', $arg1 = '', $arg2 = '' ) {
824  static $magicWords = null;
825  if ( $magicWords === null ) {
826  $magicWords = $parser->getMagicWordFactory()->newArray( [
827  'pagesincategory_all',
828  'pagesincategory_pages',
829  'pagesincategory_subcats',
830  'pagesincategory_files'
831  ] );
832  }
833  static $cache = [];
834 
835  // split the given option to its variable
836  if ( self::matchAgainstMagicword( $parser->getMagicWordFactory(), 'rawsuffix', $arg1 ) ) {
837  // {{pagesincategory:|raw[|type]}}
838  $raw = $arg1;
839  $type = $magicWords->matchStartToEnd( $arg2 );
840  } else {
841  // {{pagesincategory:[|type[|raw]]}}
842  $type = $magicWords->matchStartToEnd( $arg1 );
843  $raw = $arg2;
844  }
845  if ( !$type ) { // backward compatibility
846  $type = 'pagesincategory_all';
847  }
848 
850  if ( !$title ) { # invalid title
851  return self::formatRaw( 0, $raw, $parser->getFunctionLang() );
852  }
853  $languageConverter = MediaWikiServices::getInstance()
854  ->getLanguageConverterFactory()
855  ->getLanguageConverter( $parser->getContentLanguage() );
856  $languageConverter->findVariantLink( $name, $title, true );
857 
858  // Normalize name for cache
859  $name = $title->getDBkey();
860 
861  if ( !isset( $cache[$name] ) ) {
862  $category = Category::newFromTitle( $title );
863 
864  $allCount = $subcatCount = $fileCount = $pageCount = 0;
865  if ( $parser->incrementExpensiveFunctionCount() ) {
866  $allCount = $category->getMemberCount();
867  $subcatCount = $category->getSubcatCount();
868  $fileCount = $category->getFileCount();
869  $pageCount = $category->getPageCount( Category::COUNT_CONTENT_PAGES );
870  }
871  $cache[$name]['pagesincategory_all'] = $allCount;
872  $cache[$name]['pagesincategory_pages'] = $pageCount;
873  $cache[$name]['pagesincategory_subcats'] = $subcatCount;
874  $cache[$name]['pagesincategory_files'] = $fileCount;
875  }
876 
877  $count = $cache[$name][$type];
878  return self::formatRaw( $count, $raw, $parser->getFunctionLang() );
879  }
880 
890  public static function pagesize( $parser, $page = '', $raw = null ) {
891  $title = Title::newFromText( $page );
892 
893  if ( !is_object( $title ) ) {
894  return self::formatRaw( 0, $raw, $parser->getFunctionLang() );
895  }
896 
897  // fetch revision from cache/database and return the value
898  $rev = self::getCachedRevisionObject( $parser, $title, ParserOutputFlags::VARY_REVISION_SHA1 );
899  $length = $rev ? $rev->getSize() : 0;
900  if ( $length === null ) {
901  // We've had bugs where rev_len was not being recorded for empty pages, see T135414
902  $length = 0;
903  }
904  return self::formatRaw( $length, $raw, $parser->getFunctionLang() );
905  }
906 
919  public static function protectionlevel( $parser, $type = '', $title = '' ) {
920  $titleObject = Title::newFromText( $title ) ?? $parser->getTitle();
921  $restrictionStore = MediaWikiServices::getInstance()->getRestrictionStore();
922  if ( $restrictionStore->areRestrictionsLoaded( $titleObject ) || $parser->incrementExpensiveFunctionCount() ) {
923  $restrictions = $restrictionStore->getRestrictions( $titleObject, strtolower( $type ) );
924  # RestrictionStore::getRestrictions returns an array, its possible it may have
925  # multiple values in the future
926  return implode( ',', $restrictions );
927  }
928  return '';
929  }
930 
943  public static function protectionexpiry( $parser, $type = '', $title = '' ) {
944  $titleObject = Title::newFromText( $title ) ?? $parser->getTitle();
945  $restrictionStore = MediaWikiServices::getInstance()->getRestrictionStore();
946  if ( $restrictionStore->areRestrictionsLoaded( $titleObject ) || $parser->incrementExpensiveFunctionCount() ) {
947  $expiry = $restrictionStore->getRestrictionExpiry( $titleObject, strtolower( $type ) );
948  // getRestrictionExpiry() returns null on invalid type; trying to
949  // match protectionlevel() function that returns empty string instead
950  if ( $expiry === null ) {
951  $expiry = '';
952  }
953  return $expiry;
954  }
955  return '';
956  }
957 
965  public static function language( $parser, $code = '', $inLanguage = '' ) {
966  $code = strtolower( $code );
967  $inLanguage = strtolower( $inLanguage );
968  $lang = MediaWikiServices::getInstance()
969  ->getLanguageNameUtils()
970  ->getLanguageName( $code, $inLanguage );
971  return $lang !== '' ? $lang : LanguageCode::bcp47( $code );
972  }
973 
983  public static function pad(
984  $parser, $string, $length, $padding = '0', $direction = STR_PAD_RIGHT
985  ) {
986  $padding = $parser->killMarkers( $padding );
987  $lengthOfPadding = mb_strlen( $padding );
988  if ( $lengthOfPadding == 0 ) {
989  return $string;
990  }
991 
992  # The remaining length to add counts down to 0 as padding is added
993  $length = min( (int)$length, 500 ) - mb_strlen( $string );
994  if ( $length <= 0 ) {
995  // Nothing to add
996  return $string;
997  }
998 
999  # $finalPadding is just $padding repeated enough times so that
1000  # mb_strlen( $string ) + mb_strlen( $finalPadding ) == $length
1001  $finalPadding = '';
1002  while ( $length > 0 ) {
1003  # If $length < $lengthofPadding, truncate $padding so we get the
1004  # exact length desired.
1005  $finalPadding .= mb_substr( $padding, 0, $length );
1006  $length -= $lengthOfPadding;
1007  }
1008 
1009  if ( $direction == STR_PAD_LEFT ) {
1010  return $finalPadding . $string;
1011  } else {
1012  return $string . $finalPadding;
1013  }
1014  }
1015 
1016  public static function padleft( $parser, $string = '', $length = 0, $padding = '0' ) {
1017  return self::pad( $parser, $string, $length, $padding, STR_PAD_LEFT );
1018  }
1019 
1020  public static function padright( $parser, $string = '', $length = 0, $padding = '0' ) {
1021  return self::pad( $parser, $string, $length, $padding );
1022  }
1023 
1029  public static function anchorencode( $parser, $text ) {
1030  $text = $parser->killMarkers( $text );
1031  $section = (string)substr( $parser->guessSectionNameFromWikiText( $text ), 1 );
1032  return Sanitizer::safeEncodeAttribute( $section );
1033  }
1034 
1035  public static function special( $parser, $text ) {
1036  list( $page, $subpage ) = MediaWikiServices::getInstance()->getSpecialPageFactory()->
1037  resolveAlias( $text );
1038  if ( $page ) {
1039  $title = SpecialPage::getTitleFor( $page, $subpage );
1040  return $title->getPrefixedText();
1041  } else {
1042  // unknown special page, just use the given text as its title, if at all possible
1044  return $title ? $title->getPrefixedText() : self::special( $parser, 'Badtitle' );
1045  }
1046  }
1047 
1048  public static function speciale( $parser, $text ) {
1049  return wfUrlencode( str_replace( ' ', '_', self::special( $parser, $text ) ) );
1050  }
1051 
1060  public static function defaultsort( $parser, $text, $uarg = '' ) {
1061  static $magicWords = null;
1062  if ( $magicWords === null ) {
1063  $magicWords = $parser->getMagicWordFactory()->newArray(
1064  [ 'defaultsort_noerror', 'defaultsort_noreplace' ] );
1065  }
1066  $arg = $magicWords->matchStartToEnd( $uarg );
1067 
1068  $text = trim( $text );
1069  if ( strlen( $text ) == 0 ) {
1070  return '';
1071  }
1072  $old = $parser->getOutput()->getPageProperty( 'defaultsort' );
1073  if ( $old === null || $arg !== 'defaultsort_noreplace' ) {
1074  $parser->getOutput()->setPageProperty( 'defaultsort', $text );
1075  }
1076 
1077  if ( $old === null || $old == $text || $arg ) {
1078  return '';
1079  } else {
1080  $converter = $parser->getTargetLanguageConverter();
1081  return '<span class="error">' .
1082  wfMessage( 'duplicate-defaultsort',
1083  // Message should be parsed, but these params should only be escaped.
1084  $converter->markNoConversion( wfEscapeWikiText( $old ) ),
1085  $converter->markNoConversion( wfEscapeWikiText( $text ) )
1086  )->inContentLanguage()->text() .
1087  '</span>';
1088  }
1089  }
1090 
1102  public static function filepath( $parser, $name = '', $argA = '', $argB = '' ) {
1103  $file = MediaWikiServices::getInstance()->getRepoGroup()->findFile( $name );
1104 
1105  if ( $argA == 'nowiki' ) {
1106  // {{filepath: | option [| size] }}
1107  $isNowiki = true;
1108  $parsedWidthParam = Parser::parseWidthParam( $argB );
1109  } else {
1110  // {{filepath: [| size [|option]] }}
1111  $parsedWidthParam = Parser::parseWidthParam( $argA );
1112  $isNowiki = ( $argB == 'nowiki' );
1113  }
1114 
1115  if ( $file ) {
1116  $url = $file->getFullUrl();
1117 
1118  // If a size is requested...
1119  if ( count( $parsedWidthParam ) ) {
1120  $mto = $file->transform( $parsedWidthParam );
1121  // ... and we can
1122  if ( $mto && !$mto->isError() ) {
1123  // ... change the URL to point to a thumbnail.
1124  $url = wfExpandUrl( $mto->getUrl(), PROTO_RELATIVE );
1125  }
1126  }
1127  if ( $isNowiki ) {
1128  return [ $url, 'nowiki' => true ];
1129  }
1130  return $url;
1131  } else {
1132  return '';
1133  }
1134  }
1135 
1143  public static function tagObj( $parser, $frame, $args ) {
1144  if ( !count( $args ) ) {
1145  return '';
1146  }
1147  $tagName = strtolower( trim( $frame->expand( array_shift( $args ) ) ) );
1148 
1149  if ( count( $args ) ) {
1150  $inner = $frame->expand( array_shift( $args ) );
1151  } else {
1152  $inner = null;
1153  }
1154 
1155  $attributes = [];
1156  foreach ( $args as $arg ) {
1157  $bits = $arg->splitArg();
1158  if ( strval( $bits['index'] ) === '' ) {
1159  $name = trim( $frame->expand( $bits['name'], PPFrame::STRIP_COMMENTS ) );
1160  $value = trim( $frame->expand( $bits['value'] ) );
1161  if ( preg_match( '/^(?:["\'](.+)["\']|""|\'\')$/s', $value, $m ) ) {
1162  $value = $m[1] ?? '';
1163  }
1164  $attributes[$name] = $value;
1165  }
1166  }
1167 
1168  $stripList = $parser->getStripList();
1169  if ( !in_array( $tagName, $stripList ) ) {
1170  // we can't handle this tag (at least not now), so just re-emit it as an ordinary tag
1171  $attrText = '';
1172  foreach ( $attributes as $name => $value ) {
1173  $attrText .= ' ' . htmlspecialchars( $name ) .
1174  '="' . htmlspecialchars( $value, ENT_COMPAT ) . '"';
1175  }
1176  if ( $inner === null ) {
1177  return "<$tagName$attrText/>";
1178  }
1179  return "<$tagName$attrText>$inner</$tagName>";
1180  }
1181 
1182  $params = [
1183  'name' => $tagName,
1184  'inner' => $inner,
1185  'attributes' => $attributes,
1186  'close' => "</$tagName>",
1187  ];
1188  return $parser->extensionSubstitution( $params, $frame );
1189  }
1190 
1204  private static function getCachedRevisionObject( $parser, $title, $vary ) {
1205  if ( !$title ) {
1206  return null;
1207  }
1208 
1209  $revisionRecord = null;
1210 
1211  $isSelfReferential = $title->equals( $parser->getTitle() );
1212  if ( $isSelfReferential ) {
1213  // Revision is for the same title that is currently being parsed. Only use the last
1214  // saved revision, regardless of Parser::getRevisionId() or fake revision injection
1215  // callbacks against the current title.
1216  $parserRevisionRecord = $parser->getRevisionRecordObject();
1217  if ( $parserRevisionRecord && $parserRevisionRecord->isCurrent() ) {
1218  $revisionRecord = $parserRevisionRecord;
1219  }
1220  }
1221 
1222  $parserOutput = $parser->getOutput();
1223  if ( !$revisionRecord ) {
1224  if (
1225  !$parser->isCurrentRevisionOfTitleCached( $title ) &&
1227  ) {
1228  return null; // not allowed
1229  }
1230  // Get the current revision, ignoring Parser::getRevisionId() being null/old
1231  $revisionRecord = $parser->fetchCurrentRevisionRecordOfTitle( $title );
1232  if ( !$revisionRecord ) {
1233  // Convert `false` error return to `null`
1234  $revisionRecord = null;
1235  }
1236  // Register dependency in templatelinks
1237  $parserOutput->addTemplate(
1238  $title,
1239  $revisionRecord ? $revisionRecord->getPageId() : 0,
1240  $revisionRecord ? $revisionRecord->getId() : 0
1241  );
1242  }
1243 
1244  if ( $isSelfReferential ) {
1245  wfDebug( __METHOD__ . ": used current revision, setting $vary" );
1246  // Upon page save, the result of the parser function using this might change
1247  $parserOutput->setOutputFlag( $vary );
1248  if ( $vary === ParserOutputFlags::VARY_REVISION_SHA1 && $revisionRecord ) {
1249  try {
1250  $sha1 = $revisionRecord->getSha1();
1251  } catch ( RevisionAccessException $e ) {
1252  $sha1 = null;
1253  }
1254  $parserOutput->setRevisionUsedSha1Base36( $sha1 );
1255  }
1256  }
1257 
1258  return $revisionRecord;
1259  }
1260 
1268  public static function pageid( $parser, $title = null ) {
1270  if ( !$t ) {
1271  return '';
1272  } elseif ( !$t->canExist() || $t->isExternal() ) {
1273  return 0; // e.g. special page or interwiki link
1274  }
1275 
1276  $parserOutput = $parser->getOutput();
1277 
1278  if ( $t->equals( $parser->getTitle() ) ) {
1279  // Revision is for the same title that is currently being parsed.
1280  // Use the title from Parser in case a new page ID was injected into it.
1281  $parserOutput->setOutputFlag( ParserOutputFlags::VARY_PAGE_ID );
1282  $id = $parser->getTitle()->getArticleID();
1283  if ( $id ) {
1284  $parserOutput->setSpeculativePageIdUsed( $id );
1285  }
1286 
1287  return $id;
1288  }
1289 
1290  // Check the link cache for the title
1291  $linkCache = MediaWikiServices::getInstance()->getLinkCache();
1292  $pdbk = $t->getPrefixedDBkey();
1293  $id = $linkCache->getGoodLinkID( $pdbk );
1294  if ( $id != 0 || $linkCache->isBadLink( $pdbk ) ) {
1295  $parserOutput->addLink( $t, $id );
1296 
1297  return $id;
1298  }
1299 
1300  // We need to load it from the DB, so mark expensive
1301  if ( $parser->incrementExpensiveFunctionCount() ) {
1302  $id = $t->getArticleID();
1303  $parserOutput->addLink( $t, $id );
1304 
1305  return $id;
1306  }
1307 
1308  return null;
1309  }
1310 
1318  public static function revisionid( $parser, $title = null ) {
1320  if ( $t === null ) {
1321  return '';
1322  }
1323 
1324  $services = MediaWikiServices::getInstance();
1325  if (
1326  $t->equals( $parser->getTitle() ) &&
1327  $services->getMainConfig()->get( MainConfigNames::MiserMode ) &&
1328  !$parser->getOptions()->getInterfaceMessage() &&
1329  // @TODO: disallow this word on all namespaces (T235957)
1330  $services->getNamespaceInfo()->isSubject( $t->getNamespace() )
1331  ) {
1332  // Use a stub result instead of the actual revision ID in order to avoid
1333  // double parses on page save but still allow preview detection (T137900)
1334  if ( $parser->getRevisionId() || $parser->getOptions()->getSpeculativeRevId() ) {
1335  return '-';
1336  } else {
1337  $parser->getOutput()->setOutputFlag( ParserOutputFlags::VARY_REVISION_EXISTS );
1338  return '';
1339  }
1340  }
1341  // fetch revision from cache/database and return the value
1342  $rev = self::getCachedRevisionObject( $parser, $t, ParserOutputFlags::VARY_REVISION_ID );
1343  return $rev ? $rev->getId() : '';
1344  }
1345 
1353  public static function revisionday( $parser, $title = null ) {
1355  if ( $t === null ) {
1356  return '';
1357  }
1358  // fetch revision from cache/database and return the value
1359  $rev = self::getCachedRevisionObject( $parser, $t, ParserOutputFlags::VARY_REVISION_TIMESTAMP );
1360  return $rev ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'j' ) : '';
1361  }
1362 
1370  public static function revisionday2( $parser, $title = null ) {
1372  if ( $t === null ) {
1373  return '';
1374  }
1375  // fetch revision from cache/database and return the value
1376  $rev = self::getCachedRevisionObject( $parser, $t, ParserOutputFlags::VARY_REVISION_TIMESTAMP );
1377  return $rev ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'd' ) : '';
1378  }
1379 
1387  public static function revisionmonth( $parser, $title = null ) {
1389  if ( $t === null ) {
1390  return '';
1391  }
1392  // fetch revision from cache/database and return the value
1393  $rev = self::getCachedRevisionObject( $parser, $t, ParserOutputFlags::VARY_REVISION_TIMESTAMP );
1394  return $rev ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'm' ) : '';
1395  }
1396 
1404  public static function revisionmonth1( $parser, $title = null ) {
1406  if ( $t === null ) {
1407  return '';
1408  }
1409  // fetch revision from cache/database and return the value
1410  $rev = self::getCachedRevisionObject( $parser, $t, ParserOutputFlags::VARY_REVISION_TIMESTAMP );
1411  return $rev ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'n' ) : '';
1412  }
1413 
1421  public static function revisionyear( $parser, $title = null ) {
1423  if ( $t === null ) {
1424  return '';
1425  }
1426  // fetch revision from cache/database and return the value
1427  $rev = self::getCachedRevisionObject( $parser, $t, ParserOutputFlags::VARY_REVISION_TIMESTAMP );
1428  return $rev ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'Y' ) : '';
1429  }
1430 
1438  public static function revisiontimestamp( $parser, $title = null ) {
1440  if ( $t === null ) {
1441  return '';
1442  }
1443  // fetch revision from cache/database and return the value
1444  $rev = self::getCachedRevisionObject( $parser, $t, ParserOutputFlags::VARY_REVISION_TIMESTAMP );
1445  return $rev ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'YmdHis' ) : '';
1446  }
1447 
1455  public static function revisionuser( $parser, $title = null ) {
1457  if ( $t === null ) {
1458  return '';
1459  }
1460  // fetch revision from cache/database and return the value
1461  $rev = self::getCachedRevisionObject( $parser, $t, ParserOutputFlags::VARY_USER );
1462  if ( $rev === null ) {
1463  return '';
1464  }
1465  $user = $rev->getUser();
1466  return $user ? $user->getName() : '';
1467  }
1468 
1481  public static function cascadingsources( $parser, $title = '' ) {
1482  $titleObject = Title::newFromText( $title ) ?? $parser->getTitle();
1483  $restrictionStore = MediaWikiServices::getInstance()->getRestrictionStore();
1484  if ( $restrictionStore->areCascadeProtectionSourcesLoaded( $titleObject )
1485  || $parser->incrementExpensiveFunctionCount()
1486  ) {
1487  $names = [];
1488  $sources = $restrictionStore->getCascadeProtectionSources( $titleObject );
1489  $titleFormatter = MediaWikiServices::getInstance()->getTitleFormatter();
1490  foreach ( $sources[0] as $sourcePageIdentity ) {
1491  $names[] = $titleFormatter->getPrefixedText( $sourcePageIdentity );
1492  }
1493  return implode( '|', $names );
1494  }
1495  return '';
1496  }
1497 }
const NS_USER
Definition: Defines.php:66
const NS_FILE
Definition: Defines.php:70
const NS_SPECIAL
Definition: Defines.php:53
const NS_MEDIA
Definition: Defines.php:52
const PROTO_RELATIVE
Definition: Defines.php:195
const NS_CATEGORY
Definition: Defines.php:78
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfUrlencode( $s)
We want some things to be included as literal characters in our title URLs for prettiness,...
wfExpandUrl( $url, $defaultProto=PROTO_CURRENT)
Expand a potentially local URL to a fully-qualified URL.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.
$magicWords
@phpcs-require-sorted-array
Definition: MessagesAb.php:72
static newFromTitle(PageIdentity $page)
Factory function.
Definition: Category.php:170
const COUNT_CONTENT_PAGES
Definition: Category.php:59
Various core parser functions, registered in every Parser.
static language( $parser, $code='', $inLanguage='')
Gives language names.
static numberingroup( $parser, $name='', $raw=null)
static rootpagename( $parser, $title=null)
static localurl( $parser, $s='', $arg=null)
static formatnum( $parser, $num='', $arg=null)
static ns( $parser, $part1='')
static protectionexpiry( $parser, $type='', $title='')
Returns the requested protection expiry for the current page.
static pagenamee( $parser, $title=null)
static padleft( $parser, $string='', $length=0, $padding='0')
static fullurle( $parser, $s='', $arg=null)
static revisionmonth( $parser, $title=null)
Get the month with leading zeros from the last revision of a specified page.
static fullpagename( $parser, $title=null)
static revisionid( $parser, $title=null)
Get the id from the last revision of a specified page.
static pagesinnamespace( $parser, $namespace=0, $raw=null)
static numberofusers( $parser, $raw=null)
static special( $parser, $text)
static nse( $parser, $part1='')
static pagesize( $parser, $page='', $raw=null)
Return the size of the given page, or 0 if it's nonexistent.
static canonicalurl( $parser, $s='', $arg=null)
static basepagenamee( $parser, $title=null)
static subjectspacee( $parser, $title=null)
static numberofedits( $parser, $raw=null)
static numberoffiles( $parser, $raw=null)
static ucfirst( $parser, $s='')
static basepagename( $parser, $title=null)
static gender( $parser, $username,... $forms)
static numberofpages( $parser, $raw=null)
static lcfirst( $parser, $s='')
static urlFunction( $func, $s='', $arg=null)
static plural( $parser, $text='',... $forms)
static formatRaw( $num, $raw, $language, MagicWordFactory $magicWordFactory=null)
Formats a number according to a language.
static talkspacee( $parser, $title=null)
static bidi( $parser, $text='')
static revisionuser( $parser, $title=null)
Get the user from the last revision of a specified page.
static anchorencode( $parser, $text)
static subjectpagenamee( $parser, $title=null)
static namespacee( $parser, $title=null)
static subjectpagename( $parser, $title=null)
static filepath( $parser, $name='', $argA='', $argB='')
Usage {{filepath|300}}, {{filepath|nowiki}}, {{filepath|nowiki|300}} or {{filepath|300|nowiki}} or {{...
static padright( $parser, $string='', $length=0, $padding='0')
static pad( $parser, $string, $length, $padding='0', $direction=STR_PAD_RIGHT)
Unicode-safe str_pad with the restriction that $length is forced to be <= 500.
static canonicalurle( $parser, $s='', $arg=null)
static cascadingsources( $parser, $title='')
Returns the sources of any cascading protection acting on a specified page.
static numberofactiveusers( $parser, $raw=null)
static displaytitle( $parser, $text='', $uarg='')
Override the title of the page when viewed, provided we've been given a title which will normalise to...
static pageid( $parser, $title=null)
Get the pageid of a specified page.
static formatDate( $parser, $date, $defaultPref=null)
static urlencode( $parser, $s='', $arg=null)
urlencodes a string according to one of three patterns: (T24474)
static grammar( $parser, $case='', $word='')
static subpagenamee( $parser, $title=null)
static tagObj( $parser, $frame, $args)
Parser function to extension tag adaptor.
static revisionmonth1( $parser, $title=null)
Get the month from the last revision of a specified page.
static rootpagenamee( $parser, $title=null)
static protectionlevel( $parser, $type='', $title='')
Returns the requested protection level for the current page.
static namespacenumber( $parser, $title=null)
static revisionday( $parser, $title=null)
Get the day from the last revision of a specified page.
static subjectspace( $parser, $title=null)
static lc( $parser, $s='')
static pagesincategory( $parser, $name='', $arg1='', $arg2='')
Return the number of pages, files or subcats in the given category, or 0 if it's nonexistent.
static talkpagename( $parser, $title=null)
static fullurl( $parser, $s='', $arg=null)
static mwnamespace( $parser, $title=null)
Given a title, return the namespace name that would be given by the corresponding magic word.
static pagename( $parser, $title=null)
Functions to get and normalize pagenames, corresponding to the magic words of the same names.
static intFunction( $parser, $part1='',... $params)
static numberofadmins( $parser, $raw=null)
static numberofarticles( $parser, $raw=null)
static revisionyear( $parser, $title=null)
Get the year from the last revision of a specified page.
static revisionday2( $parser, $title=null)
Get the day with leading zeros from the last revision of a specified page.
static uc( $parser, $s='')
static talkpagenamee( $parser, $title=null)
static revisiontimestamp( $parser, $title=null)
Get the timestamp from the last revision of a specified page.
static subpagename( $parser, $title=null)
static localurle( $parser, $s='', $arg=null)
static defaultsort( $parser, $text, $uarg='')
static fullpagenamee( $parser, $title=null)
static talkspace( $parser, $title=null)
static speciale( $parser, $text)
static bcp47( $code)
Get the normalised IETF language tag See unit test for examples.
static getLocalInstance( $ts=false)
Get a timestamp instance in the server local timezone ($wgLocaltimezone)
A factory that stores information about MagicWords, and creates them on demand with caching.
get( $id)
Factory: creates an object representing an ID.
A class for passing options to services.
A class containing constants representing the names of configuration variables.
Service locator for MediaWiki core services.
Exception representing a failure to look up a revision.
Page revision base class.
static plaintextParam( $plaintext)
Definition: Message.php:1287
PHP Parser - Processes wiki markup (which uses a more user-friendly syntax, such as "[[link]]" for ma...
Definition: Parser.php:95
addTrackingCategory( $msg)
Definition: Parser.php:4150
extensionSubstitution(array $params, PPFrame $frame)
Return the text to be used for a given extension tag.
Definition: Parser.php:3981
getMagicWordFactory()
Get the MagicWordFactory that this Parser is using.
Definition: Parser.php:1236
getOptions()
Definition: Parser.php:1124
isCurrentRevisionOfTitleCached(LinkTarget $link)
Definition: Parser.php:3574
fetchCurrentRevisionRecordOfTitle(LinkTarget $link)
Fetch the current revision of a given title as a RevisionRecord.
Definition: Parser.php:3544
setFunctionHook( $id, callable $callback, $flags=0)
Create a function, e.g.
Definition: Parser.php:5016
getTitle()
Definition: Parser.php:1035
getFunctionLang()
Get a language object for use in parser functions such as {{FORMATNUM:}}.
Definition: Parser.php:1170
getStripList()
Get a list of strippable XML-like elements.
Definition: Parser.php:1342
getTargetLanguageConverter()
Shorthand for getting a Language Converter for Target language.
Definition: Parser.php:1656
getContentLanguage()
Get the content language that this Parser is using.
Definition: Parser.php:1246
getOutput()
Definition: Parser.php:1116
guessSectionNameFromWikiText( $text)
Try to guess the section anchor name based on a wikitext fragment presumably extracted from a heading...
Definition: Parser.php:6218
getRevisionId()
Get the ID of the revision we are parsing.
Definition: Parser.php:6008
static parseWidthParam( $value, $parseHeight=true)
Parsed a width param of imagelink like 300px or 200x300px.
Definition: Parser.php:6426
const SFH_OBJECT_ARGS
Definition: Parser.php:100
doQuotes( $text)
Helper function for handleAllQuotes()
Definition: Parser.php:1990
incrementExpensiveFunctionCount()
Definition: Parser.php:4083
markerSkipCallback( $s, callable $callback)
Call a callback function on all regions of the given text that are not inside strip markers,...
Definition: Parser.php:6381
killMarkers( $text)
Remove any strip markers found in the given text.
Definition: Parser.php:6412
getRevisionRecordObject()
Get the revision record object for $this->mRevisionId.
Definition: Parser.php:6018
const SFH_NO_HASH
Definition: Parser.php:99
static checkCss( $value)
Pick apart some CSS and check it for forbidden or unsafe structures.
Definition: Sanitizer.php:766
static removeSomeTags(string $text, array $options=[])
Cleans up HTML, removes dangerous tags and attributes, and removes HTML comments; the result will alw...
Definition: Sanitizer.php:392
static stripAllTags( $html)
Take a fragment of (potentially invalid) HTML and return a version with any tags removed,...
Definition: Sanitizer.php:1710
static decodeCharReferencesAndNormalize( $text)
Decode any character references, numeric or named entities, in the next and normalize the resulting s...
Definition: Sanitizer.php:1379
static safeEncodeAttribute( $text)
Encode an attribute value for HTML tags, with extra armoring against further wiki processing.
Definition: Sanitizer.php:899
static articles()
Definition: SiteStats.php:104
static pagesInNs( $ns)
Definition: SiteStats.php:203
static images()
Definition: SiteStats.php:140
static edits()
Definition: SiteStats.php:95
static users()
Definition: SiteStats.php:122
static pages()
Definition: SiteStats.php:113
static numberingroup( $group)
Find the number of users in a given user group.
Definition: SiteStats.php:151
static activeUsers()
Definition: SiteStats.php:131
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don't need a full Title object,...
Represents a title within MediaWiki.
Definition: Title.php:49
static newFromURL( $url)
THIS IS NOT THE FUNCTION YOU WANT.
Definition: Title.php:467
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:370
static makeTitleSafe( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:664
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:638
static newFromName( $name, $validate='valid')
Definition: User.php:598
const STRIP_COMMENTS
Definition: PPFrame.php:31
$cache
Definition: mcc.php:33
if( $line===false) $args
Definition: mcc.php:124
foreach( $mmfl['setupFiles'] as $fileName) if( $queue) if(empty( $mmfl['quiet'])) $s
return true
Definition: router.php:90
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition: router.php:42
if(!isset( $args[0])) $lang