diff --git a/core/lib/Drupal/Core/CoreServiceProvider.php b/core/lib/Drupal/Core/CoreServiceProvider.php index 67a1337a6590256903adbf238ac8f93ff3c265c7..5fb8d9360219b67dac18ba2cafc67f2c66150c08 100644 --- a/core/lib/Drupal/Core/CoreServiceProvider.php +++ b/core/lib/Drupal/Core/CoreServiceProvider.php @@ -9,22 +9,24 @@ use Drupal\Core\DependencyInjection\Compiler\CorsCompilerPass; use Drupal\Core\DependencyInjection\Compiler\DeprecatedServicePass; use Drupal\Core\DependencyInjection\Compiler\DevelopmentSettingsPass; +use Drupal\Core\DependencyInjection\Compiler\LoggerAwarePass; +use Drupal\Core\DependencyInjection\Compiler\ModifyServiceDefinitionsPass; use Drupal\Core\DependencyInjection\Compiler\ProxyServicesPass; +use Drupal\Core\DependencyInjection\Compiler\RegisterAccessChecksPass; +use Drupal\Core\DependencyInjection\Compiler\RegisterEventSubscribersPass; +use Drupal\Core\DependencyInjection\Compiler\RegisterServicesForDestructionPass; +use Drupal\Core\DependencyInjection\Compiler\RegisterStreamWrappersPass; use Drupal\Core\DependencyInjection\Compiler\StackedKernelPass; use Drupal\Core\DependencyInjection\Compiler\StackedSessionHandlerPass; -use Drupal\Core\DependencyInjection\Compiler\RegisterStreamWrappersPass; +use Drupal\Core\DependencyInjection\Compiler\TaggedHandlersPass; use Drupal\Core\DependencyInjection\Compiler\TwigExtensionPass; +use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\DependencyInjection\ServiceModifierInterface; use Drupal\Core\DependencyInjection\ServiceProviderInterface; -use Drupal\Core\DependencyInjection\ContainerBuilder; -use Drupal\Core\DependencyInjection\Compiler\ModifyServiceDefinitionsPass; -use Drupal\Core\DependencyInjection\Compiler\TaggedHandlersPass; -use Drupal\Core\DependencyInjection\Compiler\RegisterEventSubscribersPass; -use Drupal\Core\DependencyInjection\Compiler\RegisterAccessChecksPass; -use Drupal\Core\DependencyInjection\Compiler\RegisterServicesForDestructionPass; use Drupal\Core\Plugin\PluginManagerPass; use Drupal\Core\Render\MainContent\MainContentRenderersPass; use Drupal\Core\Site\Settings; +use Psr\Log\LoggerAwareInterface; use Symfony\Component\DependencyInjection\Compiler\PassConfig; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -81,6 +83,7 @@ public function register(ContainerBuilder $container) { // Add a compiler pass for registering event subscribers. $container->addCompilerPass(new RegisterEventSubscribersPass(), PassConfig::TYPE_AFTER_REMOVING); + $container->addCompilerPass(new LoggerAwarePass(), PassConfig::TYPE_AFTER_REMOVING); $container->addCompilerPass(new RegisterAccessChecksPass()); @@ -99,6 +102,10 @@ public function register(ContainerBuilder $container) { $container->registerForAutoconfiguration(EventSubscriberInterface::class) ->addTag('event_subscriber'); + + $container->registerForAutoconfiguration(LoggerAwareInterface::class) + ->addTag('logger_aware'); + } /** diff --git a/core/lib/Drupal/Core/DependencyInjection/Compiler/LoggerAwarePass.php b/core/lib/Drupal/Core/DependencyInjection/Compiler/LoggerAwarePass.php new file mode 100644 index 0000000000000000000000000000000000000000..4dd9e37de0088759b68738d4c3f18c491a860ae5 --- /dev/null +++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/LoggerAwarePass.php @@ -0,0 +1,37 @@ +<?php + +namespace Drupal\Core\DependencyInjection\Compiler; + +use Psr\Log\LoggerAwareInterface; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Sets the logger on all services that implement LoggerAwareInterface. + */ +class LoggerAwarePass implements CompilerPassInterface { + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container): void { + $interface = LoggerAwareInterface::class; + foreach ($container->findTaggedServiceIds('logger_aware') as $id => $attributes) { + $definition = $container->getDefinition($id); + // Skip services that are already calling setLogger(). + if ($definition->hasMethodCall('setLogger')) { + continue; + } + if (!is_subclass_of($definition->getClass(), $interface)) { + throw new \InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface)); + } + $providerTag = $definition->getTag('_provider'); + $loggerId = 'logger.channel.' . $providerTag[0]['provider']; + if ($container->has($loggerId)) { + $definition->addMethodCall('setLogger', [new Reference($loggerId)]); + } + } + } + +} diff --git a/core/modules/system/tests/modules/logger_aware_test/logger_aware_test.info.yml b/core/modules/system/tests/modules/logger_aware_test/logger_aware_test.info.yml new file mode 100644 index 0000000000000000000000000000000000000000..4dd160a8bed185aafd88acc33b1981ab1d66d86c --- /dev/null +++ b/core/modules/system/tests/modules/logger_aware_test/logger_aware_test.info.yml @@ -0,0 +1,5 @@ +name: 'Logger Aware Autoconfigure Test' +type: module +description: 'Test logger aware auto-configuration support' +package: Testing +version: VERSION diff --git a/core/modules/system/tests/modules/logger_aware_test/logger_aware_test.services.yml b/core/modules/system/tests/modules/logger_aware_test/logger_aware_test.services.yml new file mode 100644 index 0000000000000000000000000000000000000000..8fc353b61d55b900ce6bf432060b3cf11c3d1be6 --- /dev/null +++ b/core/modules/system/tests/modules/logger_aware_test/logger_aware_test.services.yml @@ -0,0 +1,18 @@ +services: + _defaults: + autoconfigure: true + + logger_aware_test.logger_aware_stub: + class: Drupal\logger_aware_test\LoggerAwareStub + + logger.channel.logger_aware_test: + parent: logger.channel_base + arguments: ['logger_aware_test'] + + logger.channel.logger_stub: + class: Drupal\logger_aware_test\LoggerStub + + logger_aware_test.logger_aware_existing: + class: Drupal\logger_aware_test\LoggerAwareStub + calls: + - [setLogger, ['@logger.channel.logger_stub']] diff --git a/core/modules/system/tests/modules/logger_aware_test/src/LoggerAwareStub.php b/core/modules/system/tests/modules/logger_aware_test/src/LoggerAwareStub.php new file mode 100644 index 0000000000000000000000000000000000000000..a11a6daef8e4eba6b6c805c4de27e1f57f97c496 --- /dev/null +++ b/core/modules/system/tests/modules/logger_aware_test/src/LoggerAwareStub.php @@ -0,0 +1,25 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\logger_aware_test; + +use Psr\Log\LoggerAwareInterface; +use Psr\Log\LoggerAwareTrait; +use Psr\Log\LoggerInterface; + +/** + * A test class that implements LoggerAwareInterface. + */ +class LoggerAwareStub implements LoggerAwareInterface { + + use LoggerAwareTrait; + + /** + * Gets the logger. + */ + public function getLogger(): LoggerInterface { + return $this->logger; + } + +} diff --git a/core/modules/system/tests/modules/logger_aware_test/src/LoggerStub.php b/core/modules/system/tests/modules/logger_aware_test/src/LoggerStub.php new file mode 100644 index 0000000000000000000000000000000000000000..734f7200de7c1478f1fe3f84769285d14bcbd42a --- /dev/null +++ b/core/modules/system/tests/modules/logger_aware_test/src/LoggerStub.php @@ -0,0 +1,19 @@ +<?php + +namespace Drupal\logger_aware_test; + +use Psr\Log\AbstractLogger; + +/** + * A logger stub. + */ +class LoggerStub extends AbstractLogger { + + /** + * {@inheritdoc} + */ + public function log($level, $message, array $context = []): void { + // Do nothing. + } + +} diff --git a/core/modules/system/tests/src/Kernel/DependencyInjection/CompilerPass/LoggerAwarePassTest.php b/core/modules/system/tests/src/Kernel/DependencyInjection/CompilerPass/LoggerAwarePassTest.php new file mode 100644 index 0000000000000000000000000000000000000000..f67aa911f2dc480573a3c87dd947ea95c7f32cee --- /dev/null +++ b/core/modules/system/tests/src/Kernel/DependencyInjection/CompilerPass/LoggerAwarePassTest.php @@ -0,0 +1,54 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\system\Kernel\DependencyInjection\CompilerPass; + +use Drupal\KernelTests\KernelTestBase; +use Drupal\logger_aware_test\LoggerAwareStub; +use Drupal\logger_aware_test\LoggerStub; +use Psr\Log\LoggerInterface; + +/** + * Tests the logger aware compiler pass. + * + * @group system + * @coversDefaultClass \Drupal\Core\DependencyInjection\Compiler\LoggerAwarePass + */ +class LoggerAwarePassTest extends KernelTestBase { + + /** + * {@inheritdoc} + */ + protected static $modules = [ + 'system', + 'logger_aware_test', + ]; + + /** + * Tests that the logger aware compiler pass works. + * + * @covers ::process + */ + public function testLoggerAwarePass(): void { + $container = $this->container; + $logger = $container->get('logger.channel.logger_aware_test'); + $this->assertInstanceOf(LoggerInterface::class, $logger); + $logger_aware_stub = $container->get('logger_aware_test.logger_aware_stub'); + $this->assertInstanceOf(LoggerAwareStub::class, $logger_aware_stub); + $this->assertSame($logger, $logger_aware_stub->getLogger()); + } + + /** + * Tests that existing loggers are not overwritten. + * + * @covers ::process + */ + public function testExistingLogger(): void { + $container = $this->container; + $logger_aware_stub = $container->get('logger_aware_test.logger_aware_existing'); + $logger = $logger_aware_stub->getLogger(); + $this->assertInstanceOf(LoggerStub::class, $logger); + } + +}