Merge "Add API warnings when upload is same as older versions"
[lhc/web/wiklou.git] / includes / Title.php
index 4555f16..24bad81 100644 (file)
@@ -394,7 +394,7 @@ class Title implements LinkTarget {
         * @return Title|null The new object, or null on an error
         */
        public static function newFromID( $id, $flags = 0 ) {
-               $db = ( $flags & self::GAID_FOR_UPDATE ) ? wfGetDB( DB_MASTER ) : wfGetDB( DB_SLAVE );
+               $db = ( $flags & self::GAID_FOR_UPDATE ) ? wfGetDB( DB_MASTER ) : wfGetDB( DB_REPLICA );
                $row = $db->selectRow(
                        'page',
                        self::getSelectFields(),
@@ -419,7 +419,7 @@ class Title implements LinkTarget {
                if ( !count( $ids ) ) {
                        return [];
                }
-               $dbr = wfGetDB( DB_SLAVE );
+               $dbr = wfGetDB( DB_REPLICA );
 
                $res = $dbr->select(
                        'page',
@@ -500,7 +500,7 @@ class Title implements LinkTarget {
         * @param string $interwiki The interwiki prefix
         * @return Title The new object
         */
-       public static function &makeTitle( $ns, $title, $fragment = '', $interwiki = '' ) {
+       public static function makeTitle( $ns, $title, $fragment = '', $interwiki = '' ) {
                $t = new Title();
                $t->mInterwiki = $interwiki;
                $t->mFragment = $fragment;
@@ -561,7 +561,7 @@ class Title implements LinkTarget {
         * @return Title|null An object representing the article, or null if no such article was found
         */
        public static function nameOf( $id ) {
-               $dbr = wfGetDB( DB_SLAVE );
+               $dbr = wfGetDB( DB_REPLICA );
 
                $s = $dbr->selectRow(
                        'page',
@@ -1773,12 +1773,13 @@ class Title implements LinkTarget {
         *
         * @param array $query
         * @param bool $query2
-        * @param string $proto Protocol to use; setting this will cause a full URL to be used
+        * @param string|int|bool $proto A PROTO_* constant on how the URL should be expanded,
+        *                               or false (default) for no expansion
         * @see self::getLocalURL for the arguments.
         * @return string The URL
         */
-       public function getLinkURL( $query = '', $query2 = false, $proto = PROTO_RELATIVE ) {
-               if ( $this->isExternal() || $proto !== PROTO_RELATIVE ) {
+       public function getLinkURL( $query = '', $query2 = false, $proto = false ) {
+               if ( $this->isExternal() || $proto !== false ) {
                        $ret = $this->getFullURL( $query, $query2, $proto );
                } elseif ( $this->getPrefixedText() === '' && $this->hasFragment() ) {
                        $ret = $this->getFragmentForURL();
@@ -1885,8 +1886,8 @@ class Title implements LinkTarget {
         * @param string $action Action that permission needs to be checked for
         * @param User $user User to check
         * @param string $rigor One of (quick,full,secure)
-        *   - quick  : does cheap permission checks from slaves (usable for GUI creation)
-        *   - full   : does cheap and expensive checks possibly from a slave
+        *   - quick  : does cheap permission checks from replica DBs (usable for GUI creation)
+        *   - full   : does cheap and expensive checks possibly from a replica DB
         *   - secure : does cheap and expensive checks, using the master as needed
         * @param array $ignoreErrors Array of Strings Set this to a list of message keys
         *   whose corresponding errors may be ignored.
@@ -2270,13 +2271,17 @@ class Title implements LinkTarget {
         * @return array List of errors
         */
        private function checkUserBlock( $action, $user, $errors, $rigor, $short ) {
+               global $wgEmailConfirmToEdit, $wgBlockDisablesLogin;
                // Account creation blocks handled at userlogin.
                // Unblocking handled in SpecialUnblock
                if ( $rigor === 'quick' || in_array( $action, [ 'createaccount', 'unblock' ] ) ) {
                        return $errors;
                }
 
-               global $wgEmailConfirmToEdit;
+               // Optimize for a very common case
+               if ( $action === 'read' && !$wgBlockDisablesLogin ) {
+                       return $errors;
+               }
 
                if ( $wgEmailConfirmToEdit && !$user->isEmailConfirmed() ) {
                        $errors[] = [ 'confirmedittext' ];
@@ -2318,8 +2323,8 @@ class Title implements LinkTarget {
                        # If the user is allowed to read pages, he is allowed to read all pages
                        $whitelisted = true;
                } elseif ( $this->isSpecial( 'Userlogin' )
-                       || $this->isSpecial( 'ChangePassword' )
                        || $this->isSpecial( 'PasswordReset' )
+                       || $this->isSpecial( 'Userlogout' )
                ) {
                        # Always grant access to the login page.
                        # Even anons need to be able to log in.
@@ -2411,8 +2416,8 @@ class Title implements LinkTarget {
         * @param string $action Action that permission needs to be checked for
         * @param User $user User to check
         * @param string $rigor One of (quick,full,secure)
-        *   - quick  : does cheap permission checks from slaves (usable for GUI creation)
-        *   - full   : does cheap and expensive checks possibly from a slave
+        *   - quick  : does cheap permission checks from replica DBs (usable for GUI creation)
+        *   - full   : does cheap and expensive checks possibly from a replica DB
         *   - secure : does cheap and expensive checks, using the master as needed
         * @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.
@@ -2433,6 +2438,7 @@ class Title implements LinkTarget {
                        $checks = [
                                'checkPermissionHooks',
                                'checkReadPermissions',
+                               'checkUserBlock', // for wgBlockDisablesLogin
                        ];
                # Don't call checkSpecialsAndNSPermissions or checkCSSandJSPermissions
                # here as it will lead to duplicate error messages. This is okay to do
@@ -2534,7 +2540,7 @@ class Title implements LinkTarget {
                }
 
                if ( $this->mTitleProtection === null ) {
-                       $dbr = wfGetDB( DB_SLAVE );
+                       $dbr = wfGetDB( DB_REPLICA );
                        $res = $dbr->select(
                                'protected_titles',
                                [
@@ -2702,7 +2708,7 @@ class Title implements LinkTarget {
                        return [ $this->mHasCascadingRestrictions, $pagerestrictions ];
                }
 
-               $dbr = wfGetDB( DB_SLAVE );
+               $dbr = wfGetDB( DB_REPLICA );
 
                if ( $this->getNamespace() == NS_FILE ) {
                        $tables = [ 'imagelinks', 'page_restrictions' ];
@@ -2869,7 +2875,7 @@ class Title implements LinkTarget {
         *   restrictions from page table (pre 1.10)
         */
        public function loadRestrictionsFromRows( $rows, $oldFashionedRestrictions = null ) {
-               $dbr = wfGetDB( DB_SLAVE );
+               $dbr = wfGetDB( DB_REPLICA );
 
                $restrictionTypes = $this->getRestrictionTypes();
 
@@ -2943,7 +2949,7 @@ class Title implements LinkTarget {
         */
        public function loadRestrictions( $oldFashionedRestrictions = null ) {
                if ( !$this->mRestrictionsLoaded ) {
-                       $dbr = wfGetDB( DB_SLAVE );
+                       $dbr = wfGetDB( DB_REPLICA );
                        if ( $this->exists() ) {
                                $res = $dbr->select(
                                        'page_restrictions',
@@ -3063,7 +3069,7 @@ class Title implements LinkTarget {
                        return [];
                }
 
-               $dbr = wfGetDB( DB_SLAVE );
+               $dbr = wfGetDB( DB_REPLICA );
                $conds['page_namespace'] = $this->getNamespace();
                $conds[] = 'page_title ' . $dbr->buildLike( $this->getDBkey() . '/', $dbr->anyString() );
                $options = [];
@@ -3090,7 +3096,7 @@ class Title implements LinkTarget {
                if ( $this->getNamespace() < 0 ) {
                        $n = 0;
                } else {
-                       $dbr = wfGetDB( DB_SLAVE );
+                       $dbr = wfGetDB( DB_REPLICA );
 
                        $n = $dbr->selectField( 'archive', 'COUNT(*)',
                                [ 'ar_namespace' => $this->getNamespace(), 'ar_title' => $this->getDBkey() ],
@@ -3115,7 +3121,7 @@ class Title implements LinkTarget {
                if ( $this->getNamespace() < 0 ) {
                        return false;
                }
-               $dbr = wfGetDB( DB_SLAVE );
+               $dbr = wfGetDB( DB_REPLICA );
                $deleted = (bool)$dbr->selectField( 'archive', '1',
                        [ 'ar_namespace' => $this->getNamespace(), 'ar_title' => $this->getDBkey() ],
                        __METHOD__
@@ -3369,7 +3375,7 @@ class Title implements LinkTarget {
                if ( count( $options ) > 0 ) {
                        $db = wfGetDB( DB_MASTER );
                } else {
-                       $db = wfGetDB( DB_SLAVE );
+                       $db = wfGetDB( DB_REPLICA );
                }
 
                $res = $db->select(
@@ -3431,7 +3437,7 @@ class Title implements LinkTarget {
                        return [];
                }
 
-               $db = wfGetDB( DB_SLAVE );
+               $db = wfGetDB( DB_REPLICA );
 
                $blNamespace = "{$prefix}_namespace";
                $blTitle = "{$prefix}_title";
@@ -3494,7 +3500,7 @@ class Title implements LinkTarget {
                        return [];
                }
 
-               $dbr = wfGetDB( DB_SLAVE );
+               $dbr = wfGetDB( DB_REPLICA );
                $res = $dbr->select(
                        [ 'page', 'pagelinks' ],
                        [ 'pl_namespace', 'pl_title' ],
@@ -3854,7 +3860,7 @@ class Title implements LinkTarget {
                        return $data;
                }
 
-               $dbr = wfGetDB( DB_SLAVE );
+               $dbr = wfGetDB( DB_REPLICA );
 
                $res = $dbr->select(
                        'categorylinks',
@@ -3922,7 +3928,7 @@ class Title implements LinkTarget {
         * @return int|bool Old revision ID, or false if none exists
         */
        public function getPreviousRevisionID( $revId, $flags = 0 ) {
-               $db = ( $flags & self::GAID_FOR_UPDATE ) ? wfGetDB( DB_MASTER ) : wfGetDB( DB_SLAVE );
+               $db = ( $flags & self::GAID_FOR_UPDATE ) ? wfGetDB( DB_MASTER ) : wfGetDB( DB_REPLICA );
                $revId = $db->selectField( 'revision', 'rev_id',
                        [
                                'rev_page' => $this->getArticleID( $flags ),
@@ -3947,7 +3953,7 @@ class Title implements LinkTarget {
         * @return int|bool Next revision ID, or false if none exists
         */
        public function getNextRevisionID( $revId, $flags = 0 ) {
-               $db = ( $flags & self::GAID_FOR_UPDATE ) ? wfGetDB( DB_MASTER ) : wfGetDB( DB_SLAVE );
+               $db = ( $flags & self::GAID_FOR_UPDATE ) ? wfGetDB( DB_MASTER ) : wfGetDB( DB_REPLICA );
                $revId = $db->selectField( 'revision', 'rev_id',
                        [
                                'rev_page' => $this->getArticleID( $flags ),
@@ -3973,7 +3979,7 @@ class Title implements LinkTarget {
        public function getFirstRevision( $flags = 0 ) {
                $pageId = $this->getArticleID( $flags );
                if ( $pageId ) {
-                       $db = ( $flags & self::GAID_FOR_UPDATE ) ? wfGetDB( DB_MASTER ) : wfGetDB( DB_SLAVE );
+                       $db = ( $flags & self::GAID_FOR_UPDATE ) ? wfGetDB( DB_MASTER ) : wfGetDB( DB_REPLICA );
                        $row = $db->selectRow( 'revision', Revision::selectFields(),
                                [ 'rev_page' => $pageId ],
                                __METHOD__,
@@ -4003,7 +4009,7 @@ class Title implements LinkTarget {
         * @return bool
         */
        public function isNewPage() {
-               $dbr = wfGetDB( DB_SLAVE );
+               $dbr = wfGetDB( DB_REPLICA );
                return (bool)$dbr->selectField( 'page', 'page_is_new', $this->pageCond(), __METHOD__ );
        }
 
@@ -4020,7 +4026,7 @@ class Title implements LinkTarget {
                }
 
                if ( $this->mIsBigDeletion === null ) {
-                       $dbr = wfGetDB( DB_SLAVE );
+                       $dbr = wfGetDB( DB_REPLICA );
 
                        $revCount = $dbr->selectRowCount(
                                'revision',
@@ -4047,7 +4053,7 @@ class Title implements LinkTarget {
                }
 
                if ( $this->mEstimateRevisions === null ) {
-                       $dbr = wfGetDB( DB_SLAVE );
+                       $dbr = wfGetDB( DB_REPLICA );
                        $this->mEstimateRevisions = $dbr->estimateRowCount( 'revision', '*',
                                [ 'rev_page' => $this->getArticleID() ], __METHOD__ );
                }
@@ -4074,7 +4080,7 @@ class Title implements LinkTarget {
                if ( !$old || !$new ) {
                        return 0; // nothing to compare
                }
-               $dbr = wfGetDB( DB_SLAVE );
+               $dbr = wfGetDB( DB_REPLICA );
                $conds = [
                        'rev_page' => $this->getArticleID(),
                        'rev_timestamp > ' . $dbr->addQuotes( $dbr->timestamp( $old->getTimestamp() ) ),
@@ -4152,7 +4158,7 @@ class Title implements LinkTarget {
                        }
                        return $authors;
                }
-               $dbr = wfGetDB( DB_SLAVE );
+               $dbr = wfGetDB( DB_REPLICA );
                $res = $dbr->select( 'revision', 'DISTINCT rev_user_text',
                        [
                                'rev_page' => $this->getArticleID(),
@@ -4366,19 +4372,23 @@ class Title implements LinkTarget {
                        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, $purgeTime ) {
-                       $dbTimestamp = $dbw->timestamp( $purgeTime ?: time() );
-
-                       $dbw->update(
-                               'page',
-                               [ 'page_touched' => $dbTimestamp ],
-                               $conds + [ 'page_touched < ' . $dbw->addQuotes( $dbTimestamp ) ],
-                               $method
-                       );
-               } );
+               DeferredUpdates::addUpdate(
+                       new AutoCommitUpdate(
+                               wfGetDB( DB_MASTER ),
+                               __METHOD__,
+                               function ( IDatabase $dbw, $fname ) use ( $conds, $purgeTime ) {
+                                       $dbTimestamp = $dbw->timestamp( $purgeTime ?: time() );
+                                       $dbw->update(
+                                               'page',
+                                               [ 'page_touched' => $dbTimestamp ],
+                                               $conds + [ 'page_touched < ' . $dbw->addQuotes( $dbTimestamp ) ],
+                                               $fname
+                                       );
+                               }
+                       ),
+                       DeferredUpdates::PRESEND
+               );
 
                return true;
        }
@@ -4403,7 +4413,7 @@ class Title implements LinkTarget {
         */
        public function getTouched( $db = null ) {
                if ( $db === null ) {
-                       $db = wfGetDB( DB_SLAVE );
+                       $db = wfGetDB( DB_REPLICA );
                }
                $touched = $db->selectField( 'page', 'page_touched', $this->pageCond(), __METHOD__ );
                return $touched;
@@ -4487,7 +4497,7 @@ class Title implements LinkTarget {
        public function getRedirectsHere( $ns = null ) {
                $redirs = [];
 
-               $dbr = wfGetDB( DB_SLAVE );
+               $dbr = wfGetDB( DB_REPLICA );
                $where = [
                        'rd_namespace' => $this->getNamespace(),
                        'rd_title' => $this->getDBkey(),
@@ -4554,10 +4564,10 @@ class Title implements LinkTarget {
         * @return bool
         */
        public function canUseNoindex() {
-               global $wgContentNamespaces, $wgExemptFromUserRobotsControl;
+               global $wgExemptFromUserRobotsControl;
 
                $bannedNamespaces = is_null( $wgExemptFromUserRobotsControl )
-                       ? $wgContentNamespaces
+                       ? MWNamespace::getContentNamespaces()
                        : $wgExemptFromUserRobotsControl;
 
                return !in_array( $this->mNamespace, $bannedNamespaces );