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 return Sanitizer::safeEncodeAttribute( $section );
1032 }
1033
1034 public static function special( $parser, $text ) {
1035 list( $page, $subpage ) = MediaWikiServices::getInstance()->getSpecialPageFactory()->
1036 resolveAlias( $text );
1037 if ( $page ) {
1038 $title = SpecialPage::getTitleFor( $page, $subpage );
1039 return $title->getPrefixedText();
1040 } else {
1041 // unknown special page, just use the given text as its title, if at all possible
1042 $title = Title::makeTitleSafe( NS_SPECIAL, $text );
1043 return $title ? $title->getPrefixedText() : self::special( $parser, 'Badtitle' );
1044 }
1045 }
1046
1047 public static function speciale( $parser, $text ) {
1048 return wfUrlencode( str_replace( ' ', '_', self::special( $parser, $text ) ) );
1049 }
1050
1059 public static function defaultsort( $parser, $text, $uarg = '' ) {
1060 static $magicWords = null;
1061 if ( $magicWords === null ) {
1062 $magicWords = $parser->getMagicWordFactory()->newArray(
1063 [ 'defaultsort_noerror', 'defaultsort_noreplace' ] );
1064 }
1065 $arg = $magicWords->matchStartToEnd( $uarg );
1066
1067 $text = trim( $text );
1068 if ( strlen( $text ) == 0 ) {
1069 return '';
1070 }
1071 $old = $parser->getOutput()->getPageProperty( 'defaultsort' );
1072 if ( $old === null || $arg !== 'defaultsort_noreplace' ) {
1073 $parser->getOutput()->setPageProperty( 'defaultsort', $text );
1074 }
1075
1076 if ( $old === null || $old == $text || $arg ) {
1077 return '';
1078 } else {
1079 $converter = $parser->getTargetLanguageConverter();
1080 return '<span class="error">' .
1081 wfMessage( 'duplicate-defaultsort',
1082 // Message should be parsed, but these params should only be escaped.
1083 $converter->markNoConversion( wfEscapeWikiText( $old ) ),
1084 $converter->markNoConversion( wfEscapeWikiText( $text ) )
1085 )->inContentLanguage()->text() .
1086 '</span>';
1087 }
1088 }
1089
1101 public static function filepath( $parser, $name = '', $argA = '', $argB = '' ) {
1102 $file = MediaWikiServices::getInstance()->getRepoGroup()->findFile( $name );
1103
1104 if ( $argA == 'nowiki' ) {
1105 // {{filepath: | option [| size] }}
1106 $isNowiki = true;
1107 $parsedWidthParam = Parser::parseWidthParam( $argB );
1108 } else {
1109 // {{filepath: [| size [|option]] }}
1110 $parsedWidthParam = Parser::parseWidthParam( $argA );
1111 $isNowiki = ( $argB == 'nowiki' );
1112 }
1113
1114 if ( $file ) {
1115 $url = $file->getFullUrl();
1116
1117 // If a size is requested...
1118 if ( count( $parsedWidthParam ) ) {
1119 $mto = $file->transform( $parsedWidthParam );
1120 // ... and we can
1121 if ( $mto && !$mto->isError() ) {
1122 // ... change the URL to point to a thumbnail.
1123 $url = wfExpandUrl( $mto->getUrl(), PROTO_RELATIVE );
1124 }
1125 }
1126 if ( $isNowiki ) {
1127 return [ $url, 'nowiki' => true ];
1128 }
1129 return $url;
1130 } else {
1131 return '';
1132 }
1133 }
1134
1142 public static function tagObj( $parser, $frame, $args ) {
1143 if ( !count( $args ) ) {
1144 return '';
1145 }
1146 $tagName = strtolower( trim( $frame->expand( array_shift( $args ) ) ) );
1147 $processNowiki = $parser->tagNeedsNowikiStrippedInTagPF( $tagName ) ? PPFrame::PROCESS_NOWIKI : 0;
1148
1149 if ( count( $args ) ) {
1150 $inner = $frame->expand( array_shift( $args ), $processNowiki );
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 (
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 ) {
1269 $t = Title::newFromText( $title );
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 ) {
1319 $t = Title::newFromText( $title );
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 ) {
1354 $t = Title::newFromText( $title );
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 ) {
1371 $t = Title::newFromText( $title );
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 ) {
1388 $t = Title::newFromText( $title );
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 ) {
1405 $t = Title::newFromText( $title );
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 ) {
1422 $t = Title::newFromText( $title );
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 ) {
1439 $t = Title::newFromText( $title );
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 ) {
1456 $t = Title::newFromText( $title );
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 )
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
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:1266
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:4150
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:5018
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:6223
getRevisionId()
Get the ID of the revision we are parsing.
Definition Parser.php:6013
static parseWidthParam( $value, $parseHeight=true)
Parsed a width param of imagelink like 300px or 200x300px.
Definition Parser.php:6431
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:6386
killMarkers( $text)
Remove any strip markers found in the given text.
Definition Parser.php:6417
getRevisionRecordObject()
Get the revision record object for $this->mRevisionId.
Definition Parser.php:6023
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:598
$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