MediaWiki REL1_39
CoreParserFunctions.php
Go to the documentation of this file.
1<?php
30use Wikimedia\RemexHtml\Tokenizer\Attributes;
31use 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 ) {
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 ) {
279 $title = Title::newFromText( $s );
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 ] );
487 $title = Title::newFromText( Sanitizer::stripAllTags( $text ) );
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 $converter->markNoConversion( wfEscapeWikiText( $filteredText ) )
508 )->inContentLanguage()->text() .
509 '</span>';
510 } else {
511 return '';
512 }
513 } else {
514 $parser->getOutput()->addWarningMsg(
515 'restricted-displaytitle',
516 // Message should be parsed, but this param should only be escaped.
517 Message::plaintextParam( $filteredText )
518 );
519 $parser->addTrackingCategory( 'restricted-displaytitle-ignored' );
520 }
521 }
522
532 private static function matchAgainstMagicword(
533 MagicWordFactory $magicWordFactory, $magicword, $value
534 ) {
535 $value = trim( strval( $value ) );
536 if ( $value === '' ) {
537 return false;
538 }
539 $mwObject = $magicWordFactory->get( $magicword );
540 return $mwObject->matchStartToEnd( $value );
541 }
542
552 public static function formatRaw(
553 $num, $raw, $language, MagicWordFactory $magicWordFactory = null
554 ) {
555 if ( $raw !== null ) {
556 if ( !$magicWordFactory ) {
557 $magicWordFactory = MediaWikiServices::getInstance()->getMagicWordFactory();
558 }
559 if ( self::matchAgainstMagicword( $magicWordFactory, 'rawsuffix', $raw ) ) {
560 return (string)$num;
561 }
562 }
563 return $language->formatNum( $num );
564 }
565
566 public static function numberofpages( $parser, $raw = null ) {
567 return self::formatRaw( SiteStats::pages(), $raw, $parser->getFunctionLang() );
568 }
569
570 public static function numberofusers( $parser, $raw = null ) {
571 return self::formatRaw( SiteStats::users(), $raw, $parser->getFunctionLang() );
572 }
573
574 public static function numberofactiveusers( $parser, $raw = null ) {
575 return self::formatRaw( SiteStats::activeUsers(), $raw, $parser->getFunctionLang() );
576 }
577
578 public static function numberofarticles( $parser, $raw = null ) {
579 return self::formatRaw( SiteStats::articles(), $raw, $parser->getFunctionLang() );
580 }
581
582 public static function numberoffiles( $parser, $raw = null ) {
583 return self::formatRaw( SiteStats::images(), $raw, $parser->getFunctionLang() );
584 }
585
586 public static function numberofadmins( $parser, $raw = null ) {
587 return self::formatRaw(
588 SiteStats::numberingroup( 'sysop' ),
589 $raw,
590 $parser->getFunctionLang()
591 );
592 }
593
594 public static function numberofedits( $parser, $raw = null ) {
595 return self::formatRaw( SiteStats::edits(), $raw, $parser->getFunctionLang() );
596 }
597
598 public static function pagesinnamespace( $parser, $namespace = 0, $raw = null ) {
599 return self::formatRaw(
600 SiteStats::pagesInNs( intval( $namespace ) ),
601 $raw,
602 $parser->getFunctionLang()
603 );
604 }
605
606 public static function numberingroup( $parser, $name = '', $raw = null ) {
607 return self::formatRaw(
608 SiteStats::numberingroup( strtolower( $name ) ),
609 $raw,
610 $parser->getFunctionLang()
611 );
612 }
613
622 public static function namespace( $parser, $title = null ) {
623 $t = Title::newFromText( $title );
624 if ( $t === null ) {
625 return '';
626 }
627 return str_replace( '_', ' ', $t->getNsText() );
628 }
629
640 public static function mwnamespace( $parser, $title = null ) {
641 wfDeprecated( __METHOD__, '1.39' );
642 return self::namespace( $parser, $title );
643 }
644
645 public static function namespacee( $parser, $title = null ) {
646 $t = Title::newFromText( $title );
647 if ( $t === null ) {
648 return '';
649 }
650 return wfUrlencode( $t->getNsText() );
651 }
652
653 public static function namespacenumber( $parser, $title = null ) {
654 $t = Title::newFromText( $title );
655 if ( $t === null ) {
656 return '';
657 }
658 return $t->getNamespace();
659 }
660
661 public static function talkspace( $parser, $title = null ) {
662 $t = Title::newFromText( $title );
663 if ( $t === null || !$t->canHaveTalkPage() ) {
664 return '';
665 }
666 return str_replace( '_', ' ', $t->getTalkNsText() );
667 }
668
669 public static function talkspacee( $parser, $title = null ) {
670 $t = Title::newFromText( $title );
671 if ( $t === null || !$t->canHaveTalkPage() ) {
672 return '';
673 }
674 return wfUrlencode( $t->getTalkNsText() );
675 }
676
677 public static function subjectspace( $parser, $title = null ) {
678 $t = Title::newFromText( $title );
679 if ( $t === null ) {
680 return '';
681 }
682 return str_replace( '_', ' ', $t->getSubjectNsText() );
683 }
684
685 public static function subjectspacee( $parser, $title = null ) {
686 $t = Title::newFromText( $title );
687 if ( $t === null ) {
688 return '';
689 }
690 return wfUrlencode( $t->getSubjectNsText() );
691 }
692
700 public static function pagename( $parser, $title = null ) {
701 $t = Title::newFromText( $title );
702 if ( $t === null ) {
703 return '';
704 }
705 return wfEscapeWikiText( $t->getText() );
706 }
707
708 public static function pagenamee( $parser, $title = null ) {
709 $t = Title::newFromText( $title );
710 if ( $t === null ) {
711 return '';
712 }
713 return wfEscapeWikiText( $t->getPartialURL() );
714 }
715
716 public static function fullpagename( $parser, $title = null ) {
717 $t = Title::newFromText( $title );
718 if ( $t === null || !$t->canHaveTalkPage() ) {
719 return '';
720 }
721 return wfEscapeWikiText( $t->getPrefixedText() );
722 }
723
724 public static function fullpagenamee( $parser, $title = null ) {
725 $t = Title::newFromText( $title );
726 if ( $t === null || !$t->canHaveTalkPage() ) {
727 return '';
728 }
729 return wfEscapeWikiText( $t->getPrefixedURL() );
730 }
731
732 public static function subpagename( $parser, $title = null ) {
733 $t = Title::newFromText( $title );
734 if ( $t === null ) {
735 return '';
736 }
737 return wfEscapeWikiText( $t->getSubpageText() );
738 }
739
740 public static function subpagenamee( $parser, $title = null ) {
741 $t = Title::newFromText( $title );
742 if ( $t === null ) {
743 return '';
744 }
745 return wfEscapeWikiText( $t->getSubpageUrlForm() );
746 }
747
748 public static function rootpagename( $parser, $title = null ) {
749 $t = Title::newFromText( $title );
750 if ( $t === null ) {
751 return '';
752 }
753 return wfEscapeWikiText( $t->getRootText() );
754 }
755
756 public static function rootpagenamee( $parser, $title = null ) {
757 $t = Title::newFromText( $title );
758 if ( $t === null ) {
759 return '';
760 }
761 return wfEscapeWikiText( wfUrlencode( str_replace( ' ', '_', $t->getRootText() ) ) );
762 }
763
764 public static function basepagename( $parser, $title = null ) {
765 $t = Title::newFromText( $title );
766 if ( $t === null ) {
767 return '';
768 }
769 return wfEscapeWikiText( $t->getBaseText() );
770 }
771
772 public static function basepagenamee( $parser, $title = null ) {
773 $t = Title::newFromText( $title );
774 if ( $t === null ) {
775 return '';
776 }
777 return wfEscapeWikiText( wfUrlencode( str_replace( ' ', '_', $t->getBaseText() ) ) );
778 }
779
780 public static function talkpagename( $parser, $title = null ) {
781 $t = Title::newFromText( $title );
782 if ( $t === null || !$t->canHaveTalkPage() ) {
783 return '';
784 }
785 return wfEscapeWikiText( $t->getTalkPage()->getPrefixedText() );
786 }
787
788 public static function talkpagenamee( $parser, $title = null ) {
789 $t = Title::newFromText( $title );
790 if ( $t === null || !$t->canHaveTalkPage() ) {
791 return '';
792 }
793 return wfEscapeWikiText( $t->getTalkPage()->getPrefixedURL() );
794 }
795
796 public static function subjectpagename( $parser, $title = null ) {
797 $t = Title::newFromText( $title );
798 if ( $t === null ) {
799 return '';
800 }
801 return wfEscapeWikiText( $t->getSubjectPage()->getPrefixedText() );
802 }
803
804 public static function subjectpagenamee( $parser, $title = null ) {
805 $t = Title::newFromText( $title );
806 if ( $t === null ) {
807 return '';
808 }
809 return wfEscapeWikiText( $t->getSubjectPage()->getPrefixedURL() );
810 }
811
822 public static function pagesincategory( $parser, $name = '', $arg1 = '', $arg2 = '' ) {
823 static $magicWords = null;
824 if ( $magicWords === null ) {
825 $magicWords = $parser->getMagicWordFactory()->newArray( [
826 'pagesincategory_all',
827 'pagesincategory_pages',
828 'pagesincategory_subcats',
829 'pagesincategory_files'
830 ] );
831 }
832 static $cache = [];
833
834 // split the given option to its variable
835 if ( self::matchAgainstMagicword( $parser->getMagicWordFactory(), 'rawsuffix', $arg1 ) ) {
836 // {{pagesincategory:|raw[|type]}}
837 $raw = $arg1;
838 $type = $magicWords->matchStartToEnd( $arg2 );
839 } else {
840 // {{pagesincategory:[|type[|raw]]}}
841 $type = $magicWords->matchStartToEnd( $arg1 );
842 $raw = $arg2;
843 }
844 if ( !$type ) { // backward compatibility
845 $type = 'pagesincategory_all';
846 }
847
848 $title = Title::makeTitleSafe( NS_CATEGORY, $name );
849 if ( !$title ) { # invalid title
850 return self::formatRaw( 0, $raw, $parser->getFunctionLang() );
851 }
852 $languageConverter = MediaWikiServices::getInstance()
853 ->getLanguageConverterFactory()
854 ->getLanguageConverter( $parser->getContentLanguage() );
855 $languageConverter->findVariantLink( $name, $title, true );
856
857 // Normalize name for cache
858 $name = $title->getDBkey();
859
860 if ( !isset( $cache[$name] ) ) {
861 $category = Category::newFromTitle( $title );
862
863 $allCount = $subcatCount = $fileCount = $pageCount = 0;
864 if ( $parser->incrementExpensiveFunctionCount() ) {
865 $allCount = $category->getMemberCount();
866 $subcatCount = $category->getSubcatCount();
867 $fileCount = $category->getFileCount();
868 $pageCount = $category->getPageCount( Category::COUNT_CONTENT_PAGES );
869 }
870 $cache[$name]['pagesincategory_all'] = $allCount;
871 $cache[$name]['pagesincategory_pages'] = $pageCount;
872 $cache[$name]['pagesincategory_subcats'] = $subcatCount;
873 $cache[$name]['pagesincategory_files'] = $fileCount;
874 }
875
876 $count = $cache[$name][$type];
877 return self::formatRaw( $count, $raw, $parser->getFunctionLang() );
878 }
879
889 public static function pagesize( $parser, $page = '', $raw = null ) {
890 $title = Title::newFromText( $page );
891
892 if ( !is_object( $title ) ) {
893 return self::formatRaw( 0, $raw, $parser->getFunctionLang() );
894 }
895
896 // fetch revision from cache/database and return the value
897 $rev = self::getCachedRevisionObject( $parser, $title, ParserOutputFlags::VARY_REVISION_SHA1 );
898 $length = $rev ? $rev->getSize() : 0;
899 if ( $length === null ) {
900 // We've had bugs where rev_len was not being recorded for empty pages, see T135414
901 $length = 0;
902 }
903 return self::formatRaw( $length, $raw, $parser->getFunctionLang() );
904 }
905
918 public static function protectionlevel( $parser, $type = '', $title = '' ) {
919 $titleObject = Title::newFromText( $title ) ?? $parser->getTitle();
920 $restrictionStore = MediaWikiServices::getInstance()->getRestrictionStore();
921 if ( $restrictionStore->areRestrictionsLoaded( $titleObject ) || $parser->incrementExpensiveFunctionCount() ) {
922 $restrictions = $restrictionStore->getRestrictions( $titleObject, strtolower( $type ) );
923 # RestrictionStore::getRestrictions returns an array, its possible it may have
924 # multiple values in the future
925 return implode( ',', $restrictions );
926 }
927 return '';
928 }
929
942 public static function protectionexpiry( $parser, $type = '', $title = '' ) {
943 $titleObject = Title::newFromText( $title ) ?? $parser->getTitle();
944 $restrictionStore = MediaWikiServices::getInstance()->getRestrictionStore();
945 if ( $restrictionStore->areRestrictionsLoaded( $titleObject ) || $parser->incrementExpensiveFunctionCount() ) {
946 $expiry = $restrictionStore->getRestrictionExpiry( $titleObject, strtolower( $type ) );
947 // getRestrictionExpiry() returns null on invalid type; trying to
948 // match protectionlevel() function that returns empty string instead
949 if ( $expiry === null ) {
950 $expiry = '';
951 }
952 return $expiry;
953 }
954 return '';
955 }
956
964 public static function language( $parser, $code = '', $inLanguage = '' ) {
965 $code = strtolower( $code );
966 $inLanguage = strtolower( $inLanguage );
967 $lang = MediaWikiServices::getInstance()
968 ->getLanguageNameUtils()
969 ->getLanguageName( $code, $inLanguage );
970 return $lang !== '' ? $lang : LanguageCode::bcp47( $code );
971 }
972
982 public static function pad(
983 $parser, $string, $length, $padding = '0', $direction = STR_PAD_RIGHT
984 ) {
985 $padding = $parser->killMarkers( $padding );
986 $lengthOfPadding = mb_strlen( $padding );
987 if ( $lengthOfPadding == 0 ) {
988 return $string;
989 }
990
991 # The remaining length to add counts down to 0 as padding is added
992 $length = min( (int)$length, 500 ) - mb_strlen( $string );
993 if ( $length <= 0 ) {
994 // Nothing to add
995 return $string;
996 }
997
998 # $finalPadding is just $padding repeated enough times so that
999 # mb_strlen( $string ) + mb_strlen( $finalPadding ) == $length
1000 $finalPadding = '';
1001 while ( $length > 0 ) {
1002 # If $length < $lengthofPadding, truncate $padding so we get the
1003 # exact length desired.
1004 $finalPadding .= mb_substr( $padding, 0, $length );
1005 $length -= $lengthOfPadding;
1006 }
1007
1008 if ( $direction == STR_PAD_LEFT ) {
1009 return $finalPadding . $string;
1010 } else {
1011 return $string . $finalPadding;
1012 }
1013 }
1014
1015 public static function padleft( $parser, $string = '', $length = 0, $padding = '0' ) {
1016 return self::pad( $parser, $string, $length, $padding, STR_PAD_LEFT );
1017 }
1018
1019 public static function padright( $parser, $string = '', $length = 0, $padding = '0' ) {
1020 return self::pad( $parser, $string, $length, $padding );
1021 }
1022
1028 public static function anchorencode( $parser, $text ) {
1029 $text = $parser->killMarkers( $text );
1030 $section = (string)substr( $parser->guessSectionNameFromWikiText( $text ), 1 );
1031 $encodedSection = Sanitizer::safeEncodeAttribute( $section );
1032 // decode underscores to avoid breaking templates (T407131)
1033 return str_replace( '&#95;', '_', $encodedSection );
1034 }
1035
1036 public static function special( $parser, $text ) {
1037 list( $page, $subpage ) = MediaWikiServices::getInstance()->getSpecialPageFactory()->
1038 resolveAlias( $text );
1039 if ( $page ) {
1040 $title = SpecialPage::getTitleFor( $page, $subpage );
1041 return $title->getPrefixedText();
1042 } else {
1043 // unknown special page, just use the given text as its title, if at all possible
1044 $title = Title::makeTitleSafe( NS_SPECIAL, $text );
1045 return $title ? $title->getPrefixedText() : self::special( $parser, 'Badtitle' );
1046 }
1047 }
1048
1049 public static function speciale( $parser, $text ) {
1050 return wfUrlencode( str_replace( ' ', '_', self::special( $parser, $text ) ) );
1051 }
1052
1061 public static function defaultsort( $parser, $text, $uarg = '' ) {
1062 static $magicWords = null;
1063 if ( $magicWords === null ) {
1064 $magicWords = $parser->getMagicWordFactory()->newArray(
1065 [ 'defaultsort_noerror', 'defaultsort_noreplace' ] );
1066 }
1067 $arg = $magicWords->matchStartToEnd( $uarg );
1068
1069 $text = trim( $text );
1070 if ( strlen( $text ) == 0 ) {
1071 return '';
1072 }
1073 $old = $parser->getOutput()->getPageProperty( 'defaultsort' );
1074 if ( $old === null || $arg !== 'defaultsort_noreplace' ) {
1075 $parser->getOutput()->setPageProperty( 'defaultsort', $text );
1076 }
1077
1078 if ( $old === null || $old == $text || $arg ) {
1079 return '';
1080 } else {
1081 $converter = $parser->getTargetLanguageConverter();
1082 return '<span class="error">' .
1083 wfMessage( 'duplicate-defaultsort',
1084 // Message should be parsed, but these params should only be escaped.
1085 $converter->markNoConversion( wfEscapeWikiText( $old ) ),
1086 $converter->markNoConversion( wfEscapeWikiText( $text ) )
1087 )->inContentLanguage()->text() .
1088 '</span>';
1089 }
1090 }
1091
1103 public static function filepath( $parser, $name = '', $argA = '', $argB = '' ) {
1104 $file = MediaWikiServices::getInstance()->getRepoGroup()->findFile( $name );
1105
1106 if ( $argA == 'nowiki' ) {
1107 // {{filepath: | option [| size] }}
1108 $isNowiki = true;
1109 $parsedWidthParam = Parser::parseWidthParam( $argB );
1110 } else {
1111 // {{filepath: [| size [|option]] }}
1112 $parsedWidthParam = Parser::parseWidthParam( $argA );
1113 $isNowiki = ( $argB == 'nowiki' );
1114 }
1115
1116 if ( $file ) {
1117 $url = $file->getFullUrl();
1118
1119 // If a size is requested...
1120 if ( count( $parsedWidthParam ) ) {
1121 $mto = $file->transform( $parsedWidthParam );
1122 // ... and we can
1123 if ( $mto && !$mto->isError() ) {
1124 // ... change the URL to point to a thumbnail.
1125 $url = wfExpandUrl( $mto->getUrl(), PROTO_RELATIVE );
1126 }
1127 }
1128 if ( $isNowiki ) {
1129 return [ $url, 'nowiki' => true ];
1130 }
1131 return $url;
1132 } else {
1133 return '';
1134 }
1135 }
1136
1144 public static function tagObj( $parser, $frame, $args ) {
1145 if ( !count( $args ) ) {
1146 return '';
1147 }
1148 $tagName = strtolower( trim( $frame->expand( array_shift( $args ) ) ) );
1149 $processNowiki = $parser->tagNeedsNowikiStrippedInTagPF( $tagName ) ? PPFrame::PROCESS_NOWIKI : 0;
1150
1151 if ( count( $args ) ) {
1152 $inner = $frame->expand( array_shift( $args ), $processNowiki );
1153 } else {
1154 $inner = null;
1155 }
1156
1157 $attributes = [];
1158 foreach ( $args as $arg ) {
1159 $bits = $arg->splitArg();
1160 if ( strval( $bits['index'] ) === '' ) {
1161 $name = trim( $frame->expand( $bits['name'], PPFrame::STRIP_COMMENTS ) );
1162 $value = trim( $frame->expand( $bits['value'] ) );
1163 if ( preg_match( '/^(?:["\'](.+)["\']|""|\'\')$/s', $value, $m ) ) {
1164 $value = $m[1] ?? '';
1165 }
1166 $attributes[$name] = $value;
1167 }
1168 }
1169
1170 $stripList = $parser->getStripList();
1171 if ( !in_array( $tagName, $stripList ) ) {
1172 // we can't handle this tag (at least not now), so just re-emit it as an ordinary tag
1173 $attrText = '';
1174 foreach ( $attributes as $name => $value ) {
1175 $attrText .= ' ' . htmlspecialchars( $name ) .
1176 '="' . htmlspecialchars( $value, ENT_COMPAT ) . '"';
1177 }
1178 if ( $inner === null ) {
1179 return "<$tagName$attrText/>";
1180 }
1181 return "<$tagName$attrText>$inner</$tagName>";
1182 }
1183
1184 $params = [
1185 'name' => $tagName,
1186 'inner' => $inner,
1187 'attributes' => $attributes,
1188 'close' => "</$tagName>",
1189 ];
1190 return $parser->extensionSubstitution( $params, $frame );
1191 }
1192
1206 private static function getCachedRevisionObject( $parser, $title, $vary ) {
1207 if ( !$title ) {
1208 return null;
1209 }
1210
1211 $revisionRecord = null;
1212
1213 $isSelfReferential = $title->equals( $parser->getTitle() );
1214 if ( $isSelfReferential ) {
1215 // Revision is for the same title that is currently being parsed. Only use the last
1216 // saved revision, regardless of Parser::getRevisionId() or fake revision injection
1217 // callbacks against the current title.
1218 $parserRevisionRecord = $parser->getRevisionRecordObject();
1219 if ( $parserRevisionRecord && $parserRevisionRecord->isCurrent() ) {
1220 $revisionRecord = $parserRevisionRecord;
1221 }
1222 }
1223
1224 $parserOutput = $parser->getOutput();
1225 if ( !$revisionRecord ) {
1226 if (
1229 ) {
1230 return null; // not allowed
1231 }
1232 // Get the current revision, ignoring Parser::getRevisionId() being null/old
1233 $revisionRecord = $parser->fetchCurrentRevisionRecordOfTitle( $title );
1234 if ( !$revisionRecord ) {
1235 // Convert `false` error return to `null`
1236 $revisionRecord = null;
1237 }
1238 // Register dependency in templatelinks
1239 $parserOutput->addTemplate(
1240 $title,
1241 $revisionRecord ? $revisionRecord->getPageId() : 0,
1242 $revisionRecord ? $revisionRecord->getId() : 0
1243 );
1244 }
1245
1246 if ( $isSelfReferential ) {
1247 wfDebug( __METHOD__ . ": used current revision, setting $vary" );
1248 // Upon page save, the result of the parser function using this might change
1249 $parserOutput->setOutputFlag( $vary );
1250 if ( $vary === ParserOutputFlags::VARY_REVISION_SHA1 && $revisionRecord ) {
1251 try {
1252 $sha1 = $revisionRecord->getSha1();
1253 } catch ( RevisionAccessException $e ) {
1254 $sha1 = null;
1255 }
1256 $parserOutput->setRevisionUsedSha1Base36( $sha1 );
1257 }
1258 }
1259
1260 return $revisionRecord;
1261 }
1262
1270 public static function pageid( $parser, $title = null ) {
1271 $t = Title::newFromText( $title );
1272 if ( !$t ) {
1273 return '';
1274 } elseif ( !$t->canExist() || $t->isExternal() ) {
1275 return 0; // e.g. special page or interwiki link
1276 }
1277
1278 $parserOutput = $parser->getOutput();
1279
1280 if ( $t->equals( $parser->getTitle() ) ) {
1281 // Revision is for the same title that is currently being parsed.
1282 // Use the title from Parser in case a new page ID was injected into it.
1283 $parserOutput->setOutputFlag( ParserOutputFlags::VARY_PAGE_ID );
1284 $id = $parser->getTitle()->getArticleID();
1285 if ( $id ) {
1286 $parserOutput->setSpeculativePageIdUsed( $id );
1287 }
1288
1289 return $id;
1290 }
1291
1292 // Check the link cache for the title
1293 $linkCache = MediaWikiServices::getInstance()->getLinkCache();
1294 $pdbk = $t->getPrefixedDBkey();
1295 $id = $linkCache->getGoodLinkID( $pdbk );
1296 if ( $id != 0 || $linkCache->isBadLink( $pdbk ) ) {
1297 $parserOutput->addLink( $t, $id );
1298
1299 return $id;
1300 }
1301
1302 // We need to load it from the DB, so mark expensive
1303 if ( $parser->incrementExpensiveFunctionCount() ) {
1304 $id = $t->getArticleID();
1305 $parserOutput->addLink( $t, $id );
1306
1307 return $id;
1308 }
1309
1310 return null;
1311 }
1312
1320 public static function revisionid( $parser, $title = null ) {
1321 $t = Title::newFromText( $title );
1322 if ( $t === null ) {
1323 return '';
1324 }
1325
1326 $services = MediaWikiServices::getInstance();
1327 if (
1328 $t->equals( $parser->getTitle() ) &&
1329 $services->getMainConfig()->get( MainConfigNames::MiserMode ) &&
1330 !$parser->getOptions()->getInterfaceMessage() &&
1331 // @TODO: disallow this word on all namespaces (T235957)
1332 $services->getNamespaceInfo()->isSubject( $t->getNamespace() )
1333 ) {
1334 // Use a stub result instead of the actual revision ID in order to avoid
1335 // double parses on page save but still allow preview detection (T137900)
1336 if ( $parser->getRevisionId() || $parser->getOptions()->getSpeculativeRevId() ) {
1337 return '-';
1338 } else {
1339 $parser->getOutput()->setOutputFlag( ParserOutputFlags::VARY_REVISION_EXISTS );
1340 return '';
1341 }
1342 }
1343 // fetch revision from cache/database and return the value
1344 $rev = self::getCachedRevisionObject( $parser, $t, ParserOutputFlags::VARY_REVISION_ID );
1345 return $rev ? $rev->getId() : '';
1346 }
1347
1355 public static function revisionday( $parser, $title = null ) {
1356 $t = Title::newFromText( $title );
1357 if ( $t === null ) {
1358 return '';
1359 }
1360 // fetch revision from cache/database and return the value
1361 $rev = self::getCachedRevisionObject( $parser, $t, ParserOutputFlags::VARY_REVISION_TIMESTAMP );
1362 return $rev ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'j' ) : '';
1363 }
1364
1372 public static function revisionday2( $parser, $title = null ) {
1373 $t = Title::newFromText( $title );
1374 if ( $t === null ) {
1375 return '';
1376 }
1377 // fetch revision from cache/database and return the value
1378 $rev = self::getCachedRevisionObject( $parser, $t, ParserOutputFlags::VARY_REVISION_TIMESTAMP );
1379 return $rev ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'd' ) : '';
1380 }
1381
1389 public static function revisionmonth( $parser, $title = null ) {
1390 $t = Title::newFromText( $title );
1391 if ( $t === null ) {
1392 return '';
1393 }
1394 // fetch revision from cache/database and return the value
1395 $rev = self::getCachedRevisionObject( $parser, $t, ParserOutputFlags::VARY_REVISION_TIMESTAMP );
1396 return $rev ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'm' ) : '';
1397 }
1398
1406 public static function revisionmonth1( $parser, $title = null ) {
1407 $t = Title::newFromText( $title );
1408 if ( $t === null ) {
1409 return '';
1410 }
1411 // fetch revision from cache/database and return the value
1412 $rev = self::getCachedRevisionObject( $parser, $t, ParserOutputFlags::VARY_REVISION_TIMESTAMP );
1413 return $rev ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'n' ) : '';
1414 }
1415
1423 public static function revisionyear( $parser, $title = null ) {
1424 $t = Title::newFromText( $title );
1425 if ( $t === null ) {
1426 return '';
1427 }
1428 // fetch revision from cache/database and return the value
1429 $rev = self::getCachedRevisionObject( $parser, $t, ParserOutputFlags::VARY_REVISION_TIMESTAMP );
1430 return $rev ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'Y' ) : '';
1431 }
1432
1440 public static function revisiontimestamp( $parser, $title = null ) {
1441 $t = Title::newFromText( $title );
1442 if ( $t === null ) {
1443 return '';
1444 }
1445 // fetch revision from cache/database and return the value
1446 $rev = self::getCachedRevisionObject( $parser, $t, ParserOutputFlags::VARY_REVISION_TIMESTAMP );
1447 return $rev ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'YmdHis' ) : '';
1448 }
1449
1457 public static function revisionuser( $parser, $title = null ) {
1458 $t = Title::newFromText( $title );
1459 if ( $t === null ) {
1460 return '';
1461 }
1462 // fetch revision from cache/database and return the value
1463 $rev = self::getCachedRevisionObject( $parser, $t, ParserOutputFlags::VARY_USER );
1464 if ( $rev === null ) {
1465 return '';
1466 }
1467 $user = $rev->getUser();
1468 return $user ? $user->getName() : '';
1469 }
1470
1483 public static function cascadingsources( $parser, $title = '' ) {
1484 $titleObject = Title::newFromText( $title ) ?? $parser->getTitle();
1485 $restrictionStore = MediaWikiServices::getInstance()->getRestrictionStore();
1486 if ( $restrictionStore->areCascadeProtectionSourcesLoaded( $titleObject )
1488 ) {
1489 $names = [];
1490 $sources = $restrictionStore->getCascadeProtectionSources( $titleObject );
1491 $titleFormatter = MediaWikiServices::getInstance()->getTitleFormatter();
1492 foreach ( $sources[0] as $sourcePageIdentity ) {
1493 $names[] = $titleFormatter->getPrefixedText( $sourcePageIdentity );
1494 }
1495 return implode( '|', $names );
1496 }
1497 return '';
1498 }
1499}
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
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)
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:1267
PHP Parser - Processes wiki markup (which uses a more user-friendly syntax, such as "[[link]]" for ma...
Definition Parser.php:96
addTrackingCategory( $msg)
Definition Parser.php:4163
getMagicWordFactory()
Get the MagicWordFactory that this Parser is using.
Definition Parser.php:1238
getOptions()
Definition Parser.php:1126
isCurrentRevisionOfTitleCached(LinkTarget $link)
Definition Parser.php:3560
extensionSubstitution(array $params, PPFrame $frame, bool $processNowiki=false)
Return the text to be used for a given extension tag.
Definition Parser.php:3980
tagNeedsNowikiStrippedInTagPF(string $lowerTagName)
Definition Parser.php:3954
fetchCurrentRevisionRecordOfTitle(LinkTarget $link)
Fetch the current revision of a given title as a RevisionRecord.
Definition Parser.php:3530
setFunctionHook( $id, callable $callback, $flags=0)
Create a function, e.g.
Definition Parser.php:5031
getTitle()
Definition Parser.php:1037
getFunctionLang()
Get a language object for use in parser functions such as {{FORMATNUM:}}.
Definition Parser.php:1172
getStripList()
Get a list of strippable XML-like elements.
Definition Parser.php:1344
getTargetLanguageConverter()
Shorthand for getting a Language Converter for Target language.
Definition Parser.php:1658
getContentLanguage()
Get the content language that this Parser is using.
Definition Parser.php:1248
getOutput()
Definition Parser.php:1118
guessSectionNameFromWikiText( $text)
Try to guess the section anchor name based on a wikitext fragment presumably extracted from a heading...
Definition Parser.php:6236
getRevisionId()
Get the ID of the revision we are parsing.
Definition Parser.php:6026
static parseWidthParam( $value, $parseHeight=true)
Parsed a width param of imagelink like 300px or 200x300px.
Definition Parser.php:6444
const SFH_OBJECT_ARGS
Definition Parser.php:101
doQuotes( $text)
Helper function for handleAllQuotes()
Definition Parser.php:1992
incrementExpensiveFunctionCount()
Definition Parser.php:4084
markerSkipCallback( $s, callable $callback)
Call a callback function on all regions of the given text that are not inside strip markers,...
Definition Parser.php:6399
killMarkers( $text)
Remove any strip markers found in the given text.
Definition Parser.php:6430
getRevisionRecordObject()
Get the revision record object for $this->mRevisionId.
Definition Parser.php:6036
const SFH_NO_HASH
Definition Parser.php:100
static articles()
static pagesInNs( $ns)
static images()
static edits()
Definition SiteStats.php:95
static users()
static pages()
static numberingroup( $group)
Find the number of users in a given user group.
static activeUsers()
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
hasFragment()
Check if a Title fragment is set.
Definition Title.php:1777
static newFromName( $name, $validate='valid')
Definition User.php:607
$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:92
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