Issue #2896993 by cburschka, andypost, mxr576, jedihe: Decorated services crash on serialization

merge-requests/2612/head
Alex Pott 2022-06-29 15:21:43 +01:00
parent 7f337ca7b1
commit b16df24b08
No known key found for this signature in database
GPG Key ID: BDA67E7EE836E5CE
6 changed files with 92 additions and 0 deletions

View File

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

View File

@ -0,0 +1,5 @@
name: 'Decorated Service Test'
type: module
description: 'Support module for decorated service test.'
package: Testing
version: VERSION

View File

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

View File

@ -0,0 +1,7 @@
<?php
namespace Drupal\decorated_service_test;
class TestService {
}

View File

@ -0,0 +1,7 @@
<?php
namespace Drupal\decorated_service_test;
class TestServiceDecorator extends TestService {
}

View File

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