Issue #3395032 by kim.pepper, acbramley, longwave: Add autoconfigure for module loggers

merge-requests/4850/merge
Lee Rowlands 2023-10-30 14:20:30 +10:00
parent a3edb28e93
commit 3d917f37b1
No known key found for this signature in database
GPG Key ID: 2B829A3DF9204DC4
7 changed files with 172 additions and 7 deletions

View File

@ -9,22 +9,24 @@ use Drupal\Core\DependencyInjection\Compiler\BackendCompilerPass;
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 @@ class CoreServiceProvider implements ServiceProviderInterface, ServiceModifierIn
// 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 @@ class CoreServiceProvider implements ServiceProviderInterface, ServiceModifierIn
$container->registerForAutoconfiguration(EventSubscriberInterface::class)
->addTag('event_subscriber');
$container->registerForAutoconfiguration(LoggerAwareInterface::class)
->addTag('logger_aware');
}
/**

View File

@ -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)]);
}
}
}
}

View File

@ -0,0 +1,5 @@
name: 'Logger Aware Autoconfigure Test'
type: module
description: 'Test logger aware auto-configuration support'
package: Testing
version: VERSION

View File

@ -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']]

View File

@ -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;
}
}

View File

@ -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.
}
}

View File

@ -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);
}
}