Merge "MWUI: Vertically align the icon pseudo elements"
[lhc/web/wiklou.git] / tests / phpunit / includes / TestingAccessWrapper.php
index 63d8971..7332e15 100644 (file)
  *    $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 ) {
+               $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 ) {
+               $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 );
-               $methodReflection = $classReflection->getMethod( $method );
+               $methodReflection = $classReflection->getMethod( $name );
                $methodReflection->setAccessible( true );
-               return $methodReflection->invokeArgs( $this->object, $args );
+               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 {
-                       return $classReflection->getProperty( $name );
+                       $propertyReflection = $classReflection->getProperty( $name );
                } catch ( ReflectionException $ex ) {
                        while ( true ) {
                                $classReflection = $classReflection->getParentClass();
@@ -54,23 +116,13 @@ class TestingAccessWrapper {
                                        continue;
                                }
                                if ( $propertyReflection->isPrivate() ) {
-                                       return $propertyReflection;
+                                       break;
                                } else {
                                        throw $ex;
                                }
                        }
                }
-       }
-
-       public function __set( $name, $value ) {
-               $propertyReflection = $this->getProperty( $name );
                $propertyReflection->setAccessible( true );
-               $propertyReflection->setValue( $this->object, $value );
-       }
-
-       public function __get( $name ) {
-               $propertyReflection = $this->getProperty( $name );
-               $propertyReflection->setAccessible( true );
-               return $propertyReflection->getValue( $this->object );
+               return $propertyReflection;
        }
 }