forked from rectorphp/rector-src
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPrivatesAccessor.php
More file actions
80 lines (63 loc) · 2.46 KB
/
PrivatesAccessor.php
File metadata and controls
80 lines (63 loc) · 2.46 KB
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
<?php
declare(strict_types=1);
namespace Rector\Util\Reflection;
use Rector\Exception\Reflection\MissingPrivatePropertyException;
use ReflectionClass;
use ReflectionMethod;
use ReflectionProperty;
/**
* @see \Rector\Tests\Util\Reflection\PrivatesAccessorTest
*/
final class PrivatesAccessor
{
/**
* @param callable(mixed $value): mixed $closure
*/
public function propertyClosure(object $object, string $propertyName, callable $closure): void
{
$property = $this->getPrivateProperty($object, $propertyName);
// modify value
$property = $closure($property);
$this->setPrivateProperty($object, $propertyName, $property);
}
/**
* @param object|class-string $object
* @param mixed[] $arguments
* @api
*/
public function callPrivateMethod(object|string $object, string $methodName, array $arguments): mixed
{
if (is_string($object)) {
$reflectionClass = new ReflectionClass($object);
$object = $reflectionClass->newInstanceWithoutConstructor();
}
$reflectionMethod = $this->createAccessibleMethodReflection($object, $methodName);
return $reflectionMethod->invokeArgs($object, $arguments);
}
public function getPrivateProperty(object $object, string $propertyName): mixed
{
$reflectionProperty = $this->resolvePropertyReflection($object, $propertyName);
return $reflectionProperty->getValue($object);
}
public function setPrivateProperty(object $object, string $propertyName, mixed $value): void
{
$reflectionProperty = $this->resolvePropertyReflection($object, $propertyName);
$reflectionProperty->setValue($object, $value);
}
private function createAccessibleMethodReflection(object $object, string $methodName): ReflectionMethod
{
return new ReflectionMethod($object, $methodName);
}
private function resolvePropertyReflection(object $object, string $propertyName): ReflectionProperty
{
if (property_exists($object, $propertyName)) {
return new ReflectionProperty($object, $propertyName);
}
$parentClass = get_parent_class($object);
if ($parentClass !== false) {
return new ReflectionProperty($parentClass, $propertyName);
}
$errorMessage = sprintf('Property "$%s" was not found in "%s" class', $propertyName, $object::class);
throw new MissingPrivatePropertyException($errorMessage);
}
}