Add StubObject::unstub, and use it for $wgAuth->getUserInstance()

PHP's __call magic method can't handle functions with reference
parameters correctly,[1] which means that we need to manually unstub
StubObjects before calling such a method. Or you could use call-time
pass by reference with call_user_func_array, which is rather backwards
and verbose.

This change adds a convenience function to do this, and applies it to
the two calls which brought it to my attention.

[1]: https://bugs.php.net/bug.php?id=40694,
https://bugs.php.net/bug.php?id=62455

Change-Id: I74a0c04bf358e164f753b82fbefbd6205d9b2451
This commit is contained in:
Brad Jorsch 2013-09-11 12:55:15 -07:00
parent c8a2f0db31
commit 37ed022c25
2 changed files with 22 additions and 0 deletions

View file

@ -25,6 +25,12 @@
* their associated module code by deferring initialisation until the first
* method call.
*
* Note on reference parameters:
*
* If the called method takes any parameters by reference, the __call magic
* here won't work correctly. The solution is to unstub the object before
* calling the method.
*
* Note on unstub loops:
*
* Unstub loops (infinite recursion) sometimes occur when a constructor calls
@ -63,6 +69,20 @@ class StubObject {
return is_object( $obj ) && !$obj instanceof StubObject;
}
/**
* Unstubs an object, if it is a stub object. Can be used to break a
* infinite loop when unstubbing an object or to avoid reference parameter
* breakage.
*
* @param $obj Object to check.
* @return void
*/
static function unstub( $obj ) {
if ( $obj instanceof StubObject ) {
$obj->_unstub( 'unstub', 3 );
}
}
/**
* Function called if any function exists with that name in this object.
* It is used to unstub the object. Only used internally, PHP will call

View file

@ -1700,6 +1700,7 @@ class User {
return $this->mLocked;
}
global $wgAuth;
StubObject::unstub( $wgAuth );
$authUser = $wgAuth->getUserInstance( $this );
$this->mLocked = (bool)$authUser->isLocked();
return $this->mLocked;
@ -1717,6 +1718,7 @@ class User {
$this->getBlockedStatus();
if ( !$this->mHideName ) {
global $wgAuth;
StubObject::unstub( $wgAuth );
$authUser = $wgAuth->getUserInstance( $this );
$this->mHideName = (bool)$authUser->isHidden();
}