Skip to content

Commit a93a1b5

Browse files
committed
v2.0 Create proxy container
1 parent 7c5ceea commit a93a1b5

11 files changed

+436
-0
lines changed

src/ContainerCompiled.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Micro\Component\DependencyInjection;
6+
7+
use Micro\Component\DependencyInjection\Proxy\ProxyBuilderInterface;
8+
use Micro\Component\DependencyInjection\Proxy\ProxyClassNameGeneratorInterface;
9+
use Psr\Container\ContainerInterface;
10+
11+
final readonly class ContainerCompiled implements ContainerInterface, ContainerRegistryCompiledInterface
12+
{
13+
public function __construct(
14+
private ContainerInterface $decorated,
15+
private ProxyClassNameGeneratorInterface $classNameGenerator,
16+
private ProxyBuilderInterface $proxyBuilder
17+
)
18+
{
19+
}
20+
21+
public function get(string $id): mixed
22+
{
23+
$proxyClass = $this->classNameGenerator->createProxyClassName($id);
24+
if(!class_exists($proxyClass)) {
25+
return $this->decorated->get($id);
26+
}
27+
28+
return new $proxyClass($this);
29+
}
30+
31+
public function has(string $id): bool
32+
{
33+
return $this->decorated->has($id);
34+
}
35+
36+
public function register(string $id, callable $service, bool $force = false): void
37+
{
38+
if(interface_exists($id)) {
39+
$this->proxyBuilder->add($id);
40+
}
41+
42+
$this->decorated->register($id, $service, $force);
43+
}
44+
45+
public function compile(): void
46+
{
47+
$this->proxyBuilder->build();
48+
}
49+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Micro\Component\DependencyInjection;
6+
7+
interface ContainerRegistryCompiledInterface extends ContainerRegistryInterface
8+
{
9+
public function compile(): void;
10+
}

src/Proxy/ProxyBuilder.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
6+
namespace Micro\Component\DependencyInjection\Proxy;
7+
8+
final class ProxyBuilder implements ProxyBuilderInterface
9+
{
10+
/**
11+
* @var class-string[]
12+
*/
13+
private array $classCollection;
14+
15+
public function __construct(
16+
private readonly ProxyClassContentFactoryInterface $classContentFactory,
17+
private readonly ProxyFileManagerInterface $proxyFileManager,
18+
private readonly string $proxyClassesNamespace = 'Micro\ClassProxy'
19+
)
20+
{
21+
$this->classCollection = [];
22+
}
23+
24+
public function add(string $className): ProxyBuilderInterface
25+
{
26+
if(in_array($className, $this->classCollection)) {
27+
return $this;
28+
}
29+
30+
$this->classCollection[] = $className;
31+
32+
return $this;
33+
}
34+
35+
public function build(): void
36+
{
37+
$namespace = $this->proxyClassesNamespace ? 'namespace '. $this->proxyClassesNamespace. ';' : '';
38+
$proxyClassContent = "
39+
<?php
40+
41+
declare(strict_types=1);
42+
43+
{$namespace};
44+
45+
use Psr\Container\ContainerInterface;
46+
";
47+
foreach ($this->classCollection as $className) {
48+
$proxyClassContent .= "\n" . $this->classContentFactory->create($className);
49+
}
50+
51+
$this->proxyFileManager->writeProxiesFileContent($proxyClassContent);
52+
$this->proxyFileManager->requireProxiesFile();
53+
}
54+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
6+
namespace Micro\Component\DependencyInjection\Proxy;
7+
8+
interface ProxyBuilderInterface
9+
{
10+
/**
11+
* @param class-string $className
12+
*/
13+
public function add(string $className): self;
14+
15+
public function build(): void;
16+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Micro\Component\DependencyInjection\Proxy;
6+
7+
final readonly class ProxyBuilderProductionDecorator implements ProxyBuilderInterface
8+
{
9+
public function __construct(
10+
private ProxyBuilderInterface $proxyBuilder,
11+
private ProxyFileManagerInterface $proxyWriter
12+
)
13+
{
14+
}
15+
16+
public function add(string $className): ProxyBuilderInterface
17+
{
18+
if($this->proxyWriter->proxyBuildAlreadyExists()) {
19+
return $this;
20+
}
21+
22+
$this->proxyBuilder->add($className);
23+
24+
return $this;
25+
}
26+
27+
public function build(): void
28+
{
29+
if(!$this->proxyWriter->proxyBuildAlreadyExists()) {
30+
$this->proxyBuilder->build();
31+
}
32+
33+
$this->proxyWriter->requireProxiesFile();
34+
}
35+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
6+
namespace Micro\Component\DependencyInjection\Proxy;
7+
8+
interface ProxyClassContentFactoryInterface
9+
{
10+
/**
11+
* @param class-string $className
12+
*/
13+
public function create(string $className): string;
14+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Micro\Component\DependencyInjection\Proxy;
6+
7+
final readonly class ProxyClassNameGenerator implements ProxyClassNameGeneratorInterface
8+
{
9+
public function __construct(private string $proxyClassNamespace)
10+
{
11+
}
12+
13+
public function createProxyClassName(string $className): string
14+
{
15+
$shortName = $this->createShortProxyClassName($className);
16+
if(!$this->proxyClassNamespace) {
17+
return $shortName;
18+
}
19+
20+
return rtrim('\\', $this->proxyClassNamespace) . '\\' . $shortName;
21+
}
22+
23+
public function createShortProxyClassName(string $className): string
24+
{
25+
return str_replace('\\', '_', $className);
26+
}
27+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
6+
namespace Micro\Component\DependencyInjection\Proxy;
7+
8+
interface ProxyClassNameGeneratorInterface
9+
{
10+
public function createProxyClassName(string $className): string;
11+
12+
public function createShortProxyClassName(string $className): string;
13+
}

0 commit comments

Comments
 (0)