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