X-Git-Url: http://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FStubObject.php;h=e18537e0549c5e3543ffeb2cd9f18d511467c75d;hb=0b730ef78432aa7f8c36cd43dda9f8e7e863eb91;hp=ceedeb44cd2048a5310a7a20da042b400abb781c;hpb=43b2fb56b6cd2684c743ce9bf4e8d2a27e8469ae;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/StubObject.php b/includes/StubObject.php index ceedeb44cd..e18537e054 100644 --- a/includes/StubObject.php +++ b/includes/StubObject.php @@ -2,72 +2,100 @@ /** * Class to implement stub globals, which are globals that delay loading the - * their associated module code by deferring initialisation until the first - * method call. + * their associated module code by deferring initialisation until the first + * method call. * - * Note on unstub loops: + * Note on unstub loops: * - * Unstub loops (infinite recursion) sometimes occur when a constructor calls - * another function, and the other function calls some method of the stub. The + * Unstub loops (infinite recursion) sometimes occur when a constructor calls + * another function, and the other function calls some method of the stub. The * best way to avoid this is to make constructors as lightweight as possible, - * deferring any initialisation which depends on other modules. As a last - * resort, you can use StubObject::isRealObject() to break the loop, but as a - * general rule, the stub object mechanism should be transparent, and code + * deferring any initialisation which depends on other modules. As a last + * resort, you can use StubObject::isRealObject() to break the loop, but as a + * general rule, the stub object mechanism should be transparent, and code * which refers to it should be kept to a minimum. */ class StubObject { var $mGlobal, $mClass, $mParams; + + /** + * Constructor. + * + * @param String $global name of the global variable. + * @param String $class name of the class of the real object. + * @param Array $param array of parameters to pass to contructor of the real + * object. + */ function __construct( $global = null, $class = null, $params = array() ) { $this->mGlobal = $global; $this->mClass = $class; $this->mParams = $params; } + /** + * Returns a bool value whetever $obj is a stub object. Can be used to break + * a infinite loop when unstubbing an object. + * + * @param Object $obj object to check. + * @return bool true if $obj is not an instance of StubObject class. + */ static function isRealObject( $obj ) { - return is_object( $obj ) && !is_a( $obj, 'StubObject' ); - } - - static function _getCaller( $level ) { - $backtrace = debug_backtrace(); - if ( isset( $backtrace[$level] ) ) { - if ( isset( $backtrace[$level]['class'] ) ) { - $caller = $backtrace[$level]['class'] . '::' . $backtrace[$level]['function']; - } else { - $caller = $backtrace[$level]['function']; - } - } else { - $caller = 'unknown'; - } - return $caller; + return is_object( $obj ) && !($obj instanceof StubObject); } + /** + * 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 + * self::__call() function and that function will call this function. + * This function will also call the function with the same name in the real + * object. + * + * @param String $name name of the function called. + * @param Array $args array of arguments. + */ function _call( $name, $args ) { $this->_unstub( $name, 5 ); return call_user_func_array( array( $GLOBALS[$this->mGlobal], $name ), $args ); } + /** + * Create a new object to replace this stub object. + */ function _newObject() { return wfCreateObject( $this->mClass, $this->mParams ); } - + + /** + * Function called by PHP if no function with that name exists in this + * object. + * + * @param String $name name of the function called + * @param Array $args array of arguments + */ function __call( $name, $args ) { return $this->_call( $name, $args ); } /** - * This is public, for the convenience of external callers wishing to access + * 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 + * + * @param String $name name of the method called in this object. + * @param Integer $level level to go in the stact trace to get the function + * who called this function. */ function _unstub( $name = '_unstub', $level = 2 ) { static $recursionLevel = 0; if ( get_class( $GLOBALS[$this->mGlobal] ) != $this->mClass ) { $fname = __METHOD__.'-'.$this->mGlobal; wfProfileIn( $fname ); - $caller = self::_getCaller( $level ); + $caller = wfGetCaller( $level ); if ( ++$recursionLevel > 2 ) { throw new MWException( "Unstub loop detected on call of \${$this->mGlobal}->$name from $caller\n" ); } - wfDebug( "Unstubbing \${$this->mGlobal} on call of \${$this->mGlobal}->$name from $caller\n" ); + wfDebug( "Unstubbing \${$this->mGlobal} on call of \${$this->mGlobal}::$name from $caller\n" ); $GLOBALS[$this->mGlobal] = $this->_newObject(); --$recursionLevel; wfProfileOut( $fname ); @@ -75,13 +103,18 @@ class StubObject { } } +/** + * Stub object for the content language of this wiki. This object have to be in + * $wgContLang global. + */ class StubContLang extends StubObject { + function __construct() { parent::__construct( 'wgContLang' ); } function __call( $name, $args ) { - return StubObject::_call( $name, $args ); + return $this->_call( $name, $args ); } function _newObject() { @@ -92,7 +125,14 @@ class StubContLang extends StubObject { return $obj; } } + +/** + * Stub object for the user language. It depends of the user preferences and + * "uselang" parameter that can be passed to index.php. This object have to be + * in $wgLang global. + */ class StubUserLang extends StubObject { + function __construct() { parent::__construct( 'wgLang' ); } @@ -102,25 +142,79 @@ class StubUserLang extends StubObject { } function _newObject() { - global $wgLanguageCode, $wgContLanguageCode, $wgRequest, $wgUser, $wgContLang; - // wgLanguageCode now specifically means the UI language - $wgLanguageCode = $wgRequest->getText('uselang', ''); - if ($wgLanguageCode == '') - $wgLanguageCode = $wgUser->getOption('language'); - # Validate $wgLanguageCode - if( empty( $wgLanguageCode ) || !preg_match( '/^[a-z]+(-[a-z]+)?$/', $wgLanguageCode ) ) { - $wgLanguageCode = $wgContLanguageCode; + global $wgContLanguageCode, $wgRequest, $wgUser, $wgContLang; + $code = $wgRequest->getVal( 'uselang', $wgUser->getOption( 'language' ) ); + + # Validate $code + if( empty( $code ) || !preg_match( '/^[a-z-]+$/', $code ) || ( $code === 'qqq' ) ) { + wfDebug( "Invalid user language code\n" ); + $code = $wgContLanguageCode; + } + + if( $code === $wgContLanguageCode ) { + return $wgContLang; + } else { + $obj = Language::factory( $code ); + return $obj; + } + } +} + +/** + * Stub object for the user variant. It depends of the user preferences and + * "variant" parameter that can be passed to index.php. This object have to be + * in $wgVariant global. + */ +class StubUserVariant extends StubObject { + + function __construct() { + parent::__construct( 'wgVariant' ); + } + + function __call( $name, $args ) { + return $this->_call( $name, $args ); + } + + function _newObject() { + global $wgContLanguageCode, $wgRequest, $wgUser, $wgContLang; + + if( $wgContLang->hasVariants() ) { + $code = $wgRequest->getVal( 'variant', $wgUser->getOption( 'variant' ) ); + } else { + $code = $wgRequest->getVal( 'variant', $wgUser->getOption( 'language' ) ); + } + + // if variant is explicitely selected, use it instead the one from wgUser + // see bug #7605 + if( $wgContLang->hasVariants() && in_array($code, $wgContLang->getVariants()) ){ + $variant = $wgContLang->getPreferredVariant(); + if( $variant != $wgContLanguageCode ) + $code = $variant; + } + + # Validate $code + if( empty( $code ) || !preg_match( '/^[a-z-]+$/', $code ) || ( $code === 'qqq' ) ) { + wfDebug( "Invalid user variant code\n" ); + $code = $wgContLanguageCode; } - if( $wgLanguageCode == $wgContLanguageCode ) { + if( $code === $wgContLanguageCode ) { return $wgContLang; } else { - $obj = Language::factory( $wgLanguageCode ); + $obj = Language::factory( $code ); return $obj; } } } + +/** + * Stub object for the user. The initialisation of the will depend of + * $wgCommandLineMode. If it's true, it will be an anonymous user and if it's + * false, the user will be loaded from credidentails provided by cookies. This + * object have to be in $wgUser global. + */ class StubUser extends StubObject { + function __construct() { parent::__construct( 'wgUser' ); } @@ -128,17 +222,14 @@ class StubUser extends StubObject { function __call( $name, $args ) { return $this->_call( $name, $args ); } - + function _newObject() { global $wgCommandLineMode; if( $wgCommandLineMode ) { $user = new User; - $user->setLoaded( true ); } else { - $user = User::loadFromSession(); + $user = User::newFromSession(); } return $user; } } - -?>