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