1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
<?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
*/
namespace MediaWiki\StubObject;
use InvalidArgumentException;
use MediaWiki\User\User;
/**
* 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;
}
/**
* @deprecated since 1.35.
* @return User
*/
// phpcs:ignore PSR2.Methods.MethodDeclaration.Underscore
public function _newObject() {
// Based on MediaWiki\StubObject\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 = MediaWiki\StubObject\StubGlobalUser::_unstub
* 3 = MediaWiki\StubObject\StubObject::_call
* 4 = MediaWiki\StubObject\StubObject::__call
* 5 = MediaWiki\StubObject\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 MediaWiki\StubObject\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 MediaWiki\StubObject\StubGlobalUser
* wrapper. Bypasses deprecation notices from converting a MediaWiki\StubObject\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 MediaWiki\StubObject\StubGlobalUser), got ' .
get_debug_type( $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 MediaWiki\StubObject\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
*/
// phpcs:ignore PSR2.Methods.MethodDeclaration.Underscore
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 );
}
}
}
/** @deprecated class alias since 1.40 */
class_alias( StubGlobalUser::class, 'StubGlobalUser' );
|