diff --git a/.gitignore b/.gitignore index 3d7e132..a8fea06 100755 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ vendor/ composer.lock .phpunit.result.cache +test-coverage-report/ diff --git a/src/Container.php b/src/Container.php index 6133f6c..9d0ecb4 100755 --- a/src/Container.php +++ b/src/Container.php @@ -60,11 +60,7 @@ public function register(string $id, \Closure $service): void */ public function decorate(string $id, \Closure $service, int $priority = 0): void { - if(!array_key_exists($id, $this->decorators)) { - $this->decorators[$id] = []; - } - - $this->decorators[$id][$priority] = $service; + $this->decorators[$id][$priority][] = $service; } /** @@ -100,12 +96,15 @@ protected function initializeService(string $serviceId): void return; } - $decorators = $this->decorators[$serviceId]; + $decoratorsByPriority = $this->decorators[$serviceId]; + krsort($decoratorsByPriority); - ksort($decorators); - - foreach ($decorators as $decorator) { - $this->services[$serviceId] = $decorator($this->services[$serviceId], $this); + foreach ($decoratorsByPriority as $decorators) { + foreach ($decorators as $decorator) { + $this->services[$serviceId] = $decorator($this->services[$serviceId], $this); + } } + + unset($this->decorators[$serviceId]); } } diff --git a/tests/unit/ContainerTest.php b/tests/unit/ContainerTest.php index dacca27..a1752d1 100755 --- a/tests/unit/ContainerTest.php +++ b/tests/unit/ContainerTest.php @@ -52,19 +52,19 @@ public function testDecorateService(): void $container = new Container(); $container->register('test', function () { - return new NamedService('D'); + return new NamedService('A'); }); $container->decorate('test', function (NamedInterface $decorated) { - return new NamedServiceDecorator($decorated, 'C'); + return new NamedServiceDecorator($decorated, 'D'); }); $container->decorate('test', function (NamedInterface $decorated) { - return new NamedServiceDecorator($decorated, 'A'); + return new NamedServiceDecorator($decorated, 'B'); }, 10); $container->decorate('test', function (NamedInterface $decorated) { - return new NamedServiceDecorator($decorated, 'B'); + return new NamedServiceDecorator($decorated, 'C'); }, 5); /** @var NamedInterface $result */ @@ -73,6 +73,37 @@ public function testDecorateService(): void $this->assertInstanceOf(NamedInterface::class, $result); $this->assertEquals('ABCD', $result->getName()); } + + public function testDecoratorsWithSamePriority(): void + { + $container = new Container(); + + $container->register('test', function () { + return new NamedService('A'); + }); + + $container->decorate('test', function (NamedInterface $decorated) { + return new NamedServiceDecorator($decorated, 'B'); + }, 10); + + $container->decorate('test', function (NamedInterface $decorated) { + return new NamedServiceDecorator($decorated, 'D'); + }); + + $container->decorate('test', function (NamedInterface $decorated) { + return new NamedServiceDecorator($decorated, 'E'); + }); + + $container->decorate('test', function (NamedInterface $decorated) { + return new NamedServiceDecorator($decorated, 'C'); + }, 10); + + /** @var NamedInterface $result */ + $result = $container->get('test'); + $this->assertInstanceOf(NamedServiceDecorator::class, $result); + $this->assertInstanceOf(NamedInterface::class, $result); + $this->assertEquals('ABCDE', $result->getName()); + } } interface NamedInterface @@ -102,6 +133,6 @@ public function __construct( public function getName(): string { - return $this->name.$this->decorated->getName(); + return $this->decorated->getName().$this->name; } }