27use Wikimedia\Assert\Assert;
199 return MediaWikiServices::getInstance()->getTitleFormatter();
211 return MediaWikiServices::getInstance()->getInterwikiLookup();
230 $t->mDbkeyform = $key;
233 $t->secureAndSplit();
254 return self::newFromLinkTarget( $titleValue, $forceClone );
269 if ( $linkTarget instanceof
Title ) {
271 if ( $forceClone === self::NEW_CLONE ) {
272 return clone $linkTarget;
277 return self::makeTitle(
293 return $linkTarget ? self::newFromLinkTarget( $linkTarget ) :
null;
318 if ( $text !==
null && !is_string( $text ) && !is_int( $text ) ) {
319 throw new InvalidArgumentException(
'$text must be a string.' );
321 if ( $text ===
null ) {
326 return self::newFromTextThrow( (
string)$text, $defaultNamespace );
354 if ( is_object( $text ) ) {
355 throw new MWException(
'$text must be a string, given an object' );
356 } elseif ( $text ===
null ) {
368 if ( $defaultNamespace ==
NS_MAIN ) {
376 $filteredText = Sanitizer::decodeCharReferencesAndNormalize( $text );
379 $t->mDbkeyform = strtr( $filteredText,
' ',
'_' );
380 $t->mDefaultNamespace = (int)$defaultNamespace;
382 $t->secureAndSplit();
383 if ( $defaultNamespace ==
NS_MAIN ) {
407 # For compatibility with old buggy URLs. "+" is usually not valid in titles,
408 # but some URLs used it as a space replacement and they still come
409 # from some external search tools.
410 if ( strpos( self::legalChars(),
'+' ) ===
false ) {
411 $url = strtr( $url,
'+',
' ' );
414 $t->mDbkeyform = strtr( $url,
' ',
'_' );
417 $t->secureAndSplit();
428 if ( self::$titleCache ===
null ) {
429 self::$titleCache =
new MapCacheLRU( self::CACHE_MAX );
431 return self::$titleCache;
445 'page_namespace',
'page_title',
'page_id',
446 'page_len',
'page_is_redirect',
'page_latest',
450 $fields[] =
'page_content_model';
454 $fields[] =
'page_lang';
468 $flags |= ( $flags & self::GAID_FOR_UPDATE ) ? self::READ_LATEST : 0;
469 list( $index, $options ) = DBAccessObjectUtils::getDBOptions( $flags );
470 $row =
wfGetDB( $index )->selectRow(
472 self::getSelectFields(),
473 [
'page_id' => $id ],
477 if ( $row !==
false ) {
478 $title = self::newFromRow( $row );
493 if ( !count( $ids ) ) {
500 self::getSelectFields(),
501 [
'page_id' => $ids ],
506 foreach (
$res as $row ) {
507 $titles[] = self::newFromRow( $row );
519 $t = self::makeTitle( $row->page_namespace, $row->page_title );
520 $t->loadFromRow( $row );
532 if ( isset( $row->page_id ) ) {
533 $this->mArticleID = (int)$row->page_id;
535 if ( isset( $row->page_len ) ) {
536 $this->mLength = (int)$row->page_len;
538 if ( isset( $row->page_is_redirect ) ) {
539 $this->mRedirect = (bool)$row->page_is_redirect;
541 if ( isset( $row->page_latest ) ) {
542 $this->mLatestID = (int)$row->page_latest;
544 if ( isset( $row->page_content_model ) ) {
549 if ( isset( $row->page_lang ) ) {
550 $this->mDbPageLanguage = (string)$row->page_lang;
552 if ( isset( $row->page_restrictions ) ) {
553 $this->mOldRestrictions = $row->page_restrictions;
556 $this->mArticleID = 0;
558 $this->mRedirect =
false;
559 $this->mLatestID = 0;
588 $t->mInterwiki = $interwiki;
589 $t->mFragment = $fragment;
590 $t->mNamespace = $ns = (int)$ns;
591 $t->mDbkeyform = strtr(
$title,
' ',
'_' );
592 $t->mArticleID = ( $ns >= 0 ) ? -1 : 0;
594 $t->mTextform = strtr(
$title,
'_',
' ' );
617 if ( !MediaWikiServices::getInstance()->getNamespaceInfo()->
exists( $ns ) ) {
622 $t->mDbkeyform = self::makeName( $ns,
$title, $fragment, $interwiki,
true );
625 $t->secureAndSplit();
651 $msg = $localizer->msg(
'mainpage' );
656 $title = self::newFromText( $msg->inContentLanguage()->text() );
663 $title = self::newFromText(
'Main Page' );
679 [
'page_namespace',
'page_title' ],
680 [
'page_id' => $id ],
683 if (
$s ===
false ) {
687 return self::makeName(
$s->page_namespace,
$s->page_title );
710 $length = strlen( $byteClass );
712 $x0 = $x1 = $x2 =
'';
714 $d0 = $d1 = $d2 =
'';
716 $ord0 = $ord1 = $ord2 = 0;
718 $r0 = $r1 = $r2 =
'';
722 $allowUnicode =
false;
723 for ( $pos = 0; $pos < $length; $pos++ ) {
734 $inChar = $byteClass[$pos];
735 if ( $inChar ==
'\\' ) {
736 if ( preg_match(
'/x([0-9a-fA-F]{2})/A', $byteClass, $m, 0, $pos + 1 ) ) {
737 $x0 = $inChar . $m[0];
738 $d0 = chr( hexdec( $m[1] ) );
739 $pos += strlen( $m[0] );
740 } elseif ( preg_match(
'/[0-7]{3}/A', $byteClass, $m, 0, $pos + 1 ) ) {
741 $x0 = $inChar . $m[0];
742 $d0 = chr( octdec( $m[0] ) );
743 $pos += strlen( $m[0] );
744 } elseif ( $pos + 1 >= $length ) {
747 $d0 = $byteClass[$pos + 1];
756 if ( $ord0 < 32 || $ord0 == 0x7f ) {
757 $r0 = sprintf(
'\x%02x', $ord0 );
758 } elseif ( $ord0 >= 0x80 ) {
760 $r0 = sprintf(
'\x%02x', $ord0 );
761 $allowUnicode =
true;
763 } elseif ( strpos(
'-\\[]^', $d0 ) !==
false ) {
769 if ( $x0 !==
'' && $x1 ===
'-' && $x2 !==
'' ) {
771 if ( $ord2 > $ord0 ) {
773 } elseif ( $ord0 >= 0x80 ) {
775 $allowUnicode =
true;
776 if ( $ord2 < 0x80 ) {
785 $x0 = $x1 = $d0 = $d1 = $r0 = $r1 =
'';
786 } elseif ( $ord2 < 0x80 ) {
791 if ( $ord1 < 0x80 ) {
794 if ( $ord0 < 0x80 ) {
797 if ( $allowUnicode ) {
798 $out .=
'\u0080-\uFFFF';
815 $canonicalNamespace =
false
817 if ( $canonicalNamespace ) {
818 $namespace = MediaWikiServices::getInstance()->getNamespaceInfo()->
819 getCanonicalName( $ns );
821 $namespace = MediaWikiServices::getInstance()->getContentLanguage()->getNsText( $ns );
823 $name = $namespace ==
'' ?
$title :
"$namespace:$title";
824 if ( strval( $interwiki ) !=
'' ) {
825 $name =
"$interwiki:$name";
827 if ( strval( $fragment ) !=
'' ) {
828 $name .=
'#' . $fragment;
864 $services = MediaWikiServices::getInstance();
865 if ( !$services->getNamespaceInfo()->exists( $this->mNamespace ) ) {
870 $services->getTitleParser()->parseTitle( $this->mDbkeyform, $this->mNamespace );
883 }
catch ( InvalidArgumentException $ex ) {
899 $iw = self::getInterwikiLookup()->fetch( $this->mInterwiki );
901 return $iw->isLocal();
913 return $this->mInterwiki !==
'';
924 return $this->mInterwiki;
933 return $this->mLocalInterwiki;
947 return self::getInterwikiLookup()->fetch( $this->mInterwiki )->isTranscludable();
960 return self::getInterwikiLookup()->fetch( $this->mInterwiki )->getWikiID();
973 if ( $this->mTitleValue ===
null ) {
981 }
catch ( InvalidArgumentException $ex ) {
982 wfDebug( __METHOD__ .
': Can\'t create a TitleValue for [[' .
987 return $this->mTitleValue;
996 return $this->mTextform;
1005 return $this->mUrlform;
1014 return $this->mDbkeyform;
1024 if ( !is_null( $this->mUserCaseDBKey ) ) {
1025 return $this->mUserCaseDBKey;
1028 return $this->mDbkeyform;
1038 return $this->mNamespace;
1050 if ( $this->mForcedContentModel ) {
1051 if ( !$this->mContentModel ) {
1052 throw new RuntimeException(
'Got out of sync; an empty model is being forced' );
1055 return $this->mContentModel;
1058 if ( DBAccessObjectUtils::hasFlags( $flags, self::READ_LATEST ) ) {
1061 ( !$this->mContentModel || $flags & self::GAID_FOR_UPDATE ) &&
1064 $linkCache = MediaWikiServices::getInstance()->getLinkCache();
1065 $linkCache->addLinkObj( $this ); # in
case we already had an article ID
1069 if ( !$this->mContentModel ) {
1073 return $this->mContentModel;
1100 if ( (
string)$model ===
'' ) {
1101 throw new InvalidArgumentException(
"Missing CONTENT_MODEL_* constant" );
1104 $this->mContentModel = $model;
1105 $this->mForcedContentModel =
true;
1114 if ( !$this->mForcedContentModel ) {
1115 $this->mContentModel = ( $model === false ) ?
false : (string)$model;
1128 $nsText = MediaWikiServices::getInstance()->getNamespaceInfo()->
1129 getCanonicalName( $this->mNamespace );
1130 if ( $nsText !==
false ) {
1136 $formatter = self::getTitleFormatter();
1137 return $formatter->getNamespaceName( $this->mNamespace, $this->mDbkeyform );
1138 }
catch ( InvalidArgumentException $ex ) {
1139 wfDebug( __METHOD__ .
': ' . $ex->getMessage() .
"\n" );
1150 $services = MediaWikiServices::getInstance();
1151 return $services->getContentLanguage()->
1152 getNsText( $services->getNamespaceInfo()->getSubject( $this->mNamespace ) );
1161 $services = MediaWikiServices::getInstance();
1162 return $services->getContentLanguage()->
1163 getNsText( $services->getNamespaceInfo()->getTalk( $this->mNamespace ) );
1178 return MediaWikiServices::getInstance()->getNamespaceInfo()->canHaveTalkPage( $this );
1187 return $this->mNamespace >=
NS_MAIN;
1199 $nsInfo = MediaWikiServices::getInstance()->getNamespaceInfo();
1201 $nsInfo->isWatchable( $this->mNamespace );
1221 list( $thisName, ) =
1222 MediaWikiServices::getInstance()->getSpecialPageFactory()->
1223 resolveAlias( $this->mDbkeyform );
1224 if ( $name == $thisName ) {
1239 $spFactory = MediaWikiServices::getInstance()->getSpecialPageFactory();
1240 list( $canonicalName, $par ) = $spFactory->resolveAlias( $this->mDbkeyform );
1241 if ( $canonicalName ) {
1242 $localName = $spFactory->getLocalNameFor( $canonicalName, $par );
1243 if ( $localName != $this->mDbkeyform ) {
1244 return self::makeTitle(
NS_SPECIAL, $localName );
1262 return MediaWikiServices::getInstance()->getNamespaceInfo()->
1263 equals( $this->mNamespace, $ns );
1274 if ( count( $namespaces ) > 0 && is_array( $namespaces[0] ) ) {
1275 $namespaces = $namespaces[0];
1278 foreach ( $namespaces as $ns ) {
1301 return MediaWikiServices::getInstance()->getNamespaceInfo()->
1302 subjectEquals( $this->mNamespace, $ns );
1313 return MediaWikiServices::getInstance()->getNamespaceInfo()->
1314 isContent( $this->mNamespace );
1325 !MediaWikiServices::getInstance()->getNamespaceInfo()->
1333 Hooks::run(
'TitleIsMovable', [ $this, &$result ] );
1348 return $this->
equals( self::newMainPage() );
1357 return MediaWikiServices::getInstance()->getNamespaceInfo()->
1359 ? strpos( $this->
getText(),
'/' ) !== false
1372 strpos( $this->
getText(),
'Conversiontable/' ) === 0;
1427 $subpage = explode(
'/', $this->mTextform );
1428 $subpage = $subpage[count( $subpage ) - 1];
1429 $lastdot = strrpos( $subpage,
'.' );
1430 if ( $lastdot ===
false ) {
1431 return $subpage; # Never happens: only called
for names ending in
'.css'/
'.json'/
'.js'
1433 return substr( $subpage, 0, $lastdot );
1491 || substr( $this->mDbkeyform, -4 ) ===
'.css'
1509 || substr( $this->mDbkeyform, -5 ) ===
'.json'
1527 || substr( $this->mDbkeyform, -3 ) ===
'.js'
1554 return MediaWikiServices::getInstance()->getNamespaceInfo()->
1555 isTalk( $this->mNamespace );
1575 $talkNS = MediaWikiServices::getInstance()->getNamespaceInfo()->getTalk( $this->mNamespace );
1576 if ( $this->mNamespace == $talkNS ) {
1580 $title = self::makeTitle( $talkNS, $this->mDbkeyform );
1616 $subjectNS = MediaWikiServices::getInstance()->getNamespaceInfo()
1617 ->getSubject( $this->mNamespace );
1618 if ( $this->mNamespace == $subjectNS ) {
1624 $title = self::makeTitle( $subjectNS, $this->mDbkeyform );
1641 if ( $this->
getText() ==
'' ) {
1643 $method .
': called on empty title ' . $this->
getFullText() .
', returning '
1652 $method .
': called on interwiki title ' . $this->
getFullText() .
', returning '
1676 throw new MWException(
'Special pages cannot have other pages' );
1682 throw new MWException(
"{$this->getPrefixedText()} does not have an other page" );
1697 return $this->mDefaultNamespace;
1708 return $this->mFragment;
1718 return $this->mFragment !==
'';
1732 $interwiki = self::getInterwikiLookup()->fetch( $this->mInterwiki );
1733 if ( $interwiki && !$interwiki->isLocal() ) {
1734 return '#' . Sanitizer::escapeIdForExternalInterwiki( $this->mFragment );
1738 return '#' . Sanitizer::escapeIdForLink( $this->mFragment );
1754 $this->mFragment = strtr( substr( $fragment, 1 ),
'_',
' ' );
1765 return self::makeTitle(
1783 $p = $this->mInterwiki .
':';
1786 if ( $this->mNamespace != 0 ) {
1789 if ( $nsText ===
false ) {
1791 $nsText = MediaWikiServices::getInstance()->getContentLanguage()->
1795 $p .= $nsText .
':';
1807 $s = $this->
prefix( $this->mDbkeyform );
1808 $s = strtr(
$s,
' ',
'_' );
1819 if ( $this->prefixedText ===
null ) {
1820 $s = $this->
prefix( $this->mTextform );
1821 $s = strtr(
$s,
'_',
' ' );
1822 $this->prefixedText =
$s;
1824 return $this->prefixedText;
1845 $text .=
'#' . $this->mFragment;
1867 !MediaWikiServices::getInstance()->getNamespaceInfo()->
1869 || strtok( $this->
getText(),
'/' ) ===
false
1874 return strtok( $this->
getText(),
'/' );
1891 Assert::postcondition(
1893 'makeTitleSafe() should always return a Title for the text returned by getRootText().'
1915 !MediaWikiServices::getInstance()->getNamespaceInfo()->
1921 $lastSlashPos = strrpos( $text,
'/' );
1923 if ( $lastSlashPos ===
false ) {
1927 return substr( $text, 0, $lastSlashPos );
1944 Assert::postcondition(
1946 'makeTitleSafe() should always return a Title for the text returned by getBaseText().'
1964 !MediaWikiServices::getInstance()->getNamespaceInfo()->
1967 return $this->mTextform;
1969 $parts = explode(
'/', $this->mTextform );
1970 return $parts[count( $parts ) - 1];
1987 return self::makeTitleSafe(
1989 $this->
getText() .
'/' . $text,
2012 $s = $this->
prefix( $this->mDbkeyform );
2031 if ( $query2 !==
false ) {
2032 wfDeprecated(
"Title::get{Canonical,Full,Link,Local,Internal}URL " .
2033 "method called with a second parameter is deprecated. Add your " .
2034 "parameter to an array passed as the first parameter.",
"1.19" );
2036 if ( is_array( $query ) ) {
2040 if ( is_string( $query2 ) ) {
2069 $query = self::fixUrlQueryArgs( $query, $query2 );
2071 # Hand off all the decisions on urls to getLocalURL
2074 # Expand the url to make it a full url. Note that getLocalURL has the
2075 # potential to output full urls for a variety of reasons, so we use
2076 # wfExpandUrl instead of simply prepending $wgServer
2079 # Finally, add the fragment.
2083 Hooks::run(
'GetFullURL', [ &$titleRef, &$url, $query ] );
2106 $target = SpecialPage::getTitleFor(
2111 return $target->getFullURL( $query,
false, $proto );
2140 $query = self::fixUrlQueryArgs( $query, $query2 );
2142 $interwiki = self::getInterwikiLookup()->fetch( $this->mInterwiki );
2145 if ( $namespace !=
'' ) {
2146 # Can this actually happen? Interwikis shouldn't be parsed.
2147 # Yes! It can in interwiki transclusion. But... it probably shouldn't.
2150 $url = $interwiki->getURL( $namespace . $this->mDbkeyform );
2154 if ( $query ==
'' ) {
2158 Hooks::run(
'GetLocalURL::Article', [ &$titleRef, &$url ] );
2167 && preg_match(
'/^(.*&|)action=([^&]*)(&(.*)|)$/', $query,
$matches )
2169 $action = urldecode(
$matches[2] );
2170 if ( isset( $articlePaths[$action] ) ) {
2175 $url = str_replace(
'$1', $dbkey, $articlePaths[$action] );
2176 if ( $query !=
'' ) {
2184 && preg_match(
'/^variant=([^&]*)$/', $query,
$matches )
2186 MediaWikiServices::getInstance()->getContentLanguage() )
2189 $variant = urldecode(
$matches[1] );
2194 $url = str_replace(
'$1', $dbkey, $url );
2198 if ( $url ===
false ) {
2199 if ( $query ==
'-' ) {
2202 $url =
"{$wgScript}?title={$dbkey}&{$query}";
2207 Hooks::run(
'GetLocalURL::Internal', [ &$titleRef, &$url, $query ] );
2211 if (
$wgRequest->getVal(
'action' ) ==
'render' ) {
2222 Hooks::run(
'GetLocalURL', [ &$titleRef, &$url, $query ] );
2243 public function getLinkURL( $query =
'', $query2 =
false, $proto =
false ) {
2244 if ( $this->
isExternal() || $proto !==
false ) {
2245 $ret = $this->
getFullURL( $query, $query2, $proto );
2270 $query = self::fixUrlQueryArgs( $query, $query2 );
2275 Hooks::run(
'GetInternalURL', [ &$titleRef, &$url, $query ] );
2293 $query = self::fixUrlQueryArgs( $query, $query2 );
2297 Hooks::run(
'GetCanonicalURL', [ &$titleRef, &$url, $query ] );
2336 return $this->
userCan( $action, $user,
false );
2354 public function userCan( $action, $user =
null, $rigor = PermissionManager::RIGOR_SECURE ) {
2355 if ( !$user instanceof
User ) {
2361 if ( $rigor ===
true ) {
2362 $rigor = PermissionManager::RIGOR_SECURE;
2363 } elseif ( $rigor ===
false ) {
2364 $rigor = PermissionManager::RIGOR_QUICK;
2367 return MediaWikiServices::getInstance()->getPermissionManager()
2368 ->userCan( $action, $user, $this, $rigor );
2393 $action, $user, $rigor = PermissionManager::RIGOR_SECURE, $ignoreErrors = []
2396 if ( $rigor ===
true ) {
2397 $rigor = PermissionManager::RIGOR_SECURE;
2398 } elseif ( $rigor ===
false ) {
2399 $rigor = PermissionManager::RIGOR_QUICK;
2402 return MediaWikiServices::getInstance()->getPermissionManager()
2403 ->getPermissionErrors( $action, $user, $this, $rigor, $ignoreErrors );
2417 # Remove the create restriction for existing titles
2418 $types = array_diff( $types, [
'create' ] );
2420 # Only the create and upload restrictions apply to non-existing titles
2421 $types = array_intersect( $types, [
'create',
'upload' ] );
2436 $types = self::getFilteredRestrictionTypes( $this->
exists() );
2438 if ( $this->mNamespace !=
NS_FILE ) {
2439 # Remove the upload restriction for non-file titles
2440 $types = array_diff( $types, [
'upload' ] );
2443 Hooks::run(
'TitleGetRestrictionTypes', [ $this, &$types ] );
2445 wfDebug( __METHOD__ .
': applicable restrictions to [[' .
2446 $this->
getPrefixedText() .
']] are {' . implode(
',', $types ) .
"}\n" );
2460 if ( $protection ) {
2461 if ( $protection[
'permission'] ==
'sysop' ) {
2462 $protection[
'permission'] =
'editprotected';
2464 if ( $protection[
'permission'] ==
'autoconfirmed' ) {
2465 $protection[
'permission'] =
'editsemiprotected';
2483 if ( $this->mNamespace < 0 ) {
2492 if ( $this->mTitleProtection ===
null ) {
2494 $commentStore = CommentStore::getStore();
2495 $commentQuery = $commentStore->getJoin(
'pt_reason' );
2497 [
'protected_titles' ] + $commentQuery[
'tables'],
2499 'user' =>
'pt_user',
2500 'expiry' =>
'pt_expiry',
2501 'permission' =>
'pt_create_perm'
2502 ] + $commentQuery[
'fields'],
2503 [
'pt_namespace' => $this->mNamespace,
'pt_title' => $this->mDbkeyform ],
2506 $commentQuery[
'joins']
2512 $this->mTitleProtection = [
2513 'user' => $row[
'user'],
2514 'expiry' =>
$dbr->decodeExpiry( $row[
'expiry'] ),
2515 'permission' => $row[
'permission'],
2516 'reason' => $commentStore->getComment(
'pt_reason', $row )->text,
2519 $this->mTitleProtection =
false;
2522 return $this->mTitleProtection;
2533 [
'pt_namespace' => $this->mNamespace,
'pt_title' => $this->mDbkeyform ],
2536 $this->mTitleProtection =
false;
2551 if ( !$restrictions || !$semi ) {
2557 foreach ( array_keys( $semi,
'autoconfirmed' ) as $key ) {
2558 $semi[$key] =
'editsemiprotected';
2560 foreach ( array_keys( $restrictions,
'autoconfirmed' ) as $key ) {
2561 $restrictions[$key] =
'editsemiprotected';
2564 return !array_diff( $restrictions, $semi );
2579 # Special pages have inherent protection
2584 # Check regular protection levels
2585 foreach ( $restrictionTypes as
$type ) {
2586 if ( $action ==
$type || $action ==
'' ) {
2589 if ( in_array( $level, $r ) && $level !=
'' ) {
2611 $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
2613 if ( !$permissionManager->userHasRight( $user, $right ) ) {
2628 return ( $sources > 0 );
2641 return $getPages ? $this->mCascadeSources !== null : $this->mHasCascadingRestrictions !==
null;
2658 $pagerestrictions = [];
2660 if ( $this->mCascadeSources !==
null && $getPages ) {
2661 return [ $this->mCascadeSources, $this->mCascadingRestrictions ];
2662 } elseif ( $this->mHasCascadingRestrictions !==
null && !$getPages ) {
2663 return [ $this->mHasCascadingRestrictions, $pagerestrictions ];
2668 if ( $this->mNamespace ==
NS_FILE ) {
2669 $tables = [
'imagelinks',
'page_restrictions' ];
2671 'il_to' => $this->mDbkeyform,
2676 $tables = [
'templatelinks',
'page_restrictions' ];
2678 'tl_namespace' => $this->mNamespace,
2679 'tl_title' => $this->mDbkeyform,
2686 $cols = [
'pr_page',
'page_namespace',
'page_title',
2687 'pr_expiry',
'pr_type',
'pr_level' ];
2688 $where_clauses[] =
'page_id=pr_page';
2691 $cols = [
'pr_expiry' ];
2694 $res =
$dbr->select( $tables, $cols, $where_clauses, __METHOD__ );
2696 $sources = $getPages ? [] :
false;
2699 foreach (
$res as $row ) {
2700 $expiry =
$dbr->decodeExpiry( $row->pr_expiry );
2701 if ( $expiry > $now ) {
2703 $page_id = $row->pr_page;
2704 $page_ns = $row->page_namespace;
2705 $page_title = $row->page_title;
2706 $sources[$page_id] = self::makeTitle( $page_ns, $page_title );
2707 # Add groups needed for each restriction type if its not already there
2708 # Make sure this restriction type still exists
2710 if ( !isset( $pagerestrictions[$row->pr_type] ) ) {
2711 $pagerestrictions[$row->pr_type] = [];
2715 isset( $pagerestrictions[$row->pr_type] )
2716 && !in_array( $row->pr_level, $pagerestrictions[$row->pr_type] )
2718 $pagerestrictions[$row->pr_type][] = $row->pr_level;
2727 $this->mCascadeSources = $sources;
2728 $this->mCascadingRestrictions = $pagerestrictions;
2730 $this->mHasCascadingRestrictions = $sources;
2733 return [ $sources, $pagerestrictions ];
2744 return $this->mRestrictionsLoaded;
2757 if ( !$this->mRestrictionsLoaded ) {
2760 return $this->mRestrictions[$action] ?? [];
2771 if ( !$this->mRestrictionsLoaded ) {
2774 return $this->mRestrictions;
2785 if ( !$this->mRestrictionsLoaded ) {
2788 return $this->mRestrictionsExpiry[$action] ??
false;
2797 if ( !$this->mRestrictionsLoaded ) {
2801 return $this->mCascadeRestriction;
2823 foreach ( $restrictionTypes as
$type ) {
2824 $this->mRestrictions[
$type] = [];
2825 $this->mRestrictionsExpiry[
$type] =
'infinity';
2828 $this->mCascadeRestriction =
false;
2830 # Backwards-compatibility: also load the restrictions from the page record (old format).
2831 if ( $oldFashionedRestrictions !==
null ) {
2832 $this->mOldRestrictions = $oldFashionedRestrictions;
2835 if ( $this->mOldRestrictions ===
false ) {
2836 $linkCache = MediaWikiServices::getInstance()->getLinkCache();
2837 $linkCache->addLinkObj( $this ); # in
case we already had an article ID
2838 $this->mOldRestrictions = $linkCache->getGoodLinkFieldObj( $this,
'restrictions' );
2841 if ( $this->mOldRestrictions !=
'' ) {
2842 foreach ( explode(
':', trim( $this->mOldRestrictions ) ) as $restrict ) {
2843 $temp = explode(
'=', trim( $restrict ) );
2844 if ( count( $temp ) == 1 ) {
2846 $this->mRestrictions[
'edit'] = explode(
',', trim( $temp[0] ) );
2847 $this->mRestrictions[
'move'] = explode(
',', trim( $temp[0] ) );
2849 $restriction = trim( $temp[1] );
2850 if ( $restriction !=
'' ) {
2851 $this->mRestrictions[$temp[0]] = explode(
',', $restriction );
2857 if ( count( $rows ) ) {
2858 # Current system - load second to make them override.
2861 # Cycle through all the restrictions.
2862 foreach ( $rows as $row ) {
2864 if ( !in_array( $row->pr_type, $restrictionTypes ) ) {
2868 $expiry =
$dbr->decodeExpiry( $row->pr_expiry );
2871 if ( !$expiry || $expiry > $now ) {
2872 $this->mRestrictionsExpiry[$row->pr_type] = $expiry;
2873 $this->mRestrictions[$row->pr_type] = explode(
',', trim( $row->pr_level ) );
2875 $this->mCascadeRestriction |= $row->pr_cascade;
2880 $this->mRestrictionsLoaded =
true;
2894 $readLatest = DBAccessObjectUtils::hasFlags( $flags, self::READ_LATEST );
2895 if ( $this->mRestrictionsLoaded && !$readLatest ) {
2901 $fname = __METHOD__;
2902 $loadRestrictionsFromDb =
function (
IDatabase $dbr ) use ( $fname, $id ) {
2903 return iterator_to_array(
2905 'page_restrictions',
2906 [
'pr_type',
'pr_expiry',
'pr_level',
'pr_cascade' ],
2907 [
'pr_page' => $id ],
2913 if ( $readLatest ) {
2915 $rows = $loadRestrictionsFromDb(
$dbr );
2917 $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
2918 $rows =
$cache->getWithSetCallback(
2920 $cache->makeKey(
'page-restrictions',
'v1', $id, $this->getLatestRevID() ),
2922 function ( $curValue, &$ttl, array &$setOpts ) use ( $loadRestrictionsFromDb ) {
2925 $setOpts += Database::getCacheSetOptions(
$dbr );
2926 $lb = MediaWikiServices::getInstance()->getDBLoadBalancer();
2927 if ( $lb->hasOrMadeRecentMasterChanges() ) {
2929 $ttl = WANObjectCache::TTL_UNCACHEABLE;
2932 return $loadRestrictionsFromDb(
$dbr );
2941 if ( $title_protection ) {
2945 if ( !$expiry || $expiry > $now ) {
2947 $this->mRestrictionsExpiry[
'create'] = $expiry;
2948 $this->mRestrictions[
'create'] =
2949 explode(
',', trim( $title_protection[
'permission'] ) );
2951 $this->mTitleProtection =
false;
2954 $this->mRestrictionsExpiry[
'create'] =
'infinity';
2956 $this->mRestrictionsLoaded =
true;
2965 $this->mRestrictionsLoaded =
false;
2966 $this->mTitleProtection =
null;
2983 $config = MediaWikiServices::getInstance()->getMainConfig();
2985 'page_restrictions',
2989 [
'LIMIT' => $config->get(
'UpdateRowsPerQuery' ) ]
2992 $dbw->
delete(
'page_restrictions', [
'pr_id' => $ids ], $fname );
3017 !MediaWikiServices::getInstance()->getNamespaceInfo()->
3024 # We dynamically add a member variable for the purpose of this method
3025 # alone to cache the result. There's no point in having it hanging
3026 # around uninitialized in every Title object; therefore we only add it
3027 # if needed and don't declare it statically.
3028 if ( $this->mHasSubpages ===
null ) {
3029 $this->mHasSubpages =
false;
3032 $this->mHasSubpages = (bool)$subpages->current();
3036 return $this->mHasSubpages;
3048 !MediaWikiServices::getInstance()->getNamespaceInfo()->
3055 $conds = [
'page_namespace' => $this->mNamespace ];
3056 $conds[] =
'page_title ' .
$dbr->buildLike( $this->mDbkeyform .
'/',
$dbr->anyString() );
3058 if ( $limit > -1 ) {
3059 $options[
'LIMIT'] = $limit;
3062 $dbr->select(
'page',
3063 [
'page_id',
'page_namespace',
'page_title',
'page_is_redirect' ],
3077 if ( $this->mNamespace < 0 ) {
3082 $n =
$dbr->selectField(
'archive',
'COUNT(*)',
3083 [
'ar_namespace' => $this->mNamespace,
'ar_title' => $this->mDbkeyform ],
3086 if ( $this->mNamespace ==
NS_FILE ) {
3087 $n +=
$dbr->selectField(
'filearchive',
'COUNT(*)',
3088 [
'fa_name' => $this->mDbkeyform ],
3102 if ( $this->mNamespace < 0 ) {
3106 $deleted = (bool)
$dbr->selectField(
'archive',
'1',
3107 [
'ar_namespace' => $this->mNamespace,
'ar_title' => $this->mDbkeyform ],
3110 if ( !$deleted && $this->mNamespace ==
NS_FILE ) {
3111 $deleted = (bool)
$dbr->selectField(
'filearchive',
'1',
3112 [
'fa_name' => $this->mDbkeyform ],
3127 if ( $this->mNamespace < 0 ) {
3128 $this->mArticleID = 0;
3130 return $this->mArticleID;
3133 $linkCache = MediaWikiServices::getInstance()->getLinkCache();
3134 if ( $flags & self::GAID_FOR_UPDATE ) {
3135 $oldUpdate = $linkCache->forUpdate(
true );
3136 $linkCache->clearLink( $this );
3137 $this->mArticleID = $linkCache->addLinkObj( $this );
3138 $linkCache->forUpdate( $oldUpdate );
3139 } elseif ( DBAccessObjectUtils::hasFlags( $flags, self::READ_LATEST ) ) {
3141 } elseif ( $this->mArticleID == -1 ) {
3142 $this->mArticleID = $linkCache->addLinkObj( $this );
3145 return $this->mArticleID;
3156 if ( DBAccessObjectUtils::hasFlags( $flags, self::READ_LATEST ) ) {
3157 $this->mRedirect = (bool)$this->
loadFieldFromDB(
'page_is_redirect', $flags );
3159 if ( $this->mRedirect !==
null ) {
3160 return $this->mRedirect;
3162 $this->mRedirect =
false;
3164 return $this->mRedirect;
3167 $linkCache = MediaWikiServices::getInstance()->getLinkCache();
3168 $linkCache->addLinkObj( $this );
3171 $this->mRedirect = (bool)$linkCache->getGoodLinkFieldObj( $this,
'redirect' );
3174 return $this->mRedirect;
3185 if ( DBAccessObjectUtils::hasFlags( $flags, self::READ_LATEST ) ) {
3188 if ( $this->mLength != -1 ) {
3189 return $this->mLength;
3192 return $this->mLength;
3195 $linkCache = MediaWikiServices::getInstance()->getLinkCache();
3196 $linkCache->addLinkObj( $this );
3199 $this->mLength = (int)$linkCache->getGoodLinkFieldObj( $this,
'length' );
3202 return $this->mLength;
3212 if ( DBAccessObjectUtils::hasFlags( $flags, self::READ_LATEST ) ) {
3213 $this->mLatestID = (int)$this->
loadFieldFromDB(
'page_latest', $flags );
3215 if ( $this->mLatestID !==
false ) {
3216 return (
int)$this->mLatestID;
3218 $this->mLatestID = 0;
3220 return $this->mLatestID;
3223 $linkCache = MediaWikiServices::getInstance()->getLinkCache();
3224 $linkCache->addLinkObj( $this );
3227 $this->mLatestID = (int)$linkCache->getGoodLinkFieldObj( $this,
'revision' );
3230 return $this->mLatestID;
3244 if ( $id ===
false ) {
3245 $this->mArticleID = -1;
3247 $this->mArticleID = (int)$id;
3249 $this->mRestrictionsLoaded =
false;
3250 $this->mRestrictions = [];
3251 $this->mOldRestrictions =
false;
3252 $this->mRedirect =
null;
3253 $this->mLength = -1;
3254 $this->mLatestID =
false;
3255 $this->mContentModel =
false;
3256 $this->mForcedContentModel =
false;
3257 $this->mEstimateRevisions =
null;
3258 $this->mPageLanguage =
null;
3259 $this->mDbPageLanguage =
false;
3260 $this->mIsBigDeletion =
null;
3262 MediaWikiServices::getInstance()->getLinkCache()->clearLink( $this );
3266 $linkCache = MediaWikiServices::getInstance()->getLinkCache();
3267 $linkCache->clear();
3281 $services = MediaWikiServices::getInstance();
3282 if ( $services->getNamespaceInfo()->isCapitalized( $ns ) ) {
3283 return $services->getContentLanguage()->ucfirst( $text );
3308 $titleCodec = MediaWikiServices::getInstance()->getTitleParser();
3309 '@phan-var MediaWikiTitleCodec $titleCodec';
3311 $parts = $titleCodec->splitTitleString( $this->mDbkeyform, $this->mDefaultNamespace );
3315 $this->mInterwiki = $parts[
'interwiki'];
3316 $this->mLocalInterwiki = $parts[
'local_interwiki'];
3317 $this->mNamespace = $parts[
'namespace'];
3318 $this->mUserCaseDBKey = $parts[
'user_case_dbkey'];
3320 $this->mDbkeyform = $parts[
'dbkey'];
3321 $this->mUrlform =
wfUrlencode( $this->mDbkeyform );
3322 $this->mTextform = strtr( $this->mDbkeyform,
'_',
' ' );
3324 # We already know that some pages won't be in the database!
3326 $this->mArticleID = 0;
3344 public function getLinksTo( $options = [], $table =
'pagelinks', $prefix =
'pl' ) {
3345 if ( count( $options ) > 0 ) {
3353 self::getSelectFields(),
3355 "{$prefix}_from=page_id",
3356 "{$prefix}_namespace" => $this->mNamespace,
3357 "{$prefix}_title" => $this->mDbkeyform ],
3363 if (
$res->numRows() ) {
3364 $linkCache = MediaWikiServices::getInstance()->getLinkCache();
3365 foreach (
$res as $row ) {
3366 $titleObj = self::makeTitle( $row->page_namespace, $row->page_title );
3368 $linkCache->addGoodLinkObjFromRow( $titleObj, $row );
3369 $retVal[] = $titleObj;
3387 return $this->
getLinksTo( $options,
'templatelinks',
'tl' );
3402 public function getLinksFrom( $options = [], $table =
'pagelinks', $prefix =
'pl' ) {
3405 # If the page doesn't exist; there can't be any link from this page
3412 $blNamespace =
"{$prefix}_namespace";
3413 $blTitle =
"{$prefix}_title";
3415 $pageQuery = WikiPage::getQueryInfo();
3417 [ $table,
'nestpage' => $pageQuery[
'tables'] ],
3419 [ $blNamespace, $blTitle ],
3420 $pageQuery[
'fields']
3422 [
"{$prefix}_from" => $id ],
3427 [
"page_namespace=$blNamespace",
"page_title=$blTitle" ]
3428 ] ] + $pageQuery[
'joins']
3432 $linkCache = MediaWikiServices::getInstance()->getLinkCache();
3433 foreach (
$res as $row ) {
3434 if ( $row->page_id ) {
3435 $titleObj = self::newFromRow( $row );
3437 $titleObj = self::makeTitle( $row->$blNamespace, $row->$blTitle );
3438 $linkCache->addBadLinkObj( $titleObj );
3440 $retVal[] = $titleObj;
3457 return $this->
getLinksFrom( $options,
'templatelinks',
'tl' );
3470 # All links from article ID 0 are false positives
3476 [
'page',
'pagelinks' ],
3477 [
'pl_namespace',
'pl_title' ],
3480 'page_namespace IS NULL'
3486 [
'pl_namespace=page_namespace',
'pl_title=page_title' ]
3492 foreach (
$res as $row ) {
3493 $retVal[] = self::makeTitle( $row->pl_namespace, $row->pl_title );
3511 if ( $pageLang->hasVariants() ) {
3512 $variants = $pageLang->getVariants();
3513 foreach ( $variants as $vCode ) {
3527 Hooks::run(
'TitleSquidURLs', [ $this, &
$urls ] );
3535 DeferredUpdates::addUpdate(
3537 DeferredUpdates::PRESEND
3556 if ( !( $nt instanceof
Title ) ) {
3559 return [ [
'badtitletext' ] ];
3562 $mp = MediaWikiServices::getInstance()->getMovePageFactory()->newMovePage( $this, $nt );
3563 $errors = $mp->isValidMove()->getErrorsArray();
3567 $mp->checkPermissions( $wgUser, $reason )->getErrorsArray()
3571 return $errors ?:
true;
3587 public function moveTo( &$nt, $auth =
true, $reason =
'', $createRedirect =
true,
3588 array $changeTags = []
3594 $mp = MediaWikiServices::getInstance()->getMovePageFactory()->newMovePage( $this, $nt );
3595 $method = $auth ?
'moveIfAllowed' :
'move';
3597 $status = $mp->$method( $wgUser, $reason, $createRedirect, $changeTags );
3598 if ( $status->isOK() ) {
3601 return $status->getErrorsArray();
3620 public function moveSubpages( $nt, $auth =
true, $reason =
'', $createRedirect =
true,
3621 array $changeTags = []
3628 $method = $auth ?
'moveSubpagesIfAllowed' :
'moveSubpages';
3630 $result = $mp->$method( $wgUser, $reason, $createRedirect, $changeTags );
3632 if ( !$result->isOK() ) {
3633 return $result->getErrorsArray();
3637 foreach ( $result->getValue() as $key => $status ) {
3639 if ( $status->isOK() ) {
3640 $retval[$key] = $status->getValue();
3642 $retval[$key] = $status->getErrorsArray();
3661 $fields = [
'page_is_redirect',
'page_latest',
'page_id' ];
3663 $fields[] =
'page_content_model';
3666 $row = $dbw->selectRow(
'page',
3672 # Cache some fields we may want
3673 $this->mArticleID = $row ? intval( $row->page_id ) : 0;
3674 $this->mRedirect = $row ? (bool)$row->page_is_redirect :
false;
3675 $this->mLatestID = $row ? intval( $row->page_latest ) :
false;
3676 $this->mContentModel = $row && isset( $row->page_content_model )
3677 ? strval( $row->page_content_model )
3680 if ( !$this->mRedirect ) {
3683 # Does the article have a history?
3684 $row = $dbw->selectField( [
'page',
'revision' ],
3686 [
'page_namespace' => $this->mNamespace,
3687 'page_title' => $this->mDbkeyform,
3689 'page_latest != rev_id'
3694 # Return true if there was no history
3695 return ( $row ===
false );
3709 # Is it an existing file?
3710 if ( $nt->getNamespace() ==
NS_FILE ) {
3711 $file = MediaWikiServices::getInstance()->getRepoGroup()->getLocalRepo()
3713 $file->load( File::READ_LATEST );
3714 if (
$file->exists() ) {
3715 wfDebug( __METHOD__ .
": file exists\n" );
3719 # Is it a redirect with no history?
3720 if ( !$nt->isSingleRevRedirect() ) {
3721 wfDebug( __METHOD__ .
": not a one-rev redirect\n" );
3724 # Get the article text
3725 $rev = Revision::newFromTitle( $nt,
false, Revision::READ_LATEST );
3726 if ( !is_object( $rev ) ) {
3730 # Does the redirect point to the source?
3731 # Or is it a broken self-redirect, usually caused by namespace collisions?
3734 if ( $redirTitle ) {
3735 if ( $redirTitle->getPrefixedDBkey() != $this->getPrefixedDBkey() &&
3736 $redirTitle->getPrefixedDBkey() != $nt->getPrefixedDBkey() ) {
3737 wfDebug( __METHOD__ .
": redirect points to other page\n" );
3743 # Fail safe (not a redirect after all. strange.)
3744 wfDebug( __METHOD__ .
": failsafe: database sais " . $nt->getPrefixedDBkey() .
3745 " is a redirect, but it doesn't contain a valid redirect.\n" );
3762 if ( $titleKey === 0 ) {
3771 [
'cl_from' => $titleKey ],
3775 if (
$res->numRows() > 0 ) {
3776 $contLang = MediaWikiServices::getInstance()->getContentLanguage();
3777 foreach (
$res as $row ) {
3779 $data[$contLang->getNsText(
NS_CATEGORY ) .
':' . $row->cl_to] =
3797 foreach ( $parents as $parent => $current ) {
3798 if ( array_key_exists( $parent, $children ) ) {
3799 # Circular reference
3800 $stack[$parent] = [];
3802 $nt = self::newFromText( $parent );
3804 $stack[$parent] = $nt->getParentCategoryTree( $children + [ $parent => 1 ] );
3820 if ( $this->mArticleID > 0 ) {
3822 return [
'page_id' => $this->mArticleID ];
3824 return [
'page_namespace' => $this->mNamespace,
'page_title' => $this->mDbkeyform ];
3836 $rl = MediaWikiServices::getInstance()->getRevisionLookup();
3837 $rev = $rl->getRevisionById( $revId, $flags );
3842 $oldRev = ( $dir ===
'next' )
3843 ? $rl->getNextRevision( $rev, $flags )
3844 : $rl->getPreviousRevision( $rev, $flags );
3846 return $oldRev ? $oldRev->getId() :
false;
3882 $flags |= ( $flags & self::GAID_FOR_UPDATE ) ? self::READ_LATEST : 0;
3883 list( $index, $options ) = DBAccessObjectUtils::getDBOptions( $flags );
3885 $row =
wfGetDB( $index )->selectRow(
3887 [
'rev_page' => $pageId ],
3891 'ORDER BY' =>
'rev_timestamp ASC, rev_id ASC',
3892 'IGNORE INDEX' => [
'revision' =>
'rev_timestamp' ],
3899 return new Revision( $row, 0, $this );
3913 return $rev ? $rev->getTimestamp() :
null;
3923 return (
bool)
$dbr->selectField(
'page',
'page_is_new', $this->
pageCond(), __METHOD__ );
3938 if ( $this->mIsBigDeletion ===
null ) {
3941 $revCount =
$dbr->selectRowCount(
3952 return $this->mIsBigDeletion;
3961 if ( !$this->
exists() ) {
3965 if ( $this->mEstimateRevisions ===
null ) {
3967 $this->mEstimateRevisions =
$dbr->estimateRowCount(
'revision',
'*',
3971 return $this->mEstimateRevisions;
3984 if ( !( $old instanceof
Revision ) ) {
3985 $old = Revision::newFromTitle( $this, (
int)$old );
3987 if ( !( $new instanceof
Revision ) ) {
3988 $new = Revision::newFromTitle( $this, (
int)$new );
3990 if ( !$old || !$new ) {
3996 'rev_timestamp > ' .
$dbr->addQuotes(
$dbr->timestamp( $old->getTimestamp() ) ),
3997 'rev_timestamp < ' .
$dbr->addQuotes(
$dbr->timestamp( $new->getTimestamp() ) )
3999 if ( $max !==
null ) {
4000 return $dbr->selectRowCount(
'revision',
'1',
4003 [
'LIMIT' => $max + 1 ]
4006 return (
int)
$dbr->selectField(
'revision',
'count(*)', $conds, __METHOD__ );
4027 if ( !( $old instanceof
Revision ) ) {
4028 $old = Revision::newFromTitle( $this, (
int)$old );
4030 if ( !( $new instanceof
Revision ) ) {
4031 $new = Revision::newFromTitle( $this, (
int)$new );
4036 if ( !$old || !$new ) {
4042 $options = (array)$options;
4043 if ( in_array(
'include_old', $options ) ) {
4046 if ( in_array(
'include_new', $options ) ) {
4049 if ( in_array(
'include_both', $options ) ) {
4054 if ( $old->getId() === $new->getId() ) {
4055 return ( $old_cmp ===
'>' && $new_cmp ===
'<' ) ?
4057 [ $old->getUserText( RevisionRecord::RAW ) ];
4058 } elseif ( $old->getId() === $new->getParentId() ) {
4059 if ( $old_cmp ===
'>=' && $new_cmp ===
'<=' ) {
4060 $authors[] = $oldUserText = $old->getUserText( RevisionRecord::RAW );
4061 $newUserText = $new->getUserText( RevisionRecord::RAW );
4062 if ( $oldUserText != $newUserText ) {
4063 $authors[] = $newUserText;
4065 } elseif ( $old_cmp ===
'>=' ) {
4066 $authors[] = $old->getUserText( RevisionRecord::RAW );
4067 } elseif ( $new_cmp ===
'<=' ) {
4068 $authors[] = $new->getUserText( RevisionRecord::RAW );
4074 $authors =
$dbr->selectFieldValues(
4079 "rev_timestamp $old_cmp " .
$dbr->addQuotes(
$dbr->timestamp( $old->getTimestamp() ) ),
4080 "rev_timestamp $new_cmp " .
$dbr->addQuotes(
$dbr->timestamp( $new->getTimestamp() ) )
4082 [
'DISTINCT',
'LIMIT' => $limit + 1 ],
4104 return $authors ? count( $authors ) : 0;
4115 return $this->mInterwiki ===
$title->getInterwiki()
4116 && $this->mNamespace ==
$title->getNamespace()
4117 && $this->mDbkeyform ===
$title->getDBkey();
4127 return $this->mInterwiki ===
$title->mInterwiki
4128 && $this->mNamespace ==
$title->mNamespace
4129 && strpos( $this->mDbkeyform,
$title->mDbkeyform .
'/' ) === 0;
4144 Hooks::run(
'TitleExists', [ $this, &$exists ] );
4177 Hooks::run(
'TitleIsAlwaysKnown', [ $this, &$isKnown ] );
4179 if ( !is_null( $isKnown ) ) {
4187 $services = MediaWikiServices::getInstance();
4188 switch ( $this->mNamespace ) {
4192 return (
bool)$services->getRepoGroup()->findFile( $this );
4195 return $services->getSpecialPageFactory()->exists( $this->mDbkeyform );
4198 return $this->mDbkeyform ==
'';
4237 $contLang = MediaWikiServices::getInstance()->getContentLanguage();
4238 list( $name, ) = MessageCache::singleton()->figureMessage(
4239 $contLang->lcfirst( $this->getText() )
4241 $message =
wfMessage( $name )->inLanguage( $contLang )->useDatabase(
false );
4242 return $message->exists();
4290 list( $name,
$lang ) = MessageCache::singleton()->figureMessage(
4291 MediaWikiServices::getInstance()->getContentLanguage()->lcfirst( $this->
getText() )
4293 $message =
wfMessage( $name )->inLanguage(
$lang )->useDatabase(
false );
4295 if ( $message->exists() ) {
4296 return $message->plain();
4311 } elseif ( $this->mArticleID === 0 ) {
4316 $dbw->onTransactionPreCommitOrIdle(
4317 function () use ( $dbw ) {
4318 ResourceLoaderWikiModule::invalidateModuleCache(
4319 $this,
null,
null, $dbw->getDomainID() );
4325 DeferredUpdates::addUpdate(
4329 function (
IDatabase $dbw, $fname ) use ( $conds, $purgeTime ) {
4330 $dbTimestamp = $dbw->
timestamp( $purgeTime ?: time() );
4333 [
'page_touched' => $dbTimestamp ],
4334 $conds + [
'page_touched < ' . $dbw->
addQuotes( $dbTimestamp ) ],
4337 MediaWikiServices::getInstance()->getLinkCache()->invalidateTitle( $this );
4340 DeferredUpdates::PRESEND
4356 [
'causeAction' =>
'page-touch' ]
4362 [
'causeAction' =>
'category-touch' ]
4366 JobQueueGroup::singleton()->lazyPush( $jobs );
4376 if ( $db ===
null ) {
4379 $touched = $db->selectField(
'page',
'page_touched', $this->
pageCond(), __METHOD__ );
4397 $uid = $user->getId();
4402 if ( array_key_exists( $uid, $this->mNotificationTimestamp ) ) {
4403 return $this->mNotificationTimestamp[$uid];
4406 if ( count( $this->mNotificationTimestamp ) >= self::CACHE_MAX ) {
4407 $this->mNotificationTimestamp = [];
4410 $store = MediaWikiServices::getInstance()->getWatchedItemStore();
4411 $watchedItem = $store->getWatchedItem( $user, $this );
4412 if ( $watchedItem ) {
4413 $this->mNotificationTimestamp[$uid] = $watchedItem->getNotificationTimestamp();
4415 $this->mNotificationTimestamp[$uid] =
false;
4418 return $this->mNotificationTimestamp[$uid];
4429 $nsInfo = MediaWikiServices::getInstance()->getNamespaceInfo();
4430 $subjectNS = $nsInfo->getSubject( $this->mNamespace );
4432 $namespaceKey = $nsInfo->getCanonicalName( $subjectNS );
4433 if ( $namespaceKey ===
false ) {
4438 $namespaceKey = MediaWikiServices::getInstance()->getContentLanguage()->lc( $namespaceKey );
4440 if ( $namespaceKey ==
'' ) {
4441 $namespaceKey =
'main';
4444 if ( $namespaceKey ==
'file' ) {
4445 $namespaceKey =
'image';
4447 return $prepend . $namespaceKey;
4461 'rd_namespace' => $this->mNamespace,
4462 'rd_title' => $this->mDbkeyform,
4466 $where[
'rd_interwiki'] = $this->mInterwiki;
4468 $where[] =
'rd_interwiki = ' .
$dbr->addQuotes(
'' ) .
' OR rd_interwiki IS NULL';
4470 if ( !is_null( $ns ) ) {
4471 $where[
'page_namespace'] = $ns;
4475 [
'redirect',
'page' ],
4476 [
'page_namespace',
'page_title' ],
4481 foreach (
$res as $row ) {
4482 $redirs[] = self::newFromRow( $row );
4497 if ( $this->
isSpecial(
'Userlogout' ) ) {
4529 MediaWikiServices::getInstance()->getNamespaceInfo()->getContentNamespaces();
4531 return !in_array( $this->mNamespace, $bannedNamespaces );
4545 $unprefixed = $this->
getText();
4551 Hooks::run(
'GetDefaultSortkey', [ $this, &$unprefixed ] );
4552 if ( $prefix !==
'' ) {
4553 # Separate with a line feed, so the unprefixed part is only used as
4554 # a tiebreaker when two pages have the exact same prefix.
4555 # In UCA, tab is the only character that can sort above LF
4556 # so we strip both of them from the original prefix.
4557 $prefix = strtr( $prefix,
"\n\t",
' ' );
4558 return "$prefix\n$unprefixed";
4576 $linkCache = MediaWikiServices::getInstance()->getLinkCache();
4577 $linkCache->addLinkObj( $this );
4578 $this->mDbPageLanguage = $linkCache->getGoodLinkFieldObj( $this,
'lang' );
4581 return $this->mDbPageLanguage;
4601 if ( $dbPageLanguage ) {
4605 if ( !$this->mPageLanguage || $this->mPageLanguage[1] !==
$wgLanguageCode ) {
4612 $contentHandler = ContentHandler::getForTitle( $this );
4613 $langObj = $contentHandler->getPageLanguage( $this );
4616 $langObj = Language::factory( $this->mPageLanguage[0] );
4636 $variant =
$wgLang->getPreferredVariant();
4637 if (
$wgLang->getCode() !== $variant ) {
4638 return Language::factory( $variant );
4646 if ( $dbPageLanguage ) {
4648 $variant = $pageLang->getPreferredVariant();
4649 if ( $pageLang->getCode() !== $variant ) {
4650 $pageLang = Language::factory( $variant );
4659 $contentHandler = ContentHandler::getForTitle( $this );
4660 $pageLang = $contentHandler->getPageViewLanguage( $this );
4678 $editnotice_ns =
'editnotice-' . $this->mNamespace;
4680 if ( $msg->exists() ) {
4681 $html = $msg->parseAsBlock();
4683 if ( trim( $html ) !==
'' ) {
4684 $notices[$editnotice_ns] = Html::rawElement(
4688 'mw-editnotice-namespace',
4689 Sanitizer::escapeClass(
"mw-$editnotice_ns" )
4697 MediaWikiServices::getInstance()->getNamespaceInfo()->
4701 $editnotice_base = $editnotice_ns;
4702 foreach ( explode(
'/', $this->mDbkeyform ) as $part ) {
4703 $editnotice_base .=
'-' . $part;
4705 if ( $msg->exists() ) {
4706 $html = $msg->parseAsBlock();
4707 if ( trim( $html ) !==
'' ) {
4708 $notices[$editnotice_base] = Html::rawElement(
4712 'mw-editnotice-base',
4713 Sanitizer::escapeClass(
"mw-$editnotice_base" )
4722 $editnoticeText = $editnotice_ns .
'-' . strtr( $this->mDbkeyform,
'/',
'-' );
4724 if ( $msg->exists() ) {
4725 $html = $msg->parseAsBlock();
4726 if ( trim( $html ) !==
'' ) {
4727 $notices[$editnoticeText] = Html::rawElement(
4731 'mw-editnotice-page',
4732 Sanitizer::escapeClass(
"mw-$editnoticeText" )
4740 Hooks::run(
'TitleGetEditNotices', [ $this, $oldid, &$notices ] );
4749 if ( !in_array( $field, self::getSelectFields(),
true ) ) {
4753 $flags |= ( $flags & self::GAID_FOR_UPDATE ) ? self::READ_LATEST : 0;
4754 list( $index, $options ) = DBAccessObjectUtils::getDBOptions( $flags );
4756 return wfGetDB( $index )->selectField(
4776 'mDefaultNamespace',
4781 $this->mArticleID = ( $this->mNamespace >= 0 ) ? -1 : 0;
4782 $this->mUrlform =
wfUrlencode( $this->mDbkeyform );
4783 $this->mTextform = strtr( $this->mDbkeyform,
'_',
' ' );
$wgRestrictionLevels
Rights which can be required for each protection level (via action=protect)
$wgExemptFromUserRobotsControl
An array of namespace keys in which the INDEX/__NOINDEX__ magic words will not function,...
$wgLegalTitleChars
Allowed title characters – regex character class Don't change this unless you know what you're doing.
bool $wgPageLanguageUseDB
Enable page language feature Allows setting page language in database.
bool $wgMainPageIsDomainRoot
Option to whether serve the main page as the domain root.
$wgSemiprotectedRestrictionLevels
Restriction levels that should be considered "semiprotected".
$wgLanguageCode
Site language code.
$wgScript
The URL path to index.php.
$wgInternalServer
Internal server name as known to CDN, if different.
$wgInvalidRedirectTargets
Array of invalid page redirect targets.
$wgNamespaceProtection
Set the minimum permissions required to edit pages in each namespace.
$wgRestrictionTypes
Set of available actions that can be restricted via action=protect You probably shouldn't change this...
$wgDeleteRevisionsLimit
Optional to restrict deletion of pages with higher revision counts to users with the 'bigdelete' perm...
$wgVariantArticlePath
Like $wgArticlePath, but on multi-variant wikis, this provides a path format that describes which par...
$wgServer
URL of the server.
string[] $wgRawHtmlMessages
List of messages which might contain raw HTML.
$wgContentHandlerUseDB
Set to false to disable use of the database fields introduced by the ContentHandler facility.
wfGetLangObj( $langcode=false)
Return a Language object from $langcode.
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,...
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
wfReadOnly()
Check whether the wiki is in read-only mode.
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
wfMergeErrorArrays(... $args)
Merge arrays in the style of getUserPermissionsErrors, with duplicate removal e.g.
wfExpandUrl( $url, $defaultProto=PROTO_CURRENT)
Expand a potentially local URL to a fully-qualified URL.
wfLogWarning( $msg, $callerOffset=1, $level=E_USER_WARNING)
Send a warning as a PHP error and the debug log.
wfAppendQuery( $url, $query)
Append a query string to an existing URL, which may or may not already have query string parameters a...
wfArrayToCgi( $array1, $array2=null, $prefix='')
This function takes one or two arrays as input, and returns a CGI-style string, e....
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
if(! $wgDBerrorLogTZ) $wgRequest
Deferrable Update for closure/callback updates via IDatabase::doAtomicSection()
Deferrable Update for closure/callback updates that should use auto-commit mode.
static get(Title $title)
Create a new BacklinkCache or reuse any existing one.
Handles purging the appropriate CDN objects given a list of URLs or Title instances.
static newForBacklinks(Title $title, $table, $params=[])
Handles a simple LRU key/value map with a maximum number of entries.
set( $key, $value, $rank=self::RANK_TOP)
Set a key/value pair.
get( $key, $maxAge=INF, $default=null)
Get the value for a key.
clear( $keys=null)
Clear one or several cache entries, or all cache entries.
Handles the backend logic of moving a page from one title to another.
static getActionPaths(array $actionPaths, $articlePath)
The TitleArray class only exists to provide the newFromResult method at pre- sent.
static newFromResult( $res)
Represents a page (or page fragment) title within MediaWiki.
Represents a title within MediaWiki.
string $mInterwiki
Interwiki prefix.
static newFromID( $id, $flags=0)
Create a new Title from an article ID.
getSubpages( $limit=-1)
Get all subpages of this page.
array null $mPageLanguage
The (string) language code of the page's language and content code.
isWatchable()
Can this title be added to a user's watchlist?
getTalkPageIfDefined()
Get a Title object associated with the talk page of this article, if such a talk page can exist.
getNamespace()
Get the namespace index, i.e.
estimateRevisionCount()
Get the approximate revision count of this page.
__wakeup()
Text form (spaces not underscores) of the main part.
static newFromDBkey( $key)
Create a new Title from a prefixed DB key.
isProtected( $action='')
Does the title correspond to a protected article?
getUserPermissionsErrors( $action, $user, $rigor=PermissionManager::RIGOR_SECURE, $ignoreErrors=[])
Can $user perform $action on this page?
const NEW_CLONE
Flag for use with factory methods like newFromLinkTarget() that have a $forceClone parameter.
getTitleProtectionInternal()
Fetch title protection settings.
getLinkURL( $query='', $query2=false, $proto=false)
Get a URL that's the simplest URL that will be valid to link, locally, to the current Title.
array $mCascadeSources
Where are the cascading restrictions coming from on this page?
isSingleRevRedirect()
Locks the page row and check if this page is single revision redirect.
wasLocalInterwiki()
Was this a local interwiki link?
getInternalURL( $query='', $query2=false)
Get the URL form for an internal link.
purgeSquid()
Purge all applicable CDN URLs.
getFullURL( $query='', $query2=false, $proto=PROTO_RELATIVE)
Get a real URL referring to this title, with interwiki link and fragment.
getRestrictions( $action)
Accessor/initialisation for mRestrictions.
static newFromLinkTarget(LinkTarget $linkTarget, $forceClone='')
Returns a Title given a LinkTarget.
isKnown()
Does this title refer to a page that can (or might) be meaningfully viewed? In particular,...
int $mEstimateRevisions
Estimated number of revisions; null of not loaded.
getBacklinkCache()
Get a backlink cache object.
static getInterwikiLookup()
B/C kludge: provide an InterwikiLookup for use by Title.
static getTitleFormatter()
B/C kludge: provide a TitleParser for use by Title.
inNamespace( $ns)
Returns true if the title is inside the specified namespace.
isDeletedQuick()
Is there a version of this page in the deletion archive?
static capitalize( $text, $ns=NS_MAIN)
Capitalize a text string for a title if it belongs to a namespace that capitalizes.
getTalkPage()
Get a Title object associated with the talk page of this article.
secureAndSplit()
Secure and split - main initialisation function for this object.
isSiteJsonConfigPage()
Is this a sitewide JSON "config" page?
isSiteCssConfigPage()
Is this a sitewide CSS "config" page?
getAllRestrictions()
Accessor/initialisation for mRestrictions.
hasContentModel( $id)
Convenience method for checking a title's content model name.
static clearCaches()
Text form (spaces not underscores) of the main part.
createFragmentTarget( $fragment)
Creates a new Title for a different fragment of the same page.
getDefaultNamespace()
Get the default namespace index, for when there is no namespace.
moveTo(&$nt, $auth=true, $reason='', $createRedirect=true, array $changeTags=[])
Move a title to a new location.
isConversionTable()
Is this a conversion table for the LanguageConverter?
getFragment()
Get the Title fragment (i.e.
isCascadeProtected()
Cascading protection: Return true if cascading restrictions apply to this page, false if not.
static getFilteredRestrictionTypes( $exists=true)
Get a filtered list of all restriction types supported by this wiki.
getPrefixedURL()
Get a URL-encoded title (not an actual URL) including interwiki.
isWikitextPage()
Does that page contain wikitext, or it is JS, CSS or whatever?
getTalkNsText()
Get the namespace text of the talk page.
areRestrictionsCascading()
Returns cascading restrictions for the current article.
hasFragment()
Check if a Title fragment is set.
static nameOf( $id)
Get the prefixed DB key associated with an ID.
isSpecial( $name)
Returns true if this title resolves to the named special page.
getRedirectsHere( $ns=null)
Get all extant redirects to this Title.
getLength( $flags=0)
What is the length of this page? Uses link cache, adding it if necessary.
array $mNotificationTimestamp
Associative array of user ID -> timestamp/false.
isValidMoveOperation(&$nt, $auth=true, $reason='')
Check whether a given move operation would be valid.
getFullText()
Get the prefixed title with spaces, plus any fragment (part beginning with '#')
areRestrictionsLoaded()
Accessor for mRestrictionsLoaded.
canUseNoindex()
Whether the magic words INDEX and NOINDEX function for this page.
exists( $flags=0)
Check if page exists.
static newFromURL( $url)
THIS IS NOT THE FUNCTION YOU WANT.
static newFromTextThrow( $text, $defaultNamespace=NS_MAIN)
Like Title::newFromText(), but throws MalformedTitleException when the title is invalid,...
isLocal()
Determine whether the object refers to a page within this project (either this wiki or a wiki with a ...
int $mLength
The page length, 0 for special pages.
loadFromRow( $row)
Load Title object fields from a DB row.
getPageLanguage()
Get the language in which the content of this page is written in wikitext.
bool $mLocalInterwiki
Was this Title created from a string with a local interwiki prefix?
getUserCaseDBKey()
Get the DB key with the initial letter case as specified by the user.
isMovable()
Would anybody with sufficient privileges be able to move this page? Some pages just aren't movable.
const CACHE_MAX
Title::newFromText maintains a cache to avoid expensive re-normalization of commonly used titles.
getRestrictionExpiry( $action)
Get the expiry time for the restriction against a given action.
getSubjectPage()
Get a title object associated with the subject page of this talk page.
getTemplateLinksTo( $options=[])
Get an array of Title objects using this Title as a template Also stores the IDs in the link cache.
fixSpecialName()
If the Title refers to a special page alias which is not the local default, resolve the alias,...
getRestrictionTypes()
Returns restriction types for the current Title.
static legalChars()
Get a regex character class describing the legal characters in a link.
__toString()
Return a string representation of this title.
hasSubjectNamespace( $ns)
Returns true if the title has the same subject namespace as the namespace specified.
isSemiProtected( $action='edit')
Is this page "semi-protected" - the only protection levels are listed in $wgSemiprotectedRestrictionL...
lazyFillContentModel( $model)
If the content model field is not frozen then update it with a retreived value.
getPrefixedDBkey()
Get the prefixed database key form.
areCascadeProtectionSourcesLoaded( $getPages=true)
Determines whether cascading protection sources have already been loaded from the database.
getPreviousRevisionID( $revId, $flags=0)
Get the revision ID of the previous revision.
getNsText()
Get the namespace text.
canExist()
Is this in a namespace that allows actual pages?
static purgeExpiredRestrictions()
Purge expired restrictions from the page_restrictions table.
getDefaultMessageText()
Get the default (plain) message contents for an page that overrides an interface message key.
getDbPageLanguageCode()
Returns the page language code saved in the database, if $wgPageLanguageUseDB is set to true in Local...
countRevisionsBetween( $old, $new, $max=null)
Get the number of revisions between the given revision.
bool $mForcedContentModel
If a content model was forced via setContentModel() this will be true to avoid having other code path...
getNotificationTimestamp( $user=null)
Get the timestamp when this page was updated since the user last saw it.
isTrans()
Determine whether the object refers to a page within this project and is transcludable.
isRawHtmlMessage()
Is this a message which can contain raw HTML?
isSiteJsConfigPage()
Is this a sitewide JS "config" page?
isNewPage()
Check if this is a new page.
touchLinks()
Update page_touched timestamps and send CDN purge messages for pages linking to this title.
isExternal()
Is this Title interwiki?
bool $mRestrictionsLoaded
Boolean for initialisation on demand.
isMainPage()
Is this the mainpage?
isUserConfigPage()
Is this a "config" (.css, .json, or .js) sub-page of a user page?
getFragmentForURL()
Get the fragment in URL form, including the "#" character if there is one.
string bool null $mDbPageLanguage
The page language code from the database, null if not saved in the database or false if not loaded,...
getAuthorsBetween( $old, $new, $limit, $options=[])
Get the authors between the given revisions or revision IDs.
loadRestrictions( $oldFashionedRestrictions=null, $flags=0)
Load restrictions from the page_restrictions table.
isSpecialPage()
Returns true if this is a special page.
isNamespaceProtected(User $user)
Determines if $user is unable to edit this page because it has been protected by $wgNamespaceProtecti...
isUserJsConfigPage()
Is this a JS "config" sub-page of a user page?
getSubpageUrlForm()
Get a URL-encoded form of the subpage text.
canHaveTalkPage()
Can this title have a corresponding talk page?
isTalkPage()
Is this a talk page of some sort?
getRootTitle()
Get the root page name title, i.e.
bool int $mLatestID
ID of most recent revision.
getBrokenLinksFrom()
Get an array of Title objects referring to non-existent articles linked from this page.
getDBkey()
Get the main part with underscores.
prefix( $name)
Prefix some arbitrary text with the namespace or interwiki prefix of this object.
getEarliestRevTime( $flags=0)
Get the oldest revision timestamp of this page.
string $mFragment
Title fragment (i.e.
getRootText()
Get the root page name text without a namespace, i.e.
getFullUrlForRedirect( $query='', $proto=PROTO_CURRENT)
Get a url appropriate for making redirects based on an untrusted url arg.
static newMainPage(MessageLocalizer $localizer=null)
Create a new Title for the Main Page.
bool string $mContentModel
ID of the page's content model, i.e.
getLatestRevID( $flags=0)
What is the page_latest field for this page?
static convertByteClassToUnicodeClass( $byteClass)
Utility method for converting a character sequence from bytes to Unicode.
userCan( $action, $user=null, $rigor=PermissionManager::RIGOR_SECURE)
Can $user perform $action on this page?
isValidRedirectTarget()
Check if this Title is a valid redirect target.
getLinksFrom( $options=[], $table='pagelinks', $prefix='pl')
Get an array of Title objects linked from this Title Also stores the IDs in the link cache.
static makeName( $ns, $title, $fragment='', $interwiki='', $canonicalNamespace=false)
Make a prefixed DB key from a DB key and a namespace index.
getLinksTo( $options=[], $table='pagelinks', $prefix='pl')
Get an array of Title objects linking to this Title Also stores the IDs in the link cache.
string null $prefixedText
Text form including namespace/interwiki, initialised on demand.
bool $mHasCascadingRestrictions
Are cascading restrictions in effect on this page?
getPartialURL()
Get the URL-encoded form of the main part.
getBaseText()
Get the base page name without a namespace, i.e.
isContentPage()
Is this Title in a namespace which contains content? In other words, is this a content page,...
getText()
Get the text form (spaces not underscores) of the main part.
getTouched( $db=null)
Get the last touched timestamp.
getTitleValue()
Get a TitleValue object representing this Title.
static MapCacheLRU null $titleCache
pageCond()
Get an associative array for selecting this title from the "page" table.
bool $mCascadeRestriction
Cascade restrictions on this page to included templates and images?
string $mUrlform
URL-encoded form of the main part.
static castFromLinkTarget( $linkTarget)
Same as newFromLinkTarget, but if passed null, returns null.
getFirstRevision( $flags=0)
Get the first revision of the page.
string $mTextform
Text form (spaces not underscores) of the main part.
getOtherPage()
Get the other title for this page, if this is a subject page get the talk page, if it is a subject pa...
static newFromIDs( $ids)
Make an array of titles from an array of IDs.
quickUserCan( $action, $user=null)
Can $user perform $action on this page? This skips potentially expensive cascading permission checks ...
static getSelectFields()
Returns a list of fields that are to be selected for initializing Title objects or LinkCache entries.
isSubpageOf(Title $title)
Check if this title is a subpage of another title.
getBaseTitle()
Get the base page name title, i.e.
getParentCategoryTree( $children=[])
Get a tree of parent categories.
bool $mHasSubpages
Whether a page has any subpages.
getNextRevisionID( $revId, $flags=0)
Get the revision ID of the next revision.
array $mRestrictionsExpiry
When do the restrictions on this page expire?
loadRestrictionsFromRows( $rows, $oldFashionedRestrictions=null)
Compiles list of active page restrictions from both page table (pre 1.10) and page_restrictions table...
static fixUrlQueryArgs( $query, $query2=false)
Helper to fix up the get{Canonical,Full,Link,Local,Internal}URL args get{Canonical,...
isUserJsonConfigPage()
Is this a JSON "config" sub-page of a user page?
isValidMoveTarget( $nt)
Checks if $this can be moved to a given Title.
isRedirect( $flags=0)
Is this an article that is a redirect page? Uses link cache, adding it if necessary.
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
invalidateCache( $purgeTime=null)
Updates page_touched for this page; called from LinksUpdate.php.
$mCascadingRestrictions
Caching the results of getCascadeProtectionSources.
getArticleID( $flags=0)
Get the article ID for this Title from the link cache, adding it if necessary.
getSubjectNsText()
Get the namespace text of the subject (rather than talk) page.
int $mNamespace
Namespace index, i.e.
warnIfPageCannotExist(Title $title, $method)
static makeTitleSafe( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
null $mRedirect
Is the article at this title a redirect?
countAuthorsBetween( $old, $new, $limit, $options=[])
Get the number of authors between the given revisions or revision IDs.
static compare(LinkTarget $a, LinkTarget $b)
Callback for usort() to do title sorts by (namespace, title)
getCanonicalURL( $query='', $query2=false)
Get the URL for a canonical link, for use in things like IRC and e-mail notifications.
isDeleted()
Is there a version of this page in the deletion archive?
getPageViewLanguage()
Get the language in which the content of this page is written when viewed by user.
const GAID_FOR_UPDATE
Used to be GAID_FOR_UPDATE define().
getSkinFromConfigSubpage()
Trim down a .css, .json, or .js subpage title to get the corresponding skin name.
array $mRestrictions
Array of groups allowed to edit this article.
isSiteConfigPage()
Could this MediaWiki namespace page contain custom CSS, JSON, or JavaScript for the global UI.
int $mDefaultNamespace
Namespace index when there is no namespace.
static newFromTitleValue(TitleValue $titleValue, $forceClone='')
Returns a Title given a TitleValue.
moveSubpages( $nt, $auth=true, $reason='', $createRedirect=true, array $changeTags=[])
Move this page's subpages to be subpages of $nt.
getRelativeRevisionID( $revId, $flags, $dir)
Get next/previous revision ID relative to another revision ID.
deleteTitleProtection()
Remove any title protection due to page existing.
getSubpage( $text)
Get the title for a subpage of the current page.
getTitleProtection()
Is this title subject to title protection? Title protection is the one applied against creation of su...
getEditURL()
Get the edit URL for this Title.
loadFieldFromDB( $field, $flags)
getParentCategories()
Get categories to which this Title belongs and return an array of categories' names.
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
int $mArticleID
Article ID, fetched from the link cache on demand.
getTemplateLinksFrom( $options=[])
Get an array of Title objects used on this Title as a template Also stores the IDs in the link cache.
getTransWikiID()
Returns the DB name of the distant wiki which owns the object.
isSubpage()
Is this a subpage?
isValid()
Returns true if the title is valid, false if it is invalid.
resetArticleID( $id)
Inject a page ID, reset DB-loaded fields, and clear the link cache for this title.
setFragment( $fragment)
Set the fragment for this title.
getLocalURL( $query='', $query2=false)
Get a URL with no fragment or server name (relative URL) from a Title object.
getContentModel( $flags=0)
Get the page's content model id, see the CONTENT_MODEL_XXX constants.
isBigDeletion()
Check whether the number of revisions of this page surpasses $wgDeleteRevisionsLimit.
bool null $mIsBigDeletion
Would deleting this page be a big deletion?
getCdnUrls()
Get a list of URLs to purge from the CDN cache when this page changes.
TitleValue null $mTitleValue
A corresponding TitleValue object.
equals(LinkTarget $title)
Compare with another title.
string $mUserCaseDBKey
Database key with the initial letter in the case specified by the user.
getInterwiki()
Get the interwiki prefix.
getEditNotices( $oldid=0)
Get a list of rendered edit notices for this page.
setContentModel( $model)
Set a proposed content model for the page for permissions checking.
getCascadeProtectionSources( $getPages=true)
Cascading protection: Get the source of any cascading restrictions on this page.
mixed $mTitleProtection
Cached value for getTitleProtection (create protection)
getSubpageText()
Get the lowest-level subpage name, i.e.
string $mDbkeyform
Main part with underscores.
hasSourceText()
Does this page have source text?
flushRestrictions()
Flush the protection cache in this object and force reload from the database.
getPrefixedText()
Get the prefixed title with spaces.
hasSubpages()
Does this have subpages? (Warning, usually requires an extra DB query.)
string bool $mOldRestrictions
Comma-separated set of permission keys indicating who can move or edit the page from the page table,...
inNamespaces(... $namespaces)
Returns true if the title is inside one of the specified namespaces.
isAlwaysKnown()
Should links to this title be shown as potentially viewable (i.e.
getNamespaceKey( $prepend='nstab-')
Generate strings used for xml 'id' names in monobook tabs.
getCategorySortkey( $prefix='')
Returns the raw sort key to be used for categories, with the specified prefix.
static newFromRow( $row)
Make a Title object from a DB row.
isUserCssConfigPage()
Is this a CSS "config" sub-page of a user page?
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
const CONTENT_MODEL_WIKITEXT
const CONTENT_MODEL_JAVASCRIPT
Interface for database access objects.
Interface for localizing messages in MediaWiki.
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
if(!isset( $args[0])) $lang