40use Wikimedia\Bcp47Code\Bcp47CodeValue;
41use Wikimedia\RemexHtml\Tokenizer\Attributes;
42use Wikimedia\RemexHtml\Tokenizer\PlainAttributes;
50 private const MAX_TTS = 900;
57 MainConfigNames::AllowDisplayTitle,
58 MainConfigNames::AllowSlowParserFunctions,
69 $options->assertRequiredOptions( self::REGISTER_OPTIONS );
70 $allowDisplayTitle = $options->get( MainConfigNames::AllowDisplayTitle );
71 $allowSlowParserFunctions = $options->get( MainConfigNames::AllowSlowParserFunctions );
73 # Syntax for arguments (see Parser::setFunctionHook):
74 # "name for lookup in localized magic words array",
76 # optional Parser::SFH_NO_HASH to omit the hash from calls (e.g. {{int:...}}
77 # instead of {{#int:...}})
79 'ns',
'nse',
'urlencode',
'lcfirst',
'ucfirst',
'lc',
'uc',
80 'localurl',
'localurle',
'fullurl',
'fullurle',
'canonicalurl',
81 'canonicalurle',
'formatnum',
'grammar',
'gender',
'plural',
'formal',
82 'bidi',
'numberingroup',
'language',
83 'padleft',
'padright',
'anchorencode',
'defaultsort',
'filepath',
84 'pagesincategory',
'pagesize',
'protectionlevel',
'protectionexpiry',
85 # The following are the "parser function" forms of magic
86 # variables defined in CoreMagicVariables. The no-args form will
87 # go through the magic variable code path (and be cached); the
88 # presence of arguments will cause the parser function form to
89 # be invoked. (Note that the actual implementation will pass
90 # a Parser object as first argument, in addition to the
91 # parser function parameters.)
93 # For this group, the first parameter to the parser function is
94 # "page title", and the no-args form (and the magic variable)
95 # defaults to "current page title".
96 'pagename',
'pagenamee',
97 'fullpagename',
'fullpagenamee',
98 'subpagename',
'subpagenamee',
99 'rootpagename',
'rootpagenamee',
100 'basepagename',
'basepagenamee',
101 'talkpagename',
'talkpagenamee',
102 'subjectpagename',
'subjectpagenamee',
103 'pageid',
'revisionid',
'revisionday',
104 'revisionday2',
'revisionmonth',
'revisionmonth1',
'revisionyear',
108 'namespace',
'namespacee',
'namespacenumber',
'talkspace',
'talkspacee',
109 'subjectspace',
'subjectspacee',
111 # More parser functions corresponding to CoreMagicVariables.
112 # For this group, the first parameter to the parser function is
113 # "raw" (uses the 'raw' format if present) and the no-args form
114 # (and the magic variable) defaults to 'not raw'.
115 'numberofarticles',
'numberoffiles',
117 'numberofactiveusers',
122 # These magic words already contain the hash, and the no-args form
123 # is the same as passing an empty first argument
127 foreach ( $noHashFunctions as $func ) {
128 $parser->
setFunctionHook( $func, [ __CLASS__, $func ], Parser::SFH_NO_HASH );
131 $parser->
setFunctionHook(
'int', [ __CLASS__,
'intFunction' ], Parser::SFH_NO_HASH );
134 $parser->
setFunctionHook(
'tag', [ __CLASS__,
'tagObj' ], Parser::SFH_OBJECT_ARGS );
137 if ( $allowDisplayTitle ) {
140 [ __CLASS__,
'displaytitle' ],
144 if ( $allowSlowParserFunctions ) {
147 [ __CLASS__,
'pagesinnamespace' ],
160 if ( strval( $part1 ) !==
'' ) {
162 ->inLanguage( $parser->
getOptions()->getUserLangObj() );
163 return [ $message->plain(),
'noparse' => false ];
165 return [
'found' => false ];
176 public static function formatDate( $parser, $date, $defaultPref =
null ) {
178 $df = MediaWikiServices::getInstance()->getDateFormatterFactory()->get( $lang );
180 $date = trim( $date );
182 $pref = $parser->
getOptions()->getDateFormat();
186 if ( $pref ==
'default' && $defaultPref ) {
187 $pref = $defaultPref;
190 $date = $df->reformat( $pref, $date, [
'match-whole' ] );
194 public static function ns( $parser, $part1 =
'' ) {
195 if ( intval( $part1 ) || $part1 ==
"0" ) {
196 $index = intval( $part1 );
198 $index = $parser->
getContentLanguage()->getNsIndex( str_replace(
' ',
'_', $part1 ) );
200 if ( $index !==
false ) {
203 return [
'found' => false ];
207 public static function nse( $parser, $part1 =
'' ) {
208 $ret = self::ns( $parser, $part1 );
209 if ( is_string( $ret ) ) {
210 $ret =
wfUrlencode( str_replace(
' ',
'_', $ret ) );
227 public static function urlencode( $parser, $s =
'', $arg =
null ) {
233 switch (
$magicWords->matchStartToEnd( $arg ??
'' ) ) {
236 $func =
'wfUrlencode';
237 $s = str_replace(
' ',
'_', $s );
242 $func =
'rawurlencode';
255 public static function lcfirst( $parser, $s =
'' ) {
259 public static function ucfirst( $parser, $s =
'' ) {
268 public static function lc( $parser, $s =
'' ) {
277 public static function uc( $parser, $s =
'' ) {
281 public static function localurl( $parser, $s =
'', $arg =
null ) {
282 return self::urlFunction(
'getLocalURL', $s, $arg );
285 public static function localurle( $parser, $s =
'', $arg =
null ) {
286 $temp = self::urlFunction(
'getLocalURL', $s, $arg );
287 if ( !is_string( $temp ) ) {
290 return htmlspecialchars( $temp, ENT_COMPAT );
294 public static function fullurl( $parser, $s =
'', $arg =
null ) {
295 return self::urlFunction(
'getFullURL', $s, $arg );
298 public static function fullurle( $parser, $s =
'', $arg =
null ) {
299 $temp = self::urlFunction(
'getFullURL', $s, $arg );
300 if ( !is_string( $temp ) ) {
303 return htmlspecialchars( $temp, ENT_COMPAT );
308 return self::urlFunction(
'getCanonicalURL', $s, $arg );
312 $temp = self::urlFunction(
'getCanonicalURL', $s, $arg );
313 if ( !is_string( $temp ) ) {
316 return htmlspecialchars( $temp, ENT_COMPAT );
320 public static function urlFunction( $func, $s =
'', $arg =
null ) {
321 # Due to order of execution of a lot of bits, the values might be encoded
322 # before arriving here; if that's true, then the title can't be created
323 # and the variable will fail. If we can't get a decent title from the first
324 # attempt, url-decode and try for a second.
325 $title = Title::newFromText( $s ) ?? Title::newFromURL( urldecode( $s ) );
326 if ( $title !==
null ) {
327 # Convert NS_MEDIA -> NS_FILE
331 if ( $arg !==
null ) {
332 $text = $title->$func( $arg );
334 $text = $title->$func();
338 return [
'found' => false ];
348 public static function formatnum( $parser, $num =
'', $arg =
null ) {
355 $func = self::getLegacyFormatNum( $parser, $func );
358 $func = self::getLegacyFormatNum( $parser, $func );
369 private static function getLegacyFormatNum( $parser, $callback ) {
374 return static function ( $number ) use ( $parser, $callback ) {
375 $validNumberRe =
'(-(?=[\d\.]))?(\d+|(?=\.\d))(\.\d*)?([Ee][-+]?\d+)?';
377 !is_numeric( $number ) &&
378 $number !== (string)NAN &&
379 $number !== (
string)INF &&
380 $number !== (string)-INF
385 return preg_replace_callback(
"/{$validNumberRe}/",
static function ( $m ) use ( $callback ) {
386 return call_user_func( $callback, $m[0] );
389 return call_user_func( $callback, $number );
399 public static function grammar( $parser, $case =
'', $word =
'' ) {
410 public static function gender( $parser, $username, ...$forms ) {
412 if ( count( $forms ) === 0 ) {
414 } elseif ( count( $forms ) === 1 ) {
418 $username = trim( $username );
420 $userOptionsLookup = MediaWikiServices::getInstance()->getUserOptionsLookup();
421 $gender = $userOptionsLookup->getDefaultOption(
'gender' );
424 $title = Title::newFromText( $username,
NS_USER );
431 $user = User::newFromName( $username );
432 $genderCache = MediaWikiServices::getInstance()->getGenderCache();
434 $gender = $genderCache->getGenderOf( $user, __METHOD__ );
435 } elseif ( $username ===
'' && $parser->
getOptions()->getInterfaceMessage() ) {
436 $gender = $genderCache->getGenderOf( $parser->
getOptions()->getUserIdentity(), __METHOD__ );
448 public static function plural( $parser, $text =
'', ...$forms ) {
450 settype( $text, ctype_digit( $text ) ?
'int' :
'float' );
455 public static function formal(
Parser $parser,
string ...$forms ): string {
456 $index = $parser->getTargetLanguage()->getFormalityIndex();
457 return $forms[$index] ?? $forms[0];
465 public static function bidi( $parser, $text =
'' ) {
478 public static function displaytitle( $parser, $text =
'', $uarg =
'' ) {
479 $restrictDisplayTitle = MediaWikiServices::getInstance()->getMainConfig()
480 ->get( MainConfigNames::RestrictDisplayTitle );
485 [
'displaytitle_noerror',
'displaytitle_noreplace' ] );
498 $bad = [
'h1',
'h2',
'h3',
'h4',
'h5',
'h6',
'div',
'blockquote',
'ol',
'ul',
'li',
'hr',
499 'table',
'tr',
'th',
'td',
'dl',
'dd',
'caption',
'p',
'ruby',
'rb',
'rt',
'rtc',
'rp',
'br' ];
502 if ( $restrictDisplayTitle ) {
505 $htmlTagsCallback =
static function ( Attributes $attr ): Attributes {
506 $decoded = $attr->getValues();
508 if ( isset( $decoded[
'style'] ) ) {
511 $decoded[
'style'] = Sanitizer::checkCss( $decoded[
'style'] );
513 if ( preg_match(
'/(display|user-select|visibility)\s*:/i', $decoded[
'style'] ) ) {
514 $decoded[
'style'] =
'/* attempt to bypass $wgRestrictDisplayTitle */';
518 return new PlainAttributes( $decoded );
521 $htmlTagsCallback =
null;
527 $text = Sanitizer::removeSomeTags( $text, [
528 'attrCallback' => $htmlTagsCallback,
529 'removeTags' => $bad,
531 $title = Title::newFromText( Sanitizer::stripAllTags( $text ) );
533 $filteredText = Sanitizer::decodeCharReferencesAndNormalize( $text );
535 if ( !$restrictDisplayTitle ||
536 ( $title instanceof
Title
540 $old = $parser->
getOutput()->getPageProperty(
'displaytitle' );
541 if ( $old ===
null || $arg !==
'displaytitle_noreplace' ) {
542 $parser->
getOutput()->setDisplayTitle( $text );
544 if ( $old !==
null && $old !== $text && !$arg ) {
547 return '<span class="error">' .
548 $parser->
msg(
'duplicate-displaytitle',
559 'restricted-displaytitle',
561 Message::plaintextParam( $filteredText )
576 private static function matchAgainstMagicword(
579 $value = trim( strval( $value ) );
580 if ( $value ===
'' ) {
583 $mwObject = $magicWordFactory->
get( $magicword );
584 return $mwObject->matchStartToEnd( $value );
599 if ( $raw !==
null && $raw !==
'' ) {
600 if ( !$magicWordFactory ) {
601 $magicWordFactory = MediaWikiServices::getInstance()->getMagicWordFactory();
603 if ( self::matchAgainstMagicword( $magicWordFactory,
'rawsuffix', $raw ) ) {
607 return $language->formatNum( $num );
611 return self::formatRaw( SiteStats::pages(), $raw, $parser->
getTargetLanguage() );
615 return self::formatRaw( SiteStats::users(), $raw, $parser->
getTargetLanguage() );
619 return self::formatRaw( SiteStats::activeUsers(), $raw, $parser->
getTargetLanguage() );
623 return self::formatRaw( SiteStats::articles(), $raw, $parser->
getTargetLanguage() );
627 return self::formatRaw( SiteStats::images(), $raw, $parser->
getTargetLanguage() );
631 return self::formatRaw(
632 SiteStats::numberingroup(
'sysop' ),
639 return self::formatRaw( SiteStats::edits(), $raw, $parser->
getTargetLanguage() );
643 return self::formatRaw(
644 SiteStats::pagesInNs( intval( $namespace ) ),
651 return self::formatRaw(
652 SiteStats::numberingroup( strtolower( $name ) ),
666 private static function makeTitle(
Parser $parser, ?
string $t ) {
671 $title = Title::newFromText( $t );
684 public static function namespace( $parser, $title = null ) {
685 $t = self::makeTitle( $parser, $title );
689 return str_replace(
'_',
' ', $t->getNsText() );
692 public static function namespacee( $parser, $title =
null ) {
693 $t = self::makeTitle( $parser, $title );
701 $t = self::makeTitle( $parser, $title );
705 return (
string)$t->getNamespace();
708 public static function talkspace( $parser, $title =
null ) {
709 $t = self::makeTitle( $parser, $title );
710 if ( $t ===
null || !$t->canHaveTalkPage() ) {
713 return str_replace(
'_',
' ', $t->getTalkNsText() );
716 public static function talkspacee( $parser, $title =
null ) {
717 $t = self::makeTitle( $parser, $title );
718 if ( $t ===
null || !$t->canHaveTalkPage() ) {
725 $t = self::makeTitle( $parser, $title );
729 return str_replace(
'_',
' ', $t->getSubjectNsText() );
733 $t = self::makeTitle( $parser, $title );
747 public static function pagename( $parser, $title =
null ) {
748 $t = self::makeTitle( $parser, $title );
755 public static function pagenamee( $parser, $title =
null ) {
756 $t = self::makeTitle( $parser, $title );
764 $t = self::makeTitle( $parser, $title );
772 $t = self::makeTitle( $parser, $title );
780 $t = self::makeTitle( $parser, $title );
788 $t = self::makeTitle( $parser, $title );
796 $t = self::makeTitle( $parser, $title );
804 $t = self::makeTitle( $parser, $title );
812 $t = self::makeTitle( $parser, $title );
820 $t = self::makeTitle( $parser, $title );
828 $t = self::makeTitle( $parser, $title );
829 if ( $t ===
null || !$t->canHaveTalkPage() ) {
836 $t = self::makeTitle( $parser, $title );
837 if ( $t ===
null || !$t->canHaveTalkPage() ) {
844 $t = self::makeTitle( $parser, $title );
852 $t = self::makeTitle( $parser, $title );
869 public static function pagesincategory( $parser, $name =
'', $arg1 =
'', $arg2 =
'' ) {
873 'pagesincategory_all',
874 'pagesincategory_pages',
875 'pagesincategory_subcats',
876 'pagesincategory_files'
892 $type =
'pagesincategory_all';
895 $title = Title::makeTitleSafe(
NS_CATEGORY, $name );
896 if ( !$title ) { # invalid title
899 $languageConverter = MediaWikiServices::getInstance()
900 ->getLanguageConverterFactory()
902 $languageConverter->findVariantLink( $name, $title,
true );
905 $name = $title->getDBkey();
907 if ( !isset( $cache[$name] ) ) {
908 $category = Category::newFromTitle( $title );
910 $allCount = $subcatCount = $fileCount = $pageCount = 0;
912 $allCount = $category->getMemberCount();
913 $subcatCount = $category->getSubcatCount();
914 $fileCount = $category->getFileCount();
915 $pageCount = $category->getPageCount( Category::COUNT_CONTENT_PAGES );
917 $cache[$name][
'pagesincategory_all'] = $allCount;
918 $cache[$name][
'pagesincategory_pages'] = $pageCount;
919 $cache[$name][
'pagesincategory_subcats'] = $subcatCount;
920 $cache[$name][
'pagesincategory_files'] = $fileCount;
923 $count = $cache[$name][$type];
936 public static function pagesize( $parser, $page =
'', $raw =
null ) {
937 $title = Title::newFromText( $page );
939 if ( !is_object( $title ) || $title->isExternal() ) {
944 $rev = self::getCachedRevisionObject( $parser, $title, ParserOutputFlags::VARY_REVISION_SHA1 );
945 $length = $rev ? $rev->getSize() : 0;
946 if ( $length ===
null ) {
966 $titleObject = Title::newFromText( $title ) ?? $parser->
getTitle();
967 $restrictionStore = MediaWikiServices::getInstance()->getRestrictionStore();
969 $restrictions = $restrictionStore->getRestrictions( $titleObject, strtolower( $type ) );
970 # RestrictionStore::getRestrictions returns an array, its possible it may have
971 # multiple values in the future
972 return implode(
',', $restrictions );
990 $titleObject = Title::newFromText( $title ) ?? $parser->
getTitle();
991 $restrictionStore = MediaWikiServices::getInstance()->getRestrictionStore();
995 return $restrictionStore->getRestrictionExpiry( $titleObject, strtolower( $type ) ) ??
'';
1008 public static function language( $parser, $code =
'', $inLanguage =
'' ) {
1009 if ( $code ===
'' ) {
1012 if ( $inLanguage ===
'' ) {
1013 $inLanguage = LanguageNameUtils::AUTONYMS;
1015 $lang = MediaWikiServices::getInstance()
1016 ->getLanguageNameUtils()
1017 ->getLanguageName( $code, $inLanguage );
1018 return $lang !==
'' ? $lang : LanguageCode::bcp47( $code );
1032 public static function dir(
Parser $parser,
string $code =
'',
string $arg =
'' ): string {
1034 $languageFactory = MediaWikiServices::getInstance()->getLanguageFactory();
1036 if ( $code ===
'' ) {
1039 if ( $arg !==
'' ) {
1043 if (
$magicWords->matchStartToEnd( $arg ) ===
'language_option_bcp47' ) {
1045 $code =
new Bcp47CodeValue( $code );
1049 $lang = $languageFactory->getLanguage( $code );
1050 }
catch ( InvalidArgumentException $ex ) {
1055 return $lang->getDir();
1066 public static function bcp47(
Parser $parser,
string $code =
'' ): string {
1067 if ( $code ===
'' ) {
1070 return LanguageCode::bcp47( $code );
1084 $parser, $string, $length, $padding =
'0', $direction = STR_PAD_RIGHT
1087 $lengthOfPadding = mb_strlen( $padding );
1088 if ( $lengthOfPadding == 0 ) {
1092 # The remaining length to add counts down to 0 as padding is added
1093 $length = min( (
int)$length, 500 ) - mb_strlen( $string );
1094 if ( $length <= 0 ) {
1099 # $finalPadding is just $padding repeated enough times so that
1100 # mb_strlen( $string ) + mb_strlen( $finalPadding ) == $length
1102 while ( $length > 0 ) {
1103 # If $length < $lengthofPadding, truncate $padding so we get the
1104 # exact length desired.
1105 $finalPadding .= mb_substr( $padding, 0, $length );
1106 $length -= $lengthOfPadding;
1109 if ( $direction == STR_PAD_LEFT ) {
1110 return $finalPadding . $string;
1112 return $string . $finalPadding;
1116 public static function padleft( $parser, $string =
'', $length = 0, $padding =
'0' ) {
1117 return self::pad( $parser, $string, $length, $padding, STR_PAD_LEFT );
1120 public static function padright( $parser, $string =
'', $length = 0, $padding =
'0' ) {
1121 return self::pad( $parser, $string, $length, $padding );
1132 return Sanitizer::safeEncodeAttribute( $section );
1135 public static function special( $parser, $text ) {
1136 [ $page, $subpage ] = MediaWikiServices::getInstance()->getSpecialPageFactory()->
1137 resolveAlias( $text );
1139 $title = SpecialPage::getTitleFor( $page, $subpage );
1140 return $title->getPrefixedText();
1143 $title = Title::makeTitleSafe(
NS_SPECIAL, $text );
1144 return $title ? $title->getPrefixedText() : self::special( $parser,
'Badtitle' );
1149 return wfUrlencode( str_replace(
' ',
'_', self::special( $parser, $text ) ) );
1164 [
'defaultsort_noerror',
'defaultsort_noreplace' ] );
1168 $text = trim( $text );
1169 if ( strlen( $text ) == 0 ) {
1172 $old = $parser->
getOutput()->getPageProperty(
'defaultsort' );
1173 if ( $old ===
null || $arg !==
'defaultsort_noreplace' ) {
1174 $parser->
getOutput()->setPageProperty(
'defaultsort', $text );
1177 if ( $old ===
null || $old == $text || $arg ) {
1181 return '<span class="error">' .
1182 $parser->
msg(
'duplicate-defaultsort',
1202 public static function filepath( $parser, $name =
'', $argA =
'', $argB =
'' ) {
1203 $file = MediaWikiServices::getInstance()->getRepoGroup()->findFile( $name );
1205 if ( $argA ==
'nowiki' ) {
1212 $isNowiki = ( $argB ==
'nowiki' );
1216 $url = $file->getFullUrl();
1219 if ( count( $parsedWidthParam ) ) {
1220 $mto = $file->transform( $parsedWidthParam );
1222 if ( $mto && !$mto->isError() ) {
1228 return [
$url,
'nowiki' => true ];
1243 public static function tagObj( $parser, $frame, $args ) {
1244 if ( !count( $args ) ) {
1247 $tagName = strtolower( trim( $frame->expand( array_shift( $args ) ) ) );
1250 if ( count( $args ) ) {
1251 $inner = $frame->expand( array_shift( $args ), $processNowiki );
1257 foreach ( $args as $arg ) {
1258 $bits = $arg->splitArg();
1259 if ( strval( $bits[
'index'] ) ===
'' ) {
1260 $name = trim( $frame->expand( $bits[
'name'], PPFrame::STRIP_COMMENTS ) );
1261 $value = trim( $frame->expand( $bits[
'value'] ) );
1262 if ( preg_match(
'/^(?:["\'](.+)["\']|""|\'\')$/s', $value, $m ) ) {
1263 $value = $m[1] ??
'';
1265 $attributes[$name] = $value;
1270 if ( !in_array( $tagName, $stripList ) ) {
1273 foreach ( $attributes as $name => $value ) {
1274 $attrText .=
' ' . htmlspecialchars( $name ) .
1275 '="' . htmlspecialchars( $value, ENT_COMPAT ) .
'"';
1277 if ( $inner ===
null ) {
1278 return "<$tagName$attrText/>";
1280 return "<$tagName$attrText>$inner</$tagName>";
1286 'attributes' => $attributes,
1287 'close' =>
"</$tagName>",
1305 private static function getCachedRevisionObject( $parser, $title, $vary ) {
1310 $revisionRecord =
null;
1312 $isSelfReferential = $title->equals( $parser->
getTitle() );
1313 if ( $isSelfReferential ) {
1324 if ( $parserRevisionRecord && $parserRevisionRecord->isCurrent() ) {
1325 $revisionRecord = $parserRevisionRecord;
1330 if ( !$revisionRecord ) {
1339 if ( !$revisionRecord ) {
1341 $revisionRecord =
null;
1344 $parserOutput->addTemplate(
1346 $revisionRecord ? $revisionRecord->getPageId() : 0,
1347 $revisionRecord ? $revisionRecord->getId() : 0
1351 if ( $isSelfReferential ) {
1352 wfDebug( __METHOD__ .
": used current revision, setting $vary" );
1354 $parserOutput->setOutputFlag( $vary );
1355 if ( $vary === ParserOutputFlags::VARY_REVISION_SHA1 && $revisionRecord ) {
1357 $sha1 = $revisionRecord->getSha1();
1361 $parserOutput->setRevisionUsedSha1Base36( $sha1 );
1365 return $revisionRecord;
1375 public static function pageid( $parser, $title =
null ) {
1376 $t = self::makeTitle( $parser, $title );
1379 } elseif ( !$t->canExist() || $t->isExternal() ) {
1385 if ( $t->equals( $parser->
getTitle() ) ) {
1388 $parserOutput->setOutputFlag( ParserOutputFlags::VARY_PAGE_ID );
1389 $id = $parser->
getTitle()->getArticleID();
1391 $parserOutput->setSpeculativePageIdUsed( $id );
1398 $linkCache = MediaWikiServices::getInstance()->getLinkCache();
1399 $pdbk = $t->getPrefixedDBkey();
1400 $id = $linkCache->getGoodLinkID( $pdbk );
1401 if ( $id != 0 || $linkCache->isBadLink( $pdbk ) ) {
1402 $parserOutput->addLink( $t, $id );
1409 $id = $t->getArticleID();
1410 $parserOutput->addLink( $t, $id );
1426 $t = self::makeTitle( $parser, $title );
1427 if ( $t ===
null || $t->isExternal() ) {
1431 $services = MediaWikiServices::getInstance();
1433 $t->equals( $parser->
getTitle() ) &&
1434 $services->getMainConfig()->get( MainConfigNames::MiserMode ) &&
1435 !$parser->
getOptions()->getInterfaceMessage() &&
1437 $services->getNamespaceInfo()->isSubject( $t->getNamespace() )
1444 $parser->
getOutput()->setOutputFlag( ParserOutputFlags::VARY_REVISION_EXISTS );
1452 if ( $t->equals( $parser->
getTitle() ) && $title ===
null ) {
1455 $parser->
getOutput()->setOutputFlag( ParserOutputFlags::VARY_REVISION_ID );
1460 $id = $rev->getId();
1464 $id = $parser->
getOptions()->getSpeculativeRevId();
1466 $parser->
getOutput()->setSpeculativeRevIdUsed( $id );
1471 $rev = self::getCachedRevisionObject( $parser, $t, ParserOutputFlags::VARY_REVISION_ID );
1472 return $rev ? $rev->getId() :
'';
1475 private static function getRevisionTimestampSubstring(
1488 if ( $title->equals( $parser->
getTitle() ) && !$parser->getOptions()->getInterfaceMessage() ) {
1503 if ( $resNow !== $resThen ) {
1506 $parser->
getOutput()->setOutputFlag( ParserOutputFlags::VARY_REVISION_TIMESTAMP );
1512 $rev = self::getCachedRevisionObject( $parser, $title, ParserOutputFlags::VARY_REVISION_TIMESTAMP );
1531 $t = self::makeTitle( $parser, $title );
1532 if ( $t ===
null || $t->isExternal() ) {
1535 return strval( (
int)self::getRevisionTimestampSubstring(
1536 $parser, $t, 6, 2, self::MAX_TTS
1548 $t = self::makeTitle( $parser, $title );
1549 if ( $t ===
null || $t->isExternal() ) {
1552 return self::getRevisionTimestampSubstring(
1553 $parser, $t, 6, 2, self::MAX_TTS
1565 $t = self::makeTitle( $parser, $title );
1566 if ( $t ===
null || $t->isExternal() ) {
1569 return self::getRevisionTimestampSubstring(
1570 $parser, $t, 4, 2, self::MAX_TTS
1582 $t = self::makeTitle( $parser, $title );
1583 if ( $t ===
null || $t->isExternal() ) {
1586 return strval( (
int)self::getRevisionTimestampSubstring(
1587 $parser, $t, 4, 2, self::MAX_TTS
1599 $t = self::makeTitle( $parser, $title );
1600 if ( $t ===
null || $t->isExternal() ) {
1603 return self::getRevisionTimestampSubstring(
1604 $parser, $t, 0, 4, self::MAX_TTS
1616 $t = self::makeTitle( $parser, $title );
1617 if ( $t ===
null || $t->isExternal() ) {
1620 return self::getRevisionTimestampSubstring(
1621 $parser, $t, 0, 14, self::MAX_TTS
1633 $t = self::makeTitle( $parser, $title );
1634 if ( $t ===
null || $t->isExternal() ) {
1640 if ( $t->equals( $parser->
getTitle() ) ) {
1642 $parser->
getOutput()->setOutputFlag( ParserOutputFlags::VARY_USER );
1649 $rev = self::getCachedRevisionObject( $parser, $t, ParserOutputFlags::VARY_USER );
1650 $user = ( $rev !== null ) ? $rev->getUser() :
null;
1651 return $user ? $user->getName() :
'';
1667 $titleObject = Title::newFromText( $title ) ?? $parser->
getTitle();
1668 $restrictionStore = MediaWikiServices::getInstance()->getRestrictionStore();
1669 if ( $restrictionStore->areCascadeProtectionSourcesLoaded( $titleObject )
1673 $sources = $restrictionStore->getCascadeProtectionSources( $titleObject );
1674 $titleFormatter = MediaWikiServices::getInstance()->getTitleFormatter();
1675 foreach ( $sources[0] as $sourcePageIdentity ) {
1676 $names[] = $titleFormatter->getPrefixedText( $sourcePageIdentity );
1678 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 bcp47(Parser $parser, string $code='')
Gives the BCP-47 code for a language given the mediawiki internal language code.
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 dir(Parser $parser, string $code='', string $arg='')
Gives direction of script of a language given a language code.
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.