<?php
-class WellProtectedClass {
+class WellProtectedParentClass {
+ private $privateParentProperty;
+
+ public function __construct() {
+ $this->privateParentProperty = 9000;
+ }
+
+ private function incrementPrivateParentPropertyValue() {
+ $this->privateParentProperty++;
+ }
+
+ public function getPrivateParentProperty() {
+ return $this->privateParentProperty;
+ }
+}
+
+class WellProtectedClass extends WellProtectedParentClass {
protected $property;
+ private $privateProperty;
public function __construct() {
+ parent::__construct();
$this->property = 1;
+ $this->privateProperty = 42;
}
protected function incrementPropertyValue() {
$this->property++;
}
+ private function incrementPrivatePropertyValue() {
+ $this->privateProperty++;
+ }
+
public function getProperty() {
return $this->property;
}
+ public function getPrivateProperty() {
+ return $this->privateProperty;
+ }
+
protected function whatSecondArg( $a, $b = false ) {
return $b;
}
return $methodReflection->invokeArgs( $this->object, $args );
}
- public function __set( $name, $value ) {
+ /**
+ * ReflectionClass::getProperty() fails if the private property is defined
+ * in a parent class. This works more like ReflectionClass::getMethod().
+ */
+ private function getProperty( $name ) {
$classReflection = new ReflectionClass( $this->object );
- $propertyReflection = $classReflection->getProperty( $name );
+ try {
+ return $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() ) {
+ return $propertyReflection;
+ } else {
+ throw $ex;
+ }
+ }
+ }
+ }
+
+ public function __set( $name, $value ) {
+ $propertyReflection = $this->getProperty( $name );
$propertyReflection->setAccessible( true );
$propertyReflection->setValue( $this->object, $value );
}
public function __get( $name ) {
- $classReflection = new ReflectionClass( $this->object );
- $propertyReflection = $classReflection->getProperty( $name );
+ $propertyReflection = $this->getProperty( $name );
$propertyReflection->setAccessible( true );
return $propertyReflection->getValue( $this->object );
}
function testGetProperty() {
$this->assertSame( 1, $this->wrapped->property );
+ $this->assertSame( 42, $this->wrapped->privateProperty );
+ $this->assertSame( 9000, $this->wrapped->privateParentProperty );
}
function testSetProperty() {
$this->wrapped->property = 10;
$this->assertSame( 10, $this->wrapped->property );
$this->assertSame( 10, $this->raw->getProperty() );
+
+ $this->wrapped->privateProperty = 11;
+ $this->assertSame( 11, $this->wrapped->privateProperty );
+ $this->assertSame( 11, $this->raw->getPrivateProperty() );
+
+ $this->wrapped->privateParentProperty = 12;
+ $this->assertSame( 12, $this->wrapped->privateParentProperty );
+ $this->assertSame( 12, $this->raw->getPrivateParentProperty() );
}
function testCallMethod() {
$this->wrapped->incrementPropertyValue();
$this->assertSame( 2, $this->wrapped->property );
$this->assertSame( 2, $this->raw->getProperty() );
+
+ $this->wrapped->incrementPrivatePropertyValue();
+ $this->assertSame( 43, $this->wrapped->privateProperty );
+ $this->assertSame( 43, $this->raw->getPrivateProperty() );
+
+ $this->wrapped->incrementPrivateParentPropertyValue();
+ $this->assertSame( 9001, $this->wrapped->privateParentProperty );
+ $this->assertSame( 9001, $this->raw->getPrivateParentProperty() );
}
function testCallMethodTwoArgs() {