Issue #2896993 by cburschka, andypost, mxr576, jedihe: Decorated services crash on serialization
parent
7f337ca7b1
commit
b16df24b08
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
name: 'Decorated Service Test'
|
||||
type: module
|
||||
description: 'Support module for decorated service test.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\decorated_service_test;
|
||||
|
||||
class TestService {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\decorated_service_test;
|
||||
|
||||
class TestServiceDecorator extends TestService {
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue