26use InvalidArgumentException;
41use Wikimedia\Bcp47Code\Bcp47CodeValue;
42use Wikimedia\RemexHtml\Tokenizer\Attributes;
43use Wikimedia\RemexHtml\Tokenizer\PlainAttributes;
51 private const MAX_TTS = 900;
70 $options->assertRequiredOptions( self::REGISTER_OPTIONS );
74 # Syntax for arguments (see Parser::setFunctionHook):
75 # "name for lookup in localized magic words array",
77 # optional Parser::SFH_NO_HASH to omit the hash from calls (e.g. {{int:...}}
78 # instead of {{#int:...}})
80 'ns',
'nse',
'urlencode',
'lcfirst',
'ucfirst',
'lc',
'uc',
81 'localurl',
'localurle',
'fullurl',
'fullurle',
'canonicalurl',
82 'canonicalurle',
'formatnum',
'grammar',
'gender',
'plural',
'formal',
83 'bidi',
'numberingroup',
'language',
84 'padleft',
'padright',
'anchorencode',
'defaultsort',
'filepath',
85 'pagesincategory',
'pagesize',
'protectionlevel',
'protectionexpiry',
86 # The following are the "parser function" forms of magic
87 # variables defined in CoreMagicVariables. The no-args form will
88 # go through the magic variable code path (and be cached); the
89 # presence of arguments will cause the parser function form to
90 # be invoked. (Note that the actual implementation will pass
91 # a Parser object as first argument, in addition to the
92 # parser function parameters.)
94 # For this group, the first parameter to the parser function is
95 # "page title", and the no-args form (and the magic variable)
96 # defaults to "current page title".
97 'pagename',
'pagenamee',
98 'fullpagename',
'fullpagenamee',
99 'subpagename',
'subpagenamee',
100 'rootpagename',
'rootpagenamee',
101 'basepagename',
'basepagenamee',
102 'talkpagename',
'talkpagenamee',
103 'subjectpagename',
'subjectpagenamee',
104 'pageid',
'revisionid',
'revisionday',
105 'revisionday2',
'revisionmonth',
'revisionmonth1',
'revisionyear',
109 'namespace',
'namespacee',
'namespacenumber',
'talkspace',
'talkspacee',
110 'subjectspace',
'subjectspacee',
112 # More parser functions corresponding to CoreMagicVariables.
113 # For this group, the first parameter to the parser function is
114 # "raw" (uses the 'raw' format if present) and the no-args form
115 # (and the magic variable) defaults to 'not raw'.
116 'numberofarticles',
'numberoffiles',
118 'numberofactiveusers',
123 # These magic words already contain the hash, and the no-args form
124 # is the same as passing an empty first argument
128 foreach ( $noHashFunctions as $func ) {
138 if ( $allowDisplayTitle ) {
141 [ __CLASS__,
'displaytitle' ],
145 if ( $allowSlowParserFunctions ) {
148 [ __CLASS__,
'pagesinnamespace' ],
161 if ( strval( $part1 ) !==
'' ) {
163 ->inLanguage( $parser->
getOptions()->getUserLangObj() );
164 return [ $message->plain(),
'noparse' => false ];
166 return [
'found' => false ];
177 public static function formatDate( $parser, $date, $defaultPref =
null ) {
181 $date = trim( $date );
183 $pref = $parser->
getOptions()->getDateFormat();
187 if ( $pref ==
'default' && $defaultPref ) {
188 $pref = $defaultPref;
191 $date = $df->reformat( $pref, $date, [
'match-whole' ] );
195 public static function ns( $parser, $part1 =
'' ) {
196 if ( intval( $part1 ) || $part1 ==
"0" ) {
197 $index = intval( $part1 );
199 $index = $parser->
getContentLanguage()->getNsIndex( str_replace(
' ',
'_', $part1 ) );
201 if ( $index !==
false ) {
204 return [
'found' => false ];
208 public static function nse( $parser, $part1 =
'' ) {
209 $ret = self::ns( $parser, $part1 );
210 if ( is_string( $ret ) ) {
211 $ret =
wfUrlencode( str_replace(
' ',
'_', $ret ) );
228 public static function urlencode( $parser, $s =
'', $arg =
null ) {
234 switch (
$magicWords->matchStartToEnd( $arg ??
'' ) ) {
237 $func =
'wfUrlencode';
238 $s = str_replace(
' ',
'_', $s );
243 $func =
'rawurlencode';
256 public static function lcfirst( $parser, $s =
'' ) {
260 public static function ucfirst( $parser, $s =
'' ) {
269 public static function lc( $parser, $s =
'' ) {
278 public static function uc( $parser, $s =
'' ) {
282 public static function localurl( $parser, $s =
'', $arg =
null ) {
283 return self::urlFunction(
'getLocalURL', $s, $arg );
286 public static function localurle( $parser, $s =
'', $arg =
null ) {
287 $temp = self::urlFunction(
'getLocalURL', $s, $arg );
288 if ( !is_string( $temp ) ) {
291 return htmlspecialchars( $temp, ENT_COMPAT );
295 public static function fullurl( $parser, $s =
'', $arg =
null ) {
296 return self::urlFunction(
'getFullURL', $s, $arg );
299 public static function fullurle( $parser, $s =
'', $arg =
null ) {
300 $temp = self::urlFunction(
'getFullURL', $s, $arg );
301 if ( !is_string( $temp ) ) {
304 return htmlspecialchars( $temp, ENT_COMPAT );
309 return self::urlFunction(
'getCanonicalURL', $s, $arg );
313 $temp = self::urlFunction(
'getCanonicalURL', $s, $arg );
314 if ( !is_string( $temp ) ) {
317 return htmlspecialchars( $temp, ENT_COMPAT );
321 public static function urlFunction( $func, $s =
'', $arg =
null ) {
322 # Due to order of execution of a lot of bits, the values might be encoded
323 # before arriving here; if that's true, then the title can't be created
324 # and the variable will fail. If we can't get a decent title from the first
325 # attempt, url-decode and try for a second.
326 $title = Title::newFromText( $s ) ?? Title::newFromURL( urldecode( $s ) );
327 if ( $title !==
null ) {
328 # Convert NS_MEDIA -> NS_FILE
332 if ( $arg !==
null ) {
333 $text = $title->$func( $arg );
335 $text = $title->$func();
339 return [
'found' => false ];
349 public static function formatnum( $parser, $num =
'', $arg =
null ) {
356 $func = self::getLegacyFormatNum( $parser, $func );
359 $func = self::getLegacyFormatNum( $parser, $func );
370 private static function getLegacyFormatNum( $parser, $callback ) {
375 return static function ( $number ) use ( $parser, $callback ) {
376 $validNumberRe =
'(-(?=[\d\.]))?(\d+|(?=\.\d))(\.\d*)?([Ee][-+]?\d+)?';
378 !is_numeric( $number ) &&
379 $number !== (string)NAN &&
380 $number !== (
string)INF &&
381 $number !== (string)-INF
386 return preg_replace_callback(
"/{$validNumberRe}/",
static function ( $m ) use ( $callback ) {
387 return call_user_func( $callback, $m[0] );
390 return call_user_func( $callback, $number );
400 public static function grammar( $parser, $case =
'', $word =
'' ) {
411 public static function gender( $parser, $username, ...$forms ) {
413 if ( count( $forms ) === 0 ) {
415 } elseif ( count( $forms ) === 1 ) {
419 $username = trim( $username );
425 $title = Title::newFromText( $username,
NS_USER );
432 $user = User::newFromName( $username );
435 $gender = $genderCache->getGenderOf( $user, __METHOD__ );
436 } elseif ( $username ===
'' && $parser->
getOptions()->getInterfaceMessage() ) {
437 $gender = $genderCache->getGenderOf( $parser->
getOptions()->getUserIdentity(), __METHOD__ );
449 public static function plural( $parser, $text =
'', ...$forms ) {
451 settype( $text, ctype_digit( $text ) ?
'int' :
'float' );
456 public static function formal(
Parser $parser,
string ...$forms ): string {
457 $index = $parser->getTargetLanguage()->getFormalityIndex();
458 return $forms[$index] ?? $forms[0];
466 public static function bidi( $parser, $text =
'' ) {
479 public static function displaytitle( $parser, $text =
'', $uarg =
'' ) {
486 [
'displaytitle_noerror',
'displaytitle_noreplace' ] );
499 $bad = [
'h1',
'h2',
'h3',
'h4',
'h5',
'h6',
'div',
'blockquote',
'ol',
'ul',
'li',
'hr',
500 'table',
'tr',
'th',
'td',
'dl',
'dd',
'caption',
'p',
'ruby',
'rb',
'rt',
'rtc',
'rp',
'br' ];
503 if ( $restrictDisplayTitle ) {
506 $htmlTagsCallback =
static function ( Attributes $attr ): Attributes {
507 $decoded = $attr->getValues();
509 if ( isset( $decoded[
'style'] ) ) {
514 if ( preg_match(
'/(display|user-select|visibility)\s*:/i', $decoded[
'style'] ) ) {
515 $decoded[
'style'] =
'/* attempt to bypass $wgRestrictDisplayTitle */';
519 return new PlainAttributes( $decoded );
522 $htmlTagsCallback =
null;
529 'attrCallback' => $htmlTagsCallback,
530 'removeTags' => $bad,
536 if ( !$restrictDisplayTitle ||
537 ( $title instanceof
Title
541 $old = $parser->
getOutput()->getPageProperty(
'displaytitle' );
542 if ( $old ===
null || $arg !==
'displaytitle_noreplace' ) {
543 $parser->
getOutput()->setDisplayTitle( $text );
545 if ( $old !==
null && $old !== $text && !$arg ) {
548 return '<span class="error">' .
549 $parser->
msg(
'duplicate-displaytitle',
560 'restricted-displaytitle',
577 private static function matchAgainstMagicword(
580 $value = trim( strval( $value ) );
581 if ( $value ===
'' ) {
584 $mwObject = $magicWordFactory->
get( $magicword );
585 return $mwObject->matchStartToEnd( $value );
600 if ( $raw !==
null && $raw !==
'' ) {
601 if ( !$magicWordFactory ) {
604 if ( self::matchAgainstMagicword( $magicWordFactory,
'rawsuffix', $raw ) ) {
608 return $language->formatNum( $num );
612 return self::formatRaw( SiteStats::pages(), $raw, $parser->
getTargetLanguage() );
616 return self::formatRaw( SiteStats::users(), $raw, $parser->
getTargetLanguage() );
620 return self::formatRaw( SiteStats::activeUsers(), $raw, $parser->
getTargetLanguage() );
624 return self::formatRaw( SiteStats::articles(), $raw, $parser->
getTargetLanguage() );
628 return self::formatRaw( SiteStats::images(), $raw, $parser->
getTargetLanguage() );
632 return self::formatRaw(
633 SiteStats::numberingroup(
'sysop' ),
640 return self::formatRaw( SiteStats::edits(), $raw, $parser->
getTargetLanguage() );
644 return self::formatRaw(
645 SiteStats::pagesInNs( intval( $namespace ) ),
652 return self::formatRaw(
653 SiteStats::numberingroup( strtolower( $name ) ),
667 private static function makeTitle(
Parser $parser, ?
string $t ) {
672 $title = Title::newFromText( $t );
685 public static function namespace( $parser, $title = null ) {
686 $t = self::makeTitle( $parser, $title );
690 return str_replace(
'_',
' ', $t->getNsText() );
693 public static function namespacee( $parser, $title =
null ) {
694 $t = self::makeTitle( $parser, $title );
702 $t = self::makeTitle( $parser, $title );
706 return (
string)$t->getNamespace();
709 public static function talkspace( $parser, $title =
null ) {
710 $t = self::makeTitle( $parser, $title );
711 if ( $t ===
null || !$t->canHaveTalkPage() ) {
714 return str_replace(
'_',
' ', $t->getTalkNsText() );
717 public static function talkspacee( $parser, $title =
null ) {
718 $t = self::makeTitle( $parser, $title );
719 if ( $t ===
null || !$t->canHaveTalkPage() ) {
726 $t = self::makeTitle( $parser, $title );
730 return str_replace(
'_',
' ', $t->getSubjectNsText() );
734 $t = self::makeTitle( $parser, $title );
748 public static function pagename( $parser, $title =
null ) {
749 $t = self::makeTitle( $parser, $title );
756 public static function pagenamee( $parser, $title =
null ) {
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 );
829 $t = self::makeTitle( $parser, $title );
830 if ( $t ===
null || !$t->canHaveTalkPage() ) {
837 $t = self::makeTitle( $parser, $title );
838 if ( $t ===
null || !$t->canHaveTalkPage() ) {
845 $t = self::makeTitle( $parser, $title );
853 $t = self::makeTitle( $parser, $title );
870 public static function pagesincategory( $parser, $name =
'', $arg1 =
'', $arg2 =
'' ) {
874 'pagesincategory_all',
875 'pagesincategory_pages',
876 'pagesincategory_subcats',
877 'pagesincategory_files'
893 $type =
'pagesincategory_all';
896 $title = Title::makeTitleSafe(
NS_CATEGORY, $name );
897 if ( !$title ) { # invalid title
901 ->getLanguageConverterFactory()
903 $languageConverter->findVariantLink( $name, $title,
true );
906 $name = $title->getDBkey();
908 if ( !isset( $cache[$name] ) ) {
909 $category = Category::newFromTitle( $title );
911 $allCount = $subcatCount = $fileCount = $pageCount = 0;
913 $allCount = $category->getMemberCount();
914 $subcatCount = $category->getSubcatCount();
915 $fileCount = $category->getFileCount();
916 $pageCount = $category->getPageCount( Category::COUNT_CONTENT_PAGES );
918 $cache[$name][
'pagesincategory_all'] = $allCount;
919 $cache[$name][
'pagesincategory_pages'] = $pageCount;
920 $cache[$name][
'pagesincategory_subcats'] = $subcatCount;
921 $cache[$name][
'pagesincategory_files'] = $fileCount;
924 $count = $cache[$name][$type];
937 public static function pagesize( $parser, $page =
'', $raw =
null ) {
938 $title = Title::newFromText( $page );
940 if ( !is_object( $title ) || $title->isExternal() ) {
945 $rev = self::getCachedRevisionObject( $parser, $title, ParserOutputFlags::VARY_REVISION_SHA1 );
946 $length = $rev ? $rev->getSize() : 0;
947 if ( $length ===
null ) {
967 $titleObject = Title::newFromText( $title ) ?? $parser->
getTitle();
970 $restrictions = $restrictionStore->getRestrictions( $titleObject, strtolower( $type ) );
971 # RestrictionStore::getRestrictions returns an array, its possible it may have
972 # multiple values in the future
973 return implode(
',', $restrictions );
991 $titleObject = Title::newFromText( $title ) ?? $parser->
getTitle();
996 return $restrictionStore->getRestrictionExpiry( $titleObject, strtolower( $type ) ) ??
'';
1009 public static function language( $parser, $code =
'', $inLanguage =
'' ) {
1010 if ( $code ===
'' ) {
1013 if ( $inLanguage ===
'' ) {
1014 $inLanguage = LanguageNameUtils::AUTONYMS;
1017 ->getLanguageNameUtils()
1018 ->getLanguageName( $code, $inLanguage );
1019 return $lang !==
'' ? $lang : LanguageCode::bcp47( $code );
1033 public static function dir(
Parser $parser,
string $code =
'',
string $arg =
'' ): string {
1037 if ( $code ===
'' ) {
1040 if ( $arg !==
'' ) {
1044 if (
$magicWords->matchStartToEnd( $arg ) ===
'language_option_bcp47' ) {
1046 $code =
new Bcp47CodeValue( $code );
1050 $lang = $languageFactory->getLanguage( $code );
1051 }
catch ( InvalidArgumentException $ex ) {
1056 return $lang->getDir();
1067 public static function bcp47(
Parser $parser,
string $code =
'' ): string {
1068 if ( $code ===
'' ) {
1071 return LanguageCode::bcp47( $code );
1085 $parser, $string, $length, $padding =
'0', $direction = STR_PAD_RIGHT
1088 $lengthOfPadding = mb_strlen( $padding );
1089 if ( $lengthOfPadding == 0 ) {
1093 # The remaining length to add counts down to 0 as padding is added
1094 $length = min( (
int)$length, 500 ) - mb_strlen( $string );
1095 if ( $length <= 0 ) {
1100 # $finalPadding is just $padding repeated enough times so that
1101 # mb_strlen( $string ) + mb_strlen( $finalPadding ) == $length
1103 while ( $length > 0 ) {
1104 # If $length < $lengthofPadding, truncate $padding so we get the
1105 # exact length desired.
1106 $finalPadding .= mb_substr( $padding, 0, $length );
1107 $length -= $lengthOfPadding;
1110 if ( $direction == STR_PAD_LEFT ) {
1111 return $finalPadding . $string;
1113 return $string . $finalPadding;
1117 public static function padleft( $parser, $string =
'', $length = 0, $padding =
'0' ) {
1118 return self::pad( $parser, $string, $length, $padding, STR_PAD_LEFT );
1121 public static function padright( $parser, $string =
'', $length = 0, $padding =
'0' ) {
1122 return self::pad( $parser, $string, $length, $padding );
1133 return Sanitizer::safeEncodeAttribute( $section );
1136 public static function special( $parser, $text ) {
1137 [ $page, $subpage ] = MediaWikiServices::getInstance()->getSpecialPageFactory()->
1138 resolveAlias( $text );
1140 $title = SpecialPage::getTitleFor( $page, $subpage );
1141 return $title->getPrefixedText();
1144 $title = Title::makeTitleSafe(
NS_SPECIAL, $text );
1145 return $title ? $title->getPrefixedText() : self::special( $parser,
'Badtitle' );
1150 return wfUrlencode( str_replace(
' ',
'_', self::special( $parser, $text ) ) );
1165 [
'defaultsort_noerror',
'defaultsort_noreplace' ] );
1169 $text = trim( $text );
1170 if ( strlen( $text ) == 0 ) {
1173 $old = $parser->
getOutput()->getPageProperty(
'defaultsort' );
1174 if ( $old ===
null || $arg !==
'defaultsort_noreplace' ) {
1175 $parser->
getOutput()->setPageProperty(
'defaultsort', $text );
1178 if ( $old ===
null || $old == $text || $arg ) {
1182 return '<span class="error">' .
1183 $parser->
msg(
'duplicate-defaultsort',
1203 public static function filepath( $parser, $name =
'', $argA =
'', $argB =
'' ) {
1204 $file = MediaWikiServices::getInstance()->getRepoGroup()->findFile( $name );
1206 if ( $argA ==
'nowiki' ) {
1213 $isNowiki = ( $argB ==
'nowiki' );
1217 $url = $file->getFullUrl();
1220 if ( count( $parsedWidthParam ) ) {
1221 $mto = $file->transform( $parsedWidthParam );
1223 if ( $mto && !$mto->isError() ) {
1225 $urlUtils = MediaWikiServices::getInstance()->getUrlUtils();
1230 return [
$url,
'nowiki' => true ];
1245 public static function tagObj( $parser, $frame, $args ) {
1246 if ( !count( $args ) ) {
1249 $tagName = strtolower( trim( $frame->expand( array_shift( $args ) ) ) );
1252 if ( count( $args ) ) {
1253 $inner = $frame->expand( array_shift( $args ), $processNowiki );
1259 foreach ( $args as $arg ) {
1260 $bits = $arg->splitArg();
1261 if ( strval( $bits[
'index'] ) ===
'' ) {
1262 $name = trim( $frame->expand( $bits[
'name'], PPFrame::STRIP_COMMENTS ) );
1263 $value = trim( $frame->expand( $bits[
'value'] ) );
1264 if ( preg_match(
'/^(?:["\'](.+)["\']|""|\'\')$/s', $value, $m ) ) {
1265 $value = $m[1] ??
'';
1267 $attributes[$name] = $value;
1272 if ( !in_array( $tagName, $stripList ) ) {
1275 foreach ( $attributes as $name => $value ) {
1276 $attrText .=
' ' . htmlspecialchars( $name ) .
1277 '="' . htmlspecialchars( $value, ENT_COMPAT ) .
'"';
1279 if ( $inner ===
null ) {
1280 return "<$tagName$attrText/>";
1282 return "<$tagName$attrText>$inner</$tagName>";
1288 'attributes' => $attributes,
1289 'close' =>
"</$tagName>",
1307 private static function getCachedRevisionObject( $parser, $title, $vary ) {
1312 $revisionRecord =
null;
1314 $isSelfReferential = $title->equals( $parser->
getTitle() );
1315 if ( $isSelfReferential ) {
1326 if ( $parserRevisionRecord && $parserRevisionRecord->isCurrent() ) {
1327 $revisionRecord = $parserRevisionRecord;
1332 if ( !$revisionRecord ) {
1341 if ( !$revisionRecord ) {
1343 $revisionRecord =
null;
1346 $parserOutput->addTemplate(
1348 $revisionRecord ? $revisionRecord->getPageId() : 0,
1349 $revisionRecord ? $revisionRecord->getId() : 0
1353 if ( $isSelfReferential ) {
1354 wfDebug( __METHOD__ .
": used current revision, setting $vary" );
1356 $parserOutput->setOutputFlag( $vary );
1357 if ( $vary === ParserOutputFlags::VARY_REVISION_SHA1 && $revisionRecord ) {
1359 $sha1 = $revisionRecord->getSha1();
1360 }
catch ( RevisionAccessException $e ) {
1363 $parserOutput->setRevisionUsedSha1Base36( $sha1 );
1367 return $revisionRecord;
1377 public static function pageid( $parser, $title =
null ) {
1378 $t = self::makeTitle( $parser, $title );
1381 } elseif ( !$t->canExist() || $t->isExternal() ) {
1387 if ( $t->equals( $parser->
getTitle() ) ) {
1390 $parserOutput->setOutputFlag( ParserOutputFlags::VARY_PAGE_ID );
1391 $id = $parser->
getTitle()->getArticleID();
1393 $parserOutput->setSpeculativePageIdUsed( $id );
1400 $linkCache = MediaWikiServices::getInstance()->getLinkCache();
1401 $pdbk = $t->getPrefixedDBkey();
1402 $id = $linkCache->getGoodLinkID( $pdbk );
1403 if ( $id != 0 || $linkCache->isBadLink( $pdbk ) ) {
1404 $parserOutput->addLink( $t, $id );
1411 $id = $t->getArticleID();
1412 $parserOutput->addLink( $t, $id );
1428 $t = self::makeTitle( $parser, $title );
1429 if ( $t ===
null || $t->isExternal() ) {
1433 $services = MediaWikiServices::getInstance();
1435 $t->equals( $parser->
getTitle() ) &&
1436 $services->getMainConfig()->get( MainConfigNames::MiserMode ) &&
1437 !$parser->
getOptions()->getInterfaceMessage() &&
1439 $services->getNamespaceInfo()->isSubject( $t->getNamespace() )
1446 $parser->
getOutput()->setOutputFlag( ParserOutputFlags::VARY_REVISION_EXISTS );
1454 if ( $t->equals( $parser->
getTitle() ) && $title ===
null ) {
1457 $parser->
getOutput()->setOutputFlag( ParserOutputFlags::VARY_REVISION_ID );
1462 $id = $rev->getId();
1466 $id = $parser->
getOptions()->getSpeculativeRevId();
1468 $parser->
getOutput()->setSpeculativeRevIdUsed( $id );
1473 $rev = self::getCachedRevisionObject( $parser, $t, ParserOutputFlags::VARY_REVISION_ID );
1474 return $rev ? $rev->getId() :
'';
1477 private static function getRevisionTimestampSubstring(
1490 if ( $title->equals( $parser->
getTitle() ) && !$parser->getOptions()->getInterfaceMessage() ) {
1505 if ( $resNow !== $resThen ) {
1508 $parser->
getOutput()->setOutputFlag( ParserOutputFlags::VARY_REVISION_TIMESTAMP );
1514 $rev = self::getCachedRevisionObject( $parser, $title, ParserOutputFlags::VARY_REVISION_TIMESTAMP );
1533 $t = self::makeTitle( $parser, $title );
1534 if ( $t ===
null || $t->isExternal() ) {
1537 return strval( (
int)self::getRevisionTimestampSubstring(
1538 $parser, $t, 6, 2, self::MAX_TTS
1550 $t = self::makeTitle( $parser, $title );
1551 if ( $t ===
null || $t->isExternal() ) {
1554 return self::getRevisionTimestampSubstring(
1555 $parser, $t, 6, 2, self::MAX_TTS
1567 $t = self::makeTitle( $parser, $title );
1568 if ( $t ===
null || $t->isExternal() ) {
1571 return self::getRevisionTimestampSubstring(
1572 $parser, $t, 4, 2, self::MAX_TTS
1584 $t = self::makeTitle( $parser, $title );
1585 if ( $t ===
null || $t->isExternal() ) {
1588 return strval( (
int)self::getRevisionTimestampSubstring(
1589 $parser, $t, 4, 2, self::MAX_TTS
1601 $t = self::makeTitle( $parser, $title );
1602 if ( $t ===
null || $t->isExternal() ) {
1605 return self::getRevisionTimestampSubstring(
1606 $parser, $t, 0, 4, self::MAX_TTS
1618 $t = self::makeTitle( $parser, $title );
1619 if ( $t ===
null || $t->isExternal() ) {
1622 return self::getRevisionTimestampSubstring(
1623 $parser, $t, 0, 14, self::MAX_TTS
1635 $t = self::makeTitle( $parser, $title );
1636 if ( $t ===
null || $t->isExternal() ) {
1642 if ( $t->equals( $parser->
getTitle() ) ) {
1644 $parser->
getOutput()->setOutputFlag( ParserOutputFlags::VARY_USER );
1651 $rev = self::getCachedRevisionObject( $parser, $t, ParserOutputFlags::VARY_USER );
1652 $user = ( $rev !== null ) ? $rev->getUser() :
null;
1653 return $user ? $user->getName() :
'';
1669 $titleObject = Title::newFromText( $title ) ?? $parser->
getTitle();
1670 $restrictionStore = MediaWikiServices::getInstance()->getRestrictionStore();
1671 if ( $restrictionStore->areCascadeProtectionSourcesLoaded( $titleObject )
1675 $sources = $restrictionStore->getCascadeProtectionSources( $titleObject );
1676 $titleFormatter = MediaWikiServices::getInstance()->getTitleFormatter();
1677 foreach ( $sources[0] as $sourcePageIdentity ) {
1678 $names[] = $titleFormatter->getPrefixedText( $sourcePageIdentity );
1680 return implode(
'|', $names );
1687class_alias( CoreParserFunctions::class,
'CoreParserFunctions' );
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,...
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'))
A class containing constants representing the names of configuration variables.
const AllowSlowParserFunctions
Name constant for the AllowSlowParserFunctions setting, for use with Config::get()
const AllowDisplayTitle
Name constant for the AllowDisplayTitle setting, for use with Config::get()
const RestrictDisplayTitle
Name constant for the RestrictDisplayTitle setting, for use with Config::get()
Parent class for all special pages.