Completed
Pull Request — master (#25)
by Alexander
02:46
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

Importance

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