SpecialRedirect: Don't pass null to explode
[mediawiki.git] / includes / StubGlobalUser.php
blob9a1dc7b02b49b972137cf6156674f98cf9d85b66
1 <?php
2 /**
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
18 * @file
21 /**
22 * Stub object for the global user ($wgUser) that makes it possible to change the
23 * relevant underlying object while still ensuring that deprecation warnings will
24 * be emitted upon method calls.
26 * @internal Will be removed in 1.38
28 * @since 1.37
29 * @author Danny712
31 class StubGlobalUser extends StubObject {
33 /** @var bool */
34 public static $destructorDeprecationDisarmed = false;
36 /** @var User */
37 public $realUser;
39 /**
40 * @param User $realUser
42 public function __construct( User $realUser ) {
43 parent::__construct( 'wgUser' );
44 $this->realUser = $realUser;
47 /**
48 * @return User
50 public function _newObject() {
51 // Based on DeprecatedGlobal::_newObject
53 * Put the caller offset for wfDeprecated as 6, as
54 * that gives the function that uses this object, since:
56 * 1 = this function ( _newObject )
57 * 2 = StubGlobalUser::_unstub
58 * 3 = StubObject::_call
59 * 4 = StubObject::__call
60 * 5 = StubGlobalUser::<method of global called>
61 * 6 = Actual function using the global.
62 * (the same applies to _get/__get or _set/__set instead of _call/__call)
64 * Of course its theoretically possible to have other call
65 * sequences for this method, but that seems to be
66 * rather unlikely.
68 // Officially deprecated since 1.35
69 wfDeprecated( '$wgUser', '1.35', false, 6 );
70 return $this->realUser;
73 /**
74 * Reset the stub global user to a different "real" user object, while ensuring that
75 * any method calls on that object will still trigger deprecation notices.
77 * @param StubGlobalUser|User $user
79 public static function setUser( $user ) {
80 // This is intended to be interacting with the deprecated global
81 // phpcs:ignore MediaWiki.Usage.DeprecatedGlobalVariables.Deprecated$wgUser
82 global $wgUser;
84 self::$destructorDeprecationDisarmed = true;
85 // Supports StubGlobalUser parameter in case something fetched the existing value of
86 // $wgUser, set it to something else, and now is trying to restore it
87 $realUser = self::getRealUser( $user );
88 $wgUser = new self( $realUser );
89 self::$destructorDeprecationDisarmed = false;
92 /**
93 * Get the relevant "real" user object based on either a User object or a StubGlobalUser
94 * wrapper. Bypasses deprecation notices from converting a StubGlobalUser to an actual
95 * user, and does not change $wgUser.
97 * @param StubGlobalUser|User $globalUser
98 * @return User
100 public static function getRealUser( $globalUser ): User {
101 if ( $globalUser instanceof StubGlobalUser ) {
102 return $globalUser->realUser;
103 } elseif ( $globalUser instanceof User ) {
104 return $globalUser;
105 } else {
106 throw new InvalidArgumentException(
107 '$globalUser must be a User (or StubGlobalUser), got ' .
108 ( is_object( $globalUser ) ? get_class( $globalUser ) : gettype( $globalUser ) )
114 * This function creates a new object of the real class and replace it in
115 * the global variable.
116 * This is public, for the convenience of external callers wishing to access
117 * properties, e.g. eval.php
119 * Overriding StubObject::_unstub because for some reason that thinks there is
120 * an unstub loop when trying to use the magic __set() logic, but there isn't
121 * any loop because _newObject() returns a specific instance of User rather
122 * than calling any methods that could then try to use $wgUser. The main difference
123 * between this and the parent method is that we don't try to check for
124 * recursion loops.
126 * @param string $name Name of the method called in this object.
127 * @param int $level Level to go in the stack trace to get the function
128 * who called this function.
129 * @return User The unstubbed version
131 public function _unstub( $name = '_unstub', $level = 2 ) {
132 if ( !$GLOBALS[$this->global] instanceof self ) {
133 return $GLOBALS[$this->global]; // already unstubbed.
136 $caller = wfGetCaller( $level );
137 wfDebug( "Unstubbing \${$this->global} on call of "
138 . "\${$this->global}::$name from $caller" );
139 $GLOBALS[$this->global] = $this->_newObject();
140 return $GLOBALS[$this->global];
143 public function __destruct() {
144 if ( !self::$destructorDeprecationDisarmed ) {
145 wfDeprecatedMsg( '$wgUser reassignment detected', '1.37', false, 3 );