39use Wikimedia\RemexHtml\Tokenizer\Attributes;
40use Wikimedia\RemexHtml\Tokenizer\PlainAttributes;
48 private const MAX_TTS = 900;
55 MainConfigNames::AllowDisplayTitle,
56 MainConfigNames::AllowSlowParserFunctions,
67 $options->assertRequiredOptions( self::REGISTER_OPTIONS );
68 $allowDisplayTitle = $options->get( MainConfigNames::AllowDisplayTitle );
69 $allowSlowParserFunctions = $options->get( MainConfigNames::AllowSlowParserFunctions );
71 # Syntax for arguments (see Parser::setFunctionHook):
72 # "name for lookup in localized magic words array",
74 # optional Parser::SFH_NO_HASH to omit the hash from calls (e.g. {{int:...}}
75 # instead of {{#int:...}})
77 'ns',
'nse',
'urlencode',
'lcfirst',
'ucfirst',
'lc',
'uc',
78 'localurl',
'localurle',
'fullurl',
'fullurle',
'canonicalurl',
79 'canonicalurle',
'formatnum',
'grammar',
'gender',
'plural',
'formal',
80 'bidi',
'numberingroup',
'language',
81 'padleft',
'padright',
'anchorencode',
'defaultsort',
'filepath',
82 'pagesincategory',
'pagesize',
'protectionlevel',
'protectionexpiry',
83 # The following are the "parser function" forms of magic
84 # variables defined in CoreMagicVariables. The no-args form will
85 # go through the magic variable code path (and be cached); the
86 # presence of arguments will cause the parser function form to
87 # be invoked. (Note that the actual implementation will pass
88 # a Parser object as first argument, in addition to the
89 # parser function parameters.)
91 # For this group, the first parameter to the parser function is
92 # "page title", and the no-args form (and the magic variable)
93 # defaults to "current page title".
94 'pagename',
'pagenamee',
95 'fullpagename',
'fullpagenamee',
96 'subpagename',
'subpagenamee',
97 'rootpagename',
'rootpagenamee',
98 'basepagename',
'basepagenamee',
99 'talkpagename',
'talkpagenamee',
100 'subjectpagename',
'subjectpagenamee',
101 'pageid',
'revisionid',
'revisionday',
102 'revisionday2',
'revisionmonth',
'revisionmonth1',
'revisionyear',
106 'namespace',
'namespacee',
'namespacenumber',
'talkspace',
'talkspacee',
107 'subjectspace',
'subjectspacee',
109 # More parser functions corresponding to CoreMagicVariables.
110 # For this group, the first parameter to the parser function is
111 # "raw" (uses the 'raw' format if present) and the no-args form
112 # (and the magic variable) defaults to 'not raw'.
113 'numberofarticles',
'numberoffiles',
115 'numberofactiveusers',
120 foreach ( $noHashFunctions as $func ) {
121 $parser->
setFunctionHook( $func, [ __CLASS__, $func ], Parser::SFH_NO_HASH );
124 $parser->
setFunctionHook(
'int', [ __CLASS__,
'intFunction' ], Parser::SFH_NO_HASH );
127 $parser->
setFunctionHook(
'tag', [ __CLASS__,
'tagObj' ], Parser::SFH_OBJECT_ARGS );
130 if ( $allowDisplayTitle ) {
133 [ __CLASS__,
'displaytitle' ],
137 if ( $allowSlowParserFunctions ) {
140 [ __CLASS__,
'pagesinnamespace' ],
153 if ( strval( $part1 ) !==
'' ) {
155 ->inLanguage( $parser->
getOptions()->getUserLangObj() );
156 return [ $message->plain(),
'noparse' => false ];
158 return [
'found' => false ];
169 public static function formatDate( $parser, $date, $defaultPref =
null ) {
171 $df = MediaWikiServices::getInstance()->getDateFormatterFactory()->get( $lang );
173 $date = trim( $date );
175 $pref = $parser->
getOptions()->getDateFormat();
179 if ( $pref ==
'default' && $defaultPref ) {
180 $pref = $defaultPref;
183 $date = $df->reformat( $pref, $date, [
'match-whole' ] );
187 public static function ns( $parser, $part1 =
'' ) {
188 if ( intval( $part1 ) || $part1 ==
"0" ) {
189 $index = intval( $part1 );
191 $index = $parser->
getContentLanguage()->getNsIndex( str_replace(
' ',
'_', $part1 ) );
193 if ( $index !==
false ) {
196 return [
'found' => false ];
200 public static function nse( $parser, $part1 =
'' ) {
201 $ret = self::ns( $parser, $part1 );
202 if ( is_string( $ret ) ) {
203 $ret =
wfUrlencode( str_replace(
' ',
'_', $ret ) );
220 public static function urlencode( $parser, $s =
'', $arg =
null ) {
226 switch (
$magicWords->matchStartToEnd( $arg ??
'' ) ) {
229 $func =
'wfUrlencode';
230 $s = str_replace(
' ',
'_', $s );
235 $func =
'rawurlencode';
248 public static function lcfirst( $parser, $s =
'' ) {
252 public static function ucfirst( $parser, $s =
'' ) {
261 public static function lc( $parser, $s =
'' ) {
270 public static function uc( $parser, $s =
'' ) {
274 public static function localurl( $parser, $s =
'', $arg =
null ) {
275 return self::urlFunction(
'getLocalURL', $s, $arg );
278 public static function localurle( $parser, $s =
'', $arg =
null ) {
279 $temp = self::urlFunction(
'getLocalURL', $s, $arg );
280 if ( !is_string( $temp ) ) {
283 return htmlspecialchars( $temp, ENT_COMPAT );
287 public static function fullurl( $parser, $s =
'', $arg =
null ) {
288 return self::urlFunction(
'getFullURL', $s, $arg );
291 public static function fullurle( $parser, $s =
'', $arg =
null ) {
292 $temp = self::urlFunction(
'getFullURL', $s, $arg );
293 if ( !is_string( $temp ) ) {
296 return htmlspecialchars( $temp, ENT_COMPAT );
301 return self::urlFunction(
'getCanonicalURL', $s, $arg );
305 $temp = self::urlFunction(
'getCanonicalURL', $s, $arg );
306 if ( !is_string( $temp ) ) {
309 return htmlspecialchars( $temp, ENT_COMPAT );
313 public static function urlFunction( $func, $s =
'', $arg =
null ) {
314 # Due to order of execution of a lot of bits, the values might be encoded
315 # before arriving here; if that's true, then the title can't be created
316 # and the variable will fail. If we can't get a decent title from the first
317 # attempt, url-decode and try for a second.
318 $title = Title::newFromText( $s ) ?? Title::newFromURL( urldecode( $s ) );
319 if ( $title !==
null ) {
320 # Convert NS_MEDIA -> NS_FILE
324 if ( $arg !==
null ) {
325 $text = $title->$func( $arg );
327 $text = $title->$func();
331 return [
'found' => false ];
341 public static function formatnum( $parser, $num =
'', $arg =
null ) {
348 $func = self::getLegacyFormatNum( $parser, $func );
351 $func = self::getLegacyFormatNum( $parser, $func );
362 private static function getLegacyFormatNum( $parser, $callback ) {
367 return static function ( $number ) use ( $parser, $callback ) {
368 $validNumberRe =
'(-(?=[\d\.]))?(\d+|(?=\.\d))(\.\d*)?([Ee][-+]?\d+)?';
370 !is_numeric( $number ) &&
371 $number !== (string)NAN &&
372 $number !== (
string)INF &&
373 $number !== (string)-INF
378 return preg_replace_callback(
"/{$validNumberRe}/",
static function ( $m ) use ( $callback ) {
379 return call_user_func( $callback, $m[0] );
382 return call_user_func( $callback, $number );
392 public static function grammar( $parser, $case =
'', $word =
'' ) {
403 public static function gender( $parser, $username, ...$forms ) {
405 if ( count( $forms ) === 0 ) {
407 } elseif ( count( $forms ) === 1 ) {
411 $username = trim( $username );
413 $userOptionsLookup = MediaWikiServices::getInstance()->getUserOptionsLookup();
414 $gender = $userOptionsLookup->getDefaultOption(
'gender' );
417 $title = Title::newFromText( $username,
NS_USER );
424 $user = User::newFromName( $username );
425 $genderCache = MediaWikiServices::getInstance()->getGenderCache();
427 $gender = $genderCache->getGenderOf( $user, __METHOD__ );
428 } elseif ( $username ===
'' && $parser->
getOptions()->getInterfaceMessage() ) {
429 $gender = $genderCache->getGenderOf( $parser->
getOptions()->getUserIdentity(), __METHOD__ );
441 public static function plural( $parser, $text =
'', ...$forms ) {
443 settype( $text, ctype_digit( $text ) ?
'int' :
'float' );
448 public static function formal(
Parser $parser,
string ...$forms ): string {
449 $index = $parser->getTargetLanguage()->getFormalityIndex();
450 return $forms[$index] ?? $forms[0];
458 public static function bidi( $parser, $text =
'' ) {
471 public static function displaytitle( $parser, $text =
'', $uarg =
'' ) {
472 $restrictDisplayTitle = MediaWikiServices::getInstance()->getMainConfig()
473 ->get( MainConfigNames::RestrictDisplayTitle );
478 [
'displaytitle_noerror',
'displaytitle_noreplace' ] );
491 $bad = [
'h1',
'h2',
'h3',
'h4',
'h5',
'h6',
'div',
'blockquote',
'ol',
'ul',
'li',
'hr',
492 'table',
'tr',
'th',
'td',
'dl',
'dd',
'caption',
'p',
'ruby',
'rb',
'rt',
'rtc',
'rp',
'br' ];
495 if ( $restrictDisplayTitle ) {
498 $htmlTagsCallback =
static function ( Attributes $attr ): Attributes {
499 $decoded = $attr->getValues();
501 if ( isset( $decoded[
'style'] ) ) {
504 $decoded[
'style'] = Sanitizer::checkCss( $decoded[
'style'] );
506 if ( preg_match(
'/(display|user-select|visibility)\s*:/i', $decoded[
'style'] ) ) {
507 $decoded[
'style'] =
'/* attempt to bypass $wgRestrictDisplayTitle */';
511 return new PlainAttributes( $decoded );
514 $htmlTagsCallback =
null;
520 $text = Sanitizer::removeSomeTags( $text, [
521 'attrCallback' => $htmlTagsCallback,
522 'removeTags' => $bad,
524 $title = Title::newFromText( Sanitizer::stripAllTags( $text ) );
526 $filteredText = Sanitizer::decodeCharReferencesAndNormalize( $text );
528 if ( !$restrictDisplayTitle ||
529 ( $title instanceof
Title
533 $old = $parser->
getOutput()->getPageProperty(
'displaytitle' );
534 if ( $old ===
null || $arg !==
'displaytitle_noreplace' ) {
535 $parser->
getOutput()->setDisplayTitle( $text );
537 if ( $old !==
null && $old !== $text && !$arg ) {
540 return '<span class="error">' .
541 $parser->
msg(
'duplicate-displaytitle',
552 'restricted-displaytitle',
554 Message::plaintextParam( $filteredText )
569 private static function matchAgainstMagicword(
572 $value = trim( strval( $value ) );
573 if ( $value ===
'' ) {
576 $mwObject = $magicWordFactory->
get( $magicword );
577 return $mwObject->matchStartToEnd( $value );
592 if ( $raw !==
null && $raw !==
'' ) {
593 if ( !$magicWordFactory ) {
594 $magicWordFactory = MediaWikiServices::getInstance()->getMagicWordFactory();
596 if ( self::matchAgainstMagicword( $magicWordFactory,
'rawsuffix', $raw ) ) {
600 return $language->formatNum( $num );
604 return self::formatRaw( SiteStats::pages(), $raw, $parser->
getTargetLanguage() );
608 return self::formatRaw( SiteStats::users(), $raw, $parser->
getTargetLanguage() );
612 return self::formatRaw( SiteStats::activeUsers(), $raw, $parser->
getTargetLanguage() );
616 return self::formatRaw( SiteStats::articles(), $raw, $parser->
getTargetLanguage() );
620 return self::formatRaw( SiteStats::images(), $raw, $parser->
getTargetLanguage() );
624 return self::formatRaw(
625 SiteStats::numberingroup(
'sysop' ),
632 return self::formatRaw( SiteStats::edits(), $raw, $parser->
getTargetLanguage() );
636 return self::formatRaw(
637 SiteStats::pagesInNs( intval( $namespace ) ),
644 return self::formatRaw(
645 SiteStats::numberingroup( strtolower( $name ) ),
659 private static function makeTitle(
Parser $parser, ?
string $t ) {
664 $title = Title::newFromText( $t );
677 public static function namespace( $parser, $title = null ) {
678 $t = self::makeTitle( $parser, $title );
682 return str_replace(
'_',
' ', $t->getNsText() );
685 public static function namespacee( $parser, $title =
null ) {
686 $t = self::makeTitle( $parser, $title );
694 $t = self::makeTitle( $parser, $title );
698 return (
string)$t->getNamespace();
701 public static function talkspace( $parser, $title =
null ) {
702 $t = self::makeTitle( $parser, $title );
703 if ( $t ===
null || !$t->canHaveTalkPage() ) {
706 return str_replace(
'_',
' ', $t->getTalkNsText() );
709 public static function talkspacee( $parser, $title =
null ) {
710 $t = self::makeTitle( $parser, $title );
711 if ( $t ===
null || !$t->canHaveTalkPage() ) {
718 $t = self::makeTitle( $parser, $title );
722 return str_replace(
'_',
' ', $t->getSubjectNsText() );
726 $t = self::makeTitle( $parser, $title );
740 public static function pagename( $parser, $title =
null ) {
741 $t = self::makeTitle( $parser, $title );
748 public static function pagenamee( $parser, $title =
null ) {
749 $t = self::makeTitle( $parser, $title );
757 $t = self::makeTitle( $parser, $title );
765 $t = self::makeTitle( $parser, $title );
773 $t = self::makeTitle( $parser, $title );
781 $t = self::makeTitle( $parser, $title );
789 $t = self::makeTitle( $parser, $title );
797 $t = self::makeTitle( $parser, $title );
805 $t = self::makeTitle( $parser, $title );
813 $t = self::makeTitle( $parser, $title );
821 $t = self::makeTitle( $parser, $title );
822 if ( $t ===
null || !$t->canHaveTalkPage() ) {
829 $t = self::makeTitle( $parser, $title );
830 if ( $t ===
null || !$t->canHaveTalkPage() ) {
837 $t = self::makeTitle( $parser, $title );
845 $t = self::makeTitle( $parser, $title );
862 public static function pagesincategory( $parser, $name =
'', $arg1 =
'', $arg2 =
'' ) {
866 'pagesincategory_all',
867 'pagesincategory_pages',
868 'pagesincategory_subcats',
869 'pagesincategory_files'
885 $type =
'pagesincategory_all';
888 $title = Title::makeTitleSafe(
NS_CATEGORY, $name );
889 if ( !$title ) { # invalid title
892 $languageConverter = MediaWikiServices::getInstance()
893 ->getLanguageConverterFactory()
895 $languageConverter->findVariantLink( $name, $title,
true );
898 $name = $title->getDBkey();
900 if ( !isset( $cache[$name] ) ) {
901 $category = Category::newFromTitle( $title );
903 $allCount = $subcatCount = $fileCount = $pageCount = 0;
905 $allCount = $category->getMemberCount();
906 $subcatCount = $category->getSubcatCount();
907 $fileCount = $category->getFileCount();
908 $pageCount = $category->getPageCount( Category::COUNT_CONTENT_PAGES );
910 $cache[$name][
'pagesincategory_all'] = $allCount;
911 $cache[$name][
'pagesincategory_pages'] = $pageCount;
912 $cache[$name][
'pagesincategory_subcats'] = $subcatCount;
913 $cache[$name][
'pagesincategory_files'] = $fileCount;
916 $count = $cache[$name][$type];
929 public static function pagesize( $parser, $page =
'', $raw =
null ) {
930 $title = Title::newFromText( $page );
932 if ( !is_object( $title ) || $title->isExternal() ) {
937 $rev = self::getCachedRevisionObject( $parser, $title, ParserOutputFlags::VARY_REVISION_SHA1 );
938 $length = $rev ? $rev->getSize() : 0;
939 if ( $length ===
null ) {
959 $titleObject = Title::newFromText( $title ) ?? $parser->
getTitle();
960 $restrictionStore = MediaWikiServices::getInstance()->getRestrictionStore();
962 $restrictions = $restrictionStore->getRestrictions( $titleObject, strtolower( $type ) );
963 # RestrictionStore::getRestrictions returns an array, its possible it may have
964 # multiple values in the future
965 return implode(
',', $restrictions );
983 $titleObject = Title::newFromText( $title ) ?? $parser->
getTitle();
984 $restrictionStore = MediaWikiServices::getInstance()->getRestrictionStore();
988 return $restrictionStore->getRestrictionExpiry( $titleObject, strtolower( $type ) ) ??
'';
1000 public static function language( $parser, $code =
'', $inLanguage =
'' ) {
1001 $code = strtolower( $code );
1002 $inLanguage = strtolower( $inLanguage );
1003 $lang = MediaWikiServices::getInstance()
1004 ->getLanguageNameUtils()
1005 ->getLanguageName( $code, $inLanguage );
1006 return $lang !==
'' ? $lang : LanguageCode::bcp47( $code );
1019 $parser, $string, $length, $padding =
'0', $direction = STR_PAD_RIGHT
1022 $lengthOfPadding = mb_strlen( $padding );
1023 if ( $lengthOfPadding == 0 ) {
1027 # The remaining length to add counts down to 0 as padding is added
1028 $length = min( (
int)$length, 500 ) - mb_strlen( $string );
1029 if ( $length <= 0 ) {
1034 # $finalPadding is just $padding repeated enough times so that
1035 # mb_strlen( $string ) + mb_strlen( $finalPadding ) == $length
1037 while ( $length > 0 ) {
1038 # If $length < $lengthofPadding, truncate $padding so we get the
1039 # exact length desired.
1040 $finalPadding .= mb_substr( $padding, 0, $length );
1041 $length -= $lengthOfPadding;
1044 if ( $direction == STR_PAD_LEFT ) {
1045 return $finalPadding . $string;
1047 return $string . $finalPadding;
1051 public static function padleft( $parser, $string =
'', $length = 0, $padding =
'0' ) {
1052 return self::pad( $parser, $string, $length, $padding, STR_PAD_LEFT );
1055 public static function padright( $parser, $string =
'', $length = 0, $padding =
'0' ) {
1056 return self::pad( $parser, $string, $length, $padding );
1067 return Sanitizer::safeEncodeAttribute( $section );
1070 public static function special( $parser, $text ) {
1071 [ $page, $subpage ] = MediaWikiServices::getInstance()->getSpecialPageFactory()->
1072 resolveAlias( $text );
1074 $title = SpecialPage::getTitleFor( $page, $subpage );
1075 return $title->getPrefixedText();
1078 $title = Title::makeTitleSafe(
NS_SPECIAL, $text );
1079 return $title ? $title->getPrefixedText() : self::special( $parser,
'Badtitle' );
1084 return wfUrlencode( str_replace(
' ',
'_', self::special( $parser, $text ) ) );
1099 [
'defaultsort_noerror',
'defaultsort_noreplace' ] );
1103 $text = trim( $text );
1104 if ( strlen( $text ) == 0 ) {
1107 $old = $parser->
getOutput()->getPageProperty(
'defaultsort' );
1108 if ( $old ===
null || $arg !==
'defaultsort_noreplace' ) {
1109 $parser->
getOutput()->setPageProperty(
'defaultsort', $text );
1112 if ( $old ===
null || $old == $text || $arg ) {
1116 return '<span class="error">' .
1117 $parser->
msg(
'duplicate-defaultsort',
1137 public static function filepath( $parser, $name =
'', $argA =
'', $argB =
'' ) {
1138 $file = MediaWikiServices::getInstance()->getRepoGroup()->findFile( $name );
1140 if ( $argA ==
'nowiki' ) {
1143 $parsedWidthParam = Parser::parseWidthParam( $argB );
1146 $parsedWidthParam = Parser::parseWidthParam( $argA );
1147 $isNowiki = ( $argB ==
'nowiki' );
1151 $url = $file->getFullUrl();
1154 if ( count( $parsedWidthParam ) ) {
1155 $mto = $file->transform( $parsedWidthParam );
1157 if ( $mto && !$mto->isError() ) {
1163 return [
$url,
'nowiki' => true ];
1178 public static function tagObj( $parser, $frame, $args ) {
1179 if ( !count( $args ) ) {
1182 $tagName = strtolower( trim( $frame->expand( array_shift( $args ) ) ) );
1185 if ( count( $args ) ) {
1186 $inner = $frame->expand( array_shift( $args ), $processNowiki );
1192 foreach ( $args as $arg ) {
1193 $bits = $arg->splitArg();
1194 if ( strval( $bits[
'index'] ) ===
'' ) {
1195 $name = trim( $frame->expand( $bits[
'name'], PPFrame::STRIP_COMMENTS ) );
1196 $value = trim( $frame->expand( $bits[
'value'] ) );
1197 if ( preg_match(
'/^(?:["\'](.+)["\']|""|\'\')$/s', $value, $m ) ) {
1198 $value = $m[1] ??
'';
1200 $attributes[$name] = $value;
1205 if ( !in_array( $tagName, $stripList ) ) {
1208 foreach ( $attributes as $name => $value ) {
1209 $attrText .=
' ' . htmlspecialchars( $name ) .
1210 '="' . htmlspecialchars( $value, ENT_COMPAT ) .
'"';
1212 if ( $inner ===
null ) {
1213 return "<$tagName$attrText/>";
1215 return "<$tagName$attrText>$inner</$tagName>";
1221 'attributes' => $attributes,
1222 'close' =>
"</$tagName>",
1240 private static function getCachedRevisionObject( $parser, $title, $vary ) {
1245 $revisionRecord =
null;
1247 $isSelfReferential = $title->equals( $parser->
getTitle() );
1248 if ( $isSelfReferential ) {
1259 if ( $parserRevisionRecord && $parserRevisionRecord->isCurrent() ) {
1260 $revisionRecord = $parserRevisionRecord;
1265 if ( !$revisionRecord ) {
1274 if ( !$revisionRecord ) {
1276 $revisionRecord =
null;
1279 $parserOutput->addTemplate(
1281 $revisionRecord ? $revisionRecord->getPageId() : 0,
1282 $revisionRecord ? $revisionRecord->getId() : 0
1286 if ( $isSelfReferential ) {
1287 wfDebug( __METHOD__ .
": used current revision, setting $vary" );
1289 $parserOutput->setOutputFlag( $vary );
1290 if ( $vary === ParserOutputFlags::VARY_REVISION_SHA1 && $revisionRecord ) {
1292 $sha1 = $revisionRecord->getSha1();
1296 $parserOutput->setRevisionUsedSha1Base36( $sha1 );
1300 return $revisionRecord;
1310 public static function pageid( $parser, $title =
null ) {
1311 $t = self::makeTitle( $parser, $title );
1314 } elseif ( !$t->canExist() || $t->isExternal() ) {
1320 if ( $t->equals( $parser->
getTitle() ) ) {
1323 $parserOutput->setOutputFlag( ParserOutputFlags::VARY_PAGE_ID );
1324 $id = $parser->
getTitle()->getArticleID();
1326 $parserOutput->setSpeculativePageIdUsed( $id );
1333 $linkCache = MediaWikiServices::getInstance()->getLinkCache();
1334 $pdbk = $t->getPrefixedDBkey();
1335 $id = $linkCache->getGoodLinkID( $pdbk );
1336 if ( $id != 0 || $linkCache->isBadLink( $pdbk ) ) {
1337 $parserOutput->addLink( $t, $id );
1344 $id = $t->getArticleID();
1345 $parserOutput->addLink( $t, $id );
1361 $t = self::makeTitle( $parser, $title );
1362 if ( $t ===
null || $t->isExternal() ) {
1366 $services = MediaWikiServices::getInstance();
1368 $t->equals( $parser->
getTitle() ) &&
1369 $services->getMainConfig()->get( MainConfigNames::MiserMode ) &&
1370 !$parser->
getOptions()->getInterfaceMessage() &&
1372 $services->getNamespaceInfo()->isSubject( $t->getNamespace() )
1379 $parser->
getOutput()->setOutputFlag( ParserOutputFlags::VARY_REVISION_EXISTS );
1387 if ( $t->equals( $parser->
getTitle() ) && $title ===
null ) {
1390 $parser->
getOutput()->setOutputFlag( ParserOutputFlags::VARY_REVISION_ID );
1395 $id = $rev->getId();
1399 $id = $parser->
getOptions()->getSpeculativeRevId();
1401 $parser->
getOutput()->setSpeculativeRevIdUsed( $id );
1406 $rev = self::getCachedRevisionObject( $parser, $t, ParserOutputFlags::VARY_REVISION_ID );
1407 return $rev ? $rev->getId() :
'';
1410 private static function getRevisionTimestampSubstring(
1423 if ( $title->equals( $parser->
getTitle() ) && !$parser->getOptions()->getInterfaceMessage() ) {
1438 if ( $resNow !== $resThen ) {
1441 $parser->
getOutput()->setOutputFlag( ParserOutputFlags::VARY_REVISION_TIMESTAMP );
1447 $rev = self::getCachedRevisionObject( $parser, $title, ParserOutputFlags::VARY_REVISION_TIMESTAMP );
1466 $t = self::makeTitle( $parser, $title );
1467 if ( $t ===
null || $t->isExternal() ) {
1470 return strval( (
int)self::getRevisionTimestampSubstring(
1471 $parser, $t, 6, 2, self::MAX_TTS
1483 $t = self::makeTitle( $parser, $title );
1484 if ( $t ===
null || $t->isExternal() ) {
1487 return self::getRevisionTimestampSubstring(
1488 $parser, $t, 6, 2, self::MAX_TTS
1500 $t = self::makeTitle( $parser, $title );
1501 if ( $t ===
null || $t->isExternal() ) {
1504 return self::getRevisionTimestampSubstring(
1505 $parser, $t, 4, 2, self::MAX_TTS
1517 $t = self::makeTitle( $parser, $title );
1518 if ( $t ===
null || $t->isExternal() ) {
1521 return strval( (
int)self::getRevisionTimestampSubstring(
1522 $parser, $t, 4, 2, self::MAX_TTS
1534 $t = self::makeTitle( $parser, $title );
1535 if ( $t ===
null || $t->isExternal() ) {
1538 return self::getRevisionTimestampSubstring(
1539 $parser, $t, 0, 4, self::MAX_TTS
1551 $t = self::makeTitle( $parser, $title );
1552 if ( $t ===
null || $t->isExternal() ) {
1555 return self::getRevisionTimestampSubstring(
1556 $parser, $t, 0, 14, self::MAX_TTS
1568 $t = self::makeTitle( $parser, $title );
1569 if ( $t ===
null || $t->isExternal() ) {
1575 if ( $t->equals( $parser->
getTitle() ) ) {
1577 $parser->
getOutput()->setOutputFlag( ParserOutputFlags::VARY_USER );
1584 $rev = self::getCachedRevisionObject( $parser, $t, ParserOutputFlags::VARY_USER );
1585 $user = ( $rev !== null ) ? $rev->getUser() :
null;
1586 return $user ? $user->getName() :
'';
1602 $titleObject = Title::newFromText( $title ) ?? $parser->
getTitle();
1603 $restrictionStore = MediaWikiServices::getInstance()->getRestrictionStore();
1604 if ( $restrictionStore->areCascadeProtectionSourcesLoaded( $titleObject )
1608 $sources = $restrictionStore->getCascadeProtectionSources( $titleObject );
1609 $titleFormatter = MediaWikiServices::getInstance()->getTitleFormatter();
1610 foreach ( $sources[0] as $sourcePageIdentity ) {
1611 $names[] = $titleFormatter->getPrefixedText( $sourcePageIdentity );
1613 return implode(
'|', $names );
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,...
wfEscapeWikiText( $input)
Escapes the given text so that it may be output using addWikiText() without any linking,...
wfExpandUrl( $url, $defaultProto=PROTO_CURRENT)
Expand a potentially local URL to a fully-qualified URL using $wgServer (or one of its alternatives).
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
$magicWords
@phpcs-require-sorted-array
array $params
The job parameters.
if(!defined('MW_SETUP_CALLBACK'))
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 formal(Parser $parser, string ... $forms)
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 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 class containing constants representing the names of configuration variables.
Parent class for all special pages.