From 2d9660be974b63ae996726ebd390c0dc63298910 Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Thu, 25 Apr 2024 01:16:19 +0400 Subject: [PATCH 1/7] Add the ability to inject needed logger using LoggerChannel attribute; add test; update phpunit config --- src/Bridge/Monolog/phpunit.xml | 23 +++++++------- .../Monolog/src/Attribute/LoggerChannel.php | 23 ++++++++++++++ src/Bridge/Monolog/src/LogFactory.php | 23 ++++++++++++-- src/Bridge/Monolog/tests/FactoryTest.php | 30 +++++++++++++++++++ 4 files changed, 84 insertions(+), 15 deletions(-) create mode 100644 src/Bridge/Monolog/src/Attribute/LoggerChannel.php diff --git a/src/Bridge/Monolog/phpunit.xml b/src/Bridge/Monolog/phpunit.xml index fbd70dd46..7d3302032 100644 --- a/src/Bridge/Monolog/phpunit.xml +++ b/src/Bridge/Monolog/phpunit.xml @@ -1,28 +1,27 @@ - + stderr="true" + cacheDirectory=".phpunit.cache" + backupStaticProperties="false"> tests - - - src - - + + + src + + diff --git a/src/Bridge/Monolog/src/Attribute/LoggerChannel.php b/src/Bridge/Monolog/src/Attribute/LoggerChannel.php new file mode 100644 index 000000000..3a1700bc8 --- /dev/null +++ b/src/Bridge/Monolog/src/Attribute/LoggerChannel.php @@ -0,0 +1,23 @@ +extractChannelAttribute($context) : null; + // always return default logger as injection - return $this->getLogger(); + return $this->getLogger($channel); } public function reset(): void @@ -127,4 +133,15 @@ protected function getProcessors(string $channel): array return $processors; } + + /** + * @return non-empty-string|null + */ + private function extractChannelAttribute(\ReflectionParameter $parameter): ?string + { + /** @var ReflectionAttribute[] $attributes */ + $attributes = $parameter->getAttributes(LoggerChannel::class); + + return $attributes[0]?->newInstance()->name; + } } diff --git a/src/Bridge/Monolog/tests/FactoryTest.php b/src/Bridge/Monolog/tests/FactoryTest.php index 086c4c93e..b0e907178 100644 --- a/src/Bridge/Monolog/tests/FactoryTest.php +++ b/src/Bridge/Monolog/tests/FactoryTest.php @@ -19,6 +19,7 @@ use Spiral\Core\Container; use Spiral\Logger\ListenerRegistry; use Spiral\Logger\LogsInterface; +use Spiral\Monolog\Attribute\LoggerChannel; use Spiral\Monolog\Bootloader\MonologBootloader; use Spiral\Monolog\Config\MonologConfig; use Spiral\Monolog\LogFactory; @@ -77,6 +78,35 @@ public function load(string $section): array $this->assertSame($logger, $this->container->get(LoggerInterface::class)); } + public function testInjectionWithAttribute(): void + { + $factory = new LogFactory(new MonologConfig([]), new ListenerRegistry(), new Container()); + + $this->container->bind(ConfiguratorInterface::class, new ConfigManager( + new class() implements LoaderInterface { + public function has(string $section): bool + { + return false; + } + + public function load(string $section): array + { + return []; + } + } + )); + + $this->container->bind(FinalizerInterface::class, $finalizer = \Mockery::mock(FinalizerInterface::class)); + $finalizer->shouldReceive('addFinalizer')->once(); + + $this->container->get(StrategyBasedBootloadManager::class)->bootload([MonologBootloader::class]); + $this->container->bind(LogFactory::class, $factory); + + $this->container->invoke(function (#[LoggerChannel('foo')] LoggerInterface $logger) { + $this->assertSame('foo', $logger->getName()); + }); + } + public function testFinalizerShouldResetDefaultLogger() { $this->container->bind(ConfiguratorInterface::class, new ConfigManager( From 0a21106c729d7e776966f7c4aeaf303a6734cb94 Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Thu, 25 Apr 2024 02:10:41 +0400 Subject: [PATCH 2/7] Create LoggerInjector and move the logic there --- .../src/Bootloader/MonologBootloader.php | 3 +- src/Bridge/Monolog/src/LogFactory.php | 24 ++-------- src/Bridge/Monolog/tests/FactoryTest.php | 2 +- .../src/Attribute/LoggerChannel.php | 6 +-- src/Logger/src/LoggerInjector.php | 46 +++++++++++++++++++ 5 files changed, 55 insertions(+), 26 deletions(-) rename src/{Bridge/Monolog => Logger}/src/Attribute/LoggerChannel.php (51%) create mode 100644 src/Logger/src/LoggerInjector.php diff --git a/src/Bridge/Monolog/src/Bootloader/MonologBootloader.php b/src/Bridge/Monolog/src/Bootloader/MonologBootloader.php index e5b2b7ace..d0395dc76 100644 --- a/src/Bridge/Monolog/src/Bootloader/MonologBootloader.php +++ b/src/Bridge/Monolog/src/Bootloader/MonologBootloader.php @@ -18,6 +18,7 @@ use Spiral\Config\Patch\Append; use Spiral\Core\Attribute\Singleton; use Spiral\Core\Container; +use Spiral\Logger\LoggerInjector; use Spiral\Logger\LogsInterface; use Spiral\Monolog\Config\MonologConfig; use Spiral\Monolog\LogFactory; @@ -72,7 +73,7 @@ public function init(Container $container, FinalizerInterface $finalizer): void 'handlers' => [], ]); - $container->bindInjector(Logger::class, LogFactory::class); + $container->bindInjector(Logger::class, LoggerInjector::class); } public function addHandler(string $channel, HandlerInterface $handler): void diff --git a/src/Bridge/Monolog/src/LogFactory.php b/src/Bridge/Monolog/src/LogFactory.php index 6c832c4e1..0a1b4ec9e 100644 --- a/src/Bridge/Monolog/src/LogFactory.php +++ b/src/Bridge/Monolog/src/LogFactory.php @@ -10,13 +10,11 @@ use Monolog\ResettableInterface; use Psr\Container\ContainerExceptionInterface; use Psr\Log\LoggerInterface; -use ReflectionAttribute; use Spiral\Core\Container\Autowire; use Spiral\Core\Container\InjectorInterface; use Spiral\Core\FactoryInterface; use Spiral\Logger\ListenerRegistryInterface; use Spiral\Logger\LogsInterface; -use Spiral\Monolog\Attribute\LoggerChannel; use Spiral\Monolog\Config\MonologConfig; use Spiral\Monolog\Exception\ConfigException; @@ -60,14 +58,9 @@ public function getLogger(string $channel = null): LoggerInterface ); } - public function createInjection( - \ReflectionClass $class, - \ReflectionParameter|null|string $context = null - ): LoggerInterface { - $channel = \is_object($context) ? $this->extractChannelAttribute($context) : null; - - // always return default logger as injection - return $this->getLogger($channel); + public function createInjection(\ReflectionClass $class, ?string $context = null): LoggerInterface + { + return $this->getLogger(); } public function reset(): void @@ -133,15 +126,4 @@ protected function getProcessors(string $channel): array return $processors; } - - /** - * @return non-empty-string|null - */ - private function extractChannelAttribute(\ReflectionParameter $parameter): ?string - { - /** @var ReflectionAttribute[] $attributes */ - $attributes = $parameter->getAttributes(LoggerChannel::class); - - return $attributes[0]?->newInstance()->name; - } } diff --git a/src/Bridge/Monolog/tests/FactoryTest.php b/src/Bridge/Monolog/tests/FactoryTest.php index b0e907178..bab834c9a 100644 --- a/src/Bridge/Monolog/tests/FactoryTest.php +++ b/src/Bridge/Monolog/tests/FactoryTest.php @@ -17,9 +17,9 @@ use Spiral\Config\ConfiguratorInterface; use Spiral\Config\LoaderInterface; use Spiral\Core\Container; +use Spiral\Logger\Attribute\LoggerChannel; use Spiral\Logger\ListenerRegistry; use Spiral\Logger\LogsInterface; -use Spiral\Monolog\Attribute\LoggerChannel; use Spiral\Monolog\Bootloader\MonologBootloader; use Spiral\Monolog\Config\MonologConfig; use Spiral\Monolog\LogFactory; diff --git a/src/Bridge/Monolog/src/Attribute/LoggerChannel.php b/src/Logger/src/Attribute/LoggerChannel.php similarity index 51% rename from src/Bridge/Monolog/src/Attribute/LoggerChannel.php rename to src/Logger/src/Attribute/LoggerChannel.php index 3a1700bc8..9e6feffff 100644 --- a/src/Bridge/Monolog/src/Attribute/LoggerChannel.php +++ b/src/Logger/src/Attribute/LoggerChannel.php @@ -2,14 +2,14 @@ declare(strict_types=1); -namespace Spiral\Monolog\Attribute; +namespace Spiral\Logger\Attribute; use Psr\Log\LoggerInterface; /** - * Used to specify the channel name for the logger Monolog when it injected as {@see LoggerInterface} on auto-wiring. + * Used to specify the channel name for the logger when it injected as {@see LoggerInterface} on auto-wiring. * - * @see \Spiral\Monolog\LogFactory the injector that is required to support this attribute. + * Note: {@see \Spiral\Logger\LoggerInjector} should be registered in the container to support this attribute. */ #[\Attribute(\Attribute::TARGET_PARAMETER)] final class LoggerChannel diff --git a/src/Logger/src/LoggerInjector.php b/src/Logger/src/LoggerInjector.php new file mode 100644 index 000000000..0105f4b68 --- /dev/null +++ b/src/Logger/src/LoggerInjector.php @@ -0,0 +1,46 @@ + + */ +final class LoggerInjector implements InjectorInterface +{ + public function __construct( + #[Proxy] + private readonly LogsInterface $factory + ) { + } + + public function createInjection( + \ReflectionClass $class, + \ReflectionParameter|null|string $context = null, + ): LoggerInterface { + $channel = \is_object($context) ? $this->extractChannelAttribute($context) : null; + + // always return default logger as injection + return $this->factory->getLogger($channel); + } + + /** + * @return non-empty-string|null + */ + private function extractChannelAttribute(\ReflectionParameter $parameter): ?string + { + /** @var ReflectionAttribute[] $attributes */ + $attributes = $parameter->getAttributes(LoggerChannel::class); + + return $attributes[0]?->newInstance()->name; + } +} From 4b808510371153801086210dc6003a9e0e9a59a5 Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Thu, 25 Apr 2024 02:38:04 +0400 Subject: [PATCH 3/7] Change Monolog bindings --- src/Bridge/Monolog/src/Bootloader/MonologBootloader.php | 4 ++-- src/Bridge/Monolog/tests/FactoryTest.php | 1 + src/Bridge/Monolog/tests/LoggerTest.php | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Bridge/Monolog/src/Bootloader/MonologBootloader.php b/src/Bridge/Monolog/src/Bootloader/MonologBootloader.php index d0395dc76..857ea7b28 100644 --- a/src/Bridge/Monolog/src/Bootloader/MonologBootloader.php +++ b/src/Bridge/Monolog/src/Bootloader/MonologBootloader.php @@ -28,7 +28,7 @@ final class MonologBootloader extends Bootloader { protected const SINGLETONS = [ LogsInterface::class => LogFactory::class, - LoggerInterface::class => Logger::class, + Logger::class => Logger::class, ]; protected const BINDINGS = [ @@ -73,7 +73,7 @@ public function init(Container $container, FinalizerInterface $finalizer): void 'handlers' => [], ]); - $container->bindInjector(Logger::class, LoggerInjector::class); + $container->bindInjector(LoggerInterface::class, LoggerInjector::class); } public function addHandler(string $channel, HandlerInterface $handler): void diff --git a/src/Bridge/Monolog/tests/FactoryTest.php b/src/Bridge/Monolog/tests/FactoryTest.php index bab834c9a..30ade9901 100644 --- a/src/Bridge/Monolog/tests/FactoryTest.php +++ b/src/Bridge/Monolog/tests/FactoryTest.php @@ -75,6 +75,7 @@ public function load(string $section): array $this->container->bind(LogFactory::class, $factory); $this->assertSame($logger, $this->container->get(Logger::class)); + $this->assertInstanceOf(LoggerInterface::class, $this->container->get(LoggerInterface::class)); $this->assertSame($logger, $this->container->get(LoggerInterface::class)); } diff --git a/src/Bridge/Monolog/tests/LoggerTest.php b/src/Bridge/Monolog/tests/LoggerTest.php index 338204af2..5002f2dd7 100644 --- a/src/Bridge/Monolog/tests/LoggerTest.php +++ b/src/Bridge/Monolog/tests/LoggerTest.php @@ -39,12 +39,12 @@ public function load(string $section): array )); $this->container->bind(FinalizerInterface::class, $finalizer = new Finalizer()); - $this->container->bind(LogFactory::class, $injector = m::mock(Container\InjectorInterface::class)); + $this->container->bind(LogFactory::class, $factory = m::mock(Container\InjectorInterface::class)); $logger = m::mock(Logger::class); $logger->shouldReceive('reset')->once(); - $injector->shouldReceive('createInjection')->once()->andReturn($logger); + $factory->shouldReceive('getLogger')->twice()->andReturn($logger); $this->container->get(StrategyBasedBootloadManager::class)->bootload([MonologBootloader::class]); $this->container->get(LoggerInterface::class); From af0b0538f8f0c2dc42a21719698660d8f4257572 Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Thu, 25 Apr 2024 02:42:47 +0400 Subject: [PATCH 4/7] Fix psalm --- src/Logger/src/LoggerInjector.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Logger/src/LoggerInjector.php b/src/Logger/src/LoggerInjector.php index 0105f4b68..f615bb1a5 100644 --- a/src/Logger/src/LoggerInjector.php +++ b/src/Logger/src/LoggerInjector.php @@ -23,6 +23,9 @@ public function __construct( ) { } + /** + * @param \ReflectionParameter|string|null $context may use extended context if possible. + */ public function createInjection( \ReflectionClass $class, \ReflectionParameter|null|string $context = null, @@ -38,7 +41,7 @@ public function createInjection( */ private function extractChannelAttribute(\ReflectionParameter $parameter): ?string { - /** @var ReflectionAttribute[] $attributes */ + /** @var \ReflectionAttribute[] $attributes */ $attributes = $parameter->getAttributes(LoggerChannel::class); return $attributes[0]?->newInstance()->name; From c958af898a1f2fde80e53976fa03b8c97a733245 Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Thu, 25 Apr 2024 02:46:56 +0400 Subject: [PATCH 5/7] Add deprecation for `Spiral\Monolog\LogFactory::createInjection` --- src/Bridge/Monolog/src/LogFactory.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Bridge/Monolog/src/LogFactory.php b/src/Bridge/Monolog/src/LogFactory.php index 0a1b4ec9e..e3497161e 100644 --- a/src/Bridge/Monolog/src/LogFactory.php +++ b/src/Bridge/Monolog/src/LogFactory.php @@ -14,6 +14,7 @@ use Spiral\Core\Container\InjectorInterface; use Spiral\Core\FactoryInterface; use Spiral\Logger\ListenerRegistryInterface; +use Spiral\Logger\LoggerInjector; use Spiral\Logger\LogsInterface; use Spiral\Monolog\Config\MonologConfig; use Spiral\Monolog\Exception\ConfigException; @@ -58,6 +59,9 @@ public function getLogger(string $channel = null): LoggerInterface ); } + /** + * @deprecated use {@see LoggerInjector} as an injector instead. + */ public function createInjection(\ReflectionClass $class, ?string $context = null): LoggerInterface { return $this->getLogger(); From d99fd146e200297272218b7f3efb934bb227b792 Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Thu, 25 Apr 2024 12:02:42 +0400 Subject: [PATCH 6/7] Add LoggerBootloader with default LoggerInterface injector. --- .../src/Bootloader/MonologBootloader.php | 8 +- src/Bridge/Monolog/src/LogFactory.php | 2 +- .../src/Bootloader/LoggerBootloader.php | 30 +++++++ src/Logger/src/LoggerInjector.php | 12 ++- src/Logger/src/NullLogger.php | 2 +- src/Logger/tests/FactoryTest.php | 87 +++++++++++++++++++ 6 files changed, 132 insertions(+), 9 deletions(-) create mode 100644 src/Logger/src/Bootloader/LoggerBootloader.php diff --git a/src/Bridge/Monolog/src/Bootloader/MonologBootloader.php b/src/Bridge/Monolog/src/Bootloader/MonologBootloader.php index 857ea7b28..955505d68 100644 --- a/src/Bridge/Monolog/src/Bootloader/MonologBootloader.php +++ b/src/Bridge/Monolog/src/Bootloader/MonologBootloader.php @@ -18,7 +18,7 @@ use Spiral\Config\Patch\Append; use Spiral\Core\Attribute\Singleton; use Spiral\Core\Container; -use Spiral\Logger\LoggerInjector; +use Spiral\Logger\Bootloader\LoggerBootloader; use Spiral\Logger\LogsInterface; use Spiral\Monolog\Config\MonologConfig; use Spiral\Monolog\LogFactory; @@ -35,6 +35,10 @@ final class MonologBootloader extends Bootloader 'log.rotate' => [self::class, 'logRotate'], ]; + protected const DEPENDENCIES = [ + LoggerBootloader::class, + ]; + private const DEFAULT_FORMAT = "[%datetime%] %level_name%: %message% %context%\n"; public function __construct( @@ -72,8 +76,6 @@ public function init(Container $container, FinalizerInterface $finalizer): void 'globalLevel' => Logger::DEBUG, 'handlers' => [], ]); - - $container->bindInjector(LoggerInterface::class, LoggerInjector::class); } public function addHandler(string $channel, HandlerInterface $handler): void diff --git a/src/Bridge/Monolog/src/LogFactory.php b/src/Bridge/Monolog/src/LogFactory.php index e3497161e..c62399bdb 100644 --- a/src/Bridge/Monolog/src/LogFactory.php +++ b/src/Bridge/Monolog/src/LogFactory.php @@ -35,7 +35,7 @@ public function __construct( $this->eventHandler = new EventHandler($listenerRegistry, $config->getEventLevel()); } - public function getLogger(string $channel = null): LoggerInterface + public function getLogger(?string $channel = null): LoggerInterface { $default = $this->config->getDefault(); diff --git a/src/Logger/src/Bootloader/LoggerBootloader.php b/src/Logger/src/Bootloader/LoggerBootloader.php new file mode 100644 index 000000000..bae94d3e1 --- /dev/null +++ b/src/Logger/src/Bootloader/LoggerBootloader.php @@ -0,0 +1,30 @@ + LogFactory::class, + ]; + + public function init(Container $container): void + { + $container->bindInjector(LoggerInterface::class, LoggerInjector::class); + } +} diff --git a/src/Logger/src/LoggerInjector.php b/src/Logger/src/LoggerInjector.php index f615bb1a5..0ed289209 100644 --- a/src/Logger/src/LoggerInjector.php +++ b/src/Logger/src/LoggerInjector.php @@ -5,7 +5,6 @@ namespace Spiral\Logger; use Psr\Log\LoggerInterface; -use Spiral\Core\Attribute\Proxy; use Spiral\Core\Container\InjectorInterface; use Spiral\Logger\Attribute\LoggerChannel; @@ -17,9 +16,10 @@ */ final class LoggerInjector implements InjectorInterface { + public const DEFAULT_CHANNEL = 'default'; + public function __construct( - #[Proxy] - private readonly LogsInterface $factory + private readonly LogsInterface $factory, ) { } @@ -32,7 +32,11 @@ public function createInjection( ): LoggerInterface { $channel = \is_object($context) ? $this->extractChannelAttribute($context) : null; - // always return default logger as injection + // Check that null argument is available + $channel ??= (new \ReflectionMethod($this->factory, 'getLogger'))->getParameters()[0]->allowsNull() + ? null + : self::DEFAULT_CHANNEL; + return $this->factory->getLogger($channel); } diff --git a/src/Logger/src/NullLogger.php b/src/Logger/src/NullLogger.php index 02d34257c..c75f95f9f 100644 --- a/src/Logger/src/NullLogger.php +++ b/src/Logger/src/NullLogger.php @@ -18,7 +18,7 @@ final class NullLogger implements LoggerInterface public function __construct( callable $receptor, - private string $channel + private readonly string $channel ) { $this->receptor = $receptor(...); } diff --git a/src/Logger/tests/FactoryTest.php b/src/Logger/tests/FactoryTest.php index 6a31aed88..2a8cbbd03 100644 --- a/src/Logger/tests/FactoryTest.php +++ b/src/Logger/tests/FactoryTest.php @@ -4,14 +4,101 @@ namespace Spiral\Tests\Logger; +use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration; +use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; +use Spiral\Boot\BootloadManager\DefaultInvokerStrategy; +use Spiral\Boot\BootloadManager\Initializer; +use Spiral\Boot\BootloadManager\InitializerInterface; +use Spiral\Boot\BootloadManager\InvokerStrategyInterface; +use Spiral\Boot\BootloadManager\StrategyBasedBootloadManager; +use Spiral\Boot\Environment; +use Spiral\Boot\EnvironmentInterface; +use Spiral\Core\Container; +use Spiral\Logger\Attribute\LoggerChannel; +use Spiral\Logger\Bootloader\LoggerBootloader; use Spiral\Logger\Event\LogEvent; use Spiral\Logger\ListenerRegistry; use Spiral\Logger\LogFactory; +use Spiral\Logger\LoggerInjector; +use Spiral\Logger\LogsInterface; class FactoryTest extends TestCase { + use MockeryPHPUnitIntegration; + + protected Container $container; + + protected function setUp(): void + { + $this->container = new Container(); + $this->container->bind(EnvironmentInterface::class, new Environment()); + $this->container->bind(InvokerStrategyInterface::class, DefaultInvokerStrategy::class); + $this->container->bind(InitializerInterface::class, Initializer::class); + } + + #[DoesNotPerformAssertions] + public function testDefaultLogger(): void + { + $factory = new LogFactory(new ListenerRegistry()); + $factory->getLogger('default'); + } + + public function testInjection(): void + { + $factory = new class () implements LogsInterface { + public function getLogger(string $channel): LoggerInterface + { + $mock = \Mockery::mock(LoggerInterface::class); + $mock->shouldReceive('getName')->andReturn($channel); + return $mock; + } + }; + $this->container->get(StrategyBasedBootloadManager::class)->bootload([LoggerBootloader::class]); + $this->container->bindSingleton(LogsInterface::class, $factory); + + $this->assertInstanceOf(LoggerInterface::class, $logger = $this->container->get(LoggerInterface::class)); + $this->assertSame(LoggerInjector::DEFAULT_CHANNEL, $logger->getName()); + } + + public function testInjectionNullableChannel(): void + { + $factory = new class () implements LogsInterface { + public function getLogger(?string $channel): LoggerInterface + { + $mock = \Mockery::mock(LoggerInterface::class); + $mock->shouldReceive('getName')->andReturn($channel); + return $mock; + } + }; + $this->container->get(StrategyBasedBootloadManager::class)->bootload([LoggerBootloader::class]); + $this->container->bindSingleton(LogsInterface::class, $factory); + + $this->assertInstanceOf(LoggerInterface::class, $logger = $this->container->get(LoggerInterface::class)); + $this->assertNull($logger->getName()); + } + + public function testInjectionWithAttribute(): void + { + $factory = new class () implements LogsInterface { + public function getLogger(?string $channel): LoggerInterface + { + $mock = \Mockery::mock(LoggerInterface::class); + $mock->shouldReceive('getName')->andReturn($channel); + return $mock; + } + }; + $this->container->get(StrategyBasedBootloadManager::class)->bootload([LoggerBootloader::class]); + $this->container->bindSingleton(LogsInterface::class, $factory); + + $this->container->invoke(function (#[LoggerChannel('foo')] LoggerInterface $logger) { + $this->assertSame('foo', $logger->getName()); + }); + } + + public function testEvent(): void { $l = new ListenerRegistry(); From 10f0e8c661610ed071d9c0225c81f46be5f6d25c Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Thu, 25 Apr 2024 12:26:48 +0400 Subject: [PATCH 7/7] Fix failed Monolog test; add Reflection cache in LoggerInjector --- src/Bridge/Monolog/tests/LoggerTest.php | 8 ++++---- src/Logger/src/LoggerInjector.php | 17 +++++++++++++---- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/Bridge/Monolog/tests/LoggerTest.php b/src/Bridge/Monolog/tests/LoggerTest.php index 5002f2dd7..6a5a44a7f 100644 --- a/src/Bridge/Monolog/tests/LoggerTest.php +++ b/src/Bridge/Monolog/tests/LoggerTest.php @@ -15,6 +15,7 @@ use Spiral\Config\ConfiguratorInterface; use Spiral\Config\LoaderInterface; use Spiral\Core\Container; +use Spiral\Logger\LogsInterface; use Spiral\Monolog\Bootloader\MonologBootloader; use Spiral\Monolog\LogFactory; @@ -39,15 +40,14 @@ public function load(string $section): array )); $this->container->bind(FinalizerInterface::class, $finalizer = new Finalizer()); - $this->container->bind(LogFactory::class, $factory = m::mock(Container\InjectorInterface::class)); $logger = m::mock(Logger::class); $logger->shouldReceive('reset')->once(); - $factory->shouldReceive('getLogger')->twice()->andReturn($logger); - $this->container->get(StrategyBasedBootloadManager::class)->bootload([MonologBootloader::class]); - $this->container->get(LoggerInterface::class); + + $this->container->bind(LogsInterface::class, $factory = m::mock(LogsInterface::class)); + $factory->shouldReceive('getLogger')->once()->andReturn($logger); $finalizer->finalize(); } diff --git a/src/Logger/src/LoggerInjector.php b/src/Logger/src/LoggerInjector.php index 0ed289209..6c68f9290 100644 --- a/src/Logger/src/LoggerInjector.php +++ b/src/Logger/src/LoggerInjector.php @@ -32,10 +32,19 @@ public function createInjection( ): LoggerInterface { $channel = \is_object($context) ? $this->extractChannelAttribute($context) : null; - // Check that null argument is available - $channel ??= (new \ReflectionMethod($this->factory, 'getLogger'))->getParameters()[0]->allowsNull() - ? null - : self::DEFAULT_CHANNEL; + if ($channel === null) { + /** + * Array of flags to check if the logger allows null argument + * + * @var array, bool> $cache + */ + static $cache = []; + + $cache[$this->factory::class] = (new \ReflectionMethod($this->factory, 'getLogger')) + ->getParameters()[0]->allowsNull(); + + $channel = $cache[$this->factory::class] ? null : self::DEFAULT_CHANNEL; + } return $this->factory->getLogger($channel); }