Completed
Push — master ( 6af734...e96280 )
by Alexander
01:52
created

ReflectionClassConstant::___debugInfo()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 1
1
<?php
2
/**
3
 * Parser Reflection API
4
 *
5
 * @copyright Copyright 2019, 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
declare(strict_types=1);
11
12
namespace Go\ParserReflection;
13
14
use Go\ParserReflection\Traits\InternalPropertiesEmulationTrait;
15
use Go\ParserReflection\ValueResolver\NodeExpressionResolver;
16
use PhpParser\Node\Const_;
17
use PhpParser\Node\Stmt\ClassConst;
18
use PhpParser\Node\Stmt\ClassLike;
19
use \ReflectionClassConstant as BaseReflectionClassConstant;
20
21
class ReflectionClassConstant extends BaseReflectionClassConstant
22
{
23
    use InternalPropertiesEmulationTrait;
24
25
    /**
26
     * Concrete class constant node
27
     *
28
     * @var ClassConst
29
     */
30
    private $classConstantNode;
31
32
    /**
33
     * @var Const_
34
     */
35
    private $constNode;
36
37
    /**
38
     * Name of the class
39
     *
40
     * @var string
41
     */
42
    private $className;
43
44
    /**
45
     * Parses class constants from the concrete class node
46
     *
47
     * @param ClassLike $classLikeNode Class-like node
48
     * @param string $reflectionClassName FQN of the class
49
     *
50
     * @return array|ReflectionClassConstant[]
51
     */
52 8
    public static function collectFromClassNode(ClassLike $classLikeNode, string $reflectionClassName): array
53
    {
54 8
        $classConstants = [];
55
56 8
        foreach ($classLikeNode->stmts as $classLevelNode) {
57 8
            if ($classLevelNode instanceof ClassConst) {
58 7
                foreach ($classLevelNode->consts as $const) {
59 7
                    $classConstName = $const->name->toString();
60 7
                    $classConstants[$classConstName] = new ReflectionClassConstant(
61 7
                        $reflectionClassName,
62 7
                        $classConstName,
63 7
                        $classLevelNode,
64 8
                        $const
65
                    );
66
                }
67
            }
68
        }
69
70 8
        return $classConstants;
71
    }
72
73
    /**
74
     * Initializes a reflection for the class constant
75
     *
76
     * @param string $className Name of the class
77
     * @param string $classConstantName Name of the class constant to reflect
78
     * @param ClassConst $classConstNode ClassConstant definition node
79
     * @param Const_|null $constNode Concrete const definition node
80
     */
81 7
    public function __construct(
82
        string $className,
83
        string $classConstantName,
84
        ClassConst $classConstNode = null,
85
        Const_ $constNode = null
86
    ) {
87 7
        $this->className = ltrim($className, '\\');
88
89 7
        if (!$classConstNode || !$constNode) {
90
            [$classConstNode, $constNode] = ReflectionEngine::parseClassConstant($className, $classConstantName);
91
        }
92
        // Let's unset original read-only property to have a control over it via __get
93 7
        unset($this->name, $this->class);
94
95 7
        $this->classConstantNode = $classConstNode;
96 7
        $this->constNode = $constNode;
97 7
    }
98
99
    /**
100
     * Emulating original behaviour of reflection
101
     */
102 1
    public function ___debugInfo()
103
    {
104
        return [
105 1
            'name' => $this->getName(),
106 1
            'class' => $this->className
107
        ];
108
    }
109
110
    /**
111
     * @inheritDoc
112
     */
113 2
    public function getDeclaringClass()
114
    {
115 2
        return new ReflectionClass($this->className);
116
    }
117
118
    /**
119
     * @inheritDoc
120
     */
121 1
    public function getDocComment()
122
    {
123 1
        $docBlock = $this->classConstantNode->getDocComment();
124
125 1
        return $docBlock ? $docBlock->getText() : false;
126
    }
127
128
    /**
129
     * @inheritDoc
130
     */
131 2
    public function getModifiers()
132
    {
133 2
        $modifiers = 0;
134 2
        if ($this->isPublic()) {
135 2
            $modifiers += ReflectionMethod::IS_PUBLIC;
136
        }
137 2
        if ($this->isProtected()) {
138 1
            $modifiers += ReflectionMethod::IS_PROTECTED;
139
        }
140 2
        if ($this->isPrivate()) {
141 1
            $modifiers += ReflectionMethod::IS_PRIVATE;
142
        }
143
144 2
        return $modifiers;
145
    }
146
147
    /**
148
     * @inheritDoc
149
     */
150 4
    public function getName()
151
    {
152 4
        return $this->constNode->name->toString();
153
    }
154
155
    /**
156
     * @inheritDoc
157
     */
158 2
    public function getValue()
159
    {
160 2
        $solver = new NodeExpressionResolver($this->getDeclaringClass());
161 2
        $solver->process($this->constNode->value);
162 2
        return $solver->getValue();
163
    }
164
165
    /**
166
     * @inheritDoc
167
     */
168 2
    public function isPrivate()
169
    {
170 2
        return $this->classConstantNode->isPrivate();
171
    }
172
173
    /**
174
     * @inheritDoc
175
     */
176 2
    public function isProtected()
177
    {
178 2
        return $this->classConstantNode->isProtected();
179
    }
180
181
    /**
182
     * @inheritDoc
183
     */
184 2
    public function isPublic()
185
    {
186 2
        return $this->classConstantNode->isPublic();
187
    }
188
189
    /**
190
     * @inheritDoc
191
     */
192 2
    public function __toString()
193
    {
194 2
        $value = $this->getValue();
195 2
        $valueType = new ReflectionType(gettype($value), null, true);
196
197 2
        return sprintf(
198 2
            "Constant [ %s %s %s ] { %s }\n",
199 2
            implode(' ', \Reflection::getModifierNames($this->getModifiers())),
200 2
            strtolower((string) ReflectionType::convertToDisplayType($valueType)),
201 2
            $this->getName(),
202 2
            (string) $value
203
        );
204
    }
205
}
206