Skip to content

Commit

Permalink
Fix instantiation for latest PHP versions.
Browse files Browse the repository at this point in the history
  • Loading branch information
whatthejeff committed Sep 7, 2014
1 parent 5bc9c7c commit fe9982d
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 55 deletions.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
}
],
"require": {
"phpdocumentor/reflection-docblock": "~2.0"
"phpdocumentor/reflection-docblock": "~2.0",
"doctrine/instantiator": "~1.0,>=1.0.2"
},

"require-dev": {
Expand Down
17 changes: 17 additions & 0 deletions spec/Prophecy/Promise/ThrowPromiseSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@ function it_instantiates_and_throws_exception_from_provided_classname($object, $
->duringExecute(array(), $object, $method);
}

/**
* @param \Prophecy\Prophecy\ObjectProphecy $object
* @param \Prophecy\Prophecy\MethodProphecy $method
*/
function it_instantiates_exceptions_with_required_arguments($object, $method)
{
$this->beConstructedWith('spec\Prophecy\Promise\RequiredArgumentException');

$this->shouldThrow('spec\Prophecy\Promise\RequiredArgumentException')
->duringExecute(array(), $object, $method);
}

/**
* @param \Prophecy\Prophecy\ObjectProphecy $object
* @param \Prophecy\Prophecy\MethodProphecy $method
Expand All @@ -39,3 +51,8 @@ function it_throws_provided_exception($object, $method)
$this->shouldThrow($exc)->duringExecute(array(), $object, $method);
}
}

class RequiredArgumentException extends \Exception
{
final public function __construct($message, $code) {}
}
62 changes: 11 additions & 51 deletions src/Prophecy/Doubler/Doubler.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Prophecy\Doubler;

use Doctrine\Instantiator\Instantiator;
use Prophecy\Doubler\Generator\ClassMirror;
use Prophecy\Doubler\Generator\ClassCreator;
use Prophecy\Exception\InvalidArgumentException;
Expand All @@ -33,6 +34,11 @@ class Doubler
*/
private $patches = array();

/**
* @var \Doctrine\Instantiator\Instantiator
*/
private $instantiator;

/**
* Initializes doubler.
*
Expand Down Expand Up @@ -106,7 +112,11 @@ public function double(ReflectionClass $class = null, array $interfaces, array $
return $reflection->newInstance();
}

return $this->createInstanceWithoutConstructor($reflection);
if (!$this->instantiator) {
$this->instantiator = new Instantiator();
}

return $this->instantiator->instantiate($classname);
}

/**
Expand All @@ -132,54 +142,4 @@ protected function createDoubleClass(ReflectionClass $class = null, array $inter

return $name;
}

/**
* Creates an instance without using its constructor using different strategies
*
* @param ReflectionClass $reflection
*
* @return object
*/
private function createInstanceWithoutConstructor(ReflectionClass $reflection)
{
if (version_compare(PHP_VERSION, '5.4', '>=')) {
if ($class = $this->createInstanceWithoutConstructorUsingReflection($reflection)) {
return $class;
}
}

return $this->createInstanceWithoutConstructorUsingUnserialize($reflection);
}

/**
* Creates an instance bypassing the constructor using unserialization
*
* @param ReflectionClass $reflection
*
* @return object
*/
private function createInstanceWithoutConstructorUsingUnserialize(ReflectionClass $reflection)
{
$classname = $reflection->getName();
$serializedObject = sprintf('O:%d:"%s":0:{}', strlen($classname), $classname);

return @unserialize($serializedObject);
}

/**
* Creates an instance bypassing the constructor using reflection, or null on failure
*
* @param ReflectionClass $reflection
*
* @return object|null
*/
private function createInstanceWithoutConstructorUsingReflection(ReflectionClass $reflection)
{
try {
return $reflection->newInstanceWithoutConstructor();
} catch (\ReflectionException $e) {
// certain internal types can't have their constructor skipped
return null;
}
}
}
13 changes: 10 additions & 3 deletions src/Prophecy/Promise/ThrowPromise.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Prophecy\Promise;

use Doctrine\Instantiator\Instantiator;
use Prophecy\Prophecy\ObjectProphecy;
use Prophecy\Prophecy\MethodProphecy;
use Prophecy\Exception\InvalidArgumentException;
Expand All @@ -25,6 +26,11 @@ class ThrowPromise implements PromiseInterface
{
private $exception;

/**
* @var \Doctrine\Instantiator\Instantiator
*/
private $instantiator;

/**
* Initializes promise.
*
Expand Down Expand Up @@ -72,11 +78,12 @@ public function execute(array $args, ObjectProphecy $object, MethodProphecy $met
if ($constructor->isPublic() && 0 == $constructor->getNumberOfRequiredParameters()) {
throw $reflection->newInstance();
}
if (version_compare(PHP_VERSION, '5.4', '<')) {
throw unserialize(sprintf('O:%d:"%s":0:{}', strlen($classname), $classname));

if (!$this->instantiator) {
$this->instantiator = new Instantiator();
}

throw $reflection->newInstanceWithoutConstructor();
throw $this->instantiator->instantiate($classname);
}

throw $this->exception;
Expand Down

0 comments on commit fe9982d

Please sign in to comment.