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\ReflectionClassLikeTrait; |
14
|
|
|
use PhpParser\Node\Name; |
15
|
|
|
use PhpParser\Node\Name\FullyQualified; |
16
|
|
|
use PhpParser\Node\Stmt\ClassLike; |
17
|
|
|
use PhpParser\Node\Stmt\Interface_; |
18
|
|
|
use PhpParser\Node\Stmt\TraitUse; |
19
|
|
|
use ReflectionClass as InternalReflectionClass; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* AST-based reflection class |
23
|
|
|
*/ |
24
|
|
|
class ReflectionClass extends InternalReflectionClass |
25
|
|
|
{ |
26
|
|
|
use ReflectionClassLikeTrait; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* Initializes reflection instance |
30
|
|
|
* |
31
|
|
|
* @param string|object $argument Class name or instance of object |
32
|
|
|
* @param ClassLike $classLikeNode AST node for class |
33
|
|
|
*/ |
34
|
17 |
|
public function __construct($argument, ClassLike $classLikeNode = null) |
35
|
|
|
{ |
36
|
17 |
|
$fullClassName = is_object($argument) ? get_class($argument) : $argument; |
37
|
17 |
|
$namespaceParts = explode('\\', $fullClassName); |
38
|
17 |
|
$this->className = array_pop($namespaceParts); |
39
|
17 |
|
$this->namespaceName = join('\\', $namespaceParts); |
40
|
|
|
|
41
|
17 |
|
$this->classLikeNode = $classLikeNode ?: ReflectionEngine::parseClass($fullClassName); |
42
|
17 |
|
} |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* Parses interfaces from the concrete class node |
46
|
|
|
* |
47
|
|
|
* @param ClassLike $classLikeNode Class-like node |
48
|
|
|
* |
49
|
|
|
* @return array|\ReflectionClass[] List of reflections of interfaces |
50
|
|
|
*/ |
51
|
9 |
|
public static function collectInterfacesFromClassNode(ClassLike $classLikeNode) |
52
|
|
|
{ |
53
|
9 |
|
$interfaces = []; |
54
|
|
|
|
55
|
9 |
|
$isInterface = $classLikeNode instanceof Interface_; |
56
|
9 |
|
$interfaceField = $isInterface ? 'extends' : 'implements'; |
57
|
9 |
|
$hasInterfaces = in_array($interfaceField, $classLikeNode->getSubNodeNames()); |
58
|
9 |
|
$implementsList = $hasInterfaces ? $classLikeNode->$interfaceField : array(); |
59
|
9 |
|
if ($implementsList) { |
60
|
1 |
|
foreach ($implementsList as $implementNode) { |
61
|
1 |
|
if ($implementNode instanceof FullyQualified) { |
62
|
1 |
|
$implementName = $implementNode->toString(); |
63
|
1 |
|
$interface = interface_exists($implementName, false) |
64
|
1 |
|
? new parent($implementName) |
65
|
1 |
|
: new static($implementName); |
66
|
1 |
|
$interfaces[$implementName] = $interface; |
67
|
1 |
|
} |
68
|
1 |
|
} |
69
|
1 |
|
} |
70
|
|
|
|
71
|
9 |
|
return $interfaces; |
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
/** |
75
|
|
|
* Parses traits from the concrete class node |
76
|
|
|
* |
77
|
|
|
* @param ClassLike $classLikeNode Class-like node |
78
|
|
|
* |
79
|
|
|
* @return array|\ReflectionClass[] List of reflections of traits |
80
|
|
|
*/ |
81
|
2 |
|
public static function collectTraitsFromClassNode(ClassLike $classLikeNode) |
82
|
|
|
{ |
83
|
2 |
|
$traits = []; |
84
|
|
|
|
85
|
2 |
|
if ($classLikeNode->stmts) { |
|
|
|
|
86
|
2 |
|
foreach ($classLikeNode->stmts as $classLevelNode) { |
87
|
2 |
|
if ($classLevelNode instanceof TraitUse) { |
88
|
1 |
|
foreach ($classLevelNode->traits as $classTraitName) { |
89
|
1 |
|
if ($classTraitName instanceof FullyQualified) { |
90
|
1 |
|
$traitName = $classTraitName->toString(); |
91
|
1 |
|
$trait = trait_exists($traitName, false) |
92
|
1 |
|
? new parent($traitName) |
93
|
1 |
|
: new static($traitName); |
94
|
1 |
|
$traits[$traitName] = $trait; |
95
|
1 |
|
} |
96
|
1 |
|
} |
97
|
1 |
|
} |
98
|
2 |
|
} |
99
|
2 |
|
} |
100
|
|
|
|
101
|
2 |
|
return $traits; |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
/** |
105
|
|
|
* Implementation of internal reflection initialization |
106
|
|
|
* |
107
|
|
|
* @return void |
108
|
|
|
*/ |
109
|
4 |
|
protected function __initialize() |
110
|
|
|
{ |
111
|
4 |
|
parent::__construct($this->getName()); |
112
|
4 |
|
} |
113
|
|
|
} |
114
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.