Emit deprecation warnings reading from $wgUser
With this patch deprecation warnings will be emitted if $wgUser is accessed or written into. The only pattern of usage still allowed is $oldUser = $wgUser; $wgUser = $newUser; // Do something $wgUser = $oldUser; Once there is no deprecation warnings, we know that nothing legitimately depends on $wgUser being set, so we can safely remove the code that's still allowed as well. Bug: T267861 Change-Id: Ia1c42b3a32acd0e2bb9b0e93f1dc3c82640dcb22
This commit is contained in:
parent
71167aa56c
commit
a2b20b63d7
27 changed files with 382 additions and 47 deletions
|
|
@ -15,7 +15,6 @@
|
|||
<exclude name="MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName" />
|
||||
<exclude name="MediaWiki.Usage.DbrQueryUsage.DbrQueryFound" />
|
||||
<exclude name="MediaWiki.Usage.DeprecatedGlobalVariables.Deprecated$wgTitle" />
|
||||
<exclude name="MediaWiki.Usage.DeprecatedGlobalVariables.Deprecated$wgUser" />
|
||||
<exclude name="MediaWiki.Usage.DeprecatedGlobalVariables.Deprecated$wgVersion" />
|
||||
<exclude name="MediaWiki.Usage.ExtendClassUsage.FunctionConfigUsage" />
|
||||
<exclude name="MediaWiki.Usage.ExtendClassUsage.FunctionVarUsage" />
|
||||
|
|
@ -177,6 +176,7 @@
|
|||
</rule>
|
||||
<rule ref="PSR2.Methods.MethodDeclaration.Underscore">
|
||||
<exclude-pattern>*/includes/StubObject\.php</exclude-pattern>
|
||||
<exclude-pattern>*/includes/StubGlobalUser\.php</exclude-pattern>
|
||||
<exclude-pattern>*/includes/StubUserLang\.php</exclude-pattern>
|
||||
</rule>
|
||||
<rule ref="MediaWiki.Usage.AssignmentInReturn.AssignmentInReturn">
|
||||
|
|
|
|||
|
|
@ -778,6 +778,11 @@ because of Phabricator reports.
|
|||
- PPDPart has been merged into PPDPart_Hash
|
||||
- PPDStack has been merged into PPDStack_Hash
|
||||
- PPDStackElement has been merged into PPDStackElement_Hash
|
||||
* By default, the global variable $wgUser is now an instance of the new class
|
||||
StubGlobalUser rather than User, and the first time it is used it will emit
|
||||
deprecation warnings (the $wgUser variable was deprecated in 1.35). For
|
||||
extensions that read from this variable, please use a relevant ContextSource
|
||||
instead, falling back to RequestContext::getMain() if none is available.
|
||||
* Collation::singleton and ::factory were deprecated, obtain an CollationFactory
|
||||
instance from MediaWikiServices instead.
|
||||
* Title::getDefaultNamespace() has been deprecated to be removed because
|
||||
|
|
|
|||
|
|
@ -1610,6 +1610,7 @@ $wgAutoloadLocalClasses = [
|
|||
'StringPrefixSearch' => __DIR__ . '/includes/search/StringPrefixSearch.php',
|
||||
'StringUtils' => __DIR__ . '/includes/libs/StringUtils.php',
|
||||
'StripState' => __DIR__ . '/includes/parser/StripState.php',
|
||||
'StubGlobalUser' => __DIR__ . '/includes/StubGlobalUser.php',
|
||||
'StubObject' => __DIR__ . '/includes/StubObject.php',
|
||||
'StubUserLang' => __DIR__ . '/includes/StubUserLang.php',
|
||||
'SubmitAction' => __DIR__ . '/includes/actions/SubmitAction.php',
|
||||
|
|
|
|||
|
|
@ -820,7 +820,10 @@ if ( !defined( 'MW_NO_SESSION' ) && !$wgCommandLineMode ) {
|
|||
* @deprecated since 1.35, use an available context source when possible, or, as a backup,
|
||||
* RequestContext::getMain()
|
||||
*/
|
||||
$wgUser = RequestContext::getMain()->getUser(); // BackCompat
|
||||
$wgUser = new StubGlobalUser( RequestContext::getMain()->getUser() ); // BackCompat
|
||||
register_shutdown_function( static function () {
|
||||
StubGlobalUser::$destructorDeprecationDisarmed = true;
|
||||
} );
|
||||
|
||||
/**
|
||||
* @var Language|StubUserLang $wgLang
|
||||
|
|
|
|||
148
includes/StubGlobalUser.php
Normal file
148
includes/StubGlobalUser.php
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
<?php
|
||||
/**
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* @file
|
||||
*/
|
||||
|
||||
/**
|
||||
* Stub object for the global user ($wgUser) that makes it possible to change the
|
||||
* relevant underlying object while still ensuring that deprecation warnings will
|
||||
* be emitted upon method calls.
|
||||
*
|
||||
* @internal Will be removed in 1.38
|
||||
*
|
||||
* @since 1.37
|
||||
* @author Danny712
|
||||
*/
|
||||
class StubGlobalUser extends StubObject {
|
||||
|
||||
/** @var bool */
|
||||
public static $destructorDeprecationDisarmed = false;
|
||||
|
||||
/** @var User */
|
||||
public $realUser;
|
||||
|
||||
/**
|
||||
* @param User $realUser
|
||||
*/
|
||||
public function __construct( User $realUser ) {
|
||||
parent::__construct( 'wgUser' );
|
||||
$this->realUser = $realUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return User
|
||||
*/
|
||||
public function _newObject() {
|
||||
// Based on DeprecatedGlobal::_newObject
|
||||
/*
|
||||
* Put the caller offset for wfDeprecated as 6, as
|
||||
* that gives the function that uses this object, since:
|
||||
*
|
||||
* 1 = this function ( _newObject )
|
||||
* 2 = StubGlobalUser::_unstub
|
||||
* 3 = StubObject::_call
|
||||
* 4 = StubObject::__call
|
||||
* 5 = StubGlobalUser::<method of global called>
|
||||
* 6 = Actual function using the global.
|
||||
* (the same applies to _get/__get or _set/__set instead of _call/__call)
|
||||
*
|
||||
* Of course its theoretically possible to have other call
|
||||
* sequences for this method, but that seems to be
|
||||
* rather unlikely.
|
||||
*/
|
||||
// Officially deprecated since 1.35
|
||||
wfDeprecated( '$wgUser', '1.35', false, 6 );
|
||||
return $this->realUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the stub global user to a different "real" user object, while ensuring that
|
||||
* any method calls on that object will still trigger deprecation notices.
|
||||
*
|
||||
* @param StubGlobalUser|User $user
|
||||
*/
|
||||
public static function setUser( $user ) {
|
||||
// This is intended to be interacting with the deprecated global
|
||||
// phpcs:ignore MediaWiki.Usage.DeprecatedGlobalVariables.Deprecated$wgUser
|
||||
global $wgUser;
|
||||
|
||||
self::$destructorDeprecationDisarmed = true;
|
||||
// Supports StubGlobalUser parameter in case something fetched the existing value of
|
||||
// $wgUser, set it to something else, and now is trying to restore it
|
||||
$realUser = self::getRealUser( $user );
|
||||
$wgUser = new self( $realUser );
|
||||
self::$destructorDeprecationDisarmed = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the relevant "real" user object based on either a User object or a StubGlobalUser
|
||||
* wrapper. Bypasses deprecation notices from converting a StubGlobalUser to an actual
|
||||
* user, and does not change $wgUser.
|
||||
*
|
||||
* @param StubGlobalUser|User $globalUser
|
||||
* @return User
|
||||
*/
|
||||
public static function getRealUser( $globalUser ): User {
|
||||
if ( $globalUser instanceof StubGlobalUser ) {
|
||||
return $globalUser->realUser;
|
||||
} elseif ( $globalUser instanceof User ) {
|
||||
return $globalUser;
|
||||
} else {
|
||||
throw new InvalidArgumentException(
|
||||
'$globalUser must be a User (or StubGlobalUser), got ' .
|
||||
( is_object( $globalUser ) ? get_class( $globalUser ) : gettype( $globalUser ) )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function creates a new object of the real class and replace it in
|
||||
* the global variable.
|
||||
* This is public, for the convenience of external callers wishing to access
|
||||
* properties, e.g. eval.php
|
||||
*
|
||||
* Overriding StubObject::_unstub because for some reason that thinks there is
|
||||
* an unstub loop when trying to use the magic __set() logic, but there isn't
|
||||
* any loop because _newObject() returns a specific instance of User rather
|
||||
* than calling any methods that could then try to use $wgUser. The main difference
|
||||
* between this and the parent method is that we don't try to check for
|
||||
* recursion loops.
|
||||
*
|
||||
* @param string $name Name of the method called in this object.
|
||||
* @param int $level Level to go in the stack trace to get the function
|
||||
* who called this function.
|
||||
* @return User The unstubbed version
|
||||
*/
|
||||
public function _unstub( $name = '_unstub', $level = 2 ) {
|
||||
if ( !$GLOBALS[$this->global] instanceof self ) {
|
||||
return $GLOBALS[$this->global]; // already unstubbed.
|
||||
}
|
||||
|
||||
$caller = wfGetCaller( $level );
|
||||
wfDebug( "Unstubbing \${$this->global} on call of "
|
||||
. "\${$this->global}::$name from $caller" );
|
||||
$GLOBALS[$this->global] = $this->_newObject();
|
||||
return $GLOBALS[$this->global];
|
||||
}
|
||||
|
||||
public function __destruct() {
|
||||
if ( !self::$destructorDeprecationDisarmed ) {
|
||||
wfDeprecatedMsg( '$wgUser reassignment detected', '1.37', false, 3 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -528,10 +528,9 @@ class ApiMain extends ApiBase {
|
|||
// If we're in a mode that breaks the same-origin policy, strip
|
||||
// user credentials for security.
|
||||
if ( $this->lacksSameOriginSecurity() ) {
|
||||
global $wgUser;
|
||||
wfDebug( "API: stripping user credentials when the same-origin policy is not applied" );
|
||||
$user = new User();
|
||||
$wgUser = $user;
|
||||
StubGlobalUser::setUser( $user );
|
||||
$derivativeContext->setUser( $user );
|
||||
$request->response()->header( 'MediaWiki-Login-Suppressed: true' );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -579,7 +579,7 @@ class RequestContext implements IContextSource, MutableContext {
|
|||
}
|
||||
|
||||
$importSessionFunc = static function ( User $user, array $params ) {
|
||||
global $wgRequest, $wgUser;
|
||||
global $wgRequest;
|
||||
|
||||
$context = RequestContext::getMain();
|
||||
|
||||
|
|
@ -608,7 +608,7 @@ class RequestContext implements IContextSource, MutableContext {
|
|||
// and caught (leaving the main context in a mixed state), there is no risk
|
||||
// of the User object being attached to the wrong IP, headers, or session.
|
||||
$context->setUser( $user );
|
||||
$wgUser = $context->getUser(); // b/c
|
||||
StubGlobalUser::setUser( $context->getUser() ); // b/c
|
||||
if ( $session && MediaWiki\Session\PHPSessionHandler::isEnabled() ) {
|
||||
session_id( $session->getId() );
|
||||
AtEase::quietCall( 'session_start' );
|
||||
|
|
|
|||
|
|
@ -446,7 +446,7 @@ abstract class Installer {
|
|||
* @throws MWException
|
||||
*/
|
||||
public function resetMediaWikiServices( Config $installerConfig = null, $serviceOverrides = [] ) {
|
||||
global $wgUser, $wgObjectCaches, $wgLang;
|
||||
global $wgObjectCaches, $wgLang;
|
||||
|
||||
$serviceOverrides += [
|
||||
// Disable interwiki lookup, to avoid database access during parses
|
||||
|
|
@ -482,7 +482,7 @@ abstract class Installer {
|
|||
// Note that this will reset the context's language,
|
||||
// so set the user before setting the language.
|
||||
$user = User::newFromId( 0 );
|
||||
$wgUser = $user;
|
||||
StubGlobalUser::setUser( $user );
|
||||
|
||||
RequestContext::getMain()->setUser( $user );
|
||||
|
||||
|
|
|
|||
|
|
@ -169,6 +169,7 @@ class DoubleRedirectJob extends Job {
|
|||
}
|
||||
|
||||
// Save it
|
||||
// phpcs:ignore MediaWiki.Usage.DeprecatedGlobalVariables.Deprecated$wgUser
|
||||
global $wgUser;
|
||||
$oldUser = $wgUser;
|
||||
$wgUser = $user;
|
||||
|
|
|
|||
|
|
@ -1841,8 +1841,9 @@ class WikiPage implements Page, IDBAccessObject, PageRecord {
|
|||
|
||||
if ( !$performer ) {
|
||||
// Its okay to fallback to $wgUser because this whole method is deprecated
|
||||
// phpcs:ignore MediaWiki.Usage.DeprecatedGlobalVariables.Deprecated$wgUser
|
||||
global $wgUser;
|
||||
$performer = $wgUser;
|
||||
$performer = StubGlobalUser::getRealUser( $wgUser );
|
||||
}
|
||||
|
||||
return $this->doUserEditContent(
|
||||
|
|
@ -2060,8 +2061,9 @@ class WikiPage implements Page, IDBAccessObject, PageRecord {
|
|||
) {
|
||||
if ( !$user ) {
|
||||
wfDeprecated( __METHOD__ . ' without a UserIdentity', '1.37' );
|
||||
// phpcs:ignore MediaWiki.Usage.DeprecatedGlobalVariables.Deprecated$wgUser
|
||||
global $wgUser;
|
||||
$user = $wgUser;
|
||||
$user = StubGlobalUser::getRealUser( $wgUser );
|
||||
}
|
||||
|
||||
$slots = RevisionSlotsUpdate::newFromContent( [ SlotRecord::MAIN => $content ] );
|
||||
|
|
|
|||
|
|
@ -484,7 +484,7 @@ abstract class LoginSignupSpecialPage extends AuthManagerSpecialPage {
|
|||
* reflected in the current request.
|
||||
*/
|
||||
protected function setSessionUserForCurrentRequest() {
|
||||
global $wgUser, $wgLang;
|
||||
global $wgLang;
|
||||
|
||||
$context = RequestContext::getMain();
|
||||
$localContext = $this->getContext();
|
||||
|
|
@ -495,7 +495,7 @@ abstract class LoginSignupSpecialPage extends AuthManagerSpecialPage {
|
|||
|
||||
$user = $context->getRequest()->getSession()->getUser();
|
||||
|
||||
$wgUser = $user;
|
||||
StubGlobalUser::setUser( $user );
|
||||
$context->setUser( $user );
|
||||
|
||||
$wgLang = $context->getLanguage();
|
||||
|
|
|
|||
|
|
@ -1386,6 +1386,7 @@ class SpecialPageFactory {
|
|||
public function capturePath(
|
||||
PageReference $page, IContextSource $context, LinkRenderer $linkRenderer = null
|
||||
) {
|
||||
// phpcs:ignore MediaWiki.Usage.DeprecatedGlobalVariables.Deprecated$wgUser
|
||||
global $wgTitle, $wgOut, $wgRequest, $wgUser, $wgLang;
|
||||
$main = RequestContext::getMain();
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ class CleanupSpam extends Maintenance {
|
|||
}
|
||||
|
||||
public function execute() {
|
||||
global $IP, $wgLocalDatabases, $wgUser;
|
||||
global $IP, $wgLocalDatabases;
|
||||
|
||||
$username = wfMessage( 'spambot_username' )->text();
|
||||
$user = User::newSystemUser( $username );
|
||||
|
|
@ -56,7 +56,7 @@ class CleanupSpam extends Maintenance {
|
|||
}
|
||||
// Hack: Grant bot rights so we don't flood RecentChanges
|
||||
MediaWikiServices::getInstance()->getUserGroupManager()->addUserToGroup( $user, 'bot' );
|
||||
$wgUser = $user;
|
||||
StubGlobalUser::setUser( $user );
|
||||
|
||||
$spec = $this->getArg( 0 );
|
||||
|
||||
|
|
|
|||
|
|
@ -50,8 +50,6 @@ class DeleteBatch extends Maintenance {
|
|||
}
|
||||
|
||||
public function execute() {
|
||||
global $wgUser;
|
||||
|
||||
# Change to current working directory
|
||||
$oldCwd = getcwd();
|
||||
chdir( $oldCwd );
|
||||
|
|
@ -69,7 +67,7 @@ class DeleteBatch extends Maintenance {
|
|||
if ( !$user ) {
|
||||
$this->fatalError( "Invalid username" );
|
||||
}
|
||||
$wgUser = $user;
|
||||
StubGlobalUser::setUser( $user );
|
||||
|
||||
if ( $this->hasArg( 0 ) ) {
|
||||
$file = fopen( $this->getArg( 0 ), 'r' );
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ class DeleteDefaultMessages extends Maintenance {
|
|||
}
|
||||
|
||||
public function execute() {
|
||||
global $wgUser;
|
||||
$services = MediaWikiServices::getInstance();
|
||||
|
||||
$this->output( "Checking existence of old default messages..." );
|
||||
|
|
@ -86,7 +85,7 @@ class DeleteDefaultMessages extends Maintenance {
|
|||
}
|
||||
$userGroupManager = $services->getUserGroupManager();
|
||||
$userGroupManager->addUserToGroup( $user, 'bot' );
|
||||
$wgUser = $user;
|
||||
StubGlobalUser::setUser( $user );
|
||||
|
||||
// Handle deletion
|
||||
$this->output( "\n...deleting old default messages (this may take a long time!)...", 'msg' );
|
||||
|
|
|
|||
|
|
@ -174,8 +174,7 @@ class DeleteEqualMessages extends Maintenance {
|
|||
if ( !$user ) {
|
||||
$this->fatalError( "Invalid username" );
|
||||
}
|
||||
global $wgUser;
|
||||
$wgUser = $user;
|
||||
StubGlobalUser::setUser( $user );
|
||||
|
||||
// Hide deletions from RecentChanges
|
||||
$userGroupManager = $services->getUserGroupManager();
|
||||
|
|
|
|||
|
|
@ -49,8 +49,6 @@ class EditCLI extends Maintenance {
|
|||
}
|
||||
|
||||
public function execute() {
|
||||
global $wgUser;
|
||||
|
||||
$userName = $this->getOption( 'user', false );
|
||||
$summary = $this->getOption( 'summary', '' );
|
||||
$remove = $this->hasOption( 'remove' );
|
||||
|
|
@ -71,7 +69,7 @@ class EditCLI extends Maintenance {
|
|||
if ( $user->isAnon() ) {
|
||||
$user->addToDatabase();
|
||||
}
|
||||
$wgUser = $user;
|
||||
StubGlobalUser::setUser( $user );
|
||||
|
||||
$title = Title::newFromText( $this->getArg( 0 ) );
|
||||
if ( !$title ) {
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ class ImportImages extends Maintenance {
|
|||
}
|
||||
|
||||
public function execute() {
|
||||
global $wgFileExtensions, $wgUser, $wgRestrictionLevels;
|
||||
global $wgFileExtensions, $wgRestrictionLevels;
|
||||
|
||||
$services = MediaWikiServices::getInstance();
|
||||
$permissionManager = $services->getPermissionManager();
|
||||
|
|
@ -160,7 +160,7 @@ class ImportImages extends Maintenance {
|
|||
if ( !$user instanceof User ) {
|
||||
$user = User::newSystemUser( User::MAINTENANCE_SCRIPT_USER, [ 'steal' => true ] );
|
||||
}
|
||||
$wgUser = $user;
|
||||
StubGlobalUser::setUser( $user );
|
||||
|
||||
# Get block check. If a value is given, this specified how often the check is performed
|
||||
$checkUserBlock = (int)$this->getOption( 'check-userblock' );
|
||||
|
|
@ -286,7 +286,7 @@ class ImportImages extends Maintenance {
|
|||
);
|
||||
continue;
|
||||
}
|
||||
$wgUser = $realUser;
|
||||
StubGlobalUser::setUser( $realUser );
|
||||
$user = $realUser;
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -41,15 +41,13 @@ class ImportSiteScripts extends Maintenance {
|
|||
}
|
||||
|
||||
public function execute() {
|
||||
global $wgUser;
|
||||
|
||||
$username = $this->getOption( 'username', false );
|
||||
if ( $username === false ) {
|
||||
$user = User::newSystemUser( 'ScriptImporter', [ 'steal' => true ] );
|
||||
} else {
|
||||
$user = User::newFromName( $username );
|
||||
}
|
||||
$wgUser = $user;
|
||||
StubGlobalUser::setUser( $user );
|
||||
|
||||
$baseUrl = $this->getArg( 1 );
|
||||
$pageList = $this->fetchScriptList();
|
||||
|
|
|
|||
|
|
@ -47,8 +47,6 @@ class MoveBatch extends Maintenance {
|
|||
}
|
||||
|
||||
public function execute() {
|
||||
global $wgUser;
|
||||
|
||||
# Change to current working directory
|
||||
$oldCwd = getcwd();
|
||||
chdir( $oldCwd );
|
||||
|
|
@ -76,7 +74,7 @@ class MoveBatch extends Maintenance {
|
|||
if ( !$user ) {
|
||||
$this->fatalError( "Invalid username" );
|
||||
}
|
||||
$wgUser = $user;
|
||||
StubGlobalUser::setUser( $user );
|
||||
|
||||
# Setup complete, now start
|
||||
$dbw = $this->getDB( DB_PRIMARY );
|
||||
|
|
|
|||
|
|
@ -214,14 +214,12 @@ class PPFuzzTest {
|
|||
}
|
||||
|
||||
public function execute() {
|
||||
global $wgUser;
|
||||
|
||||
$user = new PPFuzzUser;
|
||||
$user->mName = 'Fuzz';
|
||||
$user->mFrom = 'name';
|
||||
$user->ppfz_test = $this;
|
||||
|
||||
$wgUser = $user;
|
||||
StubGlobalUser::setUser( $user );
|
||||
|
||||
$options = ParserOptions::newFromUser( $user );
|
||||
$options->setTemplateCallback( [ $this, 'templateHook' ] );
|
||||
|
|
|
|||
|
|
@ -33,8 +33,6 @@ class Undelete extends Maintenance {
|
|||
}
|
||||
|
||||
public function execute() {
|
||||
global $wgUser;
|
||||
|
||||
$username = $this->getOption( 'user', false );
|
||||
$reason = $this->getOption( 'reason', '' );
|
||||
$pageName = $this->getArg( 0 );
|
||||
|
|
@ -51,7 +49,7 @@ class Undelete extends Maintenance {
|
|||
if ( !$user ) {
|
||||
$this->fatalError( "Invalid username" );
|
||||
}
|
||||
$wgUser = $user;
|
||||
StubGlobalUser::setUser( $user );
|
||||
|
||||
$archive = new PageArchive( $title, RequestContext::getMain()->getConfig() );
|
||||
$this->output( "Undeleting " . $title->getPrefixedDBkey() . '...' );
|
||||
|
|
|
|||
|
|
@ -1316,7 +1316,7 @@ class ParserTestRunner {
|
|||
Wikimedia\restoreWarnings();
|
||||
|
||||
// Reset context to the restored globals
|
||||
$context->setUser( $GLOBALS['wgUser'] );
|
||||
$context->setUser( StubGlobalUser::getRealUser( $GLOBALS['wgUser'] ) );
|
||||
$context->setSkin( $oldSkin );
|
||||
$context->setOutput( $GLOBALS['wgOut'] );
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1863,11 +1863,14 @@ abstract class MediaWikiIntegrationTestCase extends PHPUnit\Framework\TestCase {
|
|||
if ( in_array( 'user', $tablesUsed ) ) {
|
||||
TestUserRegistry::clear();
|
||||
|
||||
// Reset $wgUser, which is probably 127.0.0.1, as its loaded data is probably not valid
|
||||
// @todo Should we start setting $wgUser to something nondeterministic
|
||||
// Reset context user, which is probably 127.0.0.1, as its loaded
|
||||
// data is probably not valid. This used to manipulate $wgUser but
|
||||
// since that is deprecated tests are more likely to be relying on
|
||||
// RequestContext::getMain() instead.
|
||||
// @todo Should we start setting the user to something nondeterministic
|
||||
// to encourage tests to be updated to not depend on it?
|
||||
global $wgUser;
|
||||
$wgUser->clearInstanceCache( $wgUser->mFrom );
|
||||
$user = RequestContext::getMain()->getUser();
|
||||
$user->clearInstanceCache( $user->mFrom );
|
||||
}
|
||||
|
||||
$this->truncateTables( $tablesUsed, $db );
|
||||
|
|
|
|||
|
|
@ -101,8 +101,15 @@ class ApiMainTest extends ApiTestCase {
|
|||
}
|
||||
|
||||
public function testSuppressedLogin() {
|
||||
// Testing some logic that changes the global $wgUser
|
||||
// ApiMain will be setting it to a StubGlobalUser object, it should already
|
||||
// be one but in case its a full User object we will wrap the comparisons
|
||||
// in StubGlobalUser::getRealUser() which will return the inner User object
|
||||
// for a StubGlobalUser, or the actual User object if given a user.
|
||||
|
||||
// phpcs:ignore MediaWiki.Usage.DeprecatedGlobalVariables.Deprecated$wgUser
|
||||
global $wgUser;
|
||||
$origUser = $wgUser;
|
||||
$origUser = StubGlobalUser::getRealUser( $wgUser );
|
||||
|
||||
$api = $this->getNonInternalApiMain( [
|
||||
'action' => 'query',
|
||||
|
|
@ -114,7 +121,7 @@ class ApiMainTest extends ApiTestCase {
|
|||
$api->execute();
|
||||
ob_end_clean();
|
||||
|
||||
$this->assertNotSame( $origUser, $wgUser );
|
||||
$this->assertNotSame( $origUser, StubGlobalUser::getRealUser( $wgUser ) );
|
||||
$this->assertSame( 'true', $api->getContext()->getRequest()->response()
|
||||
->getHeader( 'MediaWiki-Login-Suppressed' ) );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -266,7 +266,14 @@ class WikiPageDbTest extends MediaWikiLangTestCase {
|
|||
public function testDoEditContent() {
|
||||
$this->hideDeprecated( 'WikiPage::doEditContent' );
|
||||
|
||||
// We set $wgUser to a User we create to avoid dealing with StubGlobalUser
|
||||
// deprecation, etc. The entire method is deprecated anyway.
|
||||
$user = $this->getTestSysop()->getUser();
|
||||
|
||||
// phpcs:ignore MediaWiki.Usage.DeprecatedGlobalVariables.Deprecated$wgUser
|
||||
global $wgUser;
|
||||
$originalUser = $wgUser;
|
||||
$wgUser = $user;
|
||||
|
||||
// NOTE: Test that Editing also works with a fragment title!
|
||||
$page = $this->newPage( __METHOD__ . '#Fragment' );
|
||||
|
|
@ -332,8 +339,11 @@ class WikiPageDbTest extends MediaWikiLangTestCase {
|
|||
$this->assertStringContainsString( '[[gubergren]]', $newText, 'New text must replace old text.' );
|
||||
$this->assertStringNotContainsString( '[[Lorem ipsum]]', $newText, 'New text must replace old text.' );
|
||||
$this->assertStringNotContainsString( '~~~~', $newText, 'PST must substitute signature.' );
|
||||
$this->assertStringContainsString( $wgUser->getName(), $newText,
|
||||
$this->assertStringContainsString( $user->getName(), $newText,
|
||||
'Must fall back to $wgUser when no user has been specified.' );
|
||||
|
||||
// Reset so that other tests would still fail if interacting with $wgUser
|
||||
$wgUser = $originalUser;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
169
tests/phpunit/integration/includes/StubGlobalUserTest.php
Normal file
169
tests/phpunit/integration/includes/StubGlobalUserTest.php
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* @file
|
||||
*/
|
||||
|
||||
// phpcs:disable MediaWiki.Usage.DeprecatedGlobalVariables.Deprecated$wgUser
|
||||
|
||||
/**
|
||||
* Tests the StubGlobalUser, including magic support for __get() and __set()
|
||||
*
|
||||
* @author DannyS712
|
||||
*
|
||||
* @covers \StubGlobalUser
|
||||
*/
|
||||
class StubGlobalUserTest extends MediaWikiIntegrationTestCase {
|
||||
|
||||
/** @var int */
|
||||
private $oldErrorLevel;
|
||||
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
// Make sure deprecation notices are seen
|
||||
$this->oldErrorLevel = error_reporting( -1 );
|
||||
|
||||
// Using User::newFromRow() to avoid needing any integration
|
||||
$userFields = [
|
||||
'user_id' => 12345,
|
||||
];
|
||||
$realUser = User::newFromRow( (object)$userFields );
|
||||
StubGlobalUser::setUser( $realUser );
|
||||
}
|
||||
|
||||
protected function tearDown(): void {
|
||||
error_reporting( $this->oldErrorLevel );
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
public function testRealUser() {
|
||||
// Should not be emitting deprecation warnings
|
||||
global $wgUser;
|
||||
|
||||
$this->assertInstanceOf( StubGlobalUser::class, $wgUser );
|
||||
|
||||
$real = StubGlobalUser::getRealUser( $wgUser );
|
||||
$this->assertInstanceOf( User::class, $real );
|
||||
|
||||
$real2 = StubGlobalUser::getRealUser( $real );
|
||||
$this->assertSame( $real, $real2 );
|
||||
}
|
||||
|
||||
public function testRealUser_exception() {
|
||||
$this->expectException( InvalidArgumentException::class );
|
||||
$this->expectExceptionMessage(
|
||||
'$globalUser must be a User (or StubGlobalUser), got integer'
|
||||
);
|
||||
StubGlobalUser::getRealUser( 12345 );
|
||||
}
|
||||
|
||||
public function testMagicCall() {
|
||||
$this->expectDeprecation();
|
||||
$this->expectDeprecationMessage( 'Use of $wgUser was deprecated in MediaWiki 1.35' );
|
||||
|
||||
global $wgUser;
|
||||
$this->assertInstanceOf(
|
||||
StubGlobalUser::class,
|
||||
$wgUser,
|
||||
'Sanity check: $wgUser should be a StubGlobalUser at the start of the test'
|
||||
);
|
||||
$this->assertSame(
|
||||
12345,
|
||||
$wgUser->getId(),
|
||||
'__call() based on id set in ::setUp()'
|
||||
);
|
||||
$this->assertInstanceOf(
|
||||
User::class,
|
||||
$wgUser,
|
||||
'__call() resulted in unstubbing'
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetMagic() {
|
||||
$this->expectDeprecation();
|
||||
$this->expectDeprecationMessage( 'Use of $wgUser was deprecated in MediaWiki 1.35' );
|
||||
|
||||
global $wgUser;
|
||||
$this->assertInstanceOf(
|
||||
StubGlobalUser::class,
|
||||
$wgUser,
|
||||
'Sanity check: $wgUser should be a StubGlobalUser at the start of the test'
|
||||
);
|
||||
$this->assertSame(
|
||||
12345,
|
||||
$wgUser->mId,
|
||||
'__get() based on id set in ::setUp()'
|
||||
);
|
||||
$this->assertInstanceOf(
|
||||
User::class,
|
||||
$wgUser,
|
||||
'__get() resulted in unstubbing'
|
||||
);
|
||||
}
|
||||
|
||||
public function testSetMagic() {
|
||||
// This test is why we need StubGlobalUser::_unstub to override StubObject::_unstub
|
||||
// and not try to detect and throw exceptions in unstub loops - for some reason it
|
||||
// thinks this creates a loop.
|
||||
|
||||
$this->expectDeprecation();
|
||||
$this->expectDeprecationMessage( 'Use of $wgUser was deprecated in MediaWiki 1.35' );
|
||||
|
||||
global $wgUser;
|
||||
$this->assertInstanceOf(
|
||||
StubGlobalUser::class,
|
||||
$wgUser,
|
||||
'Sanity check: $wgUser should be a StubGlobalUser at the start of the test'
|
||||
);
|
||||
$wgUser->mId = 2000;
|
||||
$this->assertInstanceOf(
|
||||
User::class,
|
||||
$wgUser,
|
||||
'__set() resulted in unstubbing'
|
||||
);
|
||||
$this->assertSame(
|
||||
2000,
|
||||
$wgUser->mId,
|
||||
'__set() call worked'
|
||||
);
|
||||
}
|
||||
|
||||
public function testDeprecationEmittedWhenReassigned() {
|
||||
$this->expectDeprecation();
|
||||
global $wgUser;
|
||||
$wgUser = new User;
|
||||
}
|
||||
|
||||
/**
|
||||
* @doesNotPerformAssertions
|
||||
*/
|
||||
public function testReassignmentWithRestoring() {
|
||||
global $wgUser;
|
||||
$oldUser = $wgUser;
|
||||
$wgUser = new User;
|
||||
$wgUser = $oldUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* @doesNotPerformAssertions
|
||||
*/
|
||||
public function testSetUserNoDeprecation() {
|
||||
StubGlobalUser::setUser( new User );
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue