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 12namespace Prophecy\Doubler; 13 14use Prophecy\Exception\Doubler\DoubleException; 15use Prophecy\Exception\Doubler\ClassNotFoundException; 16use Prophecy\Exception\Doubler\InterfaceNotFoundException; 17use ReflectionClass; 18 19/** 20 * Lazy double. 21 * Gives simple interface to describe double before creating it. 22 * 23 * @author Konstantin Kudryashov <ever.zet@gmail.com> 24 */ 25class LazyDouble 26{ 27 private $doubler; 28 private $class; 29 private $interfaces = array(); 30 private $arguments = null; 31 private $double; 32 33 /** 34 * Initializes lazy double. 35 * 36 * @param Doubler $doubler 37 */ 38 public function __construct(Doubler $doubler) 39 { 40 $this->doubler = $doubler; 41 } 42 43 /** 44 * Tells doubler to use specific class as parent one for double. 45 * 46 * @param string|ReflectionClass $class 47 * 48 * @throws \Prophecy\Exception\Doubler\ClassNotFoundException 49 * @throws \Prophecy\Exception\Doubler\DoubleException 50 */ 51 public function setParentClass($class) 52 { 53 if (null !== $this->double) { 54 throw new DoubleException('Can not extend class with already instantiated double.'); 55 } 56 57 if (!$class instanceof ReflectionClass) { 58 if (!class_exists($class)) { 59 throw new ClassNotFoundException(sprintf('Class %s not found.', $class), $class); 60 } 61 62 $class = new ReflectionClass($class); 63 } 64 65 $this->class = $class; 66 } 67 68 /** 69 * Tells doubler to implement specific interface with double. 70 * 71 * @param string|ReflectionClass $interface 72 * 73 * @throws \Prophecy\Exception\Doubler\InterfaceNotFoundException 74 * @throws \Prophecy\Exception\Doubler\DoubleException 75 */ 76 public function addInterface($interface) 77 { 78 if (null !== $this->double) { 79 throw new DoubleException( 80 'Can not implement interface with already instantiated double.' 81 ); 82 } 83 84 if (!$interface instanceof ReflectionClass) { 85 if (!interface_exists($interface)) { 86 throw new InterfaceNotFoundException( 87 sprintf('Interface %s not found.', $interface), 88 $interface 89 ); 90 } 91 92 $interface = new ReflectionClass($interface); 93 } 94 95 $this->interfaces[] = $interface; 96 } 97 98 /** 99 * Sets constructor arguments. 100 * 101 * @param array $arguments 102 */ 103 public function setArguments(array $arguments = null) 104 { 105 $this->arguments = $arguments; 106 } 107 108 /** 109 * Creates double instance or returns already created one. 110 * 111 * @return DoubleInterface 112 */ 113 public function getInstance() 114 { 115 if (null === $this->double) { 116 if (null !== $this->arguments) { 117 return $this->double = $this->doubler->double( 118 $this->class, $this->interfaces, $this->arguments 119 ); 120 } 121 122 $this->double = $this->doubler->double($this->class, $this->interfaces); 123 } 124 125 return $this->double; 126 } 127} 128