Completed
Push — master ( 79fae7...f16f1c )
by Alexander
07:00
created

ReflectionMethod::isPrivate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
/**
3
 * Parser Reflection API
4
 *
5
 * @copyright Copyright 2015, Lisachenko Alexander <[email protected]>
6
 *
7
 * This source file is subject to the license that is bundled
8
 * with this source code in the file LICENSE.
9
 */
10
11
namespace Go\ParserReflection;
12
13
use Go\ParserReflection\Traits\InternalPropertiesEmulationTrait;
14
use Go\ParserReflection\Traits\ReflectionFunctionLikeTrait;
15
use PhpParser\Node\Stmt\ClassLike;
16
use PhpParser\Node\Stmt\ClassMethod;
17
use ReflectionMethod as BaseReflectionMethod;
18
19
/**
20
 * AST-based reflection for the method in a class
21
 */
22
class ReflectionMethod extends BaseReflectionMethod
23
{
24
    use ReflectionFunctionLikeTrait, InternalPropertiesEmulationTrait;
25
26
    /**
27
     * Name of the class
28
     *
29
     * @var string
30
     */
31
    private $className;
32
33
    /**
34
     * Initializes reflection instance for the method node
35
     *
36
     * @param string $className Name of the class
37
     * @param string $methodName Name of the method
38
     * @param ClassMethod $classMethodNode AST-node for method
39
     */
40 31
    public function __construct($className, $methodName, ClassMethod $classMethodNode = null)
41
    {
42
        //for some reason, ReflectionMethod->getNamespaceName in php always returns '', so we shouldn't use it too
43 31
        $this->className        = $className;
44 31
        $this->functionLikeNode = $classMethodNode ?: ReflectionEngine::parseClassMethod($className, $methodName);
45
46
        // Let's unset original read-only properties to have a control over them via __get
47 31
        unset($this->name, $this->class);
48 31
    }
49
50
    /**
51
     * Emulating original behaviour of reflection
52
     */
53 1
    public function ___debugInfo()
54
    {
55
        return [
56 1
            'name'  => $this->getClassMethodNode()->name,
57 1
            'class' => $this->className
58
        ];
59
    }
60
61
    /**
62
     * Returns the string representation of the Reflection method object.
63
     *
64
     * @link http://php.net/manual/en/reflectionmethod.tostring.php
65
     *
66
     * @return string
67
     */
68 1
    public function __toString()
69
    {
70 1
        $paramFormat      = ($this->getNumberOfParameters() > 0) ? "\n\n  - Parameters [%d] {%s\n  }" : '';
71 1
        $methodParameters = $this->getParameters();
72
        try {
73 1
            $prototype = $this->getPrototype();
74 1
        } catch (\ReflectionException $e) {
75 1
            $prototype = null;
76
        }
77 1
        $prototypeClass = $prototype ? $prototype->getDeclaringClass()->name : '';
78
79 1
        $paramString = '';
80 1
        $identation  = str_repeat(' ', 4);
81 1
        foreach ($methodParameters as $methodParameter) {
82 1
            $paramString .= "\n{$identation}" . $methodParameter;
83
        }
84
85 1
        return sprintf(
86 1
            "%sMethod [ <user%s%s%s>%s%s%s %s method %s ] {\n  @@ %s %d - %d{$paramFormat}\n}\n",
87 1
            $this->getDocComment() ? $this->getDocComment() . "\n" : '',
88 1
            $prototype ? ", overwrites {$prototypeClass}, prototype {$prototypeClass}" : '',
89 1
            $this->isConstructor() ? ', ctor' : '',
90 1
            $this->isDestructor() ? ', dtor' : '',
91 1
            $this->isFinal() ? ' final' : '',
92 1
            $this->isStatic() ? ' static' : '',
93 1
            $this->isAbstract() ? ' abstract' : '',
94 1
            join(' ', \Reflection::getModifierNames($this->getModifiers() & 1792)),
95 1
            $this->getName(),
96 1
            $this->getFileName(),
97 1
            $this->getStartLine(),
98 1
            $this->getEndLine(),
99
            count($methodParameters),
100
            $paramString
101
        );
102
    }
103
104
    /**
105
     * {@inheritDoc}
106
     */
107 1
    public function getClosure($object)
108
    {
109 1
        $this->initializeInternalReflection();
110
111 1
        return parent::getClosure($object);
112
    }
113
114
    /**
115
     * {@inheritDoc}
116
     */
117 3
    public function getDeclaringClass()
118
    {
119 3
        return new ReflectionClass($this->className);
120
    }
121
122
    /**
123
     * {@inheritDoc}
124
     */
125 8
    public function getModifiers()
126
    {
127 8
        $modifiers = 0;
128 8
        if ($this->isPublic()) {
129 6
            $modifiers += self::IS_PUBLIC;
130
        }
131 8
        if ($this->isProtected()) {
132 3
            $modifiers += self::IS_PROTECTED;
133
        }
134 8
        if ($this->isPrivate()) {
135 5
            $modifiers += self::IS_PRIVATE;
136
        }
137 8
        if ($this->isAbstract()) {
138 4
            $modifiers += self::IS_ABSTRACT;
139
        }
140 8
        if ($this->isFinal()) {
141 3
            $modifiers += self::IS_FINAL;
142
        }
143 8
        if ($this->isStatic()) {
144 3
            $modifiers += self::IS_STATIC;
145
        }
146
147 8
        return $modifiers;
148
    }
149
150
    /**
151
     * {@inheritDoc}
152
     */
153 2
    public function getPrototype()
154
    {
155 2
        $parent = $this->getDeclaringClass()->getParentClass();
156 2
        if (!$parent) {
157
            throw new ReflectionException("No prototype");
158
        }
159
160 2
        $prototypeMethod = $parent->getMethod($this->getName());
161 1
        if (!$prototypeMethod) {
162
            throw new ReflectionException("No prototype");
163
        }
164
165 1
        return $prototypeMethod;
166
    }
167
168
    /**
169
     * {@inheritDoc}
170
     */
171 1
    public function invoke($object, $args = null)
172
    {
173 1
        $this->initializeInternalReflection();
174
175 1
        return call_user_func_array('parent::invoke', func_get_args());
176
    }
177
178
    /**
179
     * {@inheritDoc}
180
     */
181 3
    public function invokeArgs($object, array $args)
182
    {
183 3
        $this->initializeInternalReflection();
184
185 3
        return parent::invokeArgs($object, $args);
186
    }
187
188
    /**
189
     * {@inheritDoc}
190
     */
191 8
    public function isAbstract()
192
    {
193 8
        return $this->getClassMethodNode()->isAbstract();
194
    }
195
196
    /**
197
     * {@inheritDoc}
198
     */
199 1
    public function isConstructor()
200
    {
201 1
        return $this->getClassMethodNode()->name == '__construct';
202
    }
203
204
    /**
205
     * {@inheritDoc}
206
     */
207 1
    public function isDestructor()
208
    {
209 1
        return $this->getClassMethodNode()->name == '__destruct';
210
    }
211
212
    /**
213
     * {@inheritDoc}
214
     */
215 8
    public function isFinal()
216
    {
217 8
        return $this->getClassMethodNode()->isFinal();
218
    }
219
220
    /**
221
     * {@inheritDoc}
222
     */
223 8
    public function isPrivate()
224
    {
225 8
        return $this->getClassMethodNode()->isPrivate();
226
    }
227
228
    /**
229
     * {@inheritDoc}
230
     */
231 8
    public function isProtected()
232
    {
233 8
        return $this->getClassMethodNode()->isProtected();
234
    }
235
236
    /**
237
     * {@inheritDoc}
238
     */
239 11
    public function isPublic()
240
    {
241 11
        return $this->getClassMethodNode()->isPublic();
242
    }
243
244
    /**
245
     * {@inheritDoc}
246
     */
247 8
    public function isStatic()
248
    {
249 8
        return $this->getClassMethodNode()->isStatic();
250
    }
251
252
    /**
253
     * {@inheritDoc}
254
     */
255 1
    public function setAccessible($accessible)
256
    {
257 1
        $this->initializeInternalReflection();
258
259 1
        parent::setAccessible($accessible);
260 1
    }
261
262
    /**
263
     * Parses methods from the concrete class node
264
     *
265
     * @param ClassLike $classLikeNode Class-like node
266
     * @param string    $fullClassName FQN of the class
267
     *
268
     * @return array|ReflectionMethod[]
269
     */
270 66
    public static function collectFromClassNode(ClassLike $classLikeNode, $fullClassName)
271
    {
272 66
        $methods = [];
273
274 66
        foreach ($classLikeNode->stmts as $classLevelNode) {
275 55
            if ($classLevelNode instanceof ClassMethod) {
276 30
                $classLevelNode->setAttribute('fileName', $classLikeNode->getAttribute('fileName'));
277
278 30
                $methodName = $classLevelNode->name;
279 55
                $methods[$methodName] = new ReflectionMethod(
280
                    $fullClassName,
281
                    $methodName,
282
                    $classLevelNode
283
                );
284
            }
285
        }
286
287 66
        return $methods;
288
    }
289
290
    /**
291
     * Implementation of internal reflection initialization
292
     *
293
     * @return void
294
     */
295 6
    protected function __initialize()
296
    {
297 6
        parent::__construct($this->className, $this->getName());
298 6
    }
299
300
    /**
301
     * Returns ClassMethod node to prevent all possible type checks with instanceof
302
     *
303
     * @return ClassMethod
304
     */
305 12
    private function getClassMethodNode()
306
    {
307 12
        return $this->functionLikeNode;
308
    }
309
}
310