diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a1d933..03ea7d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,9 +6,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Fixed + +- Inject logger to callable instances. + ## [4.1.1] - 2025-03-21 -## Fixed +### Fixed - Inject NullLogger to LoggerAwareInterface services, when logger is not set in container ## [4.1.0] - 2025-03-15 diff --git a/src/Injector.php b/src/Injector.php index 250a5ce..99c89a2 100644 --- a/src/Injector.php +++ b/src/Injector.php @@ -85,16 +85,7 @@ public function createInstance($class): object $instance = new $class(...$constructorParams); if ($this->isLoggerInjectionRequired($instance)) { - if(array_key_exists($class, $this->loggersMap)) { - $logger = $this->loggersMap[$class]; - if(!$logger instanceof LoggerInterface && is_callable($logger)) { - $logger = $logger($this); - } - } else { - $logger = $this->has(LoggerInterface::class) ? $this->getService(LoggerInterface::class) : new NullLogger(); - } - - $instance->setLogger($logger); + $this->handleLoggerInjection($class, $instance); } return $instance; @@ -130,6 +121,14 @@ public function getService(string $type): object } elseif ($service instanceof CallableBeanContainer) { $this->loggerHelper->logLazyLoading($type, $service); $service = $service(); + + if ($this->isLoggerInjectionRequired($service)) { + $class = get_class($service); + $this->handleLoggerInjection($class, $service); + } + + + $this->setService($type, $service); } @@ -229,5 +228,19 @@ private function isLoggerInjectionRequired(object $instance): bool { return $instance instanceof LoggerAwareInterface && $this->enableLoggerAwareInjection; } + + private function handleLoggerInjection(string $class, $service): void + { + if (array_key_exists($class, $this->loggersMap)) { + $logger = $this->loggersMap[$class]; + if (!$logger instanceof LoggerInterface && is_callable($logger)) { + $logger = $logger($this); + } + } else { + $logger = $this->has(LoggerInterface::class) ? $this->getService(LoggerInterface::class) : new NullLogger(); + } + + $service->setLogger($logger); + } } diff --git a/tests/Fixture/LoggerExtendedSomeImpl.php b/tests/Fixture/LoggerExtendedSomeImpl.php new file mode 100644 index 0000000..8ed3bd7 --- /dev/null +++ b/tests/Fixture/LoggerExtendedSomeImpl.php @@ -0,0 +1,18 @@ +logger; + } +} diff --git a/tests/Fixture/SomeInterface.php b/tests/Fixture/SomeInterface.php new file mode 100644 index 0000000..750bf59 --- /dev/null +++ b/tests/Fixture/SomeInterface.php @@ -0,0 +1,9 @@ + function () use ($bar2) { return $bar2; }, + SomeInterface::class => fn() => new LoggerExtendedSomeImpl(), ], 'loggers' => [ LoggerAwareClass::class => new NullLogger(), AnotherLoggerAwareClass::class => new NullLogger(), + LoggerExtendedSomeImpl::class => $someImplLogger = new NullLogger(), ], ]); + $injector->enableLoggerAwareInjection(); + $this->assertSame($bar2, $injector->getService(Bar::class)); $this->assertInstanceOf(Foo::class, $injector->createInstance(Foo::class)); $this->assertSame($anotherServiceInstance, $injector->getService(AnotherService::class)); $this->assertSame(9000, $injector->get(ClassWithDefaultConstructorArgValue::class)->getValue()); - $this->assertCount(2, $injector->getLoggersMap()); + $this->assertSame($someImplLogger, $injector->getService(SomeInterface::class)->getLogger()); + + $this->assertCount(3, $injector->getLoggersMap()); } } diff --git a/tests/InjectorTest.php b/tests/InjectorTest.php index 431fffe..26b359c 100644 --- a/tests/InjectorTest.php +++ b/tests/InjectorTest.php @@ -13,6 +13,8 @@ use Fixture\DefaultAnotherServiceImpl; use Fixture\Foo; use Fixture\LoggerAwareClass; +use Fixture\LoggerExtendedSomeImpl; +use Fixture\SomeInterface; use Fixture\SomeService; use Fixture\SomeServiceInterface; use FreeElephants\DI\Exception\InvalidArgumentException; @@ -261,6 +263,23 @@ public function testLoggerMap() $this->assertSame($anotherLogger, $anotherLoggerAwareInstance->getLogger()); } + public function testLoggerMapPolymorohic(): void + { + $logger = new NullLogger(); + + $injector = new Injector(); + $injector->allowInstantiateNotRegisteredTypes(true); + $injector->enableLoggerAwareInjection(); + $injector->registerService(LoggerExtendedSomeImpl::class, SomeInterface::class); + $injector->setLoggersMap([ + LoggerExtendedSomeImpl::class => $logger, + ]); + + $loggerAwareImple = $injector->get(SomeInterface::class); + + $this->assertSame($logger, $loggerAwareImple->getLogger()); + } + public function testHandleInstantiateInterfaceError() { $injector = new Injector();