X-Git-Url: http://git.cyclocoop.org/?a=blobdiff_plain;f=includes%2FTitle.php;h=24811788f22f41504efdc06aee62d4fe9bfb3eae;hb=3dcf7c09b472ab396a2cc20fe1927bf924969f90;hp=b9451bea3bedc231558c613a197b932ae4ec0bfe;hpb=a8313e4358ed4a602291e1f52bd586cb83ff3bda;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/Title.php b/includes/Title.php index b9451bea3b..24811788f2 100644 --- a/includes/Title.php +++ b/includes/Title.php @@ -56,38 +56,105 @@ class Title { */ // @{ - var $mTextform = ''; // /< Text form (spaces not underscores) of the main part - var $mUrlform = ''; // /< URL-encoded form of the main part - var $mDbkeyform = ''; // /< Main part with underscores - var $mUserCaseDBKey; // /< DB key with the initial letter in the case specified by the user - var $mNamespace = NS_MAIN; // /< Namespace index, i.e. one of the NS_xxxx constants - var $mInterwiki = ''; // /< Interwiki prefix - var $mFragment = ''; // /< Title fragment (i.e. the bit after the #) - var $mArticleID = -1; // /< Article ID, fetched from the link cache on demand - var $mLatestID = false; // /< ID of most recent revision - var $mContentModel = false; // /< ID of the page's content model, i.e. one of the CONTENT_MODEL_XXX constants - private $mEstimateRevisions; // /< Estimated number of revisions; null of not loaded - var $mRestrictions = array(); // /< Array of groups allowed to edit this article - var $mOldRestrictions = false; - var $mCascadeRestriction; ///< Cascade restrictions on this page to included templates and images? - var $mCascadingRestrictions; // Caching the results of getCascadeProtectionSources - var $mRestrictionsExpiry = array(); ///< When do the restrictions on this page expire? - var $mHasCascadingRestrictions; ///< Are cascading restrictions in effect on this page? - var $mCascadeSources; ///< Where are the cascading restrictions coming from on this page? - var $mRestrictionsLoaded = false; ///< Boolean for initialisation on demand - var $mPrefixedText = null; ///< Text form including namespace/interwiki, initialised on demand - var $mTitleProtection; ///< Cached value for getTitleProtection (create protection) - # Don't change the following default, NS_MAIN is hardcoded in several - # places. See bug 696. - # Zero except in {{transclusion}} tags - var $mDefaultNamespace = NS_MAIN; // /< Namespace index when there is no namespace - var $mWatched = null; // /< Is $wgUser watching this page? null if unfilled, accessed through userIsWatching() - var $mLength = -1; // /< The page length, 0 for special pages - var $mRedirect = null; // /< Is the article at this title a redirect? - var $mNotificationTimestamp = array(); // /< Associative array of user ID -> timestamp/false - var $mHasSubpage; // /< Whether a page has any subpages - private $mPageLanguage = false; // /< The (string) language code of the page's language and content code. - private $mTitleValue = null; // /< A corresponding TitleValue object + /** @var string Text form (spaces not underscores) of the main part */ + public $mTextform = ''; + + /** @var string URL-encoded form of the main part */ + public $mUrlform = ''; + + /** @var string Main part with underscores */ + public $mDbkeyform = ''; + + /** @var string Database key with the initial letter in the case specified by the user */ + protected $mUserCaseDBKey; + + /** @var int Namespace index, i.e. one of the NS_xxxx constants */ + public $mNamespace = NS_MAIN; + + /** @var string Interwiki prefix */ + public $mInterwiki = ''; + + /** @var string Title fragment (i.e. the bit after the #) */ + public $mFragment = ''; + + /** @var int Article ID, fetched from the link cache on demand */ + public $mArticleID = -1; + + /** @var bool|int ID of most recent revision */ + protected $mLatestID = false; + + /** + * @var bool|string ID of the page's content model, i.e. one of the + * CONTENT_MODEL_XXX constants + */ + public $mContentModel = false; + + /** @var int Estimated number of revisions; null of not loaded */ + private $mEstimateRevisions; + + /** @var array Array of groups allowed to edit this article */ + public $mRestrictions = array(); + + /** @var bool */ + protected $mOldRestrictions = false; + + /** @var bool Cascade restrictions on this page to included templates and images? */ + public $mCascadeRestriction; + + /** Caching the results of getCascadeProtectionSources */ + public $mCascadingRestrictions; + + /** @var array When do the restrictions on this page expire? */ + protected $mRestrictionsExpiry = array(); + + /** @var bool Are cascading restrictions in effect on this page? */ + protected $mHasCascadingRestrictions; + + /** @var array Where are the cascading restrictions coming from on this page? */ + public $mCascadeSources; + + /** @var bool Boolean for initialisation on demand */ + public $mRestrictionsLoaded = false; + + /** @var string Text form including namespace/interwiki, initialised on demand */ + protected $mPrefixedText = null; + + /** @var mixed Cached value for getTitleProtection (create protection) */ + public $mTitleProtection; + + /** + * @var int Namespace index when there is no namespace. Don't change the + * following default, NS_MAIN is hardcoded in several places. See bug 696. + * Zero except in {{transclusion}} tags. + */ + public $mDefaultNamespace = NS_MAIN; + + /** + * @var bool Is $wgUser watching this page? null if unfilled, accessed + * through userIsWatching() + */ + protected $mWatched = null; + + /** @var int The page length, 0 for special pages */ + protected $mLength = -1; + + /** @var null Is the article at this title a redirect? */ + public $mRedirect = null; + + /** @var array Associative array of user ID -> timestamp/false */ + private $mNotificationTimestamp = array(); + + /** @var bool Whether a page has any subpages */ + private $mHasSubpages; + + /** @var bool The (string) language code of the page's language and content code. */ + private $mPageLanguage = false; + + /** @var string The page language code from the database */ + private $mDbPageLanguage = null; + + /** @var TitleValue A corresponding TitleValue object */ + private $mTitleValue = null; // @} /** @@ -115,7 +182,11 @@ class Title { } if ( !$titleCodec ) { - $titleCodec = new MediaWikiTitleCodec( $wgContLang, GenderCache::singleton(), $wgLocalInterwikis ); + $titleCodec = new MediaWikiTitleCodec( + $wgContLang, + GenderCache::singleton(), + $wgLocalInterwikis + ); $titleCodecFingerprint = $fingerprint; } @@ -136,10 +207,8 @@ class Title { return self::getTitleParser(); } - /** - * Constructor - */ - /*protected*/ function __construct() { } + function __construct() { + } /** * Create a new Title from a prefixed DB key @@ -218,8 +287,7 @@ class Title { } return $t; } else { - $ret = null; - return $ret; + return null; } } @@ -267,8 +335,9 @@ class Title { } /** - * Returns a list of fields that are to be selected for initializing Title objects or LinkCache entries. - * Uses $wgContentHandlerUseDB to determine whether to include page_content_model. + * Returns a list of fields that are to be selected for initializing Title + * objects or LinkCache entries. Uses $wgContentHandlerUseDB to determine + * whether to include page_content_model. * * @return array */ @@ -373,6 +442,9 @@ class Title { } else { $this->mContentModel = false; # initialized lazily in getContentModel() } + if ( isset( $row->page_lang ) ) { + $this->mDbPageLanguage = (string)$row->page_lang; + } } else { // page not found $this->mArticleID = 0; $this->mLength = 0; @@ -536,7 +608,7 @@ class Title { * Note that this doesn't pick up many things that could be wrong with titles, but that * replacing this regex with something valid will make many titles valid. * - * @todo: move this into MediaWikiTitleCodec + * @todo move this into MediaWikiTitleCodec * * @return string Regex string */ @@ -781,7 +853,7 @@ class Title { /** * Get a TitleValue object representing this Title. * - * @note: Not all valid Titles have a corresponding valid TitleValue + * @note Not all valid Titles have a corresponding valid TitleValue * (e.g. TitleValues cannot represent page-local links that have a * fragment but no title text). * @@ -905,9 +977,9 @@ class Title { } try { - $formatter = $this->getTitleFormatter(); + $formatter = self::getTitleFormatter(); return $formatter->getNamespaceName( $this->mNamespace, $this->mDbkeyform ); - } catch ( InvalidArgumentException $ex ) { + } catch ( InvalidArgumentException $ex ) { wfDebug( __METHOD__ . ': ' . $ex->getMessage() . "\n" ); return false; } @@ -1022,7 +1094,7 @@ class Title { /** * Returns true if the title is inside one of the specified namespaces. * - * @param ...$namespaces The namespaces to check for + * @param int $namespaces,... The namespaces to check for * @return bool * @since 1.19 */ @@ -1137,9 +1209,11 @@ class Title { * This is generally true for pages in the MediaWiki namespace having CONTENT_MODEL_CSS * or CONTENT_MODEL_JAVASCRIPT. * - * This method does *not* return true for per-user JS/CSS. Use isCssJsSubpage() for that! + * This method does *not* return true for per-user JS/CSS. Use isCssJsSubpage() + * for that! * - * Note that this method should not return true for pages that contain and show "inactive" CSS or JS. + * Note that this method should not return true for pages that contain and + * show "inactive" CSS or JS. * * @return bool */ @@ -1148,8 +1222,9 @@ class Title { && ( $this->hasContentModel( CONTENT_MODEL_CSS ) || $this->hasContentModel( CONTENT_MODEL_JAVASCRIPT ) ); - #NOTE: this hook is also called in ContentHandler::getDefaultModel. It's called here again to make sure - # hook functions can force this method to return true even outside the mediawiki namespace. + # @note This hook is also called in ContentHandler::getDefaultModel. + # It's called here again to make sure hook functions can force this + # method to return true even outside the mediawiki namespace. wfRunHooks( 'TitleIsCssOrJsPage', array( $this, &$isCssOrJsPage ) ); @@ -1296,7 +1371,6 @@ class Title { * * @param string $name The text * @return string The prefixed text - * @private */ private function prefix( $name ) { $p = ''; @@ -1472,18 +1546,6 @@ class Title { return Title::makeTitleSafe( $this->getNamespace(), $this->getText() . '/' . $text ); } - /** - * Get the HTML-escaped displayable text form. - * Used for the title field in tags. - * - * @return string The text, including any prefixes - * @deprecated since 1.19 - */ - public function getEscapedText() { - wfDeprecated( __METHOD__, '1.19' ); - return htmlspecialchars( $this->getPrefixedText() ); - } - /** * Get a URL-encoded form of the subpage text * @@ -1581,9 +1643,11 @@ class Title { * $wgServer is prepended to make an absolute URL. * * @see self::getFullURL to always get an absolute URL. + * @see self::getLinkURL to always get a URL that's the simplest URL that will be + * valid to link, locally, to the current Title. * @see self::newFromText to produce a Title object. * - * @param string|array $query an optional query string, + * @param string|array $query An optional query string, * not used for interwiki links. Can be specified as an associative array as well, * e.g., array( 'action' => 'edit' ) (keys and values will be URL-escaped). * Some query patterns will trigger various shorturl path replacements. @@ -1701,34 +1765,6 @@ class Title { return $ret; } - /** - * Get an HTML-escaped version of the URL form, suitable for - * using in a link, without a server name or fragment - * - * @see self::getLocalURL for the arguments. - * @param string $query - * @param bool|string $query2 - * @return string The URL - * @deprecated since 1.19 - */ - public function escapeLocalURL( $query = '', $query2 = false ) { - wfDeprecated( __METHOD__, '1.19' ); - return htmlspecialchars( $this->getLocalURL( $query, $query2 ) ); - } - - /** - * Get an HTML-escaped version of the URL form, suitable for - * using in a link, including the server name and fragment - * - * @see self::getLocalURL for the arguments. - * @return string The URL - * @deprecated since 1.19 - */ - public function escapeFullURL( $query = '', $query2 = false ) { - wfDeprecated( __METHOD__, '1.19' ); - return htmlspecialchars( $this->getFullURL( $query, $query2 ) ); - } - /** * Get the URL form for an internal link. * - Used in various Squid-related code, in case we have a different @@ -1768,19 +1804,6 @@ class Title { return $url; } - /** - * HTML-escaped version of getCanonicalURL() - * - * @see self::getLocalURL for the arguments. - * @since 1.18 - * @return string - * @deprecated since 1.19 - */ - public function escapeCanonicalURL( $query = '', $query2 = false ) { - wfDeprecated( __METHOD__, '1.19' ); - return htmlspecialchars( $this->getCanonicalURL( $query, $query2 ) ); - } - /** * Get the edit URL for this Title * @@ -1814,17 +1837,6 @@ class Title { return $this->mWatched; } - /** - * Can $wgUser read this page? - * - * @deprecated since 1.19; use userCan(), quickUserCan() or getUserPermissionsErrors() instead - * @return bool - */ - public function userCanRead() { - wfDeprecated( __METHOD__, '1.19' ); - return $this->userCan( 'read' ); - } - /** * Can $user perform $action on this page? * This skips potentially expensive cascading permission checks @@ -1858,7 +1870,9 @@ class Title { global $wgUser; $user = $wgUser; } - return !count( $this->getUserPermissionsErrorsInternal( $action, $user, $doExpensiveQueries, true ) ); + + return !count( $this->getUserPermissionsErrorsInternal( + $action, $user, $doExpensiveQueries, true ) ); } /** @@ -1866,15 +1880,17 @@ class Title { * * @todo FIXME: This *does not* check throttles (User::pingLimiter()). * - * @param string $action action that permission needs to be checked for + * @param string $action Action that permission needs to be checked for * @param User $user User to check * @param bool $doExpensiveQueries Set this to false to avoid doing unnecessary * queries by skipping checks for cascading protections and user blocks. - * @param array $ignoreErrors of Strings Set this to a list of message keys + * @param array $ignoreErrors Array of Strings Set this to a list of message keys * whose corresponding errors may be ignored. * @return array Array of arguments to wfMessage to explain permissions problems. */ - public function getUserPermissionsErrors( $action, $user, $doExpensiveQueries = true, $ignoreErrors = array() ) { + public function getUserPermissionsErrors( $action, $user, $doExpensiveQueries = true, + $ignoreErrors = array() + ) { $errors = $this->getUserPermissionsErrorsInternal( $action, $user, $doExpensiveQueries ); // Remove the errors being ignored. @@ -1892,7 +1908,7 @@ class Title { /** * Permissions checks that fail most often, and which are easiest to test. * - * @param string $action the action to check + * @param string $action The action to check * @param User $user User to check * @param array $errors List of current errors * @param bool $doExpensiveQueries Whether or not to perform expensive queries @@ -1900,8 +1916,12 @@ class Title { * * @return array List of errors */ - private function checkQuickPermissions( $action, $user, $errors, $doExpensiveQueries, $short ) { - if ( !wfRunHooks( 'TitleQuickPermissions', array( $this, $user, $action, &$errors, $doExpensiveQueries, $short ) ) ) { + private function checkQuickPermissions( $action, $user, $errors, + $doExpensiveQueries, $short + ) { + if ( !wfRunHooks( 'TitleQuickPermissions', + array( $this, $user, $action, &$errors, $doExpensiveQueries, $short ) ) + ) { return $errors; } @@ -2029,7 +2049,9 @@ class Title { * * @return array List of errors */ - private function checkSpecialsAndNSPermissions( $action, $user, $errors, $doExpensiveQueries, $short ) { + private function checkSpecialsAndNSPermissions( $action, $user, $errors, + $doExpensiveQueries, $short + ) { # Only 'createaccount' can be performed on special pages, # which don't actually exist in the DB. if ( NS_SPECIAL == $this->mNamespace && $action !== 'createaccount' ) { @@ -2128,7 +2150,9 @@ class Title { * * @return array List of errors */ - private function checkCascadingSourcesRestrictions( $action, $user, $errors, $doExpensiveQueries, $short ) { + private function checkCascadingSourcesRestrictions( $action, $user, $errors, + $doExpensiveQueries, $short + ) { if ( $doExpensiveQueries && !$this->isCssJsSubpage() ) { # We /could/ use the protection level on the source page, but it's # fairly ugly as we have to establish a precedence hierarchy for pages @@ -2175,11 +2199,15 @@ class Title { * * @return array List of errors */ - private function checkActionPermissions( $action, $user, $errors, $doExpensiveQueries, $short ) { + private function checkActionPermissions( $action, $user, $errors, + $doExpensiveQueries, $short + ) { global $wgDeleteRevisionsLimit, $wgLang; if ( $action == 'protect' ) { - if ( count( $this->getUserPermissionsErrorsInternal( 'edit', $user, $doExpensiveQueries, true ) ) ) { + if ( count( $this->getUserPermissionsErrorsInternal( 'edit', + $user, $doExpensiveQueries, true ) ) + ) { // If they can't edit, they shouldn't protect. $errors[] = array( 'protect-cantedit' ); } @@ -2195,7 +2223,11 @@ class Title { if ( $title_protection['pt_create_perm'] == '' || !$user->isAllowed( $title_protection['pt_create_perm'] ) ) { - $errors[] = array( 'titleprotected', User::whoIs( $title_protection['pt_user'] ), $title_protection['pt_reason'] ); + $errors[] = array( + 'titleprotected', + User::whoIs( $title_protection['pt_user'] ), + $title_protection['pt_reason'] + ); } } } elseif ( $action == 'move' ) { @@ -2376,7 +2408,9 @@ class Title { * @param bool $short Set this to true to stop after the first permission error. * @return array Array of arrays of the arguments to wfMessage to explain permissions problems. */ - protected function getUserPermissionsErrorsInternal( $action, $user, $doExpensiveQueries = true, $short = false ) { + protected function getUserPermissionsErrorsInternal( $action, $user, + $doExpensiveQueries = true, $short = false + ) { wfProfileIn( __METHOD__ ); # Read has special handling @@ -2472,7 +2506,7 @@ class Title { return false; } - if ( !isset( $this->mTitleProtection ) ) { + if ( $this->mTitleProtection === null ) { $dbr = wfGetDB( DB_SLAVE ); $res = $dbr->select( 'protected_titles', @@ -2487,30 +2521,6 @@ class Title { return $this->mTitleProtection; } - /** - * Update the title protection status - * - * @deprecated since 1.19; use WikiPage::doUpdateRestrictions() instead. - * @param string $create_perm Permission required for creation - * @param string $reason Reason for protection - * @param string $expiry Expiry timestamp - * @return bool - */ - public function updateTitleProtection( $create_perm, $reason, $expiry ) { - wfDeprecated( __METHOD__, '1.19' ); - - global $wgUser; - - $limit = array( 'create' => $create_perm ); - $expiry = array( 'create' => $expiry ); - - $page = WikiPage::factory( $this ); - $cascade = false; - $status = $page->doUpdateRestrictions( $limit, $expiry, $cascade, $reason, $wgUser ); - - return $status->isOK(); - } - /** * Remove any title protection due to page existing */ @@ -2556,7 +2566,7 @@ class Title { /** * Does the title correspond to a protected article? * - * @param string $action the action the page is protected from, + * @param string $action The action the page is protected from, * by default checks all actions. * @return bool */ @@ -2625,26 +2635,29 @@ class Title { * @since 1.23 */ public function areCascadeProtectionSourcesLoaded( $getPages = true ) { - return $getPages ? isset( $this->mCascadeSources ) : isset( $this->mHasCascadingRestrictions ); + return $getPages ? $this->mCascadeSources !== null : $this->mHasCascadingRestrictions !== null; } /** * Cascading protection: Get the source of any cascading restrictions on this page. * * @param bool $getPages Whether or not to retrieve the actual pages - * that the restrictions have come from. - * @return array|bool Array of Title objects of the pages from which cascading restrictions - * have come, false for none, or true if such restrictions exist, but $getPages - * was not set. The restriction array is an array of each type, each of which - * contains a array of unique groups. + * that the restrictions have come from and the actual restrictions + * themselves. + * @return array Two elements: First is an array of Title objects of the + * pages from which cascading restrictions have come, false for + * none, or true if such restrictions exist but $getPages was not + * set. Second is an array like that returned by + * Title::getAllRestrictions(), or an empty array if $getPages is + * false. */ public function getCascadeProtectionSources( $getPages = true ) { global $wgContLang; $pagerestrictions = array(); - if ( isset( $this->mCascadeSources ) && $getPages ) { + if ( $this->mCascadeSources !== null && $getPages ) { return array( $this->mCascadeSources, $this->mCascadingRestrictions ); - } elseif ( isset( $this->mHasCascadingRestrictions ) && !$getPages ) { + } elseif ( $this->mHasCascadingRestrictions !== null && !$getPages ) { return array( $this->mHasCascadingRestrictions, $pagerestrictions ); } @@ -2743,7 +2756,8 @@ class Title { * Accessor/initialisation for mRestrictions * * @param string $action Action that permission needs to be checked for - * @return array Array of Strings the array of groups allowed to edit this article + * @return array Restriction levels needed to take the action. All levels + * are required. */ public function getRestrictions( $action ) { if ( !$this->mRestrictionsLoaded ) { @@ -2757,9 +2771,8 @@ class Title { /** * Accessor/initialisation for mRestrictions * - * @return array Array of Arrays of Strings the first level indexed by - * action, the second level containing the names of the groups - * allowed to perform each action + * @return array Keys are actions, values are arrays as returned by + * Title::getRestrictions() * @since 1.23 */ public function getAllRestrictions() { @@ -2961,7 +2974,7 @@ class Title { $method = __METHOD__; $dbw = wfGetDB( DB_MASTER ); - $dbw->onTransactionIdle( function() use ( $dbw, $method ) { + $dbw->onTransactionIdle( function () use ( $dbw, $method ) { $dbw->delete( 'page_restrictions', array( 'pr_expiry < ' . $dbw->addQuotes( $dbw->timestamp() ) ), @@ -2990,7 +3003,7 @@ class Title { # alone to cache the result. There's no point in having it hanging # around uninitialized in every Title object; therefore we only add it # if needed and don't declare it statically. - if ( !isset( $this->mHasSubpages ) ) { + if ( $this->mHasSubpages === null ) { $this->mHasSubpages = false; $subpages = $this->getSubpages( 1 ); if ( $subpages instanceof TitleArray ) { @@ -3226,6 +3239,7 @@ class Title { $this->mContentModel = false; $this->mEstimateRevisions = null; $this->mPageLanguage = false; + $this->mDbPageLanguage = null; } /** @@ -3268,7 +3282,7 @@ class Title { // @note: splitTitleString() is a temporary hack to allow MediaWikiTitleCodec to share // the parsing code with Title, while avoiding massive refactoring. // @todo: get rid of secureAndSplit, refactor parsing code. - $parser = $this->getTitleParser(); + $parser = self::getTitleParser(); $parts = $parser->splitTitleString( $dbkey, $this->getDefaultNamespace() ); } catch ( MalformedTitleException $ex ) { return false; @@ -3381,7 +3395,15 @@ class Title { $namespaceFiled = "{$prefix}_namespace"; $titleField = "{$prefix}_title"; - $fields = array( $namespaceFiled, $titleField, 'page_id', 'page_len', 'page_is_redirect', 'page_latest' ); + $fields = array( + $namespaceFiled, + $titleField, + 'page_id', + 'page_len', + 'page_is_redirect', + 'page_latest' + ); + if ( $wgContentHandlerUseDB ) { $fields[] = 'page_content_model'; } @@ -3392,7 +3414,10 @@ class Title { array( "{$prefix}_from" => $id ), __METHOD__, $options, - array( 'page' => array( 'LEFT JOIN', array( "page_namespace=$namespaceFiled", "page_title=$titleField" ) ) ) + array( 'page' => array( + 'LEFT JOIN', + array( "page_namespace=$namespaceFiled", "page_title=$titleField" ) + ) ) ); $retVal = array(); @@ -3428,9 +3453,11 @@ class Title { } /** - * Get an array of Title objects referring to non-existent articles linked from this page + * Get an array of Title objects referring to non-existent articles linked + * from this page. * - * @todo check if needed (used only in SpecialBrokenRedirects.php, and should use redirect table in this case) + * @todo check if needed (used only in SpecialBrokenRedirects.php, and + * should use redirect table in this case). * @return Title[] Array of Title the Title objects */ public function getBrokenLinksFrom() { @@ -3767,7 +3794,13 @@ class Title { $comment .= wfMessage( 'colon-separator' )->inContentLanguage()->text() . $reason; } // @todo FIXME: $params? - $logId = $log->addEntry( 'move_prot', $nt, $comment, array( $this->getPrefixedText() ), $wgUser ); + $logId = $log->addEntry( + 'move_prot', + $nt, + $comment, + array( $this->getPrefixedText() ), + $wgUser + ); // reread inserted pr_ids for log relation $insertedPrIds = $dbw->select( @@ -3783,13 +3816,31 @@ class Title { $log->addRelations( 'pr_id', $logRelationsValues, $logId ); } + // Update *_from_namespace fields as needed + if ( $this->getNamespace() != $nt->getNamespace() ) { + $dbw->update( 'pagelinks', + array( 'pl_from_namespace' => $nt->getNamespace() ), + array( 'pl_from' => $pageid ), + __METHOD__ + ); + $dbw->update( 'templatelinks', + array( 'tl_from_namespace' => $nt->getNamespace() ), + array( 'tl_from' => $pageid ), + __METHOD__ + ); + $dbw->update( 'imagelinks', + array( 'il_from_namespace' => $nt->getNamespace() ), + array( 'il_from' => $pageid ), + __METHOD__ + ); + } + # Update watchlists - $oldnamespace = MWNamespace::getSubject( $this->getNamespace() ); - $newnamespace = MWNamespace::getSubject( $nt->getNamespace() ); $oldtitle = $this->getDBkey(); $newtitle = $nt->getDBkey(); - - if ( $oldnamespace != $newnamespace || $oldtitle != $newtitle ) { + $oldsnamespace = MWNamespace::getSubject( $this->getNamespace() ); + $newsnamespace = MWNamespace::getSubject( $nt->getNamespace() ); + if ( $oldsnamespace != $newsnamespace || $oldtitle != $newtitle ) { WatchedItem::duplicateEntries( $this, $nt ); } @@ -3821,9 +3872,12 @@ class Title { } if ( $createRedirect ) { - if ( $this->getNamespace() == NS_CATEGORY && !wfMessage( 'category-move-redirect-override' )->isDisabled() ) { + if ( $this->getNamespace() == NS_CATEGORY + && !wfMessage( 'category-move-redirect-override' )->inContentLanguage()->isDisabled() + ) { $redirectContent = new WikitextContent( - wfMessage( 'category-move-redirect-override' )->params( $nt->getPrefixedText() )->inContentLanguage()->plain() ); + wfMessage( 'category-move-redirect-override' ) + ->params( $nt->getPrefixedText() )->inContentLanguage()->plain() ); } else { $contentHandler = ContentHandler::getForTitle( $this ); $redirectContent = $contentHandler->makeRedirectContent( $nt, @@ -4039,7 +4093,10 @@ class Title { $this->mArticleID = $row ? intval( $row->page_id ) : 0; $this->mRedirect = $row ? (bool)$row->page_is_redirect : false; $this->mLatestID = $row ? intval( $row->page_latest ) : false; - $this->mContentModel = $row && isset( $row->page_content_model ) ? strval( $row->page_content_model ) : false; + $this->mContentModel = $row && isset( $row->page_content_model ) + ? strval( $row->page_content_model ) + : false; + if ( !$this->mRedirect ) { return false; } @@ -4568,7 +4625,9 @@ class Title { // Use always content language to avoid loading hundreds of languages // to get the link color. global $wgContLang; - list( $name, ) = MessageCache::singleton()->figureMessage( $wgContLang->lcfirst( $this->getText() ) ); + list( $name, ) = MessageCache::singleton()->figureMessage( + $wgContLang->lcfirst( $this->getText() ) + ); $message = wfMessage( $name )->inLanguage( $wgContLang )->useDatabase( false ); return $message->exists(); } @@ -4588,7 +4647,9 @@ class Title { return false; } - list( $name, $lang ) = MessageCache::singleton()->figureMessage( $wgContLang->lcfirst( $this->getText() ) ); + list( $name, $lang ) = MessageCache::singleton()->figureMessage( + $wgContLang->lcfirst( $this->getText() ) + ); $message = wfMessage( $name )->inLanguage( $lang )->useDatabase( false ); if ( $message->exists() ) { @@ -4608,10 +4669,14 @@ class Title { return false; } + if ( $this->mArticleID === 0 ) { + return true; // avoid gap locking if we know it's not there + } + $method = __METHOD__; $dbw = wfGetDB( DB_MASTER ); $conds = $this->pageCond(); - $dbw->onTransactionIdle( function() use ( $dbw, $conds, $method ) { + $dbw->onTransactionIdle( function () use ( $dbw, $conds, $method ) { $dbw->update( 'page', array( 'page_touched' => $dbw->timestamp() ), @@ -4645,7 +4710,9 @@ class Title { * @return string Last-touched timestamp */ public function getTouched( $db = null ) { - $db = isset( $db ) ? $db : wfGetDB( DB_SLAVE ); + if ( $db === null ) { + $db = wfGetDB( DB_SLAVE ); + } $touched = $db->selectField( 'page', 'page_touched', $this->pageCond(), __METHOD__ ); return $touched; } @@ -4850,16 +4917,26 @@ class Title { return $wgLang; } + // Checking if DB language is set + if ( $this->mDbPageLanguage ) { + wfProfileOut( __METHOD__ ); + return wfGetLangObj( $this->mDbPageLanguage ); + } + if ( !$this->mPageLanguage || $this->mPageLanguage[1] !== $wgLanguageCode ) { - // Note that this may depend on user settings, so the cache should be only per-request. - // NOTE: ContentHandler::getPageLanguage() may need to load the content to determine the page language! - // Checking $wgLanguageCode hasn't changed for the benefit of unit tests. + // Note that this may depend on user settings, so the cache should + // be only per-request. + // NOTE: ContentHandler::getPageLanguage() may need to load the + // content to determine the page language! + // Checking $wgLanguageCode hasn't changed for the benefit of unit + // tests. $contentHandler = ContentHandler::getForTitle( $this ); $langObj = wfGetLangObj( $contentHandler->getPageLanguage( $this ) ); $this->mPageLanguage = array( $langObj->getCode(), $wgLanguageCode ); } else { $langObj = wfGetLangObj( $this->mPageLanguage[0] ); } + wfProfileOut( __METHOD__ ); return $langObj; } @@ -4886,8 +4963,9 @@ class Title { return $wgLang; } - //NOTE: can't be cached persistently, depends on user settings - //NOTE: ContentHandler::getPageViewLanguage() may need to load the content to determine the page language! + // @note Can't be cached persistently, depends on user settings. + // @note ContentHandler::getPageViewLanguage() may need to load the + // content to determine the page language! $contentHandler = ContentHandler::getForTitle( $this ); $pageLang = $contentHandler->getPageViewLanguage( $this ); return $pageLang;