diff --git a/core/lib/Drupal/Core/DependencyInjection/Compiler/DependencySerializationTraitPass.php b/core/lib/Drupal/Core/DependencyInjection/Compiler/DependencySerializationTraitPass.php index 4952283967863dd72b0038d11d54885e33afeb45..a0ba7f0225e37255ea7b0aead8ab6c6a80d0a133 100644 --- a/core/lib/Drupal/Core/DependencyInjection/Compiler/DependencySerializationTraitPass.php +++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/DependencySerializationTraitPass.php @@ -16,12 +16,34 @@ class DependencySerializationTraitPass implements CompilerPassInterface { * {@inheritdoc} */ public function process(ContainerBuilder $container) { + $decorations = new \SplPriorityQueue(); + $order = PHP_INT_MAX; + foreach ($container->getDefinitions() as $service_id => $definition) { // Only add the property to services that are public (as private services // can not be reloaded through Container::get()) and are objects. if (!$definition->hasTag('parameter_service') && $definition->isPublic()) { $definition->setProperty('_serviceId', $service_id); } + + if ($decorated = $definition->getDecoratedService()) { + $decorations->insert([$service_id, $definition], [$decorated[2], --$order]); + } + } + + foreach ($decorations as list($service_id, $definition)) { + list($inner, $renamedId) = $definition->getDecoratedService(); + if (!$renamedId) { + $renamedId = $service_id . '.inner'; + } + + $original = $container->getDefinition($inner); + if ($original->isPublic()) { + // The old service is renamed. + $original->setProperty('_serviceId', $renamedId); + // The decorating service takes over the old ID. + $definition->setProperty('_serviceId', $inner); + } } } diff --git a/core/modules/system/tests/modules/decorated_service_test/decorated_service_test.info.yml b/core/modules/system/tests/modules/decorated_service_test/decorated_service_test.info.yml new file mode 100644 index 0000000000000000000000000000000000000000..08d66bdb6904a2b4c419145e5a85250b32dd36ce --- /dev/null +++ b/core/modules/system/tests/modules/decorated_service_test/decorated_service_test.info.yml @@ -0,0 +1,5 @@ +name: 'Decorated Service Test' +type: module +description: 'Support module for decorated service test.' +package: Testing +version: VERSION diff --git a/core/modules/system/tests/modules/decorated_service_test/decorated_service_test.services.yml b/core/modules/system/tests/modules/decorated_service_test/decorated_service_test.services.yml new file mode 100644 index 0000000000000000000000000000000000000000..a00c56c7d0cc06607b6b1258c56479a9328fa162 --- /dev/null +++ b/core/modules/system/tests/modules/decorated_service_test/decorated_service_test.services.yml @@ -0,0 +1,17 @@ +services: + test_service: + class: 'Drupal\decorated_service_test\TestService' + test_service_decorator: + class: 'Drupal\decorated_service_test\TestServiceDecorator' + public: false + decorates: test_service + test_service2: + class: 'Drupal\decorated_service_test\TestService' + test_service2_decorator: + class: 'Drupal\decorated_service_test\TestServiceDecorator' + public: false + decorates: test_service2 + test_service2_decorator2: + class: 'Drupal\decorated_service_test\TestServiceDecorator' + public: false + decorates: test_service2 diff --git a/core/modules/system/tests/modules/decorated_service_test/src/TestService.php b/core/modules/system/tests/modules/decorated_service_test/src/TestService.php new file mode 100644 index 0000000000000000000000000000000000000000..8e708019ffaedc11d753f5fc37ab98b298e6339e --- /dev/null +++ b/core/modules/system/tests/modules/decorated_service_test/src/TestService.php @@ -0,0 +1,7 @@ +<?php + +namespace Drupal\decorated_service_test; + +class TestService { + +} diff --git a/core/modules/system/tests/modules/decorated_service_test/src/TestServiceDecorator.php b/core/modules/system/tests/modules/decorated_service_test/src/TestServiceDecorator.php new file mode 100644 index 0000000000000000000000000000000000000000..30dcb023bd95c34e0c9a5aa375aa19f178d2a826 --- /dev/null +++ b/core/modules/system/tests/modules/decorated_service_test/src/TestServiceDecorator.php @@ -0,0 +1,7 @@ +<?php + +namespace Drupal\decorated_service_test; + +class TestServiceDecorator extends TestService { + +} diff --git a/core/modules/system/tests/src/Kernel/DecoratedServiceTest.php b/core/modules/system/tests/src/Kernel/DecoratedServiceTest.php new file mode 100644 index 0000000000000000000000000000000000000000..854662df18bb9804472ec6c5295b422175079b5b --- /dev/null +++ b/core/modules/system/tests/src/Kernel/DecoratedServiceTest.php @@ -0,0 +1,34 @@ +<?php + +namespace Drupal\Tests\system\Kernel; + +use Drupal\decorated_service_test\TestServiceDecorator; +use Drupal\KernelTests\KernelTestBase; + +/** + * Test handling of decorated services in DependencySerializationTraitPass. + * + * @group system + */ +class DecoratedServiceTest extends KernelTestBase { + + protected static $modules = [ + 'decorated_service_test', + ]; + + /** + * Check that decorated services keep their original service ID. + */ + public function testDecoratedServiceId() { + // Service decorated once. + $test_service = $this->container->get('test_service'); + $this->assertEquals('test_service', $test_service->_serviceId); + $this->assertInstanceOf(TestServiceDecorator::class, $test_service); + + // Service decorated twice. + $test_service2 = $this->container->get('test_service2'); + $this->assertEquals('test_service2', $test_service2->_serviceId); + $this->assertInstanceOf(TestServiceDecorator::class, $test_service2); + } + +}