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

/vendor/mockery/mockery/library/Mockery.php

https://gitlab.com/ealexis.t/trends
PHP | 739 lines | 387 code | 101 blank | 251 comment | 42 complexity | 8245a9089d30a5b788cdb9be3299596c MD5 | raw file
  1. <?php
  2. /**
  3. * Mockery
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://github.com/padraic/mockery/blob/master/LICENSE
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to padraic@php.net so we can send you a copy immediately.
  14. *
  15. * @category Mockery
  16. * @package Mockery
  17. * @copyright Copyright (c) 2010-2014 Pádraic Brady (http://blog.astrumfutura.com)
  18. * @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
  19. */
  20. use Mockery\ExpectationInterface;
  21. use Mockery\Generator\CachingGenerator;
  22. use Mockery\Generator\Generator;
  23. use Mockery\Generator\MockConfigurationBuilder;
  24. use Mockery\Generator\StringManipulationGenerator;
  25. use Mockery\Generator\StringManipulation\Pass\CallTypeHintPass;
  26. use Mockery\Generator\StringManipulation\Pass\ClassNamePass;
  27. use Mockery\Generator\StringManipulation\Pass\ClassPass;
  28. use Mockery\Generator\StringManipulation\Pass\InstanceMockPass;
  29. use Mockery\Generator\StringManipulation\Pass\InterfacePass;
  30. use Mockery\Generator\StringManipulation\Pass\MethodDefinitionPass;
  31. use Mockery\Generator\StringManipulation\Pass\RemoveBuiltinMethodsThatAreFinalPass;
  32. use Mockery\Generator\StringManipulation\Pass\RemoveUnserializeForInternalSerializableClassesPass;
  33. use Mockery\Loader\EvalLoader;
  34. use Mockery\Loader\Loader;
  35. class Mockery
  36. {
  37. const BLOCKS = 'Mockery_Forward_Blocks';
  38. /**
  39. * Global container to hold all mocks for the current unit test running.
  40. *
  41. * @var \Mockery\Container
  42. */
  43. protected static $_container = null;
  44. /**
  45. * Global configuration handler containing configuration options.
  46. *
  47. * @var \Mockery\Configuration
  48. */
  49. protected static $_config = null;
  50. /**
  51. * @var \Mockery\Generator\Generator
  52. */
  53. protected static $_generator;
  54. /**
  55. * @var \Mockery\Loader\Loader
  56. */
  57. protected static $_loader;
  58. /**
  59. * Static shortcut to \Mockery\Container::mock().
  60. *
  61. * @return \Mockery\MockInterface
  62. */
  63. public static function mock()
  64. {
  65. $args = func_get_args();
  66. return call_user_func_array(array(self::getContainer(), 'mock'), $args);
  67. }
  68. /**
  69. * @return \Mockery\MockInterface
  70. */
  71. public static function spy()
  72. {
  73. $args = func_get_args();
  74. return call_user_func_array(array(self::getContainer(), 'mock'), $args)->shouldIgnoreMissing();
  75. }
  76. /**
  77. * @return \Mockery\MockInterface
  78. */
  79. public static function instanceMock()
  80. {
  81. $args = func_get_args();
  82. return call_user_func_array(array(self::getContainer(), 'mock'), $args);
  83. }
  84. /**
  85. * Static shortcut to \Mockery\Container::mock(), first argument names the mock.
  86. *
  87. * @return \Mockery\MockInterface
  88. */
  89. public static function namedMock()
  90. {
  91. $args = func_get_args();
  92. $name = array_shift($args);
  93. $builder = new MockConfigurationBuilder();
  94. $builder->setName($name);
  95. array_unshift($args, $builder);
  96. return call_user_func_array(array(self::getContainer(), 'mock'), $args);
  97. }
  98. /**
  99. * Static shortcut to \Mockery\Container::self().
  100. *
  101. * @throws LogicException
  102. *
  103. * @return \Mockery\MockInterface
  104. */
  105. public static function self()
  106. {
  107. if (is_null(self::$_container)) {
  108. throw new \LogicException('You have not declared any mocks yet');
  109. }
  110. return self::$_container->self();
  111. }
  112. /**
  113. * Static shortcut to closing up and verifying all mocks in the global
  114. * container, and resetting the container static variable to null.
  115. *
  116. * @return void
  117. */
  118. public static function close()
  119. {
  120. if (is_null(self::$_container)) {
  121. return;
  122. }
  123. self::$_container->mockery_teardown();
  124. self::$_container->mockery_close();
  125. self::$_container = null;
  126. }
  127. /**
  128. * Static fetching of a mock associated with a name or explicit class poser.
  129. *
  130. * @param $name
  131. *
  132. * @return \Mockery\Mock
  133. */
  134. public static function fetchMock($name)
  135. {
  136. return self::$_container->fetchMock($name);
  137. }
  138. /**
  139. * Get the container.
  140. */
  141. public static function getContainer()
  142. {
  143. if (is_null(self::$_container)) {
  144. self::$_container = new Mockery\Container(self::getGenerator(), self::getLoader());
  145. }
  146. return self::$_container;
  147. }
  148. /**
  149. * @param \Mockery\Generator\Generator $generator
  150. */
  151. public static function setGenerator(Generator $generator)
  152. {
  153. self::$_generator = $generator;
  154. }
  155. public static function getGenerator()
  156. {
  157. if (is_null(self::$_generator)) {
  158. self::$_generator = self::getDefaultGenerator();
  159. }
  160. return self::$_generator;
  161. }
  162. public static function getDefaultGenerator()
  163. {
  164. $generator = new StringManipulationGenerator(array(
  165. new CallTypeHintPass(),
  166. new ClassPass(),
  167. new ClassNamePass(),
  168. new InstanceMockPass(),
  169. new InterfacePass(),
  170. new MethodDefinitionPass(),
  171. new RemoveUnserializeForInternalSerializableClassesPass(),
  172. new RemoveBuiltinMethodsThatAreFinalPass(),
  173. ));
  174. return new CachingGenerator($generator);
  175. }
  176. /**
  177. * @param Loader $loader
  178. */
  179. public static function setLoader(Loader $loader)
  180. {
  181. self::$_loader = $loader;
  182. }
  183. /**
  184. * @return Loader
  185. */
  186. public static function getLoader()
  187. {
  188. if (is_null(self::$_loader)) {
  189. self::$_loader = self::getDefaultLoader();
  190. }
  191. return self::$_loader;
  192. }
  193. /**
  194. * @return EvalLoader
  195. */
  196. public static function getDefaultLoader()
  197. {
  198. return new EvalLoader();
  199. }
  200. /**
  201. * Set the container.
  202. *
  203. * @param \Mockery\Container $container
  204. *
  205. * @return \Mockery\Container
  206. */
  207. public static function setContainer(Mockery\Container $container)
  208. {
  209. return self::$_container = $container;
  210. }
  211. /**
  212. * Reset the container to null.
  213. */
  214. public static function resetContainer()
  215. {
  216. self::$_container = null;
  217. }
  218. /**
  219. * Return instance of ANY matcher.
  220. *
  221. * @return \Mockery\Matcher\Any
  222. */
  223. public static function any()
  224. {
  225. return new \Mockery\Matcher\Any();
  226. }
  227. /**
  228. * Return instance of TYPE matcher.
  229. *
  230. * @param $expected
  231. *
  232. * @return \Mockery\Matcher\Type
  233. */
  234. public static function type($expected)
  235. {
  236. return new \Mockery\Matcher\Type($expected);
  237. }
  238. /**
  239. * Return instance of DUCKTYPE matcher.
  240. *
  241. * @return \Mockery\Matcher\Ducktype
  242. */
  243. public static function ducktype()
  244. {
  245. return new \Mockery\Matcher\Ducktype(func_get_args());
  246. }
  247. /**
  248. * Return instance of SUBSET matcher.
  249. *
  250. * @param array $part
  251. *
  252. * @return \Mockery\Matcher\Subset
  253. */
  254. public static function subset(array $part)
  255. {
  256. return new \Mockery\Matcher\Subset($part);
  257. }
  258. /**
  259. * Return instance of CONTAINS matcher.
  260. *
  261. * @return \Mockery\Matcher\Contains
  262. */
  263. public static function contains()
  264. {
  265. return new \Mockery\Matcher\Contains(func_get_args());
  266. }
  267. /**
  268. * Return instance of HASKEY matcher.
  269. *
  270. * @param $key
  271. *
  272. * @return \Mockery\Matcher\HasKey
  273. */
  274. public static function hasKey($key)
  275. {
  276. return new \Mockery\Matcher\HasKey($key);
  277. }
  278. /**
  279. * Return instance of HASVALUE matcher.
  280. *
  281. * @param $val
  282. *
  283. * @return \Mockery\Matcher\HasValue
  284. */
  285. public static function hasValue($val)
  286. {
  287. return new \Mockery\Matcher\HasValue($val);
  288. }
  289. /**
  290. * Return instance of CLOSURE matcher.
  291. *
  292. * @param $closure
  293. *
  294. * @return \Mockery\Matcher\Closure
  295. */
  296. public static function on($closure)
  297. {
  298. return new \Mockery\Matcher\Closure($closure);
  299. }
  300. /**
  301. * Return instance of MUSTBE matcher.
  302. *
  303. * @param $expected
  304. *
  305. * @return \Mockery\Matcher\MustBe
  306. */
  307. public static function mustBe($expected)
  308. {
  309. return new \Mockery\Matcher\MustBe($expected);
  310. }
  311. /**
  312. * Return instance of NOT matcher.
  313. *
  314. * @param $expected
  315. *
  316. * @return \Mockery\Matcher\Not
  317. */
  318. public static function not($expected)
  319. {
  320. return new \Mockery\Matcher\Not($expected);
  321. }
  322. /**
  323. * Return instance of ANYOF matcher.
  324. *
  325. * @return \Mockery\Matcher\AnyOf
  326. */
  327. public static function anyOf()
  328. {
  329. return new \Mockery\Matcher\AnyOf(func_get_args());
  330. }
  331. /**
  332. * Return instance of NOTANYOF matcher.
  333. *
  334. * @return \Mockery\Matcher\NotAnyOf
  335. */
  336. public static function notAnyOf()
  337. {
  338. return new \Mockery\Matcher\NotAnyOf(func_get_args());
  339. }
  340. /**
  341. * Get the global configuration container.
  342. */
  343. public static function getConfiguration()
  344. {
  345. if (is_null(self::$_config)) {
  346. self::$_config = new \Mockery\Configuration();
  347. }
  348. return self::$_config;
  349. }
  350. /**
  351. * Utility method to format method name and arguments into a string.
  352. *
  353. * @param string $method
  354. * @param array $arguments
  355. *
  356. * @return string
  357. */
  358. public static function formatArgs($method, array $arguments = null)
  359. {
  360. if (is_null($arguments)) {
  361. return $method . '()';
  362. }
  363. $formattedArguments = array();
  364. foreach ($arguments as $argument) {
  365. $formattedArguments[] = self::formatArgument($argument);
  366. }
  367. return $method . '(' . implode(', ', $formattedArguments) . ')';
  368. }
  369. private static function formatArgument($argument, $depth = 0)
  370. {
  371. if (is_object($argument)) {
  372. return 'object(' . get_class($argument) . ')';
  373. }
  374. if (is_int($argument) || is_float($argument)) {
  375. return $argument;
  376. }
  377. if (is_array($argument)) {
  378. if ($depth === 1) {
  379. $argument = 'array(...)';
  380. } else {
  381. $sample = array();
  382. foreach ($argument as $key => $value) {
  383. $sample[$key] = self::formatArgument($value, $depth + 1);
  384. }
  385. $argument = preg_replace("{\s}", '', var_export($sample, true));
  386. }
  387. return ((strlen($argument) > 1000) ? substr($argument, 0, 1000).'...)' : $argument);
  388. }
  389. if (is_bool($argument)) {
  390. return $argument ? 'true' : 'false';
  391. }
  392. if (is_resource($argument)) {
  393. return 'resource(...)';
  394. }
  395. if (is_null($argument)) {
  396. return 'NULL';
  397. }
  398. $argument = (string) $argument;
  399. return $depth === 0 ? '"' . $argument . '"' : $argument;
  400. }
  401. /**
  402. * Utility function to format objects to printable arrays.
  403. *
  404. * @param array $objects
  405. *
  406. * @return string
  407. */
  408. public static function formatObjects(array $objects = null)
  409. {
  410. static $formatting;
  411. if ($formatting) {
  412. return '[Recursion]';
  413. }
  414. if (is_null($objects)) {
  415. return '';
  416. }
  417. $objects = array_filter($objects, 'is_object');
  418. if (empty($objects)) {
  419. return '';
  420. }
  421. $formatting = true;
  422. $parts = array();
  423. foreach ($objects as $object) {
  424. $parts[get_class($object)] = self::objectToArray($object);
  425. }
  426. $formatting = false;
  427. return 'Objects: ( ' . var_export($parts, true) . ')';
  428. }
  429. /**
  430. * Utility function to turn public properties and public get* and is* method values into an array.
  431. *
  432. * @param $object
  433. * @param int $nesting
  434. *
  435. * @return array
  436. */
  437. private static function objectToArray($object, $nesting = 3)
  438. {
  439. if ($nesting == 0) {
  440. return array('...');
  441. }
  442. return array(
  443. 'class' => get_class($object),
  444. 'properties' => self::extractInstancePublicProperties($object, $nesting),
  445. 'getters' => self::extractGetters($object, $nesting)
  446. );
  447. }
  448. /**
  449. * Returns all public instance properties.
  450. *
  451. * @param $object
  452. * @param $nesting
  453. *
  454. * @return array
  455. */
  456. private static function extractInstancePublicProperties($object, $nesting)
  457. {
  458. $reflection = new \ReflectionClass(get_class($object));
  459. $properties = $reflection->getProperties(\ReflectionProperty::IS_PUBLIC);
  460. $cleanedProperties = array();
  461. foreach ($properties as $publicProperty) {
  462. if (!$publicProperty->isStatic()) {
  463. $name = $publicProperty->getName();
  464. $cleanedProperties[$name] = self::cleanupNesting($object->$name, $nesting);
  465. }
  466. }
  467. return $cleanedProperties;
  468. }
  469. /**
  470. * Returns all object getters.
  471. *
  472. * @param $object
  473. * @param $nesting
  474. *
  475. * @return array
  476. */
  477. private static function extractGetters($object, $nesting)
  478. {
  479. $reflection = new \ReflectionClass(get_class($object));
  480. $publicMethods = $reflection->getMethods(\ReflectionMethod::IS_PUBLIC);
  481. $getters = array();
  482. foreach ($publicMethods as $publicMethod) {
  483. $name = $publicMethod->getName();
  484. $irrelevantName = (substr($name, 0, 3) !== 'get' && substr($name, 0, 2) !== 'is');
  485. $isStatic = $publicMethod->isStatic();
  486. $numberOfParameters = $publicMethod->getNumberOfParameters();
  487. if ($irrelevantName || $numberOfParameters != 0 || $isStatic) {
  488. continue;
  489. }
  490. try {
  491. $getters[$name] = self::cleanupNesting($object->$name(), $nesting);
  492. } catch (\Exception $e) {
  493. $getters[$name] = '!! ' . get_class($e) . ': ' . $e->getMessage() . ' !!';
  494. }
  495. }
  496. return $getters;
  497. }
  498. private static function cleanupNesting($argument, $nesting)
  499. {
  500. if (is_object($argument)) {
  501. $object = self::objectToArray($argument, $nesting - 1);
  502. $object['class'] = get_class($argument);
  503. return $object;
  504. }
  505. if (is_array($argument)) {
  506. return self::cleanupArray($argument, $nesting - 1);
  507. }
  508. return $argument;
  509. }
  510. private static function cleanupArray($argument, $nesting = 3)
  511. {
  512. if ($nesting == 0) {
  513. return '...';
  514. }
  515. foreach ($argument as $key => $value) {
  516. if (is_array($value)) {
  517. $argument[$key] = self::cleanupArray($value, $nesting - 1);
  518. } elseif (is_object($value)) {
  519. $argument[$key] = self::objectToArray($value, $nesting - 1);
  520. }
  521. }
  522. return $argument;
  523. }
  524. /**
  525. * Utility function to parse shouldReceive() arguments and generate
  526. * expectations from such as needed.
  527. *
  528. * @param Mockery\MockInterface $mock
  529. * @param array $args
  530. * @param callable $add
  531. * @return \Mockery\CompositeExpectation
  532. */
  533. public static function parseShouldReturnArgs(\Mockery\MockInterface $mock, $args, $add)
  534. {
  535. $composite = new \Mockery\CompositeExpectation();
  536. foreach ($args as $arg) {
  537. if (is_array($arg)) {
  538. foreach ($arg as $k => $v) {
  539. $expectation = self::buildDemeterChain($mock, $k, $add)->andReturn($v);
  540. $composite->add($expectation);
  541. }
  542. } elseif (is_string($arg)) {
  543. $expectation = self::buildDemeterChain($mock, $arg, $add);
  544. $composite->add($expectation);
  545. }
  546. }
  547. return $composite;
  548. }
  549. /**
  550. * Sets up expectations on the members of the CompositeExpectation and
  551. * builds up any demeter chain that was passed to shouldReceive.
  552. *
  553. * @param \Mockery\MockInterface $mock
  554. * @param string $arg
  555. * @param callable $add
  556. * @throws Mockery\Exception
  557. * @return \Mockery\ExpectationDirector
  558. */
  559. protected static function buildDemeterChain(\Mockery\MockInterface $mock, $arg, $add)
  560. {
  561. /** @var Mockery\Container $container */
  562. $container = $mock->mockery_getContainer();
  563. $methodNames = explode('->', $arg);
  564. reset($methodNames);
  565. if (!\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed()
  566. && !$mock->mockery_isAnonymous()
  567. && !in_array(current($methodNames), $mock->mockery_getMockableMethods())
  568. ) {
  569. throw new \Mockery\Exception(
  570. 'Mockery\'s configuration currently forbids mocking the method '
  571. . current($methodNames) . ' as it does not exist on the class or object '
  572. . 'being mocked'
  573. );
  574. }
  575. /** @var ExpectationInterface|null $expectations */
  576. $expectations = null;
  577. /** @var Callable $nextExp */
  578. $nextExp = function ($method) use ($add) {
  579. return $add($method);
  580. };
  581. while (true) {
  582. $method = array_shift($methodNames);
  583. $expectations = $mock->mockery_getExpectationsFor($method);
  584. if (is_null($expectations) || self::noMoreElementsInChain($methodNames)) {
  585. $expectations = $nextExp($method);
  586. if (self::noMoreElementsInChain($methodNames)) {
  587. break;
  588. }
  589. $mock = self::getNewDemeterMock($container, $method, $expectations);
  590. } else {
  591. $demeterMockKey = $container->getKeyOfDemeterMockFor($method);
  592. if ($demeterMockKey) {
  593. $mock = self::getExistingDemeterMock($container, $demeterMockKey);
  594. }
  595. }
  596. $nextExp = function ($n) use ($mock) {
  597. return $mock->shouldReceive($n);
  598. };
  599. }
  600. return $expectations;
  601. }
  602. /**
  603. * @param \Mockery\Container $container
  604. * @param string $method
  605. * @param Mockery\ExpectationInterface $exp
  606. *
  607. * @return \Mockery\Mock
  608. */
  609. private static function getNewDemeterMock(Mockery\Container $container,
  610. $method,
  611. Mockery\ExpectationInterface $exp
  612. ) {
  613. $mock = $container->mock('demeter_' . $method);
  614. $exp->andReturn($mock);
  615. return $mock;
  616. }
  617. /**
  618. * @param \Mockery\Container $container
  619. * @param string $demeterMockKey
  620. *
  621. * @return mixed
  622. */
  623. private static function getExistingDemeterMock(Mockery\Container $container, $demeterMockKey)
  624. {
  625. $mocks = $container->getMocks();
  626. $mock = $mocks[$demeterMockKey];
  627. return $mock;
  628. }
  629. /**
  630. * @param array $methodNames
  631. *
  632. * @return bool
  633. */
  634. private static function noMoreElementsInChain(array $methodNames)
  635. {
  636. return empty($methodNames);
  637. }
  638. }