gluon-web-remote

Web remote Administration for big size of gluon routers
git clone git://archive.git.mtrnord.blog/MTRNord/gluon-web-remote.git
Log | Files | Refs | README

Doubler.php (4239B)


      1 <?php
      2 
      3 /*
      4  * This file is part of the Prophecy.
      5  * (c) Konstantin Kudryashov <ever.zet@gmail.com>
      6  *     Marcello Duarte <marcello.duarte@gmail.com>
      7  *
      8  * For the full copyright and license information, please view the LICENSE
      9  * file that was distributed with this source code.
     10  */
     11 
     12 namespace Prophecy\Doubler;
     13 
     14 use Doctrine\Instantiator\Instantiator;
     15 use Prophecy\Doubler\ClassPatch\ClassPatchInterface;
     16 use Prophecy\Doubler\Generator\ClassMirror;
     17 use Prophecy\Doubler\Generator\ClassCreator;
     18 use Prophecy\Exception\InvalidArgumentException;
     19 use ReflectionClass;
     20 
     21 /**
     22  * Cached class doubler.
     23  * Prevents mirroring/creation of the same structure twice.
     24  *
     25  * @author Konstantin Kudryashov <ever.zet@gmail.com>
     26  */
     27 class Doubler
     28 {
     29     private $mirror;
     30     private $creator;
     31     private $namer;
     32 
     33     /**
     34      * @var ClassPatchInterface[]
     35      */
     36     private $patches = array();
     37 
     38     /**
     39      * @var \Doctrine\Instantiator\Instantiator
     40      */
     41     private $instantiator;
     42 
     43     /**
     44      * Initializes doubler.
     45      *
     46      * @param ClassMirror   $mirror
     47      * @param ClassCreator  $creator
     48      * @param NameGenerator $namer
     49      */
     50     public function __construct(ClassMirror $mirror = null, ClassCreator $creator = null,
     51                                 NameGenerator $namer = null)
     52     {
     53         $this->mirror  = $mirror  ?: new ClassMirror;
     54         $this->creator = $creator ?: new ClassCreator;
     55         $this->namer   = $namer   ?: new NameGenerator;
     56     }
     57 
     58     /**
     59      * Returns list of registered class patches.
     60      *
     61      * @return ClassPatchInterface[]
     62      */
     63     public function getClassPatches()
     64     {
     65         return $this->patches;
     66     }
     67 
     68     /**
     69      * Registers new class patch.
     70      *
     71      * @param ClassPatchInterface $patch
     72      */
     73     public function registerClassPatch(ClassPatchInterface $patch)
     74     {
     75         $this->patches[] = $patch;
     76 
     77         @usort($this->patches, function (ClassPatchInterface $patch1, ClassPatchInterface $patch2) {
     78             return $patch2->getPriority() - $patch1->getPriority();
     79         });
     80     }
     81 
     82     /**
     83      * Creates double from specific class or/and list of interfaces.
     84      *
     85      * @param ReflectionClass   $class
     86      * @param ReflectionClass[] $interfaces Array of ReflectionClass instances
     87      * @param array             $args       Constructor arguments
     88      *
     89      * @return DoubleInterface
     90      *
     91      * @throws \Prophecy\Exception\InvalidArgumentException
     92      */
     93     public function double(ReflectionClass $class = null, array $interfaces, array $args = null)
     94     {
     95         foreach ($interfaces as $interface) {
     96             if (!$interface instanceof ReflectionClass) {
     97                 throw new InvalidArgumentException(sprintf(
     98                     "[ReflectionClass \$interface1 [, ReflectionClass \$interface2]] array expected as\n".
     99                     "a second argument to `Doubler::double(...)`, but got %s.",
    100                     is_object($interface) ? get_class($interface).' class' : gettype($interface)
    101                 ));
    102             }
    103         }
    104 
    105         $classname  = $this->createDoubleClass($class, $interfaces);
    106         $reflection = new ReflectionClass($classname);
    107 
    108         if (null !== $args) {
    109             return $reflection->newInstanceArgs($args);
    110         }
    111         if ((null === $constructor = $reflection->getConstructor())
    112             || ($constructor->isPublic() && !$constructor->isFinal())) {
    113             return $reflection->newInstance();
    114         }
    115 
    116         if (!$this->instantiator) {
    117             $this->instantiator = new Instantiator();
    118         }
    119 
    120         return $this->instantiator->instantiate($classname);
    121     }
    122 
    123     /**
    124      * Creates double class and returns its FQN.
    125      *
    126      * @param ReflectionClass   $class
    127      * @param ReflectionClass[] $interfaces
    128      *
    129      * @return string
    130      */
    131     protected function createDoubleClass(ReflectionClass $class = null, array $interfaces)
    132     {
    133         $name = $this->namer->name($class, $interfaces);
    134         $node = $this->mirror->reflect($class, $interfaces);
    135 
    136         foreach ($this->patches as $patch) {
    137             if ($patch->supports($node)) {
    138                 $patch->apply($node);
    139             }
    140         }
    141 
    142         $this->creator->create($name, $node);
    143 
    144         return $name;
    145     }
    146 }