File: StubGlobalUser.php

package info (click to toggle)
mediawiki 1%3A1.43.3%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 417,464 kB
  • sloc: php: 1,062,949; javascript: 664,290; sql: 9,714; python: 5,458; xml: 3,489; sh: 1,131; makefile: 64
file content (159 lines) | stat: -rw-r--r-- 5,529 bytes parent folder | download
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' );