-
Notifications
You must be signed in to change notification settings - Fork 1
/
ReflectionTrait.php
104 lines (84 loc) · 3.02 KB
/
ReflectionTrait.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
<?php
declare(strict_types=1);
namespace YourNamespace\App\Tests\Traits;
/**
* Trait ReflectionTrait.
*
* Provides methods to work with class reflection.
*
* @phpstan-ignore trait.unused
*/
trait ReflectionTrait {
/**
* Call protected methods on the class.
*
* @param object|string $object
* Object or class name to use for a method call.
* @param string $name
* Method name. Method can be static.
* @param array $args
* Array of arguments to pass to the method. To pass arguments by reference,
* pass them by reference as an element of this array.
*
* @return mixed
* Method result.
*/
protected static function callProtectedMethod(object|string $object, string $name, array $args = []) {
$object_or_class = is_object($object) ? $object::class : $object;
if (!class_exists($object_or_class)) {
throw new \InvalidArgumentException(sprintf('Class %s does not exist', $object_or_class));
}
$class = new \ReflectionClass($object_or_class);
if (!$class->hasMethod($name)) {
throw new \InvalidArgumentException(sprintf('Method %s does not exist', $name));
}
$method = $class->getMethod($name);
$original_accessibility = $method->isPublic();
// Set method accessibility to true, so it can be invoked.
$method->setAccessible(TRUE);
// If the method is static, we won't pass an object instance to invokeArgs()
// Otherwise, we ensure to pass the object instance.
$invoke_object = $method->isStatic() ? NULL : (is_object($object) ? $object : NULL);
// Ensure we have an object for non-static methods.
if (!$method->isStatic() && $invoke_object === NULL) {
throw new \InvalidArgumentException("An object instance is required for non-static methods");
}
$result = $method->invokeArgs($invoke_object, $args);
// Reset the method's accessibility to its original state.
$method->setAccessible($original_accessibility);
return $result;
}
/**
* Set protected property value.
*
* @param object $object
* Object to set the value on.
* @param string $property
* Property name to set the value. Property should exists in the object.
* @param mixed $value
* Value to set to the property.
*/
protected static function setProtectedValue($object, $property, mixed $value): void {
$class = new \ReflectionClass($object::class);
$property = $class->getProperty($property);
$property->setAccessible(TRUE);
$property->setValue($object, $value);
}
/**
* Get protected value from the object.
*
* @param object $object
* Object to set the value on.
* @param string $property
* Property name to get the value. Property should exists in the object.
*
* @return mixed
* Protected property value.
*/
protected static function getProtectedValue($object, $property): mixed {
$class = new \ReflectionClass($object::class);
$property = $class->getProperty($property);
$property->setAccessible(TRUE);
return $property->getValue($class);
}
}