PageRenderTime 41ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://gitlab.com/ealexis.t/trends
PHP | 437 lines | 215 code | 51 blank | 171 comment | 18 complexity | 3a93fa04a61f2cef86ed4e6ac8f86660 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 Prophecy\Argument;
  12. use Prophecy\Prophet;
  13. use Prophecy\Promise;
  14. use Prophecy\Prediction;
  15. use Prophecy\Exception\Doubler\MethodNotFoundException;
  16. use Prophecy\Exception\InvalidArgumentException;
  17. use Prophecy\Exception\Prophecy\MethodProphecyException;
  18. /**
  19. * Method prophecy.
  20. *
  21. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  22. */
  23. class MethodProphecy
  24. {
  25. private $objectProphecy;
  26. private $methodName;
  27. private $argumentsWildcard;
  28. private $promise;
  29. private $prediction;
  30. private $checkedPredictions = array();
  31. private $bound = false;
  32. /**
  33. * Initializes method prophecy.
  34. *
  35. * @param ObjectProphecy $objectProphecy
  36. * @param string $methodName
  37. * @param null|Argument\ArgumentsWildcard|array $arguments
  38. *
  39. * @throws \Prophecy\Exception\Doubler\MethodNotFoundException If method not found
  40. */
  41. public function __construct(ObjectProphecy $objectProphecy, $methodName, $arguments = null)
  42. {
  43. $double = $objectProphecy->reveal();
  44. if (!method_exists($double, $methodName)) {
  45. throw new MethodNotFoundException(sprintf(
  46. 'Method `%s::%s()` is not defined.', get_class($double), $methodName
  47. ), get_class($double), $methodName, $arguments);
  48. }
  49. $this->objectProphecy = $objectProphecy;
  50. $this->methodName = $methodName;
  51. $reflectedMethod = new \ReflectionMethod($double, $methodName);
  52. if ($reflectedMethod->isFinal()) {
  53. throw new MethodProphecyException(sprintf(
  54. "Can not add prophecy for a method `%s::%s()`\n".
  55. "as it is a final method.",
  56. get_class($double),
  57. $methodName
  58. ), $this);
  59. }
  60. if (null !== $arguments) {
  61. $this->withArguments($arguments);
  62. }
  63. if (version_compare(PHP_VERSION, '7.0', '>=') && true === $reflectedMethod->hasReturnType()) {
  64. $type = (string) $reflectedMethod->getReturnType();
  65. $this->will(function () use ($type) {
  66. switch ($type) {
  67. case 'string': return '';
  68. case 'float': return 0.0;
  69. case 'int': return 0;
  70. case 'bool': return false;
  71. case 'array': return array();
  72. case 'callable':
  73. case 'Closure':
  74. return function () {};
  75. case 'Traversable':
  76. case 'Generator':
  77. // Remove eval() when minimum version >=5.5
  78. $generator = eval('return function () { yield; };');
  79. return $generator();
  80. default:
  81. $prophet = new Prophet;
  82. return $prophet->prophesize($type)->reveal();
  83. }
  84. });
  85. }
  86. }
  87. /**
  88. * Sets argument wildcard.
  89. *
  90. * @param array|Argument\ArgumentsWildcard $arguments
  91. *
  92. * @return $this
  93. *
  94. * @throws \Prophecy\Exception\InvalidArgumentException
  95. */
  96. public function withArguments($arguments)
  97. {
  98. if (is_array($arguments)) {
  99. $arguments = new Argument\ArgumentsWildcard($arguments);
  100. }
  101. if (!$arguments instanceof Argument\ArgumentsWildcard) {
  102. throw new InvalidArgumentException(sprintf(
  103. "Either an array or an instance of ArgumentsWildcard expected as\n".
  104. 'a `MethodProphecy::withArguments()` argument, but got %s.',
  105. gettype($arguments)
  106. ));
  107. }
  108. $this->argumentsWildcard = $arguments;
  109. return $this;
  110. }
  111. /**
  112. * Sets custom promise to the prophecy.
  113. *
  114. * @param callable|Promise\PromiseInterface $promise
  115. *
  116. * @return $this
  117. *
  118. * @throws \Prophecy\Exception\InvalidArgumentException
  119. */
  120. public function will($promise)
  121. {
  122. if (is_callable($promise)) {
  123. $promise = new Promise\CallbackPromise($promise);
  124. }
  125. if (!$promise instanceof Promise\PromiseInterface) {
  126. throw new InvalidArgumentException(sprintf(
  127. 'Expected callable or instance of PromiseInterface, but got %s.',
  128. gettype($promise)
  129. ));
  130. }
  131. $this->bindToObjectProphecy();
  132. $this->promise = $promise;
  133. return $this;
  134. }
  135. /**
  136. * Sets return promise to the prophecy.
  137. *
  138. * @see Prophecy\Promise\ReturnPromise
  139. *
  140. * @return $this
  141. */
  142. public function willReturn()
  143. {
  144. return $this->will(new Promise\ReturnPromise(func_get_args()));
  145. }
  146. /**
  147. * Sets return argument promise to the prophecy.
  148. *
  149. * @param int $index The zero-indexed number of the argument to return
  150. *
  151. * @see Prophecy\Promise\ReturnArgumentPromise
  152. *
  153. * @return $this
  154. */
  155. public function willReturnArgument($index = 0)
  156. {
  157. return $this->will(new Promise\ReturnArgumentPromise($index));
  158. }
  159. /**
  160. * Sets throw promise to the prophecy.
  161. *
  162. * @see Prophecy\Promise\ThrowPromise
  163. *
  164. * @param string|\Exception $exception Exception class or instance
  165. *
  166. * @return $this
  167. */
  168. public function willThrow($exception)
  169. {
  170. return $this->will(new Promise\ThrowPromise($exception));
  171. }
  172. /**
  173. * Sets custom prediction to the prophecy.
  174. *
  175. * @param callable|Prediction\PredictionInterface $prediction
  176. *
  177. * @return $this
  178. *
  179. * @throws \Prophecy\Exception\InvalidArgumentException
  180. */
  181. public function should($prediction)
  182. {
  183. if (is_callable($prediction)) {
  184. $prediction = new Prediction\CallbackPrediction($prediction);
  185. }
  186. if (!$prediction instanceof Prediction\PredictionInterface) {
  187. throw new InvalidArgumentException(sprintf(
  188. 'Expected callable or instance of PredictionInterface, but got %s.',
  189. gettype($prediction)
  190. ));
  191. }
  192. $this->bindToObjectProphecy();
  193. $this->prediction = $prediction;
  194. return $this;
  195. }
  196. /**
  197. * Sets call prediction to the prophecy.
  198. *
  199. * @see Prophecy\Prediction\CallPrediction
  200. *
  201. * @return $this
  202. */
  203. public function shouldBeCalled()
  204. {
  205. return $this->should(new Prediction\CallPrediction);
  206. }
  207. /**
  208. * Sets no calls prediction to the prophecy.
  209. *
  210. * @see Prophecy\Prediction\NoCallsPrediction
  211. *
  212. * @return $this
  213. */
  214. public function shouldNotBeCalled()
  215. {
  216. return $this->should(new Prediction\NoCallsPrediction);
  217. }
  218. /**
  219. * Sets call times prediction to the prophecy.
  220. *
  221. * @see Prophecy\Prediction\CallTimesPrediction
  222. *
  223. * @param $count
  224. *
  225. * @return $this
  226. */
  227. public function shouldBeCalledTimes($count)
  228. {
  229. return $this->should(new Prediction\CallTimesPrediction($count));
  230. }
  231. /**
  232. * Checks provided prediction immediately.
  233. *
  234. * @param callable|Prediction\PredictionInterface $prediction
  235. *
  236. * @return $this
  237. *
  238. * @throws \Prophecy\Exception\InvalidArgumentException
  239. */
  240. public function shouldHave($prediction)
  241. {
  242. if (is_callable($prediction)) {
  243. $prediction = new Prediction\CallbackPrediction($prediction);
  244. }
  245. if (!$prediction instanceof Prediction\PredictionInterface) {
  246. throw new InvalidArgumentException(sprintf(
  247. 'Expected callable or instance of PredictionInterface, but got %s.',
  248. gettype($prediction)
  249. ));
  250. }
  251. if (null === $this->promise) {
  252. $this->willReturn();
  253. }
  254. $calls = $this->getObjectProphecy()->findProphecyMethodCalls(
  255. $this->getMethodName(),
  256. $this->getArgumentsWildcard()
  257. );
  258. try {
  259. $prediction->check($calls, $this->getObjectProphecy(), $this);
  260. $this->checkedPredictions[] = $prediction;
  261. } catch (\Exception $e) {
  262. $this->checkedPredictions[] = $prediction;
  263. throw $e;
  264. }
  265. return $this;
  266. }
  267. /**
  268. * Checks call prediction.
  269. *
  270. * @see Prophecy\Prediction\CallPrediction
  271. *
  272. * @return $this
  273. */
  274. public function shouldHaveBeenCalled()
  275. {
  276. return $this->shouldHave(new Prediction\CallPrediction);
  277. }
  278. /**
  279. * Checks no calls prediction.
  280. *
  281. * @see Prophecy\Prediction\NoCallsPrediction
  282. *
  283. * @return $this
  284. */
  285. public function shouldNotHaveBeenCalled()
  286. {
  287. return $this->shouldHave(new Prediction\NoCallsPrediction);
  288. }
  289. /**
  290. * Checks no calls prediction.
  291. *
  292. * @see Prophecy\Prediction\NoCallsPrediction
  293. * @deprecated
  294. *
  295. * @return $this
  296. */
  297. public function shouldNotBeenCalled()
  298. {
  299. return $this->shouldNotHaveBeenCalled();
  300. }
  301. /**
  302. * Checks call times prediction.
  303. *
  304. * @see Prophecy\Prediction\CallTimesPrediction
  305. *
  306. * @param int $count
  307. *
  308. * @return $this
  309. */
  310. public function shouldHaveBeenCalledTimes($count)
  311. {
  312. return $this->shouldHave(new Prediction\CallTimesPrediction($count));
  313. }
  314. /**
  315. * Checks currently registered [with should(...)] prediction.
  316. */
  317. public function checkPrediction()
  318. {
  319. if (null === $this->prediction) {
  320. return;
  321. }
  322. $this->shouldHave($this->prediction);
  323. }
  324. /**
  325. * Returns currently registered promise.
  326. *
  327. * @return null|Promise\PromiseInterface
  328. */
  329. public function getPromise()
  330. {
  331. return $this->promise;
  332. }
  333. /**
  334. * Returns currently registered prediction.
  335. *
  336. * @return null|Prediction\PredictionInterface
  337. */
  338. public function getPrediction()
  339. {
  340. return $this->prediction;
  341. }
  342. /**
  343. * Returns predictions that were checked on this object.
  344. *
  345. * @return Prediction\PredictionInterface[]
  346. */
  347. public function getCheckedPredictions()
  348. {
  349. return $this->checkedPredictions;
  350. }
  351. /**
  352. * Returns object prophecy this method prophecy is tied to.
  353. *
  354. * @return ObjectProphecy
  355. */
  356. public function getObjectProphecy()
  357. {
  358. return $this->objectProphecy;
  359. }
  360. /**
  361. * Returns method name.
  362. *
  363. * @return string
  364. */
  365. public function getMethodName()
  366. {
  367. return $this->methodName;
  368. }
  369. /**
  370. * Returns arguments wildcard.
  371. *
  372. * @return Argument\ArgumentsWildcard
  373. */
  374. public function getArgumentsWildcard()
  375. {
  376. return $this->argumentsWildcard;
  377. }
  378. private function bindToObjectProphecy()
  379. {
  380. if ($this->bound) {
  381. return;
  382. }
  383. $this->getObjectProphecy()->addMethodProphecy($this);
  384. $this->bound = true;
  385. }
  386. }