You are here

Doubler.php in Zircon Profile 8

Same filename and directory in other branches
  1. 8.0 vendor/phpspec/prophecy/src/Prophecy/Doubler/Doubler.php

Namespace

Prophecy\Doubler

File

vendor/phpspec/prophecy/src/Prophecy/Doubler/Doubler.php
View source
<?php

/*
 * This file is part of the Prophecy.
 * (c) Konstantin Kudryashov <ever.zet@gmail.com>
 *     Marcello Duarte <marcello.duarte@gmail.com>
 *
 * 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 <ever.zet@gmail.com>
 */
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;
  }

}

Classes

Namesort descending Description
Doubler Cached class doubler. Prevents mirroring/creation of the same structure twice.