Skip to content

Commit 9ad766d

Browse files
committed
Service decorator implementation
1 parent 2a9453c commit 9ad766d

11 files changed

+124
-15
lines changed

.gitignore

100644100755
File mode changed.

LICENSE.md

100644100755
File mode changed.

README.md

100644100755
File mode changed.

composer.json

100644100755
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@
1717
],
1818
"require": {
1919
"php": ">=8.0",
20-
"psr/container": "^2.0"
20+
"psr/container": "^2.0",
21+
"micro/component-autowire": "*"
2122
},
2223
"require-dev": {
23-
"phpunit/phpunit": "^9"
24+
"phpmd/phpmd" : "@stable",
25+
"phpunit/phpunit": "^9",
26+
"squizlabs/php_codesniffer": "^3.6"
2427
}
2528
}

phpunit.xml

100644100755
File mode changed.

src/Container.php

100644100755
Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,39 @@
33
namespace Micro\Component\DependencyInjection;
44

55

6+
use Micro\Component\DependencyInjection\Autowire\AutowireHelperFactory;
7+
use Micro\Component\DependencyInjection\Autowire\AutowireHelperFactoryInterface;
68
use Micro\Component\DependencyInjection\Exception\ServiceNotRegisteredException;
79
use Micro\Component\DependencyInjection\Exception\ServiceRegistrationException;
8-
use Psr\Container\ContainerInterface;
910
use \Closure;
11+
use Psr\Container\ContainerInterface;
1012

11-
class Container implements ContainerInterface, ContainerRegistryInterface
13+
class Container implements ContainerInterface, ContainerRegistryInterface, ContainerDecoratorInterface
1214
{
1315
/**
1416
* @var array<string, object>
1517
*/
1618
private array $services;
1719

1820
/**
19-
* @var array<string, Closure>
21+
* @var array<string, Closure|string>
2022
*/
2123
private array $servicesRaw;
2224

25+
/**
26+
* @var array<string, array<Closure, int>>
27+
*/
28+
private array $decorators = [];
29+
30+
/**
31+
* @var AutowireHelperFactoryInterface
32+
*/
33+
private AutowireHelperFactoryInterface $autowireHelperFactory;
2334

24-
public function __construct()
35+
public function __construct(
36+
)
2537
{
38+
$this->autowireHelperFactory = new AutowireHelperFactory($this);
2639
$this->services = [];
2740
$this->servicesRaw = [];
2841
}
@@ -46,13 +59,30 @@ public function has(string $id): bool
4659
/**
4760
* {@inheritDoc}
4861
*/
49-
public function register(string $id, \Closure $service): void
62+
public function register(string $id, Closure $service): void
5063
{
64+
if($this->has($id)) {
65+
throw new ServiceRegistrationException(sprintf('Service "%s" already registered', $id));
66+
}
67+
5168
$this->servicesRaw[$id] = $service;
5269
}
5370

71+
/**
72+
* {@inheritDoc}
73+
*/
74+
public function decorate(string $id, Closure $service, int $priority = 0): void
75+
{
76+
if(!array_key_exists($id, $this->decorators)) {
77+
$this->decorators[$id] = [];
78+
}
79+
80+
$this->decorators[$id][] = [$service, $priority];
81+
}
82+
5483
/**
5584
* @param string $id
85+
*
5686
* @return object
5787
*/
5888
private function lookup(string $id): object
@@ -61,23 +91,41 @@ private function lookup(string $id): object
6191
return $this->services[$id];
6292
}
6393

64-
return $this->createServiceInstance($id);
94+
$this->initializeService($id);
95+
96+
return $this->services[$id];
6597
}
6698

6799
/**
68-
* @param string $id
100+
* @param string $serviceId
69101
* @return object
70102
*/
71-
private function createServiceInstance(string $id): object
103+
protected function initializeService(string $serviceId): void
72104
{
73-
if(empty($this->servicesRaw[$id])) {
74-
throw new ServiceNotRegisteredException($id);
105+
if(empty($this->servicesRaw[$serviceId])) {
106+
throw new ServiceNotRegisteredException($serviceId);
75107
}
76108

77-
$raw = $this->servicesRaw[$id];
109+
$raw = $this->servicesRaw[$serviceId];
110+
78111
$service = $raw($this);
79-
$this->services[$id] = $service;
80112

81-
return $service;
113+
$this->services[$serviceId] = $service;
114+
115+
if(!array_key_exists($serviceId, $this->decorators)) {
116+
return;
117+
}
118+
119+
$decorators = $this->decorators[$serviceId];
120+
121+
usort($decorators, function(array $left, array $right): bool {
122+
return $left[1] > $right[1];
123+
});
124+
125+
$helper = $this->autowireHelperFactory->create();
126+
127+
foreach ($decorators as $decorator) {
128+
$this->services[$serviceId] = $helper->autowire($decorator[0])();
129+
}
82130
}
83131
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace Micro\Component\DependencyInjection;
4+
5+
interface ContainerDecoratorInterface
6+
{
7+
/**
8+
* @param string $id
9+
* @param \Closure $service
10+
* @param int $priority
11+
*
12+
* @return void
13+
*/
14+
public function decorate(string $id, \Closure $service, int $priority = 0): void;
15+
}

src/ContainerRegistryInterface.php

100644100755
File mode changed.

src/Exception/ServiceNotRegisteredException.php

100644100755
File mode changed.

src/Exception/ServiceRegistrationException.php

100644100755
File mode changed.

0 commit comments

Comments
 (0)