Merge "Revert "Revert "Title::checkUserBlock should call User::isBlockedFrom for...
[lhc/web/wiklou.git] / includes / Title.php
index c151f4a..3496668 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;
 
@@ -954,6 +954,7 @@ class Title implements LinkTarget {
 
        /**
         * Get the DB key with the initial letter case as specified by the user
+        * @deprecated since 1.33; please use Title::getDBKey() instead
         *
         * @return string DB key
         */
@@ -978,6 +979,8 @@ class Title implements LinkTarget {
        /**
         * Get the page's content model id, see the CONTENT_MODEL_XXX constants.
         *
+        * @todo Deprecate this in favor of SlotRecord::getModel()
+        *
         * @param int $flags A bit field; may be Title::GAID_FOR_UPDATE to select for update
         * @return string Content model id
         */
@@ -1659,7 +1662,7 @@ class Title implements LinkTarget {
                        $p = $this->mInterwiki . ':';
                }
 
-               if ( 0 != $this->mNamespace ) {
+               if ( $this->mNamespace != 0 ) {
                        $nsText = $this->getNsText();
 
                        if ( $nsText === false ) {
@@ -2696,10 +2699,14 @@ class Title implements LinkTarget {
                }
 
                // Determine if the user is blocked from this action on this page.
-               try {
+               // What gets passed into this method is a user right, not an action nmae.
+               // There is no way to instantiate an action by restriction. However, this
+               // 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 ) ) {
                        // @todo FIXME: Pass the relevant context into this function.
                        $action = Action::factory( $action, WikiPage::factory( $this ), RequestContext::getMain() );
-               } catch ( Exception $e ) {
+               } else {
                        $action = null;
                }
 
@@ -2710,7 +2717,7 @@ class Title implements LinkTarget {
                                // @todo FIXME: Pass the relevant context into this function.
                                $errors[] = $block
                                        ? $block->getPermissionsError( RequestContext::getMain() )
-                                       : [ 'badaccess-group0' ];
+                                       : [ 'actionblockedtext' ];
                        }
                }
 
@@ -2874,10 +2881,12 @@ class Title implements LinkTarget {
                }
 
                $errors = [];
-               while ( count( $checks ) > 0 &&
-                               !( $short && count( $errors ) > 0 ) ) {
-                       $method = array_shift( $checks );
+               foreach ( $checks as $method ) {
                        $errors = $this->$method( $action, $user, $errors, $rigor, $short );
+
+                       if ( $short && $errors !== [] ) {
+                               break;
+                       }
                }
 
                return $errors;
@@ -3291,6 +3300,9 @@ class Title implements LinkTarget {
         * Example: "edit=autoconfirmed,sysop:move=sysop"
         */
        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();
@@ -3361,35 +3373,50 @@ 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 int $flags A bit field. If self::READ_LATEST is set, skip replicas and read
+        *  from the master DB.
         */
-       public function loadRestrictions( $oldFashionedRestrictions = null ) {
-               if ( $this->mRestrictionsLoaded ) {
+       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() ),
-                               $cache::TTL_DAY,
-                               function ( $curValue, &$ttl, array &$setOpts ) use ( $fname ) {
-                                       $dbr = wfGetDB( DB_REPLICA );
-
-                                       $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 );
                } else {
@@ -3587,7 +3614,7 @@ class Title implements LinkTarget {
                        $this->mArticleID = $linkCache->addLinkObj( $this );
                        $linkCache->forUpdate( $oldUpdate );
                } else {
-                       if ( -1 == $this->mArticleID ) {
+                       if ( $this->mArticleID == -1 ) {
                                $this->mArticleID = $linkCache->addLinkObj( $this );
                        }
                }
@@ -5234,10 +5261,9 @@ class Title implements LinkTarget {
 
                if ( MWNamespace::hasSubpages( $this->mNamespace ) ) {
                        // Optional notice for page itself and any parent page
-                       $parts = explode( '/', $this->mDbkeyform );
                        $editnotice_base = $editnotice_ns;
-                       while ( count( $parts ) > 0 ) {
-                               $editnotice_base .= '-' . array_shift( $parts );
+                       foreach ( explode( '/', $this->mDbkeyform ) as $part ) {
+                               $editnotice_base .= '-' . $part;
                                $msg = wfMessage( $editnotice_base );
                                if ( $msg->exists() ) {
                                        $html = $msg->parseAsBlock();