From f56d9a43c88a9120ae1c2602ca60a3753acb8a8e Mon Sep 17 00:00:00 2001 From: Khartir Date: Mon, 13 Jul 2020 14:14:57 +0200 Subject: [PATCH] Add support for non-singleton services (definitions) (#30) * add support for non-singleton services * remove unused code * fix coding style Co-authored-by: Thomas Gnandt --- src/ServiceMap.php | 36 +++++++++++++++++-------------- tests/ServiceMapTest.php | 4 ++++ tests/assets/yii-config-valid.php | 9 ++++++++ 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/src/ServiceMap.php b/src/ServiceMap.php index 1cec311..9cd7ac3 100644 --- a/src/ServiceMap.php +++ b/src/ServiceMap.php @@ -30,16 +30,10 @@ public function __construct(string $configPath) $config = require $configPath; foreach ($config['container']['singletons'] ?? [] as $id => $service) { - if ($service instanceof \Closure || \is_string($service)) { - $returnType = (new \ReflectionFunction($service))->getReturnType(); - if (!$returnType instanceof \ReflectionNamedType) { - throw new \RuntimeException(sprintf('Please provide return type for %s service closure', $id)); - } - - $this->services[$id] = $returnType->getName(); - } else { - $this->services[$id] = $service['class'] ?? $service[0]['class']; - } + $this->addServiceDefinition($id, $service); + } + foreach ($config['container']['definitions'] ?? [] as $id => $service) { + $this->addServiceDefinition($id, $service); } foreach ($config['components'] ?? [] as $id => $component) { @@ -52,10 +46,6 @@ public function __construct(string $configPath) throw new \RuntimeException(sprintf('Invalid value for component with id %s. Expected object or array.', $id)); } - if (null !== $identityClass = $component['identityClass'] ?? null) { - $this->components[$id]['identityClass'] = $identityClass; - } - if (null !== $class = $component['class'] ?? null) { $this->components[$id]['class'] = $class; } @@ -81,8 +71,22 @@ public function getComponentClassById(string $id): ?string return $this->components[$id]['class'] ?? null; } - public function getComponentIdentityClassById(string $id): ?string + /** + * @param string|\Closure|array $service + * + * @throws \ReflectionException + */ + private function addServiceDefinition(string $id, $service): void { - return $this->components[$id]['identityClass'] ?? null; + if ($service instanceof \Closure || \is_string($service)) { + $returnType = (new \ReflectionFunction($service))->getReturnType(); + if (!$returnType instanceof \ReflectionNamedType) { + throw new \RuntimeException(sprintf('Please provide return type for %s service closure', $id)); + } + + $this->services[$id] = $returnType->getName(); + } else { + $this->services[$id] = $service['class'] ?? $service[0]['class']; + } } } diff --git a/tests/ServiceMapTest.php b/tests/ServiceMapTest.php index a497752..7d5bf4a 100644 --- a/tests/ServiceMapTest.php +++ b/tests/ServiceMapTest.php @@ -39,6 +39,10 @@ public function testItLoadsServicesAndComponents(): void { $serviceMap = new ServiceMap(__DIR__.DIRECTORY_SEPARATOR.'assets'.DIRECTORY_SEPARATOR.'yii-config-valid.php'); + $this->assertSame(\SplStack::class, $serviceMap->getServiceClassFromNode(new String_('singleton-closure'))); + $this->assertSame(\SplObjectStorage::class, $serviceMap->getServiceClassFromNode(new String_('singleton-service'))); + $this->assertSame(\SplFileInfo::class, $serviceMap->getServiceClassFromNode(new String_('singleton-nested-service-class'))); + $this->assertSame(\SplStack::class, $serviceMap->getServiceClassFromNode(new String_('closure'))); $this->assertSame(\SplObjectStorage::class, $serviceMap->getServiceClassFromNode(new String_('service'))); $this->assertSame(\SplFileInfo::class, $serviceMap->getServiceClassFromNode(new String_('nested-service-class'))); diff --git a/tests/assets/yii-config-valid.php b/tests/assets/yii-config-valid.php index 36896bb..2653b72 100644 --- a/tests/assets/yii-config-valid.php +++ b/tests/assets/yii-config-valid.php @@ -11,6 +11,15 @@ ], 'container' => [ 'singletons' => [ + 'singleton-closure' => function(): \SplStack { + return new \SplStack(); + }, + 'singleton-service' => ['class' => \SplObjectStorage::class], + 'singleton-nested-service-class' => [ + ['class' => \SplFileInfo::class] + ] + ], + 'definitions' => [ 'closure' => function(): \SplStack { return new \SplStack(); },