Completed
Push — master ( 555240...fa2155 )
by Alexander
115:41 queued 90:43
created

ReflectionClassConstant::__debugInfo()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 2
cts 2
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 Reflection;
20
use ReflectionClassConstant as BaseReflectionClassConstant;
21
22
class ReflectionClassConstant extends BaseReflectionClassConstant
23
{
24
    use InternalPropertiesEmulationTrait;
25
26
    /**
27
     * Concrete class constant node
28
     *
29
     * @var ClassConst
30
     */
31
    private $classConstantNode;
32
33
    /**
34
     * @var Const_
35
     */
36
    private $constNode;
37
38
    /**
39
     * Name of the class
40
     *
41
     * @var string
42
     */
43
    private $className;
44
45
    /**
46
     * Parses class constants from the concrete class node
47
     *
48
     * @param ClassLike $classLikeNode Class-like node
49
     * @param string $reflectionClassName FQN of the class
50
     *
51
     * @return array|ReflectionClassConstant[]
52 8
     */
53
    public static function collectFromClassNode(ClassLike $classLikeNode, string $reflectionClassName): array
54 8
    {
55
        $classConstants = [];
56 8
57 8
        foreach ($classLikeNode->stmts as $classLevelNode) {
58 7
            if ($classLevelNode instanceof ClassConst) {
59 7
                foreach ($classLevelNode->consts as $const) {
60 7
                    $classConstName = $const->name->toString();
61 7
                    $classConstants[$classConstName] = new ReflectionClassConstant(
62
                        $reflectionClassName,
63
                        $classConstName,
64
                        $classLevelNode,
65
                        $const
66
                    );
67
                }
68
            }
69
        }
70 8
71
        return $classConstants;
72
    }
73
74
    /**
75
     * Initializes a reflection for the class constant
76
     *
77
     * @param string      $className         Name of the class
78
     * @param string      $classConstantName Name of the class constant to reflect
79
     * @param ?ClassConst $classConstNode    ClassConstant definition node
0 ignored issues
show
Documentation introduced by
The doc-type ?ClassConst could not be parsed: Unknown type name "?ClassConst" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
80
     * @param Const_|null $constNode         Concrete const definition node
81 7
     */
82
    public function __construct(
83
        string $className,
84
        string $classConstantName,
85
        ClassConst $classConstNode = null,
86
        Const_ $constNode = null
87 7
    ) {
88
        $this->className = ltrim($className, '\\');
89 7
90
        if (!$classConstNode || !$constNode) {
91
            [$classConstNode, $constNode] = ReflectionEngine::parseClassConstant($className, $classConstantName);
92
        }
93 7
        // Let's unset original read-only property to have a control over it via __get
94
        unset($this->name, $this->class);
95 7
96 7
        $this->classConstantNode = $classConstNode;
97 7
        $this->constNode = $constNode;
98
    }
99
100
    /**
101
     * Emulating original behaviour of reflection
102 1
     */
103
    public function __debugInfo(): array
104
    {
105 1
        return [
106 1
            'name' => $this->getName(),
107
            'class' => $this->className
108
        ];
109
    }
110
111
    /**
112
     * @inheritDoc
113 2
     */
114
    public function getDeclaringClass()
115 2
    {
116
        return new ReflectionClass($this->className);
117
    }
118
119
    /**
120
     * @inheritDoc
121 1
     */
122
    public function getDocComment()
123 1
    {
124
        $docBlock = $this->classConstantNode->getDocComment();
125 1
126
        return $docBlock ? $docBlock->getText() : false;
127
    }
128
129
    /**
130
     * @inheritDoc
131 2
     */
132
    public function getModifiers()
133 2
    {
134 2
        $modifiers = 0;
135 2
        if ($this->isPublic()) {
136
            $modifiers += ReflectionMethod::IS_PUBLIC;
137 2
        }
138 1
        if ($this->isProtected()) {
139
            $modifiers += ReflectionMethod::IS_PROTECTED;
140 2
        }
141 1
        if ($this->isPrivate()) {
142
            $modifiers += ReflectionMethod::IS_PRIVATE;
143
        }
144 2
145
        return $modifiers;
146
    }
147
148
    /**
149
     * @inheritDoc
150 4
     */
151
    public function getName()
152 4
    {
153
        return $this->constNode->name->toString();
154
    }
155
156
    /**
157
     * @inheritDoc
158 2
     */
159
    public function getValue()
160 2
    {
161 2
        $solver = new NodeExpressionResolver($this->getDeclaringClass());
162 2
        $solver->process($this->constNode->value);
163
        return $solver->getValue();
164
    }
165
166
    /**
167
     * @inheritDoc
168 2
     */
169
    public function isPrivate()
170 2
    {
171
        return $this->classConstantNode->isPrivate();
172
    }
173
174
    /**
175
     * @inheritDoc
176 2
     */
177
    public function isProtected()
178 2
    {
179
        return $this->classConstantNode->isProtected();
180
    }
181
182
    /**
183
     * @inheritDoc
184 2
     */
185
    public function isPublic()
186 2
    {
187
        return $this->classConstantNode->isPublic();
188
    }
189
190
    /**
191
     * @inheritDoc
192 2
     */
193
    public function __toString()
194
    {
195 2
        # Starting from PHP7.3 gettype returns different names, need to remap them
196
        static $typeMap = [
197
            'integer' => 'int',
198
            'boolean' => 'bool',
199
            'double'  => 'float',
200 2
        ];
201 2
        $value = $this->getValue();
202 2
        $type  = gettype($value);
203 2
        if (PHP_VERSION_ID >= 70300 && isset($typeMap[$type])) {
204
            $type = $typeMap[$type];
205 2
        }
206
        $valueType = new ReflectionType($type, null, true);
207 2
208 2
        return sprintf(
209 2
            "Constant [ %s %s %s ] { %s }\n",
210 2
            implode(' ', Reflection::getModifierNames($this->getModifiers())),
211 2
            strtolower((string) ReflectionType::convertToDisplayType($valueType)),
212 2
            $this->getName(),
213
            (string) $value
214
        );
215
    }
216
}
217