Completed
Push — 2.x ( 32fdaa...87188e )
by Akihito
01:56
created

CodeGenMethod::addMethodDocComment()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 3
Bugs 1 Features 0
Metric Value
c 3
b 1
f 0
dl 0
loc 10
ccs 7
cts 7
cp 1
rs 9.4286
cc 2
eloc 6
nc 2
nop 2
crap 2
1
<?php
2
/**
3
 * This file is part of the Ray.Aop package
4
 *
5
 * @license http://opensource.org/licenses/bsd-license.php BSD
6
 */
7
namespace Ray\Aop;
8
9
use PHPParser\Builder\Method;
10
use PhpParser\Builder\Param;
11
use PhpParser\BuilderFactory;
12
use PhpParser\Comment\Doc;
13
use PhpParser\Parser;
14
use PhpParser\PrettyPrinter\Standard;
15
16
final class CodeGenMethod
17
{
18
    /**
19
     * @var \PHPParser\Parser
20
     */
21
    private $parser;
22
23
    /**
24
     * @var \PHPParser\BuilderFactory
25
     */
26
    private $factory;
27
28
    /**
29
     * @var \PHPParser\PrettyPrinter\Standard
30
     */
31
    private $printer;
32
33
    /**
34
     * @param \PHPParser\Parser                 $parser
35
     * @param \PHPParser\BuilderFactory         $factory
36
     * @param \PHPParser\PrettyPrinter\Standard $printer
37
     */
38 20
    public function __construct(
39
        Parser $parser,
40
        BuilderFactory $factory,
41
        Standard $printer
42
    ) {
43 20
        $this->parser = $parser;
44 20
        $this->factory = $factory;
45 20
        $this->printer = $printer;
46 20
    }
47
48
    /**
49
     * @param \ReflectionClass $class
50
     *
51
     * @return array
52
     */
53 6
    public function getMethods(\ReflectionClass $class, BindInterface $bind)
54
    {
55 6
        $bindingMethods = array_keys($bind->getBindings());
56 6
        $stmts = [];
57 6
        $methods = $class->getMethods();
58 6
        foreach ($methods as $method) {
59 6
            $isBindingMethod = in_array($method->getName(), $bindingMethods);
60
            /* @var $method \ReflectionMethod */
61 6
            if ($isBindingMethod && $method->isPublic()) {
62 5
                $stmts[] = $this->getMethod($method);
63 5
            }
64 6
        }
65
66 6
        return $stmts;
67
    }
68
69
    /**
70
     * Return method statement
71
     *
72
     * @param \ReflectionMethod $method
73
     *
74
     * @return \PhpParser\Node\Stmt\ClassMethod
75
     */
76 5
    private function getMethod(\ReflectionMethod $method)
77
    {
78 5
        $methodStmt = $this->factory->method($method->name);
79 5
        $params = $method->getParameters();
80 5
        foreach ($params as $param) {
81 5
            $methodStmt = $this->getMethodStatement($param, $methodStmt);
82 5
        }
83 5
        $methodInsideStatements = $this->getMethodInsideStatement();
84 5
        $methodStmt->addStmts($methodInsideStatements);
85 5
        $node = $this->addMethodDocComment($methodStmt, $method);
86
87 5
        return $node;
88
    }
89
90
    /**
91
     * Return parameter reflection
92
     *
93
     * @param \ReflectionParameter      $param
94
     * @param \PHPParser\Builder\Method $methodStmt
95
     *
96
     * @return \PHPParser\Builder\Method
97
     */
98 5
    private function getMethodStatement(\ReflectionParameter $param, Method $methodStmt)
99
    {
100
        /** @var $paramStmt Param */
101 5
        $paramStmt = $this->factory->param($param->name);
102
        /* @var $param \ReflectionParameter */
103 5
        $typeHint = $param->getClass();
104 5
        $this->setTypeHint($param, $paramStmt, $typeHint);
105 5
        $this->setDefault($param, $paramStmt);
106 5
        $methodStmt->addParam($paramStmt);
107
108 5
        return $methodStmt;
109
    }
110
111
    /**
112
     * @param Method            $methodStmt
113
     * @param \ReflectionMethod $method
114
     *
115
     * @return \PhpParser\Node\Stmt\ClassMethod
116
     */
117 5
    private function addMethodDocComment(Method $methodStmt, \ReflectionMethod $method)
118
    {
119 5
        $node = $methodStmt->getNode();
120 5
        $docComment = $method->getDocComment();
121 5
        if ($docComment) {
122 2
            $node->setAttribute('comments', [new Doc($docComment)]);
123 2
        }
124
125 5
        return $node;
126
    }
127
128
    /**
129
     * @return \PHPParser\Node[]
130
     */
131 5
    private function getMethodInsideStatement()
132
    {
133 5
        $code = file_get_contents(dirname(__DIR__) . '/src-data/CodeGenTemplate.php');
134 5
        $node = $this->parser->parse($code)[0];
135
        /** @var $node \PHPParser\Node\Stmt\Class_ */
136 5
        $node = $node->getMethods()[0];
137
138 5
        return $node->stmts;
139
    }
140
141
    /**
142
     * @param \ReflectionParameter $param
143
     * @param Param                $paramStmt
144
     * @param \ReflectionClass     $typeHint
145
     */
146 5
    private function setTypeHint(\ReflectionParameter $param, Param $paramStmt, \ReflectionClass $typeHint = null)
147
    {
148 5
        if ($typeHint) {
149 2
            $paramStmt->setTypeHint($typeHint->name);
150 2
        }
151 5
        if ($param->isArray()) {
152 1
            $paramStmt->setTypeHint('array');
153 1
        }
154 5
        if ($param->isCallable()) {
155 1
            $paramStmt->setTypeHint('callable');
156 1
        }
157 5
    }
158
159
    /**
160
     * @param \ReflectionParameter $param
161
     * @param Param                $paramStmt
162
     */
163 5
    private function setDefault(\ReflectionParameter $param, $paramStmt)
164
    {
165 5
        if ($param->isDefaultValueAvailable()) {
166 2
            $paramStmt->setDefault($param->getDefaultValue());
167 2
        }
168 5
    }
169
}
170