Pull merge.
[yaffs-website] / vendor / phpspec / prophecy / src / Prophecy / Doubler / ClassPatch / ProphecySubjectPatch.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\Doubler\ClassPatch;
13
14 use Prophecy\Doubler\Generator\Node\ClassNode;
15 use Prophecy\Doubler\Generator\Node\MethodNode;
16 use Prophecy\Doubler\Generator\Node\ArgumentNode;
17
18 /**
19  * Add Prophecy functionality to the double.
20  * This is a core class patch for Prophecy.
21  *
22  * @author Konstantin Kudryashov <ever.zet@gmail.com>
23  */
24 class ProphecySubjectPatch implements ClassPatchInterface
25 {
26     /**
27      * Always returns true.
28      *
29      * @param ClassNode $node
30      *
31      * @return bool
32      */
33     public function supports(ClassNode $node)
34     {
35         return true;
36     }
37
38     /**
39      * Apply Prophecy functionality to class node.
40      *
41      * @param ClassNode $node
42      */
43     public function apply(ClassNode $node)
44     {
45         $node->addInterface('Prophecy\Prophecy\ProphecySubjectInterface');
46         $node->addProperty('objectProphecy', 'private');
47
48         foreach ($node->getMethods() as $name => $method) {
49             if ('__construct' === strtolower($name)) {
50                 continue;
51             }
52
53             if ($method->getReturnType() === 'void') {
54                 $method->setCode(
55                     '$this->getProphecy()->makeProphecyMethodCall(__FUNCTION__, func_get_args());'
56                 );
57             } else {
58                 $method->setCode(
59                     'return $this->getProphecy()->makeProphecyMethodCall(__FUNCTION__, func_get_args());'
60                 );
61             }
62         }
63
64         $prophecySetter = new MethodNode('setProphecy');
65         $prophecyArgument = new ArgumentNode('prophecy');
66         $prophecyArgument->setTypeHint('Prophecy\Prophecy\ProphecyInterface');
67         $prophecySetter->addArgument($prophecyArgument);
68         $prophecySetter->setCode('$this->objectProphecy = $prophecy;');
69
70         $prophecyGetter = new MethodNode('getProphecy');
71         $prophecyGetter->setCode('return $this->objectProphecy;');
72
73         if ($node->hasMethod('__call')) {
74             $__call = $node->getMethod('__call');
75         } else {
76             $__call = new MethodNode('__call');
77             $__call->addArgument(new ArgumentNode('name'));
78             $__call->addArgument(new ArgumentNode('arguments'));
79
80             $node->addMethod($__call, true);
81         }
82
83         $__call->setCode(<<<PHP
84 throw new \Prophecy\Exception\Doubler\MethodNotFoundException(
85     sprintf('Method `%s::%s()` not found.', get_class(\$this), func_get_arg(0)),
86     \$this->getProphecy(), func_get_arg(0)
87 );
88 PHP
89         );
90
91         $node->addMethod($prophecySetter, true);
92         $node->addMethod($prophecyGetter, true);
93     }
94
95     /**
96      * Returns patch priority, which determines when patch will be applied.
97      *
98      * @return int Priority number (higher - earlier)
99      */
100     public function getPriority()
101     {
102         return 0;
103     }
104 }