Merge "Enable/disable Special:Block widgets according to block parameters"
[lhc/web/wiklou.git] / includes / user / User.php
index 3fcba46..5b07315 100644 (file)
@@ -28,6 +28,7 @@ use MediaWiki\Auth\AuthenticationResponse;
 use MediaWiki\Auth\AuthenticationRequest;
 use MediaWiki\User\UserIdentity;
 use MediaWiki\Logger\LoggerFactory;
+use Wikimedia\Assert\Assert;
 use Wikimedia\IPSet;
 use Wikimedia\ScopedCallback;
 use Wikimedia\Rdbms\Database;
@@ -1404,10 +1405,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() );
                }
        }
 
@@ -1670,11 +1671,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 );
@@ -1749,6 +1750,23 @@ class User implements IDBAccessObject, UserIdentity {
                }
        }
 
+       /** @var array|null */
+       private static $defOpt = null;
+       /** @var string|null */
+       private static $defOptLang = null;
+
+       /**
+        * Reset the process cache of default user options. This is only necessary
+        * if the wiki configuration has changed since defaults were calculated,
+        * and as such should only be performed inside the testing suite that
+        * regularly changes wiki configuration.
+        */
+       public static function resetGetDefaultOptionsForTestsOnly() {
+               Assert::invariant( defined( 'MW_PHPUNIT_TEST' ), 'Unit tests only' );
+               self::$defOpt = null;
+               self::$defOptLang = null;
+       }
+
        /**
         * Combine the language default options with any site-specific options
         * and add the default language variants.
@@ -1758,26 +1776,23 @@ class User implements IDBAccessObject, UserIdentity {
        public static function getDefaultOptions() {
                global $wgNamespacesToBeSearchedDefault, $wgDefaultUserOptions, $wgDefaultSkin;
 
-               static $defOpt = null;
-               static $defOptLang = null;
-
                $contLang = MediaWikiServices::getInstance()->getContentLanguage();
-               if ( $defOpt !== null && $defOptLang === $contLang->getCode() ) {
+               if ( self::$defOpt !== null && self::$defOptLang === $contLang->getCode() ) {
                        // The content language does not change (and should not change) mid-request, but the
                        // unit tests change it anyway, and expect this method to return values relevant to the
                        // current content language.
-                       return $defOpt;
+                       return self::$defOpt;
                }
 
-               $defOpt = $wgDefaultUserOptions;
+               self::$defOpt = $wgDefaultUserOptions;
                // Default language setting
-               $defOptLang = $contLang->getCode();
-               $defOpt['language'] = $defOptLang;
+               self::$defOptLang = $contLang->getCode();
+               self::$defOpt['language'] = self::$defOptLang;
                foreach ( LanguageConverter::$languagesWithVariants as $langCode ) {
                        if ( $langCode === $contLang->getCode() ) {
-                               $defOpt['variant'] = $langCode;
+                               self::$defOpt['variant'] = $langCode;
                        } else {
-                               $defOpt["variant-$langCode"] = $langCode;
+                               self::$defOpt["variant-$langCode"] = $langCode;
                        }
                }
 
@@ -1785,13 +1800,13 @@ class User implements IDBAccessObject, UserIdentity {
                // since extensions may change the set of searchable namespaces depending
                // on user groups/permissions.
                foreach ( $wgNamespacesToBeSearchedDefault as $nsnum => $val ) {
-                       $defOpt['searchNs' . $nsnum] = (bool)$val;
+                       self::$defOpt['searchNs' . $nsnum] = (bool)$val;
                }
-               $defOpt['skin'] = Skin::normalizeKey( $wgDefaultSkin );
+               self::$defOpt['skin'] = Skin::normalizeKey( $wgDefaultSkin );
 
-               Hooks::run( 'UserGetDefaultOptions', [ &$defOpt ] );
+               Hooks::run( 'UserGetDefaultOptions', [ &self::$defOpt ] );
 
-               return $defOpt;
+               return self::$defOpt;
        }
 
        /**
@@ -2190,6 +2205,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;
@@ -2221,6 +2239,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 );
@@ -2276,29 +2297,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 );
        }
 
        /**
@@ -4409,10 +4416,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 " .
@@ -5728,4 +5733,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;
+       }
+
 }