diff --git a/src/ServiceMap.php b/src/ServiceMap.php index 00f3c3f..1c90359 100644 --- a/src/ServiceMap.php +++ b/src/ServiceMap.php @@ -14,7 +14,7 @@ final class ServiceMap private $services = []; /** - * @var string[][] + * @var (string[]|object)[] */ private $components = []; @@ -43,6 +43,15 @@ public function __construct(string $configPath) } foreach ($config['components'] ?? [] as $id => $component) { + if (is_object($component)) { + $this->components[$id] = $component; + continue; + } + + if (!is_array($component)) { + 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; } @@ -64,6 +73,11 @@ public function getServiceClassFromNode(Node $node): ?string public function getComponentClassById(string $id): ?string { + // Special case in which the component is already initialized + if (is_object($this->components[$id])) { + return get_class($this->components[$id]); + } + return $this->components[$id]['class'] ?? null; } diff --git a/tests/ServiceMapTest.php b/tests/ServiceMapTest.php index d81bdfb..a497752 100644 --- a/tests/ServiceMapTest.php +++ b/tests/ServiceMapTest.php @@ -27,6 +27,14 @@ public function testThrowExceptionWhenClosureServiceHasMissingReturnType(): void new ServiceMap(__DIR__.DIRECTORY_SEPARATOR.'assets'.DIRECTORY_SEPARATOR.'yii-config-invalid.php'); } + public function testThrowExceptionWhenComponentHasInvalidValue(): void + { + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Invalid value for component with id customComponent. Expected object or array.'); + + new ServiceMap(__DIR__.DIRECTORY_SEPARATOR.'assets'.DIRECTORY_SEPARATOR.'yii-config-invalid-component.php'); + } + public function testItLoadsServicesAndComponents(): void { $serviceMap = new ServiceMap(__DIR__.DIRECTORY_SEPARATOR.'assets'.DIRECTORY_SEPARATOR.'yii-config-valid.php'); @@ -36,6 +44,7 @@ public function testItLoadsServicesAndComponents(): void $this->assertSame(\SplFileInfo::class, $serviceMap->getServiceClassFromNode(new String_('nested-service-class'))); $this->assertSame(MyActiveRecord::class, $serviceMap->getComponentClassById('customComponent')); + $this->assertSame(MyActiveRecord::class, $serviceMap->getComponentClassById('customInitializedComponent')); } /** diff --git a/tests/assets/yii-config-invalid-component.php b/tests/assets/yii-config-invalid-component.php new file mode 100644 index 0000000..2671607 --- /dev/null +++ b/tests/assets/yii-config-invalid-component.php @@ -0,0 +1,7 @@ + [ + 'customComponent' => 5, + ], +]; diff --git a/tests/assets/yii-config-valid.php b/tests/assets/yii-config-valid.php index 39e05e6..36896bb 100644 --- a/tests/assets/yii-config-valid.php +++ b/tests/assets/yii-config-valid.php @@ -7,6 +7,7 @@ 'customComponent' => [ 'class' => MyActiveRecord::class, ], + 'customInitializedComponent' => new MyActiveRecord(), ], 'container' => [ 'singletons' => [