Skip to content

Commit

Permalink
Merge pull request #78 from ThomasNunninger/master
Browse files Browse the repository at this point in the history
Do not create MethodMetadata::$reflection on constructor/unserialize,…
  • Loading branch information
goetas committed Apr 21, 2019
2 parents 5217840 + f34214a commit d2ef520
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 7 deletions.
40 changes: 33 additions & 7 deletions src/MethodMetadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
* properties, and flags.
*
* @author Johannes M. Schmitt <[email protected]>
*
* @property $reflection
*/
class MethodMetadata implements \Serializable
{
Expand All @@ -27,15 +29,12 @@ class MethodMetadata implements \Serializable
/**
* @var \ReflectionMethod
*/
public $reflection;
private $reflection;

public function __construct(string $class, string $name)
{
$this->class = $class;
$this->name = $name;

$this->reflection = new \ReflectionMethod($class, $name);
$this->reflection->setAccessible(true);
}

/**
Expand All @@ -45,7 +44,7 @@ public function __construct(string $class, string $name)
*/
public function invoke(object $obj, array $args = [])
{
return $this->reflection->invokeArgs($obj, $args);
return $this->getReflection()->invokeArgs($obj, $args);
}

/**
Expand All @@ -71,8 +70,35 @@ public function serialize()
public function unserialize($str)
{
list($this->class, $this->name) = unserialize($str);
}

/**
* @return mixed
*/
public function __get(string $propertyName)
{
if ('reflection' === $propertyName) {
return $this->getReflection();
}

return $this->$propertyName;
}

/**
* @param mixed $value
*/
public function __set(string $propertyName, $value): void
{
$this->$propertyName = $value;
}

private function getReflection(): \ReflectionMethod
{
if (null === $this->reflection) {
$this->reflection = new \ReflectionMethod($this->class, $this->name);
$this->reflection->setAccessible(true);
}

$this->reflection = new \ReflectionMethod($this->class, $this->name);
$this->reflection->setAccessible(true);
return $this->reflection;
}
}
62 changes: 62 additions & 0 deletions tests/MethodMetadataTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Metadata\MethodMetadata;
use Metadata\Tests\Fixtures\TestObject;
use PHPUnit\Framework\Error\Notice;
use PHPUnit\Framework\TestCase;

class MethodMetadataTest extends TestCase
Expand Down Expand Up @@ -37,4 +38,65 @@ public function testInvoke()
$metadata->invoke($obj, ['foo']);
$this->assertEquals('foo', $obj->getFoo());
}

public function testLazyReflectionCreationOnConstruction()
{
$metadata = new MethodMetadata(TestObject::class, 'setFoo');

$reflectionProperty = new \ReflectionProperty(MethodMetadata::class, 'reflection');
$reflectionProperty->setAccessible(true);

$this->assertNull($reflectionProperty->getValue($metadata));
}

public function testLazyReflectionCreationOnUnserialize()
{
$metadata = new MethodMetadata(TestObject::class, 'setFoo');
$metadataUnserialized = unserialize(serialize($metadata));

$reflectionProperty = new \ReflectionProperty(MethodMetadata::class, 'reflection');
$reflectionProperty->setAccessible(true);

$this->assertNull($reflectionProperty->getValue($metadata));
}

public function testReflectionReadAccessReturnsSameInstance()
{
$metadata = new MethodMetadata(TestObject::class, 'setFoo');

$reflection1 = $metadata->reflection;
$reflection2 = $metadata->reflection;

$this->assertInstanceOf(\ReflectionMethod::class, $reflection1);
$this->assertSame($reflection1, $reflection2);
}

public function testReflectionWriteAccess()
{
$metadata = new MethodMetadata(TestObject::class, 'setFoo');

$otherValue = new \ReflectionMethod(TestObject::class, 'getFoo');
$metadata->reflection = $otherValue;

$this->assertSame($otherValue, $metadata->reflection);
}

public function testReadAccessForUnknownProperty()
{
$metadata = new MethodMetadata(TestObject::class, 'setFoo');

$this->expectException(Notice::class);
$this->expectExceptionMessage('Undefined property: Metadata\MethodMetadata::$unknownProperty');

$metadata->unknownProperty;
}

public function testWriteAccessForUnknownProperty()
{
$metadata = new MethodMetadata(TestObject::class, 'setFoo');

$metadata->unknownProperty = 'some value';

$this->assertSame('some value', $metadata->unknownProperty);
}
}

0 comments on commit d2ef520

Please sign in to comment.