annotate vendor/phpspec/prophecy/src/Prophecy/Call/CallCenter.php @ 9:1fc0ff908d1f

Add another data file
author Chris Cannam
date Mon, 05 Feb 2018 12:34:32 +0000
parents 4c8ae668cc8c
children 129ea1e6d783
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 /*
Chris@0 4 * This file is part of the Prophecy.
Chris@0 5 * (c) Konstantin Kudryashov <ever.zet@gmail.com>
Chris@0 6 * Marcello Duarte <marcello.duarte@gmail.com>
Chris@0 7 *
Chris@0 8 * For the full copyright and license information, please view the LICENSE
Chris@0 9 * file that was distributed with this source code.
Chris@0 10 */
Chris@0 11
Chris@0 12 namespace Prophecy\Call;
Chris@0 13
Chris@0 14 use Prophecy\Exception\Prophecy\MethodProphecyException;
Chris@0 15 use Prophecy\Prophecy\MethodProphecy;
Chris@0 16 use Prophecy\Prophecy\ObjectProphecy;
Chris@0 17 use Prophecy\Argument\ArgumentsWildcard;
Chris@0 18 use Prophecy\Util\StringUtil;
Chris@0 19 use Prophecy\Exception\Call\UnexpectedCallException;
Chris@0 20
Chris@0 21 /**
Chris@0 22 * Calls receiver & manager.
Chris@0 23 *
Chris@0 24 * @author Konstantin Kudryashov <ever.zet@gmail.com>
Chris@0 25 */
Chris@0 26 class CallCenter
Chris@0 27 {
Chris@0 28 private $util;
Chris@0 29
Chris@0 30 /**
Chris@0 31 * @var Call[]
Chris@0 32 */
Chris@0 33 private $recordedCalls = array();
Chris@0 34
Chris@0 35 /**
Chris@0 36 * Initializes call center.
Chris@0 37 *
Chris@0 38 * @param StringUtil $util
Chris@0 39 */
Chris@0 40 public function __construct(StringUtil $util = null)
Chris@0 41 {
Chris@0 42 $this->util = $util ?: new StringUtil;
Chris@0 43 }
Chris@0 44
Chris@0 45 /**
Chris@0 46 * Makes and records specific method call for object prophecy.
Chris@0 47 *
Chris@0 48 * @param ObjectProphecy $prophecy
Chris@0 49 * @param string $methodName
Chris@0 50 * @param array $arguments
Chris@0 51 *
Chris@0 52 * @return mixed Returns null if no promise for prophecy found or promise return value.
Chris@0 53 *
Chris@0 54 * @throws \Prophecy\Exception\Call\UnexpectedCallException If no appropriate method prophecy found
Chris@0 55 */
Chris@0 56 public function makeCall(ObjectProphecy $prophecy, $methodName, array $arguments)
Chris@0 57 {
Chris@0 58 // For efficiency exclude 'args' from the generated backtrace
Chris@0 59 if (PHP_VERSION_ID >= 50400) {
Chris@0 60 // Limit backtrace to last 3 calls as we don't use the rest
Chris@0 61 // Limit argument was introduced in PHP 5.4.0
Chris@0 62 $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3);
Chris@0 63 } elseif (defined('DEBUG_BACKTRACE_IGNORE_ARGS')) {
Chris@0 64 // DEBUG_BACKTRACE_IGNORE_ARGS was introduced in PHP 5.3.6
Chris@0 65 $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
Chris@0 66 } else {
Chris@0 67 $backtrace = debug_backtrace();
Chris@0 68 }
Chris@0 69
Chris@0 70 $file = $line = null;
Chris@0 71 if (isset($backtrace[2]) && isset($backtrace[2]['file'])) {
Chris@0 72 $file = $backtrace[2]['file'];
Chris@0 73 $line = $backtrace[2]['line'];
Chris@0 74 }
Chris@0 75
Chris@0 76 // If no method prophecies defined, then it's a dummy, so we'll just return null
Chris@0 77 if ('__destruct' === $methodName || 0 == count($prophecy->getMethodProphecies())) {
Chris@0 78 $this->recordedCalls[] = new Call($methodName, $arguments, null, null, $file, $line);
Chris@0 79
Chris@0 80 return null;
Chris@0 81 }
Chris@0 82
Chris@0 83 // There are method prophecies, so it's a fake/stub. Searching prophecy for this call
Chris@0 84 $matches = array();
Chris@0 85 foreach ($prophecy->getMethodProphecies($methodName) as $methodProphecy) {
Chris@0 86 if (0 < $score = $methodProphecy->getArgumentsWildcard()->scoreArguments($arguments)) {
Chris@0 87 $matches[] = array($score, $methodProphecy);
Chris@0 88 }
Chris@0 89 }
Chris@0 90
Chris@0 91 // If fake/stub doesn't have method prophecy for this call - throw exception
Chris@0 92 if (!count($matches)) {
Chris@0 93 throw $this->createUnexpectedCallException($prophecy, $methodName, $arguments);
Chris@0 94 }
Chris@0 95
Chris@0 96 // Sort matches by their score value
Chris@0 97 @usort($matches, function ($match1, $match2) { return $match2[0] - $match1[0]; });
Chris@0 98
Chris@0 99 // If Highest rated method prophecy has a promise - execute it or return null instead
Chris@0 100 $methodProphecy = $matches[0][1];
Chris@0 101 $returnValue = null;
Chris@0 102 $exception = null;
Chris@0 103 if ($promise = $methodProphecy->getPromise()) {
Chris@0 104 try {
Chris@0 105 $returnValue = $promise->execute($arguments, $prophecy, $methodProphecy);
Chris@0 106 } catch (\Exception $e) {
Chris@0 107 $exception = $e;
Chris@0 108 }
Chris@0 109 }
Chris@0 110
Chris@0 111 if ($methodProphecy->hasReturnVoid() && $returnValue !== null) {
Chris@0 112 throw new MethodProphecyException(
Chris@0 113 "The method \"$methodName\" has a void return type, but the promise returned a value",
Chris@0 114 $methodProphecy
Chris@0 115 );
Chris@0 116 }
Chris@0 117
Chris@0 118 $this->recordedCalls[] = new Call(
Chris@0 119 $methodName, $arguments, $returnValue, $exception, $file, $line
Chris@0 120 );
Chris@0 121
Chris@0 122 if (null !== $exception) {
Chris@0 123 throw $exception;
Chris@0 124 }
Chris@0 125
Chris@0 126 return $returnValue;
Chris@0 127 }
Chris@0 128
Chris@0 129 /**
Chris@0 130 * Searches for calls by method name & arguments wildcard.
Chris@0 131 *
Chris@0 132 * @param string $methodName
Chris@0 133 * @param ArgumentsWildcard $wildcard
Chris@0 134 *
Chris@0 135 * @return Call[]
Chris@0 136 */
Chris@0 137 public function findCalls($methodName, ArgumentsWildcard $wildcard)
Chris@0 138 {
Chris@0 139 return array_values(
Chris@0 140 array_filter($this->recordedCalls, function (Call $call) use ($methodName, $wildcard) {
Chris@0 141 return $methodName === $call->getMethodName()
Chris@0 142 && 0 < $wildcard->scoreArguments($call->getArguments())
Chris@0 143 ;
Chris@0 144 })
Chris@0 145 );
Chris@0 146 }
Chris@0 147
Chris@0 148 private function createUnexpectedCallException(ObjectProphecy $prophecy, $methodName,
Chris@0 149 array $arguments)
Chris@0 150 {
Chris@0 151 $classname = get_class($prophecy->reveal());
Chris@0 152 $argstring = implode(', ', array_map(array($this->util, 'stringify'), $arguments));
Chris@0 153 $expected = implode("\n", array_map(function (MethodProphecy $methodProphecy) {
Chris@0 154 return sprintf(' - %s(%s)',
Chris@0 155 $methodProphecy->getMethodName(),
Chris@0 156 $methodProphecy->getArgumentsWildcard()
Chris@0 157 );
Chris@0 158 }, call_user_func_array('array_merge', $prophecy->getMethodProphecies())));
Chris@0 159
Chris@0 160 return new UnexpectedCallException(
Chris@0 161 sprintf(
Chris@0 162 "Method call:\n".
Chris@0 163 " - %s(%s)\n".
Chris@0 164 "on %s was not expected, expected calls were:\n%s",
Chris@0 165
Chris@0 166 $methodName, $argstring, $classname, $expected
Chris@0 167 ),
Chris@0 168 $prophecy, $methodName, $arguments
Chris@0 169 );
Chris@0 170 }
Chris@0 171 }