Completed
Push — master ( 34991a...adfc38 )
by Alexander
13s
created

ReflectionProperty::isStatic()   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\InitializationTrait;
14
use Go\ParserReflection\Traits\InternalPropertiesEmulationTrait;
15
use Go\ParserReflection\ValueResolver\NodeExpressionResolver;
16
use PhpParser\Node\Stmt\ClassLike;
17
use PhpParser\Node\Stmt\Property;
18
use PhpParser\Node\Stmt\PropertyProperty;
19
use ReflectionProperty as BaseReflectionProperty;
20
21
/**
22
 * AST-based reflection for class property
23
 */
24
class ReflectionProperty extends BaseReflectionProperty
25
{
26
    use InitializationTrait, InternalPropertiesEmulationTrait;
27
28
    /**
29
     * Type of property node
30
     *
31
     * @var Property
32
     */
33
    private $propertyTypeNode;
34
35
    /**
36
     * Concrete property node
37
     *
38
     * @var PropertyProperty
39
     */
40
    private $propertyNode;
41
42
    /**
43
     * Name of the class
44
     *
45
     * @var string
46
     */
47
    private $className;
48
49
    /**
50
     * Initializes a reflection for the property
51
     *
52
     * @param string $className Name of the class with properties
53
     * @param string $propertyName Name of the property to reflect
54
     * @param Property $propertyType Property type definition node
55
     * @param PropertyProperty $propertyNode Concrete property definition (value, name)
56
     */
57 19
    public function __construct(
58
        $className,
59
        $propertyName,
60
        Property $propertyType = null,
61
        PropertyProperty $propertyNode = null
62
    ) {
63 19
        $this->className    = $className;
64 19
        if (!$propertyType || !$propertyNode) {
65 1
            list ($propertyType, $propertyNode) = ReflectionEngine::parseClassProperty($className, $propertyName);
66
        }
67
68 19
        $this->propertyTypeNode = $propertyType;
69 19
        $this->propertyNode     = $propertyNode;
70
71
        // Let's unset original read-only properties to have a control over them via __get
72 19
        unset($this->name, $this->class);
73 19
    }
74
75
    /**
76
     * Returns an AST-node for property
77
     *
78
     * @return PropertyProperty
79
     */
80
    public function getNode()
81
    {
82
        return $this->propertyNode;
83
    }
84
85
    /**
86
     * Returns an AST-node for property type
87
     *
88
     * @return Property
89
     */
90
    public function getTypeNode()
91
    {
92
        return $this->propertyTypeNode;
93
    }
94
95
    /**
96
     * Emulating original behaviour of reflection
97
     */
98 1
    public function ___debugInfo()
99
    {
100
        return array(
101 1
            'name'  => isset($this->propertyNode) ? $this->propertyNode->name : 'unknown',
102 1
            'class' => $this->className
103
        );
104
    }
105
106
    /**
107
     * Return string representation of this little old property.
108
     *
109
     * @return string
110
     */
111 26
    public function __toString()
112
    {
113 26
        return sprintf(
114 26
            "Property [%s %s $%s ]\n",
115 26
            $this->isStatic() ? '' : ($this->isDefault() ? ' <default>' : ' <dynamic>'),
116 26
            join(' ', \Reflection::getModifierNames($this->getModifiers())),
117 26
            $this->getName()
118
        );
119
    }
120
121
    /**
122
     * {@inheritDoc}
123
     */
124 14
    public function getDeclaringClass()
125
    {
126 14
        return new ReflectionClass($this->className);
127
    }
128
129
    /**
130
     * @inheritDoc
131
     */
132 26
    public function getDocComment()
133
    {
134 26
        $docBlock = $this->propertyTypeNode->getDocComment();
135
136 26
        return $docBlock ? $docBlock->getText() : false;
137
    }
138
139
    /**
140
     * {@inheritDoc}
141
     */
142 59
    public function getModifiers()
143
    {
144 59
        $modifiers = 0;
145 59
        if ($this->isPublic()) {
146 27
            $modifiers += self::IS_PUBLIC;
147
        }
148 59
        if ($this->isProtected()) {
149 21
            $modifiers += self::IS_PROTECTED;
150
        }
151 59
        if ($this->isPrivate()) {
152 21
            $modifiers += self::IS_PRIVATE;
153
        }
154 59
        if ($this->isStatic()) {
155 31
            $modifiers += self::IS_STATIC;
156
        }
157
158 59
        return $modifiers;
159
    }
160
161
    /**
162
     * @inheritDoc
163
     */
164 267
    public function getName()
165
    {
166 267
        return $this->propertyNode->name;
167
    }
168
169
    /**
170
     * @inheritDoc
171
     */
172 15
    public function getValue($object = null)
173
    {
174 15
        if (!isset($object)) {
175 14
            $solver = new NodeExpressionResolver($this->getDeclaringClass());
176 14
            if (!isset($this->propertyNode->default)) {
177 2
                return null;
178
            }
179 12
            $solver->process($this->propertyNode->default);
180
181 12
            return $solver->getValue();
182
        }
183
184 1
        $this->initializeInternalReflection();
185
186 1
        return parent::getValue($object);
187
    }
188
189
    /**
190
     * @inheritDoc
191
     */
192 39
    public function isDefault()
193
    {
194
        // TRUE if the property was declared at compile-time
195
196 39
        return true;
197
    }
198
199
    /**
200
     * {@inheritDoc}
201
     */
202 85
    public function isPrivate()
203
    {
204 85
        return $this->propertyTypeNode->isPrivate();
205
    }
206
207
    /**
208
     * {@inheritDoc}
209
     */
210 85
    public function isProtected()
211
    {
212 85
        return $this->propertyTypeNode->isProtected();
213
    }
214
215
    /**
216
     * {@inheritDoc}
217
     */
218 85
    public function isPublic()
219
    {
220 85
        return $this->propertyTypeNode->isPublic();
221
    }
222
223
    /**
224
     * {@inheritDoc}
225
     */
226 92
    public function isStatic()
227
    {
228 92
        return $this->propertyTypeNode->isStatic();
229
    }
230
231
    /**
232
     * {@inheritDoc}
233
     */
234 2
    public function setAccessible($accessible)
235
    {
236 2
        $this->initializeInternalReflection();
237
238 2
        parent::setAccessible($accessible);
239 2
    }
240
241
    /**
242
     * @inheritDoc
243
     */
244 1
    public function setValue($object, $value = null)
245
    {
246 1
        $this->initializeInternalReflection();
247
248 1
        parent::setValue($object, $value);
249 1
    }
250
251
    /**
252
     * Parses properties from the concrete class node
253
     *
254
     * @param ClassLike $classLikeNode Class-like node
255
     * @param string    $fullClassName FQN of the class
256
     *
257
     * @return array|ReflectionProperty[]
258
     */
259 43
    public static function collectFromClassNode(ClassLike $classLikeNode, $fullClassName)
260
    {
261 43
        $properties = [];
262
263 43
        foreach ($classLikeNode->stmts as $classLevelNode) {
264 39
            if ($classLevelNode instanceof Property) {
265 18
                foreach ($classLevelNode->props as $classPropertyNode) {
266 18
                    $propertyName = $classPropertyNode->name;
267 18
                    $properties[$propertyName] = new static(
268 18
                        $fullClassName,
269 18
                        $propertyName,
270 18
                        $classLevelNode,
271 39
                        $classPropertyNode
272
                    );
273
                }
274
            }
275
        }
276
277 43
        return $properties;
278
    }
279
280
    /**
281
     * Implementation of internal reflection initialization
282
     *
283
     * @return void
284
     */
285 2
    protected function __initialize()
286
    {
287 2
        parent::__construct($this->className, $this->getName());
288 2
    }
289
}
290