Add missing IDatabase type hints to all doAtomicSection() calls
[lhc/web/wiklou.git] / includes / user / User.php
index fa74cb3..6608d99 100644 (file)
@@ -46,18 +46,20 @@ use Wikimedia\Rdbms\IDatabase;
  * of the database.
  */
 class User implements IDBAccessObject, UserIdentity {
+
        /**
-        * @const int Number of characters in user_token field.
+        * Number of characters required for the user_token field.
         */
        const TOKEN_LENGTH = 32;
 
        /**
-        * @const string An invalid value for user_token
+        * An invalid string value for the user_token field.
         */
        const INVALID_TOKEN = '*** INVALID ***';
 
        /**
-        * @const int Serialized record version.
+        * Version number to tag cached versions of serialized User objects. Should be increased when
+        * {@link $mCacheVars} or one of it's members changes.
         */
        const VERSION = 13;
 
@@ -1288,17 +1290,6 @@ class User implements IDBAccessObject, UserIdentity {
                return $name;
        }
 
-       /**
-        * Return a random password.
-        *
-        * @deprecated since 1.27, use PasswordFactory::generateRandomPasswordString()
-        * @return string New random password
-        */
-       public static function randomPassword() {
-               global $wgMinimalPasswordLength;
-               return PasswordFactory::generateRandomPasswordString( $wgMinimalPasswordLength );
-       }
-
        /**
         * Set cached properties to default.
         *
@@ -1405,10 +1396,10 @@ class User implements IDBAccessObject, UserIdentity {
        public function trackBlockWithCookie() {
                $block = $this->getBlock();
 
-               if ( $block && $this->getRequest()->getCookie( 'BlockID' ) === null ) {
-                       if ( $block->shouldTrackWithCookie( $this->isAnon() ) ) {
-                               $block->setCookie( $this->getRequest()->response() );
-                       }
+               if ( $block && $this->getRequest()->getCookie( 'BlockID' ) === null
+                       && $block->shouldTrackWithCookie( $this->isAnon() )
+               ) {
+                       $block->setCookie( $this->getRequest()->response() );
                }
        }
 
@@ -1671,11 +1662,11 @@ class User implements IDBAccessObject, UserIdentity {
         * protected against race conditions using a compare-and-set (CAS) mechanism
         * based on comparing $this->mTouched with the user_touched field.
         *
-        * @param Database $db
+        * @param IDatabase $db
         * @param array $conditions WHERE conditions for use with Database::update
         * @return array WHERE conditions for use with Database::update
         */
-       protected function makeUpdateConditions( Database $db, array $conditions ) {
+       protected function makeUpdateConditions( IDatabase $db, array $conditions ) {
                if ( $this->mTouched ) {
                        // CAS check: only update if the row wasn't changed sicne it was loaded.
                        $conditions['user_touched'] = $db->timestamp( $this->mTouched );
@@ -1715,7 +1706,7 @@ class User implements IDBAccessObject, UserIdentity {
 
                if ( $success ) {
                        $this->mTouched = $newTouched;
-                       $this->clearSharedCache();
+                       $this->clearSharedCache( 'changed' );
                } else {
                        // Clears on failure too since that is desired if the cache is stale
                        $this->clearSharedCache( 'refresh' );
@@ -2205,6 +2196,9 @@ class User implements IDBAccessObject, UserIdentity {
 
                // Set the user limit key
                if ( $userLimit !== false ) {
+                       // phan is confused because &can-bypass's value is a bool, so it assumes
+                       // that $userLimit is also a bool here.
+                       // @phan-suppress-next-line PhanTypeInvalidExpressionArrayDestructuring
                        list( $max, $period ) = $userLimit;
                        wfDebug( __METHOD__ . ": effective user limit: $max in {$period}s\n" );
                        $keys[$cache->makeKey( 'limiter', $action, 'user', $id )] = $userLimit;
@@ -2236,6 +2230,9 @@ class User implements IDBAccessObject, UserIdentity {
 
                $triggered = false;
                foreach ( $keys as $key => $limit ) {
+                       // phan is confused because &can-bypass's value is a bool, so it assumes
+                       // that $userLimit is also a bool here.
+                       // @phan-suppress-next-line PhanTypeInvalidExpressionArrayDestructuring
                        list( $max, $period ) = $limit;
                        $summary = "(limit $max in {$period}s)";
                        $count = $cache->get( $key );
@@ -2291,29 +2288,15 @@ class User implements IDBAccessObject, UserIdentity {
         * @param Title $title Title to check
         * @param bool $fromReplica Whether to check the replica DB instead of the master
         * @return bool
+        * @throws MWException
+        *
+        * @deprecated since 1.33,
+        * use MediaWikiServices::getInstance()->getPermissionManager()->isBlockedFrom(..)
+        *
         */
        public function isBlockedFrom( $title, $fromReplica = false ) {
-               $blocked = $this->isHidden();
-
-               if ( !$blocked ) {
-                       $block = $this->getBlock( $fromReplica );
-                       if ( $block ) {
-                               // Special handling for a user's own talk page. The block is not aware
-                               // of the user, so this must be done here.
-                               if ( $title->equals( $this->getTalkPage() ) ) {
-                                       $blocked = $block->appliesToUsertalk( $title );
-                               } else {
-                                       $blocked = $block->appliesToTitle( $title );
-                               }
-                       }
-               }
-
-               // only for the purpose of the hook. We really don't need this here.
-               $allowUsertalk = $this->mAllowUsertalk;
-
-               Hooks::run( 'UserIsBlockedFrom', [ $this, $title, &$blocked, &$allowUsertalk ] );
-
-               return $blocked;
+               return MediaWikiServices::getInstance()->getPermissionManager()
+                       ->isBlockedFrom( $this, $title, $fromReplica );
        }
 
        /**
@@ -2779,29 +2762,26 @@ class User implements IDBAccessObject, UserIdentity {
         *
         * Called implicitly from invalidateCache() and saveSettings().
         *
-        * @param string $mode Use 'refresh' to clear now; otherwise before DB commit
+        * @param string $mode Use 'refresh' to clear now or 'changed' to clear before DB commit
         */
-       public function clearSharedCache( $mode = 'changed' ) {
+       public function clearSharedCache( $mode = 'refresh' ) {
                if ( !$this->getId() ) {
                        return;
                }
 
+               $lb = MediaWikiServices::getInstance()->getDBLoadBalancer();
                $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
                $key = $this->getCacheKey( $cache );
+
                if ( $mode === 'refresh' ) {
-                       $cache->delete( $key, 1 );
+                       $cache->delete( $key, 1 ); // low tombstone/"hold-off" TTL
                } else {
-                       $lb = MediaWikiServices::getInstance()->getDBLoadBalancer();
-                       if ( $lb->hasOrMadeRecentMasterChanges() ) {
-                               $lb->getConnection( DB_MASTER )->onTransactionPreCommitOrIdle(
-                                       function () use ( $cache, $key ) {
-                                               $cache->delete( $key );
-                                       },
-                                       __METHOD__
-                               );
-                       } else {
-                               $cache->delete( $key );
-                       }
+                       $lb->getConnection( DB_MASTER )->onTransactionPreCommitOrIdle(
+                               function () use ( $cache, $key ) {
+                                       $cache->delete( $key );
+                               },
+                               __METHOD__
+                       );
                }
        }
 
@@ -2812,7 +2792,7 @@ class User implements IDBAccessObject, UserIdentity {
         */
        public function invalidateCache() {
                $this->touch();
-               $this->clearSharedCache();
+               $this->clearSharedCache( 'changed' );
        }
 
        /**
@@ -4217,7 +4197,7 @@ class User implements IDBAccessObject, UserIdentity {
                $newTouched = $this->newTouchedTimestamp();
 
                $dbw = wfGetDB( DB_MASTER );
-               $dbw->doAtomicSection( __METHOD__, function ( $dbw, $fname ) use ( $newTouched ) {
+               $dbw->doAtomicSection( __METHOD__, function ( IDatabase $dbw, $fname ) use ( $newTouched ) {
                        global $wgActorTableSchemaMigrationStage;
 
                        $dbw->update( 'user',
@@ -4263,7 +4243,7 @@ class User implements IDBAccessObject, UserIdentity {
                $this->saveOptions();
 
                Hooks::run( 'UserSaveSettings', [ $this ] );
-               $this->clearSharedCache();
+               $this->clearSharedCache( 'changed' );
                $this->getUserPage()->purgeSquid();
        }
 
@@ -4343,7 +4323,7 @@ class User implements IDBAccessObject, UserIdentity {
                        $fields["user_$name"] = $value;
                }
 
-               return $dbw->doAtomicSection( __METHOD__, function ( $dbw, $fname ) use ( $fields ) {
+               return $dbw->doAtomicSection( __METHOD__, function ( IDatabase $dbw, $fname ) use ( $fields ) {
                        $dbw->insert( 'user', $fields, $fname, [ 'IGNORE' ] );
                        if ( $dbw->affectedRows() ) {
                                $newUser = self::newFromId( $dbw->insertId() );
@@ -4397,7 +4377,7 @@ class User implements IDBAccessObject, UserIdentity {
                $this->mTouched = $this->newTouchedTimestamp();
 
                $dbw = wfGetDB( DB_MASTER );
-               $status = $dbw->doAtomicSection( __METHOD__, function ( $dbw, $fname ) {
+               $status = $dbw->doAtomicSection( __METHOD__, function ( IDatabase $dbw, $fname ) {
                        $noPass = PasswordFactory::newInvalidPassword()->toString();
                        $dbw->insert( 'user',
                                [
@@ -4424,10 +4404,8 @@ class User implements IDBAccessObject, UserIdentity {
                                        [ 'LOCK IN SHARE MODE' ]
                                );
                                $loaded = false;
-                               if ( $this->mId ) {
-                                       if ( $this->loadFromDatabase( self::READ_LOCKING ) ) {
-                                               $loaded = true;
-                                       }
+                               if ( $this->mId && $this->loadFromDatabase( self::READ_LOCKING ) ) {
+                                       $loaded = true;
                                }
                                if ( !$loaded ) {
                                        throw new MWException( $fname . ": hit a key conflict attempting " .
@@ -5743,4 +5721,14 @@ class User implements IDBAccessObject, UserIdentity {
                // XXX it's not clear whether central ID providers are supposed to obey this
                return $this->getName() === $user->getName();
        }
+
+       /**
+        * Checks if usertalk is allowed
+        *
+        * @return bool
+        */
+       public function isAllowUsertalk() {
+               return $this->mAllowUsertalk;
+       }
+
 }