Issue #2147451 by dawehner: ContainerBuild has to ensure synchronized services.
parent
f3b78fbfe6
commit
d329ec0f15
|
@ -9,6 +9,7 @@ namespace Drupal\Core\DependencyInjection;
|
|||
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder as SymfonyContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Container as SymfonyContainer;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
/**
|
||||
* Drupal's dependency injection container builder.
|
||||
|
@ -40,6 +41,52 @@ class ContainerBuilder extends SymfonyContainerBuilder {
|
|||
*/
|
||||
public function set($id, $service, $scope = self::SCOPE_CONTAINER) {
|
||||
SymfonyContainer::set($id, $service, $scope);
|
||||
|
||||
if ($this->hasDefinition($id) && ($definition = $this->getDefinition($id)) && $definition->isSynchronized()) {
|
||||
$this->synchronize($id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronizes a service change.
|
||||
*
|
||||
* This method is a copy of the ContainerBuilder of symfony.
|
||||
*
|
||||
* This method updates all services that depend on the given
|
||||
* service by calling all methods referencing it.
|
||||
*
|
||||
* @param string $id A service id
|
||||
*/
|
||||
private function synchronize($id) {
|
||||
foreach ($this->getDefinitions() as $definitionId => $definition) {
|
||||
// only check initialized services
|
||||
if (!$this->initialized($definitionId)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($definition->getMethodCalls() as $call) {
|
||||
foreach ($call[1] as $argument) {
|
||||
if ($argument instanceof Reference && $id == (string) $argument) {
|
||||
$this->callMethod($this->get($definitionId), $call);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A 1to1 copy of parent::callMethod.
|
||||
*/
|
||||
protected function callMethod($service, $call) {
|
||||
$services = self::getServiceConditionals($call[1]);
|
||||
|
||||
foreach ($services as $s) {
|
||||
if (!$this->has($s)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
call_user_func_array(array($service, $call[0]), $this->resolveServices($this->getParameterBag()->resolveValue($call[1])));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\DependencyInjection\ContainerBuilderTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\DependencyInjection;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
require_once __DIR__ . '../../../../../../vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php';
|
||||
|
||||
/**
|
||||
* Dependency injection container builder.
|
||||
*
|
||||
* @see \Drupal\Core\DependencyInjection\ContainerBuilder
|
||||
*/
|
||||
class ContainerBuilderTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Dependency injection container builder',
|
||||
'description' => 'Tests the dependency injection container builder overrides of Drupal.',
|
||||
'group' => 'System'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests set with a synchronized service.
|
||||
*/
|
||||
public function testSetOnSynchronizedService() {
|
||||
$container = new ContainerBuilder();
|
||||
$container->register('baz', 'BazClass')
|
||||
->setSynchronized(TRUE);
|
||||
$container->register('bar', 'BarClass')
|
||||
->addMethodCall('setBaz', array(new Reference('baz')));
|
||||
|
||||
$container->set('baz', $baz = new \BazClass());
|
||||
$this->assertSame($baz, $container->get('bar')->getBaz());
|
||||
|
||||
$container->set('baz', $baz = new \BazClass());
|
||||
$this->assertSame($baz, $container->get('bar')->getBaz());
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue