diff --git a/core/.phpstan-baseline.php b/core/.phpstan-baseline.php index 69791e0b36b9a9a7fddfd439a3c7fff6a6c7d527..3d61c10c9f735144847c06553f4dbe01dfe7b555 100644 --- a/core/.phpstan-baseline.php +++ b/core/.phpstan-baseline.php @@ -472,18 +472,6 @@ 'count' => 1, 'path' => __DIR__ . '/lib/Drupal/Core/Lock/NullLockBackend.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Class Drupal\\\\Core\\\\Logger\\\\LoggerChannelFactory implements deprecated interface Symfony\\\\Component\\\\DependencyInjection\\\\ContainerAwareInterface\\: -since Symfony 6\\.4, use dependency injection instead$#', - 'count' => 1, - 'path' => __DIR__ . '/lib/Drupal/Core/Logger/LoggerChannelFactory.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Usage of deprecated trait Symfony\\\\Component\\\\DependencyInjection\\\\ContainerAwareTrait in class Drupal\\\\Core\\\\Logger\\\\LoggerChannelFactory\\: -since Symfony 6\\.4, use dependency injection instead$#', - 'count' => 1, - 'path' => __DIR__ . '/lib/Drupal/Core/Logger/LoggerChannelFactory.php', -]; $ignoreErrors[] = [ 'message' => '#^Variable \\$parent in isset\\(\\) always exists and is not nullable\\.$#', 'count' => 1, diff --git a/core/core.services.yml b/core/core.services.yml index df762b1a4c6d3ea42afe455bc0c58f1d0c00a17e..1272400dbfe9b80e9d6904f45418286811e5d56b 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -495,7 +495,7 @@ services: arguments: ['@serialization.phpserialize', '@database', '@datetime.time'] logger.factory: class: Drupal\Core\Logger\LoggerChannelFactory - parent: container.trait + arguments: ['@request_stack', '@current_user'] tags: - { name: service_collector, tag: logger, call: addLogger } Drupal\Core\Logger\LoggerChannelFactoryInterface: '@logger.factory' diff --git a/core/lib/Drupal/Core/Logger/LoggerChannelFactory.php b/core/lib/Drupal/Core/Logger/LoggerChannelFactory.php index 6c487d1753175711ce9f18b7a3edd9fcad925961..90bda23459afcc4282859ca0a0fb1f1e97a44715 100644 --- a/core/lib/Drupal/Core/Logger/LoggerChannelFactory.php +++ b/core/lib/Drupal/Core/Logger/LoggerChannelFactory.php @@ -2,15 +2,24 @@ namespace Drupal\Core\Logger; +use Drupal\Core\Session\AccountInterface; use Psr\Log\LoggerInterface; -use Symfony\Component\DependencyInjection\ContainerAwareInterface; -use Symfony\Component\DependencyInjection\ContainerAwareTrait; +use Symfony\Component\HttpFoundation\RequestStack; /** * Defines a factory for logging channels. */ -class LoggerChannelFactory implements LoggerChannelFactoryInterface, ContainerAwareInterface { - use ContainerAwareTrait; +class LoggerChannelFactory implements LoggerChannelFactoryInterface { + + /** + * The request stack. + */ + protected ?RequestStack $requestStack = NULL; + + /** + * The current user. + */ + protected ?AccountInterface $currentUser = NULL; /** * Array of all instantiated logger channels keyed by channel name. @@ -26,20 +35,47 @@ class LoggerChannelFactory implements LoggerChannelFactoryInterface, ContainerAw */ protected $loggers = []; + /** + * Constructs a LoggerChannelFactory. + * + * @param \Symfony\Component\HttpFoundation\RequestStack|null $requestStack + * (optional) The request stack. + * @param \Drupal\Core\Session\AccountInterface|null $currentUser + * (optional) The current user. + */ + public function __construct( + ?RequestStack $requestStack = NULL, + ?AccountInterface $currentUser = NULL, + ) { + $this->requestStack = $requestStack; + $this->currentUser = $currentUser; + if (!$requestStack) { + @trigger_error('Calling ' . __METHOD__ . ' without the $requestStack argument is deprecated in drupal:10.3.0 and it will be required in drupal:11.0.0. See https://www.drupal.org/node/3416354', E_USER_DEPRECATED); + $this->requestStack = \Drupal::service('request_stack'); + } + if (!$currentUser) { + @trigger_error('Calling ' . __METHOD__ . ' without the $currentUser argument is deprecated in drupal:10.3.0 and it will be required in drupal:11.0.0. See https://www.drupal.org/node/3416354', E_USER_DEPRECATED); + $this->currentUser = \Drupal::service('current_user'); + } + } + /** * {@inheritdoc} */ public function get($channel) { + if (!$this->requestStack || !$this->currentUser) { + @trigger_error('Calling ' . __METHOD__ . ' without calling the constructor is deprecated in drupal:10.3.0 and it will be required in drupal:11.0.0. See https://www.drupal.org/node/3416354', E_USER_DEPRECATED); + $this->requestStack = \Drupal::service('request_stack'); + $this->currentUser = \Drupal::service('current_user'); + } + if (!isset($this->channels[$channel])) { $instance = new LoggerChannel($channel); - // If we have a container set the request_stack and current_user services - // on the channel. It is up to the channel to determine if there is a - // current request. - if ($this->container) { - $instance->setRequestStack($this->container->get('request_stack')); - $instance->setCurrentUser($this->container->get('current_user')); - } + // Set the request_stack and current_user services on the channel. + // It is up to the channel to determine if there is a current request. + $instance->setRequestStack($this->requestStack); + $instance->setCurrentUser($this->currentUser); // Pass the loggers to the channel. $instance->setLoggers($this->loggers); @@ -61,4 +97,26 @@ public function addLogger(LoggerInterface $logger, $priority = 0) { } } + /** + * Sets the service container. + * + * @deprecated in drupal:10.3.0 and is removed from drupal:11.0.0. Use + * dependency injection instead. + * + * @see https://www.drupal.org/node/3416354 + */ + public function setContainer() { + @trigger_error('Calling ' . __METHOD__ . '() is deprecated in drupal:10.3.0 and is removed from drupal:11.0.0. Use dependency injection instead. See https://www.drupal.org/node/3416354', E_USER_DEPRECATED); + } + + /** + * {@inheritdoc} + */ + public function __get(string $name) { + if ($name === 'container') { + @trigger_error('Accessing the container property in ' . __CLASS__ . ' is deprecated in drupal:10.3.0 and is removed from drupal:11.0.0. Use dependency injection instead. See https://www.drupal.org/node/3416354', E_USER_DEPRECATED); + return \Drupal::getContainer(); + } + } + } diff --git a/core/modules/media/tests/src/Unit/ProviderRepositoryTest.php b/core/modules/media/tests/src/Unit/ProviderRepositoryTest.php index c45b1e4d609aa7aa5aa18fd3dce655ba5998a2a4..6070467bc8c04724cb1919bc79d7f10eb1418cc4 100644 --- a/core/modules/media/tests/src/Unit/ProviderRepositoryTest.php +++ b/core/modules/media/tests/src/Unit/ProviderRepositoryTest.php @@ -5,8 +5,7 @@ namespace Drupal\Tests\media\Unit; use Drupal\Core\KeyValueStore\KeyValueMemoryFactory; -use Drupal\Core\Logger\LoggerChannelFactory; -use Drupal\Core\Logger\RfcLogLevel; +use Drupal\Core\Logger\LoggerChannelFactoryInterface; use Drupal\media\OEmbed\ProviderException; use Drupal\media\OEmbed\ProviderRepository; use Drupal\Tests\UnitTestCase; @@ -14,7 +13,6 @@ use GuzzleHttp\Handler\MockHandler; use GuzzleHttp\HandlerStack; use GuzzleHttp\Psr7\Response; -use Prophecy\Argument; /** * @coversDefaultClass \Drupal\media\OEmbed\ProviderRepository @@ -78,8 +76,8 @@ protected function setUp(): void { $time->getCurrentTime()->willReturn($this->currentTime); $this->logger = $this->prophesize('\Psr\Log\LoggerInterface'); - $logger_factory = new LoggerChannelFactory(); - $logger_factory->addLogger($this->logger->reveal()); + $logger_factory = $this->prophesize(LoggerChannelFactoryInterface::class); + $logger_factory->get('media')->willReturn($this->logger); $this->responses = new MockHandler(); $client = new Client([ @@ -90,7 +88,7 @@ protected function setUp(): void { $config_factory, $time->reveal(), $key_value_factory, - $logger_factory + $logger_factory->reveal() ); } @@ -233,10 +231,8 @@ public function testCorruptProviderIgnored(): void { $this->responses->append($response); // The corrupt provider should cause a warning to be logged. - $this->logger->log( - RfcLogLevel::WARNING, + $this->logger->warning( "Provider Uncle Rico's football videos does not define a valid external URL.", - Argument::type('array') )->shouldBeCalled(); $youtube = $this->repository->get('YouTube'); diff --git a/core/tests/Drupal/Tests/Core/Logger/LoggerChannelFactoryTest.php b/core/tests/Drupal/Tests/Core/Logger/LoggerChannelFactoryTest.php index fe9884151d6067fa0466bd8cd9510dfc1f812a42..6ba4d9c2e0cbe4bb5b81f16a563916e7c0633b0e 100644 --- a/core/tests/Drupal/Tests/Core/Logger/LoggerChannelFactoryTest.php +++ b/core/tests/Drupal/Tests/Core/Logger/LoggerChannelFactoryTest.php @@ -5,7 +5,11 @@ namespace Drupal\Tests\Core\Logger; use Drupal\Core\Logger\LoggerChannelFactory; +use Drupal\Core\Session\AccountInterface; +use Drupal\Core\Session\AccountProxy; use Drupal\Tests\UnitTestCase; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\HttpFoundation\RequestStack; /** * @coversDefaultClass \Drupal\Core\Logger\LoggerChannelFactory @@ -19,12 +23,88 @@ class LoggerChannelFactoryTest extends UnitTestCase { * @covers ::get */ public function testGet() { - $factory = new LoggerChannelFactory(); - $factory->setContainer($this->createMock('Symfony\Component\DependencyInjection\ContainerInterface')); + $factory = new LoggerChannelFactory( + $this->createMock(RequestStack::class), + $this->createMock(AccountInterface::class), + ); // Ensure that when called with the same argument, always the same instance // will be returned. $this->assertSame($factory->get('test'), $factory->get('test')); } + /** + * @covers ::__construct + * @group legacy + */ + public function testConstructorDeprecation() { + $container = $this->prophesize(ContainerInterface::class); + $container->get('request_stack') + ->willReturn($this->prophesize(RequestStack::class)->reveal()); + $container->get('current_user') + ->willReturn($this->prophesize(AccountProxy::class)->reveal()); + \Drupal::setContainer($container->reveal()); + + $this->expectDeprecation('Calling Drupal\Core\Logger\LoggerChannelFactory::__construct without the $requestStack argument is deprecated in drupal:10.3.0 and it will be required in drupal:11.0.0. See https://www.drupal.org/node/3416354'); + $this->expectDeprecation('Calling Drupal\Core\Logger\LoggerChannelFactory::__construct without the $currentUser argument is deprecated in drupal:10.3.0 and it will be required in drupal:11.0.0. See https://www.drupal.org/node/3416354'); + new LoggerChannelFactory(); + } + + /** + * @covers ::get + * @group legacy + */ + public function testWithoutConstructor() { + $container = $this->prophesize(ContainerInterface::class); + $container->get('request_stack') + ->willReturn($this->prophesize(RequestStack::class)->reveal()); + $container->get('current_user') + ->willReturn($this->prophesize(AccountProxy::class)->reveal()); + \Drupal::setContainer($container->reveal()); + + $factory = new LoggerChannelWithoutConstructor(); + + $this->expectDeprecation('Calling Drupal\Core\Logger\LoggerChannelFactory::get without calling the constructor is deprecated in drupal:10.3.0 and it will be required in drupal:11.0.0. See https://www.drupal.org/node/3416354'); + $this->assertSame($factory->get('test'), $factory->get('test')); + } + + /** + * @covers ::setContainer + * @group legacy + */ + public function testDeprecatedSetContainer() { + $factory = new LoggerChannelFactory( + $this->createMock(RequestStack::class), + $this->createMock(AccountInterface::class), + ); + + $this->expectDeprecation('Calling Drupal\Core\Logger\LoggerChannelFactory::setContainer() is deprecated in drupal:10.3.0 and is removed from drupal:11.0.0. Use dependency injection instead. See https://www.drupal.org/node/3416354'); + $factory->setContainer(); + } + + /** + * @covers ::__get + * @group legacy + */ + public function testDeprecatedGetContainer() { + $factory = new LoggerChannelFactory( + $this->createMock(RequestStack::class), + $this->createMock(AccountInterface::class), + ); + + $container = $this->prophesize(ContainerInterface::class); + $request_stack = $this->prophesize(RequestStack::class)->reveal(); + $container->get('request_stack')->willReturn($request_stack); + \Drupal::setContainer($container->reveal()); + + $this->expectDeprecation('Accessing the container property in Drupal\Core\Logger\LoggerChannelFactory is deprecated in drupal:10.3.0 and is removed from drupal:11.0.0. Use dependency injection instead. See https://www.drupal.org/node/3416354'); + $this->assertSame($request_stack, $factory->container->get('request_stack')); + } + +} + +class LoggerChannelWithoutConstructor extends LoggerChannelFactory { + + public function __construct() {} + }