Completed
Push — variadic-params ( 7e8cf4...be4969 )
by Akihito
03:11 queued 02:00
created

CodeGenMethod::getMethodInsideStatement()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 17
rs 9.7
c 0
b 0
f 0
cc 3
nc 3
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Ray\Aop;
6
7
use PhpParser\BuilderFactory;
8
use PhpParser\Node\Stmt\Class_;
9
use PhpParser\Parser;
10
use PhpParser\PrettyPrinter\Standard;
11
12
final class CodeGenMethod
13
{
14
    /**
15
     * @var \PhpParser\Parser
16
     */
17
    private $parser;
18
19
    /**
20
     * @var \PhpParser\BuilderFactory
21
     */
22
    private $factory;
23
24
    /**
25
     * @var \PhpParser\PrettyPrinter\Standard
26
     */
27
    private $printer;
28
29
    /**
30
     * @throws \Doctrine\Common\Annotations\AnnotationException
31
     */
32
    public function __construct(
33
        Parser $parser,
34
        BuilderFactory $factory,
35
        Standard $printer
36
    ) {
37
        $this->parser = $parser;
38
        $this->factory = $factory;
39
        $this->printer = $printer;
40
    }
41
42
    public function getMethods(\ReflectionClass $class, BindInterface $bind, CodeVisitor $code) : array
43
    {
44
        $bindingMethods = array_keys($bind->getBindings());
45
        $classMethods = $code->classMethod;
46
        $methods = [];
47
        foreach ($classMethods as $classMethod) {
48
            $methodName = $classMethod->name->name;
49
            $method = new \ReflectionMethod($class->name, $methodName);
0 ignored issues
show
Unused Code introduced by
$method is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
50
            $isBindingMethod = in_array($methodName, $bindingMethods, true);
51
            /* @var $method \ReflectionMethod */
52
            $isPublic = $classMethod->flags === Class_::MODIFIER_PUBLIC;
53
            if ($isBindingMethod && $isPublic) {
54
                $methodInsideStatements = $this->getTemplateMethodNodeStmts();
55
                // replace statements in the method
56
                $classMethod->stmts = $methodInsideStatements;
57
                $methods[] = $classMethod;
58
            }
59
        }
60
61
        return $methods;
62
    }
63
64
    private function getTemplateMethodNodeStmts() : array
65
    {
66
        $code = $this->getTemplateCode();
67
        $node = $this->parser->parse($code)[0];
68
        if (! $node instanceof Class_) {
69
            throw new \LogicException; // @codeCoverageIgnore
70
        }
71
        $methodNode = $node->getMethods()[0];
72
        if ($methodNode->stmts === null) {
73
            throw new \LogicException; // @codeCoverageIgnore
74
        }
75
76
        return $methodNode->stmts;
77
    }
78
79
    /**
80
     * Return CodeGenTemplate string
81
     *
82
     * Compiler takes only the statements in the method. Then create new inherit code with interceptors.
83
     *
84
     * @see http://paul-m-jones.com/archives/182
85
     * @see http://stackoverflow.com/questions/8343399/calling-a-function-with-explicit-parameters-vs-call-user-func-array
86
     * @see http://stackoverflow.com/questions/1796100/what-is-faster-many-ifs-or-else-if
87
     * @see http://stackoverflow.com/questions/2401478/why-is-faster-than-in-php
88
     */
89
    private function getTemplateCode() : string
90
    {
91
        return /* @lang PHP */
92
            <<<'EOT'
93
<?php
94
class AopTemplate extends \Ray\Aop\FakeMock implements Ray\Aop\WeavedInterface
95
{
96
    /**
97
     * @var array
98
     *
99
     * [$methodName => [$interceptorA[]][]
100
     */
101
    public $bindings;
102
103
    /**
104
     * @var bool
105
     */
106
    private $isAspect = true;
107
108
    /**
109
     * Method Template
110
     *
111
     * @param mixed $a
112
     */
113
    public function templateMethod($a, $b)
114
    {
115
        if (! $this->isAspect) {
116
            $this->isAspect = true;
117
118
            return call_user_func_array([$this, 'parent::' . __FUNCTION__], func_get_args());
119
        }
120
121
        $this->isAspect = false;
122
        $result = (new Invocation($this, __FUNCTION__, func_get_args(), $this->bindings[__FUNCTION__]))->proceed();
123
        $this->isAspect = true;
124
125
        return $result;
126
    }
127
}
128
EOT;
129
    }
130
}
131