Completed
Push — master ( e5a942...818f4f )
by Ciaran
01:39 queued 22s
created

MagicCallPatch::apply()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 31
rs 8.8017
c 0
b 0
f 0
cc 6
nc 6
nop 1
1
<?php
2
3
/*
4
 * This file is part of the Prophecy.
5
 * (c) Konstantin Kudryashov <[email protected]>
6
 *     Marcello Duarte <[email protected]>
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\PhpDocumentor\ClassAndInterfaceTagRetriever;
17
use Prophecy\PhpDocumentor\MethodTagRetrieverInterface;
18
19
/**
20
 * Discover Magical API using "@method" PHPDoc format.
21
 *
22
 * @author Thomas Tourlourat <[email protected]>
23
 * @author Kévin Dunglas <[email protected]>
24
 * @author Théo FIDRY <[email protected]>
25
 */
26
class MagicCallPatch implements ClassPatchInterface
27
{
28
    private $tagRetriever;
29
30
    public function __construct(MethodTagRetrieverInterface $tagRetriever = null)
31
    {
32
        $this->tagRetriever = null === $tagRetriever ? new ClassAndInterfaceTagRetriever() : $tagRetriever;
33
    }
34
35
    /**
36
     * Support any class
37
     *
38
     * @param ClassNode $node
39
     *
40
     * @return boolean
41
     */
42
    public function supports(ClassNode $node)
43
    {
44
        return true;
45
    }
46
47
    /**
48
     * Discover Magical API
49
     *
50
     * @param ClassNode $node
51
     */
52
    public function apply(ClassNode $node)
53
    {
54
        $types = array_filter($node->getInterfaces(), function ($interface) {
55
            return 0 !== strpos($interface, 'Prophecy\\');
56
        });
57
        $types[] = $node->getParentClass();
58
59
        foreach ($types as $type) {
60
            $reflectionClass = new \ReflectionClass($type);
61
62
            while ($reflectionClass) {
63
                $tagList = $this->tagRetriever->getTagList($reflectionClass);
64
65
                foreach ($tagList as $tag) {
66
                    $methodName = $tag->getMethodName();
67
68
                    if (empty($methodName)) {
69
                        continue;
70
                    }
71
72
                    if (!$reflectionClass->hasMethod($methodName)) {
73
                        $methodNode = new MethodNode($methodName);
74
                        $methodNode->setStatic($tag->isStatic());
75
                        $node->addMethod($methodNode);
76
                    }
77
                }
78
79
                $reflectionClass = $reflectionClass->getParentClass();
80
            }
81
        }
82
    }
83
84
    /**
85
     * Returns patch priority, which determines when patch will be applied.
86
     *
87
     * @return integer Priority number (higher - earlier)
88
     */
89
    public function getPriority()
90
    {
91
        return 50;
92
    }
93
}
94
95