Completed
Pull Request — master (#263)
by Kévin
02:06
created

MagicCallPatch::getPriority()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
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 phpDocumentor\Reflection\DocBlock\Tags\Method;
15
use phpDocumentor\Reflection\DocBlockFactory;
16
use phpDocumentor\Reflection\DocBlockFactoryInterface;
17
use phpDocumentor\Reflection\Types\ContextFactory;
18
use Prophecy\Doubler\Generator\Node\ClassNode;
19
use Prophecy\Doubler\Generator\Node\MethodNode;
20
21
/**
22
 * Discover Magical API using "@method" PHPDoc format.
23
 *
24
 * @author Thomas Tourlourat <[email protected]>
25
 * @author Kévin Dunglas <[email protected]>
26
 */
27
class MagicCallPatch implements ClassPatchInterface
28
{
29
    private $docBlockFactory;
30
    private $contextFactory;
31
32
    public function __construct()
33
    {
34
        $this->docBlockFactory = DocBlockFactory::createInstance();
35
        $this->contextFactory = new ContextFactory();
36
    }
37
38
    /**
39
     * Support any class
40
     *
41
     * @param ClassNode $node
42
     *
43
     * @return boolean
44
     */
45
    public function supports(ClassNode $node)
46
    {
47
        return true;
48
    }
49
50
    /**
51
     * Discover Magical API
52
     *
53
     * @param ClassNode $node
54
     */
55
    public function apply(ClassNode $node)
56
    {
57
        $parentClass = $node->getParentClass();
58
        $reflectionClass = new \ReflectionClass($parentClass);
59
60
        try {
61
            $phpdoc = $this->docBlockFactory->create($reflectionClass, $this->contextFactory->createFromReflector($reflectionClass));
62
            $tagList = $phpdoc->getTagsByName('method');
63
        } catch (\InvalidArgumentException $e) {
64
            // No DocBlock
65
            $tagList = array();
66
        }
67
68
        $interfaces = $reflectionClass->getInterfaces();
69
        foreach($interfaces as $interface) {
70
            try {
71
                $phpdoc = $this->docBlockFactory->create($interface, $this->contextFactory->createFromReflector($interface));
72
                $tagList = array_merge($tagList, $phpdoc->getTagsByName('method'));
73
            } catch (\InvalidArgumentException $e) {
74
                // No DocBlock
75
            }
76
        }
77
78
        foreach($tagList as $tag) {
79
            $methodName = $tag->getMethodName();
80
81
            if (empty($methodName)) {
82
                continue;
83
            }
84
85
            if (!$reflectionClass->hasMethod($methodName)) {
86
                $methodNode = new MethodNode($tag->getMethodName());
87
                $methodNode->setStatic($tag->isStatic());
88
89
                $node->addMethod($methodNode);
90
            }
91
        }
92
    }
93
94
    /**
95
     * Returns patch priority, which determines when patch will be applied.
96
     *
97
     * @return integer Priority number (higher - earlier)
98
     */
99
    public function getPriority()
100
    {
101
        return 50;
102
    }
103
}
104
105