ReflectionApi::writeProperty()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 9
cts 9
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 7
nc 2
nop 3
crap 2
1
<?php declare(strict_types=1);
2
3
namespace Igni\Utils;
4
5
use Closure;
6
use Igni\Utils\Exception\ReflectionApiException;
7
use Igni\Utils\ReflectionApi\RuntimeClass;
8
use ReflectionClass;
9
use ReflectionFunction;
10
use ReflectionMethod;
11
use Throwable;
12
13
final class ReflectionApi
14
{
15
    /**
16
     * @var ReflectionClass[]
17
     */
18
    private static $reflections = [];
19
20
    /**
21
     * @var object[]
22
     */
23
    private static $instances = [];
24
25
    /**
26
     * Creates instance of the given class.
27
     *
28
     * @param string $class
29
     * @return object
30
     */
31 4
    public static function createInstance(string $class)
32
    {
33 4
        if (!isset(self::$instances[$class])) {
34 4
            if (!class_exists($class)) {
35 1
                throw ReflectionApiException::forNonExistentClass($class);
36
            }
37
            try {
38 3
                self::$instances[$class] = unserialize(sprintf('O:%d:"%s":0:{}', strlen($class), $class));
39 1
            } catch (Throwable $exception) {
40 1
                throw ReflectionApiException::forInstantiationFailure($class, $exception->getMessage());
41
            }
42
        }
43
44 2
        return clone self::$instances[$class];
45
    }
46
47 2
    public static function createClass(string $class): RuntimeClass
48
    {
49 2
        return new RuntimeClass($class);
50
    }
51
52 3
    public static function getClosureBody(Closure $closure): string
53
    {
54 3
        $reflection = self::reflectFunction($closure);
55 3
        $lines = file($reflection->getFileName());
56 3
        $body = '';
57 3
        for($l = $reflection->getStartLine() - 1; $l < $reflection->getEndLine(); $l++) {
58 3
            $body .= $lines[$l];
59
        }
60
61 3
        preg_match('#function\([^{].*?\{(.*)\}#is', $body, $matches);
62
63 3
        return trim($matches[1]);
64
    }
65
66
    /**
67
     * Overrides object's property value.
68
     *
69
     * @param $instance
70
     * @param string $property property name
71
     * @param $value
72
     */
73 2
    public static function writeProperty($instance, string $property, $value): void
74
    {
75 2
        static $writer;
76 2
        if ($writer === null) {
77 2
            $writer = function ($name, $value) {
78 2
                $this->$name = $value;
79 2
            };
80
        }
81
82 2
        $set = Closure::bind($writer, $instance, $instance);
83 2
        $set($property, $value);
84 2
    }
85
86
    /**
87
     * @param $instance
88
     * @param string $property
89
     * @return mixed
90
     */
91 2
    public static function readProperty($instance, string $property)
92
    {
93 2
        static $reader;
94 2
        if ($reader === null) {
95 2
            $reader = function ($name) {
96 2
                return $this->$name ?? null;
97 1
            };
98
        }
99
100 2
        $read = Closure::bind($reader, $instance, $instance);
101
102 2
        return $read($property);
103
    }
104
105
    /**
106
     * Creates and caches in memory reflection of the given class.
107
     *
108
     * @param string $className
109
     * @return ReflectionClass
110
     * @throws \ReflectionException
111
     */
112 1
    public static function reflectClass(string $className): ReflectionClass
113
    {
114 1
        if (isset(self::$reflections[$className])) {
115 1
            return self::$reflections[$className];
116
        }
117
118 1
        return self::$reflections[$className] = new ReflectionClass($className);
119
    }
120
121
    /**
122
     * Creates and caches in memory reflection of the given function.
123
     *
124
     * @param $function
125
     * @return ReflectionFunction
126
     * @throws \ReflectionException
127
     */
128 3
    public static function reflectFunction($function): ReflectionFunction
129
    {
130 3
        if (!is_string($function)) {
131 3
            return new ReflectionFunction($function);
132
        }
133
134
        if (isset(self::$reflections[$function])) {
135
            return self::$reflections[$function];
136
        }
137
138
        return self::$reflections[$function] = new ReflectionFunction($function);
139
    }
140
141
    /**
142
     * Creates and caches in memory reflection of the given method.
143
     *
144
     * @param string $class
145
     * @param string $method
146
     * @return ReflectionMethod
147
     * @throws \ReflectionException
148
     */
149
    public static function reflectMethod(string $class, string $method): ReflectionMethod
150
    {
151
        $class = self::reflectClass($class);
152
153
        return $class->getMethod($method);
154
    }
155
}
156