Improve docs for Title::getInternalURL/getCanonicalURL
[lhc/web/wiklou.git] / includes / Title.php
index 0c1d32a..057880c 100644 (file)
@@ -36,7 +36,7 @@ use MediaWiki\MediaWikiServices;
  * @note Consider using a TitleValue object instead. TitleValue is more lightweight
  *       and does not rely on global state or the database.
  */
-class Title implements LinkTarget {
+class Title implements LinkTarget, IDBAccessObject {
        /** @var MapCacheLRU */
        static private $titleCache = null;
 
@@ -1609,11 +1609,15 @@ class Title implements LinkTarget {
        public function getFragmentForURL() {
                if ( !$this->hasFragment() ) {
                        return '';
-               } elseif ( $this->isExternal()
-                       && !self::getInterwikiLookup()->fetch( $this->mInterwiki )->isLocal()
-               ) {
-                       return '#' . Sanitizer::escapeIdForExternalInterwiki( $this->mFragment );
+               } elseif ( $this->isExternal() ) {
+                       // Note: If the interwiki is unknown, it's treated as a namespace on the local wiki,
+                       // so we treat it like a local interwiki.
+                       $interwiki = self::getInterwikiLookup()->fetch( $this->mInterwiki );
+                       if ( $interwiki && !$interwiki->isLocal() ) {
+                               return '#' . Sanitizer::escapeIdForExternalInterwiki( $this->mFragment );
+                       }
                }
+
                return '#' . Sanitizer::escapeIdForLink( $this->mFragment );
        }
 
@@ -2100,8 +2104,8 @@ class Title implements LinkTarget {
         * protocol-relative, the URL will be expanded to http://
         *
         * @see self::getLocalURL for the arguments.
-        * @param string $query
-        * @param string|bool $query2
+        * @param string|string[] $query
+        * @param string|bool $query2 Deprecated
         * @return string The URL
         */
        public function getInternalURL( $query = '', $query2 = false ) {
@@ -2123,8 +2127,8 @@ class Title implements LinkTarget {
         * NOTE: Unlike getInternalURL(), the canonical URL includes the fragment
         *
         * @see self::getLocalURL for the arguments.
-        * @param string $query
-        * @param string|bool $query2
+        * @param string|string[] $query
+        * @param string|bool $query2 Deprecated
         * @return string The URL
         * @since 1.18
         */
@@ -2704,8 +2708,13 @@ class Title implements LinkTarget {
                // will get the action where the restriction is the same. This may result
                // in actions being blocked that shouldn't be.
                if ( Action::exists( $action ) ) {
+                       // Clone the title to prevent mutations to this object which is done
+                       // by Title::loadFromRow() in WikiPage::loadFromRow().
+                       $page = WikiPage::factory( clone $this );
+                       // Creating an action will perform several database queries to ensure that
+                       // the action has not been overridden by the content type.
                        // @todo FIXME: Pass the relevant context into this function.
-                       $action = Action::factory( $action, WikiPage::factory( $this ), RequestContext::getMain() );
+                       $action = Action::factory( $action, $page, RequestContext::getMain() );
                } else {
                        $action = null;
                }
@@ -3298,13 +3307,12 @@ class Title implements LinkTarget {
         * indicating who can move or edit the page from the page table, (pre 1.10) rows.
         * Edit and move sections are separated by a colon
         * Example: "edit=autoconfirmed,sysop:move=sysop"
-        * @param bool $readLatest When true, skip replicas and read from the master DB.
         */
-       public function loadRestrictionsFromRows(
-               $rows, $oldFashionedRestrictions = null, $readLatest = false
-       ) {
-               $whichDb = $readLatest ? DB_MASTER : DB_REPLICA;
-               $dbr = wfGetDB( $whichDb );
+       public function loadRestrictionsFromRows( $rows, $oldFashionedRestrictions = null ) {
+               // This function will only read rows from a table that we migrated away
+               // from before adding READ_LATEST support to loadRestrictions, so we
+               // don't need to support reading from DB_MASTER here.
+               $dbr = wfGetDB( DB_REPLICA );
 
                $restrictionTypes = $this->getRestrictionTypes();
 
@@ -3374,39 +3382,52 @@ class Title implements LinkTarget {
         * indicating who can move or edit the page from the page table, (pre 1.10) rows.
         * Edit and move sections are separated by a colon
         * Example: "edit=autoconfirmed,sysop:move=sysop"
-        * @param bool $readLatest When true, skip replicas and read from the master DB.
+        * @param int $flags A bit field. If self::READ_LATEST is set, skip replicas and read
+        *  from the master DB.
         */
-       public function loadRestrictions( $oldFashionedRestrictions = null, $readLatest = false ) {
+       public function loadRestrictions( $oldFashionedRestrictions = null, $flags = 0 ) {
+               $readLatest = DBAccessObjectUtils::hasFlags( $flags, self::READ_LATEST );
                if ( $this->mRestrictionsLoaded && !$readLatest ) {
                        return;
                }
 
+               // TODO: should probably pass $flags into getArticleID, but it seems hacky
+               // to mix READ_LATEST and GAID_FOR_UPDATE, even if they have the same value.
+               // Maybe deprecate GAID_FOR_UPDATE now that we implement IDBAccessObject?
                $id = $this->getArticleID();
                if ( $id ) {
-                       $cache = ObjectCache::getMainWANInstance();
                        $fname = __METHOD__;
-                       $rows = $cache->getWithSetCallback(
-                               // Page protections always leave a new null revision
-                               $cache->makeKey( 'page-restrictions', $id, $this->getLatestRevID(), $readLatest ),
-                               $cache::TTL_DAY,
-                               function ( $curValue, &$ttl, array &$setOpts ) use ( $fname, $readLatest ) {
-                                       $whichDb = $readLatest ? DB_MASTER : DB_REPLICA;
-                                       $dbr = wfGetDB( $whichDb );
-
-                                       $setOpts += Database::getCacheSetOptions( $dbr );
-
-                                       return iterator_to_array(
-                                               $dbr->select(
-                                                       'page_restrictions',
-                                                       [ 'pr_type', 'pr_expiry', 'pr_level', 'pr_cascade' ],
-                                                       [ 'pr_page' => $this->getArticleID() ],
-                                                       $fname
-                                               )
-                                       );
-                               }
-                       );
+                       $loadRestrictionsFromDb = function ( Database $dbr ) use ( $fname, $id ) {
+                               return iterator_to_array(
+                                       $dbr->select(
+                                               'page_restrictions',
+                                               [ 'pr_type', 'pr_expiry', 'pr_level', 'pr_cascade' ],
+                                               [ 'pr_page' => $id ],
+                                               $fname
+                                       )
+                               );
+                       };
+
+                       if ( $readLatest ) {
+                               $dbr = wfGetDB( DB_MASTER );
+                               $rows = $loadRestrictionsFromDb( $dbr );
+                       } else {
+                               $cache = ObjectCache::getMainWANInstance();
+                               $rows = $cache->getWithSetCallback(
+                                       // Page protections always leave a new null revision
+                                       $cache->makeKey( 'page-restrictions', $id, $this->getLatestRevID() ),
+                                       $cache::TTL_DAY,
+                                       function ( $curValue, &$ttl, array &$setOpts ) use ( $loadRestrictionsFromDb ) {
+                                               $dbr = wfGetDB( DB_REPLICA );
+
+                                               $setOpts += Database::getCacheSetOptions( $dbr );
+
+                                               return $loadRestrictionsFromDb( $dbr );
+                                       }
+                               );
+                       }
 
-                       $this->loadRestrictionsFromRows( $rows, $oldFashionedRestrictions, $readLatest );
+                       $this->loadRestrictionsFromRows( $rows, $oldFashionedRestrictions );
                } else {
                        $title_protection = $this->getTitleProtectionInternal();