/vendor/phpspec/prophecy/src/Prophecy/Prophecy/ObjectProphecy.php

https://gitlab.com/techniconline/kmc · PHP · 281 lines · 138 code · 36 blank · 107 comment · 9 complexity · 717acac13b12cf7c0d130bc031e4f255 MD5 · raw file

  1. <?php
  2. /*
  3. * This file is part of the Prophecy.
  4. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  5. * Marcello Duarte <marcello.duarte@gmail.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Prophecy\Prophecy;
  11. use SebastianBergmann\Comparator\ComparisonFailure;
  12. use Prophecy\Comparator\Factory as ComparatorFactory;
  13. use Prophecy\Call\Call;
  14. use Prophecy\Doubler\LazyDouble;
  15. use Prophecy\Argument\ArgumentsWildcard;
  16. use Prophecy\Call\CallCenter;
  17. use Prophecy\Exception\Prophecy\ObjectProphecyException;
  18. use Prophecy\Exception\Prophecy\MethodProphecyException;
  19. use Prophecy\Exception\Prediction\AggregateException;
  20. use Prophecy\Exception\Prediction\PredictionException;
  21. /**
  22. * Object prophecy.
  23. *
  24. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  25. */
  26. class ObjectProphecy implements ProphecyInterface
  27. {
  28. private $lazyDouble;
  29. private $callCenter;
  30. private $revealer;
  31. private $comparatorFactory;
  32. /**
  33. * @var MethodProphecy[][]
  34. */
  35. private $methodProphecies = array();
  36. /**
  37. * Initializes object prophecy.
  38. *
  39. * @param LazyDouble $lazyDouble
  40. * @param CallCenter $callCenter
  41. * @param RevealerInterface $revealer
  42. * @param ComparatorFactory $comparatorFactory
  43. */
  44. public function __construct(
  45. LazyDouble $lazyDouble,
  46. CallCenter $callCenter = null,
  47. RevealerInterface $revealer = null,
  48. ComparatorFactory $comparatorFactory = null
  49. )
  50. {
  51. $this->lazyDouble = $lazyDouble;
  52. $this->callCenter = $callCenter ?: new CallCenter;
  53. $this->revealer = $revealer ?: new Revealer;
  54. $this->comparatorFactory = $comparatorFactory ?: ComparatorFactory::getInstance();
  55. }
  56. /**
  57. * Forces double to extend specific class.
  58. *
  59. * @param string $class
  60. *
  61. * @return $this
  62. */
  63. public function willExtend($class)
  64. {
  65. $this->lazyDouble->setParentClass($class);
  66. return $this;
  67. }
  68. /**
  69. * Forces double to implement specific interface.
  70. *
  71. * @param string $interface
  72. *
  73. * @return $this
  74. */
  75. public function willImplement($interface)
  76. {
  77. $this->lazyDouble->addInterface($interface);
  78. return $this;
  79. }
  80. /**
  81. * Sets constructor arguments.
  82. *
  83. * @param array $arguments
  84. *
  85. * @return $this
  86. */
  87. public function willBeConstructedWith(array $arguments = null)
  88. {
  89. $this->lazyDouble->setArguments($arguments);
  90. return $this;
  91. }
  92. /**
  93. * Reveals double.
  94. *
  95. * @return object
  96. *
  97. * @throws \Prophecy\Exception\Prophecy\ObjectProphecyException If double doesn't implement needed interface
  98. */
  99. public function reveal()
  100. {
  101. $double = $this->lazyDouble->getInstance();
  102. if (null === $double || !$double instanceof ProphecySubjectInterface) {
  103. throw new ObjectProphecyException(
  104. "Generated double must implement ProphecySubjectInterface, but it does not.\n" .
  105. 'It seems you have wrongly configured doubler without required ClassPatch.',
  106. $this
  107. );
  108. }
  109. $double->setProphecy($this);
  110. return $double;
  111. }
  112. /**
  113. * Adds method prophecy to object prophecy.
  114. *
  115. * @param MethodProphecy $methodProphecy
  116. *
  117. * @throws \Prophecy\Exception\Prophecy\MethodProphecyException If method prophecy doesn't
  118. * have arguments wildcard
  119. */
  120. public function addMethodProphecy(MethodProphecy $methodProphecy)
  121. {
  122. $argumentsWildcard = $methodProphecy->getArgumentsWildcard();
  123. if (null === $argumentsWildcard) {
  124. throw new MethodProphecyException(sprintf(
  125. "Can not add prophecy for a method `%s::%s()`\n" .
  126. "as you did not specify arguments wildcard for it.",
  127. get_class($this->reveal()),
  128. $methodProphecy->getMethodName()
  129. ), $methodProphecy);
  130. }
  131. $methodName = $methodProphecy->getMethodName();
  132. if (!isset($this->methodProphecies[$methodName])) {
  133. $this->methodProphecies[$methodName] = array();
  134. }
  135. $this->methodProphecies[$methodName][] = $methodProphecy;
  136. }
  137. /**
  138. * Returns either all or related to single method prophecies.
  139. *
  140. * @param null|string $methodName
  141. *
  142. * @return MethodProphecy[]
  143. */
  144. public function getMethodProphecies($methodName = null)
  145. {
  146. if (null === $methodName) {
  147. return $this->methodProphecies;
  148. }
  149. if (!isset($this->methodProphecies[$methodName])) {
  150. return array();
  151. }
  152. return $this->methodProphecies[$methodName];
  153. }
  154. /**
  155. * Makes specific method call.
  156. *
  157. * @param string $methodName
  158. * @param array $arguments
  159. *
  160. * @return mixed
  161. */
  162. public function makeProphecyMethodCall($methodName, array $arguments)
  163. {
  164. $arguments = $this->revealer->reveal($arguments);
  165. $return = $this->callCenter->makeCall($this, $methodName, $arguments);
  166. return $this->revealer->reveal($return);
  167. }
  168. /**
  169. * Finds calls by method name & arguments wildcard.
  170. *
  171. * @param string $methodName
  172. * @param ArgumentsWildcard $wildcard
  173. *
  174. * @return Call[]
  175. */
  176. public function findProphecyMethodCalls($methodName, ArgumentsWildcard $wildcard)
  177. {
  178. return $this->callCenter->findCalls($methodName, $wildcard);
  179. }
  180. /**
  181. * Checks that registered method predictions do not fail.
  182. *
  183. * @throws \Prophecy\Exception\Prediction\AggregateException If any of registered predictions fail
  184. */
  185. public function checkProphecyMethodsPredictions()
  186. {
  187. $exception = new AggregateException(sprintf("%s:\n", get_class($this->reveal())));
  188. $exception->setObjectProphecy($this);
  189. foreach ($this->methodProphecies as $prophecies) {
  190. foreach ($prophecies as $prophecy) {
  191. try {
  192. $prophecy->checkPrediction();
  193. } catch (PredictionException $e) {
  194. $exception->append($e);
  195. }
  196. }
  197. }
  198. if (count($exception->getExceptions())) {
  199. throw $exception;
  200. }
  201. }
  202. /**
  203. * Creates new method prophecy using specified method name and arguments.
  204. *
  205. * @param string $methodName
  206. * @param array $arguments
  207. *
  208. * @return MethodProphecy
  209. */
  210. public function __call($methodName, array $arguments)
  211. {
  212. $arguments = new ArgumentsWildcard($this->revealer->reveal($arguments));
  213. foreach ($this->getMethodProphecies($methodName) as $prophecy) {
  214. $argumentsWildcard = $prophecy->getArgumentsWildcard();
  215. $comparator = $this->comparatorFactory->getComparatorFor(
  216. $argumentsWildcard, $arguments
  217. );
  218. try {
  219. $comparator->assertEquals($argumentsWildcard, $arguments);
  220. return $prophecy;
  221. } catch (ComparisonFailure $failure) {
  222. }
  223. }
  224. return new MethodProphecy($this, $methodName, $arguments);
  225. }
  226. /**
  227. * Tries to get property value from double.
  228. *
  229. * @param string $name
  230. */
  231. public function __get($name)
  232. {
  233. return $this->reveal()->$name;
  234. }
  235. /**
  236. * Tries to set property value to double.
  237. *
  238. * @param string $name
  239. * @param string $value
  240. */
  241. public function __set($name, $value)
  242. {
  243. $this->reveal()->$name = $this->revealer->reveal($value);
  244. }
  245. }