X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=tests%2Fphpunit%2Fincludes%2FTestingAccessWrapper.php;h=7332e15e8d95cb74954e6e8fe30cdc3c09271c94;hb=b86ef89dd17f51841a220e8ef9b3b8b2402e2547;hp=84c0f9b5be7c5090104b6fc842cbb55911446acc;hpb=6b1a173f07f1a04188735f4688ce6335da14c3b7;p=lhc%2Fweb%2Fwiklou.git diff --git a/tests/phpunit/includes/TestingAccessWrapper.php b/tests/phpunit/includes/TestingAccessWrapper.php index 84c0f9b5be..7332e15e8d 100644 --- a/tests/phpunit/includes/TestingAccessWrapper.php +++ b/tests/phpunit/includes/TestingAccessWrapper.php @@ -12,39 +12,117 @@ * $formatter = $title->getTitleFormatter(); * * TODO: - * - Provide access to static methods and properties. * - Organize other helper classes in tests/testHelpers.inc into a directory. */ class TestingAccessWrapper { + /** @var mixed The object, or the class name for static-only access */ public $object; /** * Return the same object, without access restrictions. */ public static function newFromObject( $object ) { + if ( !is_object( $object ) ) { + throw new InvalidArgumentException( __METHOD__ . ' must be called with an object' ); + } $wrapper = new TestingAccessWrapper(); $wrapper->object = $object; return $wrapper; } + /** + * Allow access to non-public static methods and properties of the class. + * Use non-static access, + */ + public static function newFromClass( $className ) { + if ( !is_string( $className ) ) { + throw new InvalidArgumentException( __METHOD__ . ' must be called with a class name' ); + } + $wrapper = new TestingAccessWrapper(); + $wrapper->object = $className; + return $wrapper; + } + public function __call( $method, $args ) { - $classReflection = new ReflectionClass( $this->object ); - $methodReflection = $classReflection->getMethod( $method ); - $methodReflection->setAccessible( true ); - return $methodReflection->invokeArgs( $this->object, $args ); + $methodReflection = $this->getMethod( $method ); + + if ( $this->isStatic() && !$methodReflection->isStatic() ) { + throw new DomainException( __METHOD__ . ': Cannot call non-static when wrapping static class' ); + } + + return $methodReflection->invokeArgs( $methodReflection->isStatic() ? null : $this->object, + $args ); } public function __set( $name, $value ) { - $classReflection = new ReflectionClass( $this->object ); - $propertyReflection = $classReflection->getProperty( $name ); - $propertyReflection->setAccessible( true ); + $propertyReflection = $this->getProperty( $name ); + + if ( $this->isStatic() && !$propertyReflection->isStatic() ) { + throw new DomainException( __METHOD__ . ': Cannot set property when wrapping static class' ); + } + $propertyReflection->setValue( $this->object, $value ); } public function __get( $name ) { + $propertyReflection = $this->getProperty( $name ); + + if ( $this->isStatic() && !$propertyReflection->isStatic() ) { + throw new DomainException( __METHOD__ . ': Cannot get property when wrapping static class' ); + } + + return $propertyReflection->getValue( $this->object ); + } + + private function isStatic() { + return is_string( $this->object ); + } + + /** + * Return a property and make it accessible. + * @param string $name + * @return ReflectionMethod + */ + private function getMethod( $name ) { $classReflection = new ReflectionClass( $this->object ); - $propertyReflection = $classReflection->getProperty( $name ); + $methodReflection = $classReflection->getMethod( $name ); + $methodReflection->setAccessible( true ); + return $methodReflection; + } + + /** + * Return a property and make it accessible. + * + * ReflectionClass::getProperty() fails if the private property is defined + * in a parent class. This works more like ReflectionClass::getMethod(). + * + * @param string $name + * @return ReflectionProperty + * @throws ReflectionException + */ + private function getProperty( $name ) { + $classReflection = new ReflectionClass( $this->object ); + try { + $propertyReflection = $classReflection->getProperty( $name ); + } catch ( ReflectionException $ex ) { + while ( true ) { + $classReflection = $classReflection->getParentClass(); + if ( !$classReflection ) { + throw $ex; + } + try { + $propertyReflection = $classReflection->getProperty( $name ); + } catch ( ReflectionException $ex2 ) { + continue; + } + if ( $propertyReflection->isPrivate() ) { + break; + } else { + throw $ex; + } + } + } $propertyReflection->setAccessible( true ); - return $propertyReflection->getValue( $this->object ); + return $propertyReflection; } }