1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* AppserverIo\Lang\Reflection\ReflectionClass |
5
|
|
|
* |
6
|
|
|
* NOTICE OF LICENSE |
7
|
|
|
* |
8
|
|
|
* This source file is subject to the Open Software License (OSL 3.0) |
9
|
|
|
* that is available through the world-wide-web at this URL: |
10
|
|
|
* http://opensource.org/licenses/osl-3.0.php |
11
|
|
|
* |
12
|
|
|
* PHP version 5 |
13
|
|
|
* |
14
|
|
|
* @author Tim Wagner <[email protected]> |
15
|
|
|
* @copyright 2015 TechDivision GmbH <[email protected]> |
16
|
|
|
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) |
17
|
|
|
* @link https://github.com/appserver-io/lang |
18
|
|
|
* @link http://www.appserver.io |
19
|
|
|
*/ |
20
|
|
|
|
21
|
|
|
namespace AppserverIo\Lang\Reflection; |
22
|
|
|
|
23
|
|
|
use AppserverIo\Lang\Object; |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* A wrapper instance for a reflection class. |
27
|
|
|
* |
28
|
|
|
* @author Tim Wagner <[email protected]> |
29
|
|
|
* @copyright 2015 TechDivision GmbH <[email protected]> |
30
|
|
|
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) |
31
|
|
|
* @link https://github.com/appserver-io/lang |
32
|
|
|
* @link http://www.appserver.io |
33
|
|
|
*/ |
34
|
|
|
class ReflectionClass extends Object implements ClassInterface, \Serializable |
35
|
|
|
{ |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* The passed class name to invoke the method on. |
39
|
|
|
* |
40
|
|
|
* @var string |
41
|
|
|
*/ |
42
|
|
|
protected $passedName; |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* The class annotations. |
46
|
|
|
* |
47
|
|
|
* @var array|null |
48
|
|
|
*/ |
49
|
|
|
protected $annotations; |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* The class methods in an associative, three dimensional array with modifiers and method names as keys. |
53
|
|
|
* |
54
|
|
|
* @var array |
55
|
|
|
*/ |
56
|
|
|
protected $methods; |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* The class properties in an associative, three dimensional array with modifiers and property names as keys. |
60
|
|
|
* |
61
|
|
|
* @var array |
62
|
|
|
*/ |
63
|
|
|
protected $properties; |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* Array with annotations names we want to ignore when loaded. |
67
|
|
|
* |
68
|
|
|
* @var array |
69
|
|
|
*/ |
70
|
|
|
protected $annotationsToIgnore; |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* Array with annotation aliases used when create annotation instances. |
74
|
|
|
* |
75
|
|
|
* @var array |
76
|
|
|
*/ |
77
|
|
|
protected $annotationAliases; |
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* Initializes the timed object with the passed data. |
81
|
|
|
* |
82
|
|
|
* @param string $name The class name to invoke the method on |
83
|
|
|
* @param array $annotationsToIgnore An array with annotations names we want to ignore when loaded |
84
|
|
|
* @param array $annotationAliases An array with annotation aliases used when create annotation instances |
85
|
|
|
*/ |
86
|
24 |
|
public function __construct($name, array $annotationsToIgnore = array(), array $annotationAliases = array()) |
87
|
|
|
{ |
88
|
|
|
// initialize property default values here, as declarative default values may break thread safety, |
89
|
|
|
// when utilizing static and non-static access on class methods within same thread context! |
90
|
24 |
|
$this->passedName = ''; |
91
|
24 |
|
$this->annotations = null; |
92
|
24 |
|
$this->methods = array(); |
93
|
24 |
|
$this->properties = array(); |
94
|
24 |
|
$this->annotationsToIgnore = array(); |
95
|
24 |
|
$this->annotationAliases = array(); |
96
|
|
|
|
97
|
24 |
|
$this->passedName = $name; |
98
|
24 |
|
$this->annotationsToIgnore = $annotationsToIgnore; |
99
|
24 |
|
$this->annotationAliases = $annotationAliases; |
100
|
24 |
|
} |
101
|
|
|
|
102
|
|
|
/** |
103
|
|
|
* This method returns the class name as |
104
|
|
|
* a string. |
105
|
|
|
* |
106
|
|
|
* @return string |
107
|
|
|
*/ |
108
|
1 |
|
public static function __getClass() |
109
|
|
|
{ |
110
|
1 |
|
return __CLASS__; |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* Returns the class name passed to the constructor. |
115
|
|
|
* |
116
|
|
|
* @return string The class name passed to the constructor |
117
|
|
|
*/ |
118
|
21 |
|
protected function getPassedName() |
119
|
|
|
{ |
120
|
21 |
|
return $this->passedName; |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* Returns the class name. |
125
|
|
|
* |
126
|
|
|
* @return string The class name |
127
|
|
|
* @see \AppserverIo\Lang\Reflection\ClassInterface::getClassName() |
128
|
|
|
*/ |
129
|
2 |
|
public function getName() |
130
|
|
|
{ |
131
|
2 |
|
return $this->toPhpReflectionClass()->getName(); |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
/** |
135
|
|
|
* Returns the short class name (without namespace). |
136
|
|
|
* |
137
|
|
|
* @return string The short class name |
138
|
|
|
* @see \AppserverIo\Lang\Reflection\ClassInterface::getClassName() |
139
|
|
|
*/ |
140
|
|
|
public function getShortName() |
141
|
|
|
{ |
142
|
|
|
return $this->toPhpReflectionClass()->getShortName(); |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* Returns an array with annotation names we want to ignore when loaded. |
147
|
|
|
* |
148
|
|
|
* @return array The annotation names we want to ignore |
149
|
|
|
* @see \AppserverIo\Lang\Reflection\ClassInterface::getAnnotationsToIgnore() |
150
|
|
|
*/ |
151
|
16 |
|
public function getAnnotationsToIgnore() |
152
|
|
|
{ |
153
|
16 |
|
return $this->annotationsToIgnore; |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
/** |
157
|
|
|
* Returns an array with annotation aliases used when create annotation instances. |
158
|
|
|
* |
159
|
|
|
* @return array The annotation aliases used when create annotation instances |
160
|
|
|
* @see \AppserverIo\Lang\Reflection\ClassInterface::getAnnotationAliases() |
161
|
|
|
*/ |
162
|
17 |
|
public function getAnnotationAliases() |
163
|
|
|
{ |
164
|
17 |
|
return $this->annotationAliases; |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
/** |
168
|
|
|
* Registers the annotation alias for the passed class name. |
169
|
|
|
* |
170
|
|
|
* @param string $annotationName The alias |
171
|
|
|
* @param string $annotationClassName The resolving class name |
172
|
|
|
* |
173
|
|
|
* @return void |
174
|
|
|
* @see \AppserverIo\Lang\Reflection\ClassInterface::addAnnotationAlias() |
175
|
|
|
*/ |
176
|
1 |
|
public function addAnnotationAlias($annotationName, $annotationClassName) |
177
|
|
|
{ |
178
|
1 |
|
$this->annotationAliases[$annotationName] = $annotationClassName; |
179
|
1 |
|
} |
180
|
|
|
|
181
|
|
|
/** |
182
|
|
|
* Returns the class annotations. |
183
|
|
|
* |
184
|
|
|
* @return array The class annotations |
185
|
|
|
* @see \AppserverIo\Lang\Reflection\ClassInterface::getAnnotations() |
186
|
|
|
*/ |
187
|
4 |
|
public function getAnnotations() |
188
|
|
|
{ |
189
|
|
|
|
190
|
|
|
// check if the annotations has been loaded |
191
|
4 |
|
if (isset($this->annotations) === false) { |
192
|
4 |
|
$this->annotations = ReflectionAnnotation::fromReflectionClass($this); |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
// return the annotations |
196
|
4 |
|
return $this->annotations; |
197
|
|
|
} |
198
|
|
|
|
199
|
|
|
/** |
200
|
|
|
* Queries whether the reflection class has an annotation with the passed name or not. |
201
|
|
|
* |
202
|
|
|
* @param string $annotationName The annotation we want to query |
203
|
|
|
* |
204
|
|
|
* @return boolean TRUE if the reflection class has the annotation, else FALSE |
205
|
|
|
* @see \AppserverIo\Lang\Reflection\ClassInterface::hasAnnotation() |
206
|
|
|
*/ |
207
|
1 |
|
public function hasAnnotation($annotationName) |
208
|
|
|
{ |
209
|
1 |
|
$annotations = $this->getAnnotations(); |
210
|
1 |
|
return isset($annotations[$annotationName]); |
211
|
|
|
} |
212
|
|
|
|
213
|
|
|
/** |
214
|
|
|
* Returns the annotation instance with the passed name. |
215
|
|
|
* |
216
|
|
|
* @param string $annotationName The name of the requested annotation instance |
217
|
|
|
* |
218
|
|
|
* @return \AppserverIo\Lang\Reflection\AnnotationInterface|null The requested annotation instance |
219
|
|
|
* @throws \AppserverIo\Lang\Reflection\ReflectionException Is thrown if the requested annotation is not available |
220
|
|
|
* @see \AppserverIo\Lang\Reflection\ClassInterface::getAnnotation() |
221
|
|
|
*/ |
222
|
3 |
View Code Duplication |
public function getAnnotation($annotationName) |
|
|
|
|
223
|
|
|
{ |
224
|
|
|
|
225
|
|
|
// first check if the method is available |
226
|
3 |
|
$annotations = $this->getAnnotations(); |
227
|
3 |
|
if (isset($annotations[$annotationName])) { |
228
|
|
|
// if yes, return it |
229
|
2 |
|
return $annotations[$annotationName]; |
230
|
|
|
} |
231
|
|
|
|
232
|
|
|
// if not, throw an exception |
233
|
1 |
|
throw new ReflectionException(sprintf('The requested reflection annotation %s is not available', $annotationName)); |
234
|
|
|
} |
235
|
|
|
|
236
|
|
|
/** |
237
|
|
|
* Returns the class methods. |
238
|
|
|
* |
239
|
|
|
* @param integer $filter Filter the results to include only methods with certain attributes |
240
|
|
|
* |
241
|
|
|
* @return array The class methods |
242
|
|
|
* @see \AppserverIo\Lang\Reflection\ClassInterface::getMethods() |
243
|
|
|
* @link http://php.net/manual/en/reflectionclass.getmethods.php |
244
|
|
|
*/ |
245
|
10 |
View Code Duplication |
public function getMethods($filter = ReflectionProperty::ALL_MODIFIERS) |
|
|
|
|
246
|
|
|
{ |
247
|
|
|
|
248
|
|
|
// check if the methods for the requested filter has been loaded |
249
|
10 |
|
if (isset($this->methods[$filter]) === false) { |
250
|
10 |
|
$this->methods[$filter] = ReflectionMethod::fromReflectionClass($this, $filter, $this->getAnnotationsToIgnore(), $this->getAnnotationAliases()); |
251
|
|
|
} |
252
|
|
|
|
253
|
|
|
// return the requested method |
254
|
10 |
|
return $this->methods[$filter]; |
255
|
|
|
} |
256
|
|
|
|
257
|
|
|
/** |
258
|
|
|
* Queries whether the reflection class has an method with the passed name or not. |
259
|
|
|
* |
260
|
|
|
* @param string $name The method we want to query |
261
|
|
|
* |
262
|
|
|
* @return boolean TRUE if the reflection class has the method, else FALSE |
263
|
|
|
* @see \AppserverIo\Lang\Reflection\ClassInterface::hasMethod() |
264
|
|
|
*/ |
265
|
2 |
|
public function hasMethod($name) |
266
|
|
|
{ |
267
|
2 |
|
$methods = $this->getMethods(); |
268
|
2 |
|
return isset($methods[$name]); |
269
|
|
|
} |
270
|
|
|
|
271
|
|
|
/** |
272
|
|
|
* Returns the requested reflection method. |
273
|
|
|
* |
274
|
|
|
* @param string $name The name of the reflection method to return |
275
|
|
|
* |
276
|
|
|
* @return \AppserverIo\Lang\Reflection\ReflectionMethod The requested reflection method |
277
|
|
|
* @throws \AppserverIo\Lang\Reflection\ReflectionException Is thrown if the requested method is not available |
278
|
|
|
* @see \AppserverIo\Lang\Reflection\ClassInterface::getMethod() |
279
|
|
|
* @link http://php.net/manual/en/reflectionclass.getmethod.php |
280
|
|
|
*/ |
281
|
8 |
|
public function getMethod($name) |
282
|
|
|
{ |
283
|
|
|
|
284
|
|
|
// first check if the method is available |
285
|
8 |
|
$methods = $this->getMethods(); |
286
|
8 |
|
if (isset($methods[$name])) { |
287
|
|
|
// if yes, return it |
288
|
7 |
|
return $methods[$name]; |
289
|
|
|
} |
290
|
|
|
|
291
|
|
|
// if not, throw an exception |
292
|
1 |
|
throw new ReflectionException(sprintf('The requested reflection method %s is not available', $name)); |
293
|
|
|
} |
294
|
|
|
|
295
|
|
|
/** |
296
|
|
|
* Returns the class properties. |
297
|
|
|
* |
298
|
|
|
* @param integer $filter Filter the results to include only properties with certain attributes |
299
|
|
|
* |
300
|
|
|
* @return array The class properties |
301
|
|
|
* @see \AppserverIo\Lang\Reflection\ClassInterface::getProperties() |
302
|
|
|
* @link http://php.net/manual/en/reflectionclass.getproperties.php |
303
|
|
|
*/ |
304
|
1 |
View Code Duplication |
public function getProperties($filter = ReflectionProperty::ALL_MODIFIERS) |
|
|
|
|
305
|
|
|
{ |
306
|
|
|
|
307
|
|
|
// check if the properties for the requested filter has been loaded |
308
|
1 |
|
if (isset($this->properties[$filter]) === false) { |
309
|
1 |
|
$this->properties[$filter] = ReflectionProperty::fromReflectionClass($this, $filter, $this->getAnnotationsToIgnore(), $this->getAnnotationAliases()); |
310
|
|
|
} |
311
|
|
|
|
312
|
|
|
// return the requested properties |
313
|
1 |
|
return $this->properties[$filter]; |
314
|
|
|
} |
315
|
|
|
|
316
|
|
|
/** |
317
|
|
|
* Queries whether the reflection class has an property with the passed name or not. |
318
|
|
|
* |
319
|
|
|
* @param string $name The property we want to query |
320
|
|
|
* |
321
|
|
|
* @return boolean TRUE if the reflection class has the property, else FALSE |
322
|
|
|
* @see \AppserverIo\Lang\Reflection\ClassInterface::hasProperty() |
323
|
|
|
*/ |
324
|
1 |
|
public function hasProperty($name) |
325
|
|
|
{ |
326
|
1 |
|
$properties = $this->getProperties(); |
327
|
1 |
|
return isset($properties[$name]); |
328
|
|
|
} |
329
|
|
|
|
330
|
|
|
/** |
331
|
|
|
* Returns the requested reflection property. |
332
|
|
|
* |
333
|
|
|
* @param string $name The name of the reflection property to return |
334
|
|
|
* |
335
|
|
|
* @return \AppserverIo\Lang\Reflection\ReflectionProperty The requested reflection property |
336
|
|
|
* @throws \AppserverIo\Lang\Reflection\ReflectionException Is thrown if the requested property is not available |
337
|
|
|
* @see \AppserverIo\Lang\Reflection\ClassInterface::getProperty() |
338
|
|
|
* @link http://php.net/manual/en/reflectionclass.getproperty.php |
339
|
|
|
*/ |
340
|
|
|
public function getProperty($name) |
341
|
|
|
{ |
342
|
|
|
|
343
|
|
|
// first check if the property is available |
344
|
|
|
$properties = $this->getProperties(); |
345
|
|
|
if (isset($properties[$name])) { |
346
|
|
|
// if yes, return it |
347
|
|
|
return $properties[$name]; |
348
|
|
|
} |
349
|
|
|
|
350
|
|
|
// if not, throw an exception |
351
|
|
|
throw new ReflectionException(sprintf('The requested reflection property %s is not available', $name)); |
352
|
|
|
} |
353
|
|
|
|
354
|
|
|
/** |
355
|
|
|
* Returns a new annotation instance. |
356
|
|
|
* |
357
|
|
|
* You can pass a random number of arguments to this function. These |
358
|
|
|
* arguments will be passed to the constructor of the new instance. |
359
|
|
|
* |
360
|
|
|
* @return object A new annotation instance initialized with the passed arguments |
361
|
|
|
* @see \AppserverIo\Lang\Reflection\ClassInterface::newInstance() |
362
|
|
|
*/ |
363
|
|
|
public function newInstance() |
364
|
|
|
{ |
365
|
|
|
return $this->newInstanceArgs(func_get_args()); |
366
|
|
|
} |
367
|
|
|
|
368
|
|
|
/** |
369
|
|
|
* Returns a new annotation instance. |
370
|
|
|
* |
371
|
|
|
* @param array $args The arguments that will be passed to the instance constructor |
372
|
|
|
* |
373
|
|
|
* @return object A new annotation instance initialized with the passed arguments |
374
|
|
|
* @see \AppserverIo\Lang\Reflection\ClassInterface::newInstanceArgs() |
375
|
|
|
*/ |
376
|
1 |
|
public function newInstanceArgs(array $args = array()) |
377
|
|
|
{ |
378
|
|
|
// create a reflection instance of the found annotation name |
379
|
1 |
|
$reflectionClass = $this->toPhpReflectionClass(); |
380
|
|
|
|
381
|
|
|
// create a new instance passing the found arguements to the constructor |
382
|
1 |
|
return $reflectionClass->newInstanceArgs($args); |
383
|
|
|
} |
384
|
|
|
|
385
|
|
|
/** |
386
|
|
|
* Serializes the timeout method and returns a string representation. |
387
|
|
|
* |
388
|
|
|
* @return string The serialized string representation of the instance |
389
|
|
|
* @see \Serializable::serialize() |
390
|
|
|
*/ |
391
|
1 |
|
public function serialize() |
392
|
|
|
{ |
393
|
1 |
|
return serialize(get_object_vars($this)); |
394
|
|
|
} |
395
|
|
|
|
396
|
|
|
/** |
397
|
|
|
* Restores the instance with the serialized data of the passed string. |
398
|
|
|
* |
399
|
|
|
* @param string $data The serialized method representation |
400
|
|
|
* |
401
|
|
|
* @return void |
402
|
|
|
* @see \Serializable::unserialize() |
403
|
|
|
*/ |
404
|
1 |
|
public function unserialize($data) |
405
|
|
|
{ |
406
|
1 |
|
foreach (unserialize($data) as $propertyName => $propertyValue) { |
407
|
1 |
|
$this->$propertyName = $propertyValue; |
408
|
|
|
} |
409
|
1 |
|
} |
410
|
|
|
|
411
|
|
|
/** |
412
|
|
|
* Checks whether it implements the passed interface or not. |
413
|
|
|
* |
414
|
|
|
* @param string $interface The interface name |
415
|
|
|
* |
416
|
|
|
* @return boolean Returns TRUE on success or FALSE on failure |
417
|
|
|
* @see \AppserverIo\Lang\Reflection\ClassInterface::implementsInterface() |
418
|
|
|
*/ |
419
|
1 |
|
public function implementsInterface($interface) |
420
|
|
|
{ |
421
|
1 |
|
return $this->toPhpReflectionClass()->implementsInterface($interface); |
422
|
|
|
} |
423
|
|
|
|
424
|
|
|
/** |
425
|
|
|
* Checks whether the class is an interface. |
426
|
|
|
* |
427
|
|
|
* @return boolean Returns TRUE on success or FALSE on failure |
428
|
|
|
* @see \AppserverIo\Lang\Reflection\ClassInterface::isInterface() |
429
|
|
|
*/ |
430
|
1 |
|
public function isInterface() |
431
|
|
|
{ |
432
|
1 |
|
return $this->toPhpReflectionClass()->isInterface(); |
433
|
|
|
} |
434
|
|
|
|
435
|
|
|
/** |
436
|
|
|
* Checks if the class is abstract. |
437
|
|
|
* |
438
|
|
|
* @return boolean Rturns TRUE on success or FALSE on failure |
439
|
|
|
* @see \AppserverIo\Lang\Reflection\ClassInterface::isAbstract() |
440
|
|
|
*/ |
441
|
1 |
|
public function isAbstract() |
442
|
|
|
{ |
443
|
1 |
|
return $this->toPhpReflectionClass()->isInterface(); |
444
|
|
|
} |
445
|
|
|
|
446
|
|
|
/** |
447
|
|
|
* Returns a PHP reflection class representation of this instance. |
448
|
|
|
* |
449
|
|
|
* @return \ReflectionClass The PHP reflection class instance |
450
|
|
|
* @see \AppserverIo\Lang\Reflection\ClassInterface::toPhpReflectionClass() |
451
|
|
|
*/ |
452
|
21 |
|
public function toPhpReflectionClass() |
453
|
|
|
{ |
454
|
21 |
|
return new \ReflectionClass($this->getPassedName()); |
455
|
|
|
} |
456
|
|
|
|
457
|
|
|
/** |
458
|
|
|
* Creates a new reflection class instance from the passed PHP reflection class. |
459
|
|
|
* |
460
|
|
|
* @param \ReflectionClass $reflectionClass The PHP reflection class to load the data from |
461
|
|
|
* @param array $annotationsToIgnore An array with annotations names we want to ignore when loaded |
462
|
|
|
* @param array $annotationAliases An array with annotation aliases used when create annotation instances |
463
|
|
|
* |
464
|
|
|
* @return \AppserverIo\Lang\Reflection\ReflectionClass The instance |
465
|
|
|
*/ |
466
|
1 |
|
public static function fromPhpReflectionClass(\ReflectionClass $reflectionClass, array $annotationsToIgnore = array(), array $annotationAliases = array()) |
467
|
|
|
{ |
468
|
1 |
|
return new ReflectionClass($reflectionClass->getName(), $annotationsToIgnore, $annotationAliases); |
469
|
|
|
} |
470
|
|
|
} |
471
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.