1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
namespace Spiral\Core\Internal; |
6
|
|
|
|
7
|
|
|
use Spiral\Core\Internal\Proxy\ProxyClassRenderer; |
8
|
|
|
|
9
|
|
|
/** |
10
|
|
|
* @internal |
11
|
|
|
*/ |
12
|
|
|
final class Proxy |
13
|
|
|
{ |
14
|
|
|
/** @var array<class-string, object> */ |
|
|
|
|
15
|
|
|
private static array $cache = []; |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* @template TClass of object |
19
|
|
|
* @param \ReflectionClass<TClass> $type |
20
|
|
|
* @return TClass |
|
|
|
|
21
|
|
|
*/ |
22
|
15 |
|
public static function create( |
23
|
|
|
\ReflectionClass $type, |
24
|
|
|
\Stringable|string|null $context, |
25
|
|
|
\Spiral\Core\Attribute\Proxy $attribute, |
26
|
|
|
): object { |
27
|
15 |
|
$interface = $type->getName(); |
28
|
|
|
|
29
|
15 |
|
if (!\array_key_exists($interface, self::$cache)) { |
30
|
|
|
/** @var class-string<TClass> $className */ |
31
|
4 |
|
$className = "{$type->getNamespaceName()}\\{$type->getShortName()} SCOPED PROXY"; |
32
|
|
|
|
33
|
|
|
try { |
34
|
4 |
|
$classString = ProxyClassRenderer::renderClass($type, $className, $attribute->magicCall ? [ |
35
|
4 |
|
Proxy\MagicCallTrait::class, |
36
|
4 |
|
] : []); |
37
|
|
|
|
38
|
4 |
|
eval($classString); |
|
|
|
|
39
|
|
|
} catch (\Throwable $e) { |
40
|
|
|
throw new \Error("Unable to create proxy for `{$interface}`: {$e->getMessage()}", 0, $e); |
41
|
|
|
} |
42
|
|
|
|
43
|
4 |
|
$instance = new $className(); |
44
|
4 |
|
(static fn() => $instance::$__container_proxy_alias = $interface)->bindTo(null, $instance::class)(); |
45
|
|
|
|
46
|
|
|
// Store in cache without context |
47
|
4 |
|
self::$cache[$interface] = $instance; |
48
|
|
|
} else { |
49
|
|
|
/** @var TClass $instance */ |
50
|
11 |
|
$instance = self::$cache[$interface]; |
51
|
|
|
} |
52
|
|
|
|
53
|
15 |
|
if ($context !== null) { |
54
|
15 |
|
$instance = clone $instance; |
55
|
15 |
|
(static fn() => $instance->__container_proxy_context = $context)->bindTo(null, $instance::class)(); |
56
|
|
|
} |
57
|
|
|
|
58
|
15 |
|
return $instance; |
59
|
|
|
} |
60
|
|
|
} |
61
|
|
|
|