Merge "Title::getLinkURL(): Allow expanding PROTO_RELATIVE too"
[lhc/web/wiklou.git] / includes / user / User.php
index 2dba380..a774aba 100644 (file)
@@ -772,15 +772,15 @@ class User implements IDBAccessObject {
                        return self::$idCacheByName[$name];
                }
 
-               $db = ( $flags & self::READ_LATEST )
-                       ? wfGetDB( DB_MASTER )
-                       : wfGetDB( DB_SLAVE );
+               list( $index, $options ) = DBAccessObjectUtils::getDBOptions( $flags );
+               $db = wfGetDB( $index );
 
                $s = $db->selectRow(
                        'user',
                        [ 'user_id' ],
                        [ 'user_name' => $nt->getText() ],
-                       __METHOD__
+                       __METHOD__,
+                       $options
                );
 
                if ( $s === false ) {
@@ -806,7 +806,7 @@ class User implements IDBAccessObject {
        }
 
        /**
-        * Does the string match an anonymous IPv4 address?
+        * Does the string match an anonymous IP address?
         *
         * This function exists for username validation, in order to reject
         * usernames which are similar in form to IP addresses. Strings such
@@ -1524,16 +1524,19 @@ class User implements IDBAccessObject {
                global $wgNamespacesToBeSearchedDefault, $wgDefaultUserOptions, $wgContLang, $wgDefaultSkin;
 
                static $defOpt = null;
-               if ( !defined( 'MW_PHPUNIT_TEST' ) && $defOpt !== null ) {
-                       // Disabling this for the unit tests, as they rely on being able to change $wgContLang
-                       // mid-request and see that change reflected in the return value of this function.
-                       // Which is insane and would never happen during normal MW operation
+               static $defOptLang = null;
+
+               if ( $defOpt !== null && $defOptLang === $wgContLang->getCode() ) {
+                       // $wgContLang 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 $wgContLang.
                        return $defOpt;
                }
 
                $defOpt = $wgDefaultUserOptions;
                // Default language setting
-               $defOpt['language'] = $wgContLang->getCode();
+               $defOptLang = $wgContLang->getCode();
+               $defOpt['language'] = $defOptLang;
                foreach ( LanguageConverter::$languagesWithVariants as $langCode ) {
                        $defOpt[$langCode == $wgContLang->getCode() ? 'variant' : "variant-$langCode"] = $langCode;
                }
@@ -2560,23 +2563,16 @@ class User implements IDBAccessObject {
                                throw new LogicException( 'Cannot set a password for a user that is not in the database.' );
                        }
 
-                       $data = [
+                       $status = $this->changeAuthenticationData( [
                                'username' => $this->getName(),
                                'password' => $str,
                                'retype' => $str,
-                       ];
-                       $reqs = $manager->getAuthenticationRequests( AuthManager::ACTION_CHANGE, $this );
-                       $reqs = AuthenticationRequest::loadRequestsFromSubmission( $reqs, $data );
-                       foreach ( $reqs as $req ) {
-                               $status = $manager->allowsAuthenticationDataChange( $req );
-                               if ( !$status->isGood() ) {
-                                       \MediaWiki\Logger\LoggerFactory::getInstance( 'authentication' )
-                                               ->info( __METHOD__ . ': Password change rejected: ' . $status->getWikiText() );
-                                       return false;
-                               }
-                       }
-                       foreach ( $reqs as $req ) {
-                               $manager->changeAuthenticationData( $req );
+                       ] );
+                       if ( !$status->isGood() ) {
+                               \MediaWiki\Logger\LoggerFactory::getInstance( 'authentication' )
+                                       ->info( __METHOD__ . ': Password change rejected: '
+                                               . $status->getWikiText( null, null, 'en' ) );
+                               return false;
                        }
 
                        $this->setOption( 'watchlisttoken', false );
@@ -2587,6 +2583,45 @@ class User implements IDBAccessObject {
                return true;
        }
 
+       /**
+        * Changes credentials of the user.
+        *
+        * This is a convenience wrapper around AuthManager::changeAuthenticationData.
+        * Note that this can return a status that isOK() but not isGood() on certain types of failures,
+        * e.g. when no provider handled the change.
+        *
+        * @param array $data A set of authentication data in fieldname => value format. This is the
+        *   same data you would pass the changeauthenticationdata API - 'username', 'password' etc.
+        * @return Status
+        * @since 1.27
+        */
+       public function changeAuthenticationData( array $data ) {
+               global $wgDisableAuthManager;
+               if ( $wgDisableAuthManager ) {
+                       throw new LogicException( __METHOD__ . ' cannot be called when $wgDisableAuthManager '
+                               . 'is true' );
+               }
+
+               $manager = AuthManager::singleton();
+               $reqs = $manager->getAuthenticationRequests( AuthManager::ACTION_CHANGE, $this );
+               $reqs = AuthenticationRequest::loadRequestsFromSubmission( $reqs, $data );
+
+               $status = Status::newGood( 'ignored' );
+               foreach ( $reqs as $req ) {
+                       $status->merge( $manager->allowsAuthenticationDataChange( $req ), true );
+               }
+               if ( $status->getValue() === 'ignored' ) {
+                       $status->warning( 'authenticationdatachange-ignored' );
+               }
+
+               if ( $status->isGood() ) {
+                       foreach ( $reqs as $req ) {
+                               $manager->changeAuthenticationData( $req );
+                       }
+               }
+               return $status;
+       }
+
        /**
         * Get the user's current token.
         * @param bool $forceCreation Force the generation of a new token if the