summaryrefslogtreecommitdiff
path: root/vendor/phpspec/prophecy/src/Prophecy/Doubler/Doubler.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/phpspec/prophecy/src/Prophecy/Doubler/Doubler.php')
-rw-r--r--vendor/phpspec/prophecy/src/Prophecy/Doubler/Doubler.php146
1 files changed, 146 insertions, 0 deletions
diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/Doubler.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Doubler.php
new file mode 100644
index 000000000..a378ae279
--- /dev/null
+++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Doubler.php
@@ -0,0 +1,146 @@
+<?php
+
+/*
+ * This file is part of the Prophecy.
+ * (c) Konstantin Kudryashov <[email protected]>
+ * Marcello Duarte <[email protected]>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Prophecy\Doubler;
+
+use Doctrine\Instantiator\Instantiator;
+use Prophecy\Doubler\ClassPatch\ClassPatchInterface;
+use Prophecy\Doubler\Generator\ClassMirror;
+use Prophecy\Doubler\Generator\ClassCreator;
+use Prophecy\Exception\InvalidArgumentException;
+use ReflectionClass;
+
+/**
+ * Cached class doubler.
+ * Prevents mirroring/creation of the same structure twice.
+ *
+ * @author Konstantin Kudryashov <[email protected]>
+ */
+class Doubler
+{
+ private $mirror;
+ private $creator;
+ private $namer;
+
+ /**
+ * @var ClassPatchInterface[]
+ */
+ private $patches = array();
+
+ /**
+ * @var \Doctrine\Instantiator\Instantiator
+ */
+ private $instantiator;
+
+ /**
+ * Initializes doubler.
+ *
+ * @param ClassMirror $mirror
+ * @param ClassCreator $creator
+ * @param NameGenerator $namer
+ */
+ public function __construct(ClassMirror $mirror = null, ClassCreator $creator = null,
+ NameGenerator $namer = null)
+ {
+ $this->mirror = $mirror ?: new ClassMirror;
+ $this->creator = $creator ?: new ClassCreator;
+ $this->namer = $namer ?: new NameGenerator;
+ }
+
+ /**
+ * Returns list of registered class patches.
+ *
+ * @return ClassPatchInterface[]
+ */
+ public function getClassPatches()
+ {
+ return $this->patches;
+ }
+
+ /**
+ * Registers new class patch.
+ *
+ * @param ClassPatchInterface $patch
+ */
+ public function registerClassPatch(ClassPatchInterface $patch)
+ {
+ $this->patches[] = $patch;
+
+ @usort($this->patches, function (ClassPatchInterface $patch1, ClassPatchInterface $patch2) {
+ return $patch2->getPriority() - $patch1->getPriority();
+ });
+ }
+
+ /**
+ * Creates double from specific class or/and list of interfaces.
+ *
+ * @param ReflectionClass $class
+ * @param ReflectionClass[] $interfaces Array of ReflectionClass instances
+ * @param array $args Constructor arguments
+ *
+ * @return DoubleInterface
+ *
+ * @throws \Prophecy\Exception\InvalidArgumentException
+ */
+ public function double(ReflectionClass $class = null, array $interfaces, array $args = null)
+ {
+ foreach ($interfaces as $interface) {
+ if (!$interface instanceof ReflectionClass) {
+ throw new InvalidArgumentException(sprintf(
+ "[ReflectionClass \$interface1 [, ReflectionClass \$interface2]] array expected as\n".
+ "a second argument to `Doubler::double(...)`, but got %s.",
+ is_object($interface) ? get_class($interface).' class' : gettype($interface)
+ ));
+ }
+ }
+
+ $classname = $this->createDoubleClass($class, $interfaces);
+ $reflection = new ReflectionClass($classname);
+
+ if (null !== $args) {
+ return $reflection->newInstanceArgs($args);
+ }
+ if ((null === $constructor = $reflection->getConstructor())
+ || ($constructor->isPublic() && !$constructor->isFinal())) {
+ return $reflection->newInstance();
+ }
+
+ if (!$this->instantiator) {
+ $this->instantiator = new Instantiator();
+ }
+
+ return $this->instantiator->instantiate($classname);
+ }
+
+ /**
+ * Creates double class and returns its FQN.
+ *
+ * @param ReflectionClass $class
+ * @param ReflectionClass[] $interfaces
+ *
+ * @return string
+ */
+ protected function createDoubleClass(ReflectionClass $class = null, array $interfaces)
+ {
+ $name = $this->namer->name($class, $interfaces);
+ $node = $this->mirror->reflect($class, $interfaces);
+
+ foreach ($this->patches as $patch) {
+ if ($patch->supports($node)) {
+ $patch->apply($node);
+ }
+ }
+
+ $this->creator->create($name, $node);
+
+ return $name;
+ }
+}