* $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();
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;
}
}