From 7c299770378ee0c941875e5346f45f4aefdd2520 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 2 Jul 2018 15:56:57 +0200 Subject: [PATCH] [DI] Allow autoconfiguring bindings --- .../Argument/BoundArgument.php | 8 ++++-- .../ResolveInstanceofConditionalsPass.php | 5 +++- .../Configurator/InstanceofConfigurator.php | 1 + .../Loader/YamlFileLoader.php | 1 + .../schema/dic/services/services-1.0.xsd | 1 + .../ResolveInstanceofConditionalsPassTest.php | 26 ++++++++++++++++++- 6 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Argument/BoundArgument.php b/src/Symfony/Component/DependencyInjection/Argument/BoundArgument.php index f72f2110744c1..332f5354fa8f6 100644 --- a/src/Symfony/Component/DependencyInjection/Argument/BoundArgument.php +++ b/src/Symfony/Component/DependencyInjection/Argument/BoundArgument.php @@ -22,10 +22,14 @@ final class BoundArgument implements ArgumentInterface private $identifier; private $used; - public function __construct($value) + public function __construct($value, bool $trackUsage = true) { $this->value = $value; - $this->identifier = ++self::$sequence; + if ($trackUsage) { + $this->identifier = ++self::$sequence; + } else { + $this->used = true; + } } /** diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php index 63309b3a17e77..41ef09c1146d3 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php @@ -62,6 +62,7 @@ private function processDefinition(ContainerBuilder $container, $id, Definition $parent = $shared = null; $instanceofTags = array(); $instanceofCalls = array(); + $instanceofBindings = array(); foreach ($conditionals as $interface => $instanceofDefs) { if ($interface !== $class && (!$container->getReflectionClass($class, false))) { @@ -79,6 +80,7 @@ private function processDefinition(ContainerBuilder $container, $id, Definition $parent = '.instanceof.'.$interface.'.'.$key.'.'.$id; $container->setDefinition($parent, $instanceofDef); $instanceofTags[] = $instanceofDef->getTags(); + $instanceofBindings = $instanceofDef->getBindings() + $instanceofBindings; foreach ($instanceofDef->getMethodCalls() as $methodCall) { $instanceofCalls[] = $methodCall; @@ -86,6 +88,7 @@ private function processDefinition(ContainerBuilder $container, $id, Definition $instanceofDef->setTags(array()); $instanceofDef->setMethodCalls(array()); + $instanceofDef->setBindings(array()); if (isset($instanceofDef->getChanges()['shared'])) { $shared = $instanceofDef->isShared(); @@ -123,7 +126,7 @@ private function processDefinition(ContainerBuilder $container, $id, Definition } $definition->setMethodCalls(array_merge($instanceofCalls, $definition->getMethodCalls())); - $definition->setBindings($bindings); + $definition->setBindings($bindings + $instanceofBindings); // reset fields with "merge" behavior $abstract diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/InstanceofConfigurator.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/InstanceofConfigurator.php index 78a8e3c327f85..ad9a6872b6800 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/Configurator/InstanceofConfigurator.php +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/InstanceofConfigurator.php @@ -26,6 +26,7 @@ class InstanceofConfigurator extends AbstractServiceConfigurator use Traits\PublicTrait; use Traits\ShareTrait; use Traits\TagTrait; + use Traits\BindTrait; /** * Defines an instanceof-conditional to be applied to following service definitions. diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index 11eb8e45c7507..779bfb2e3e5db 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -93,6 +93,7 @@ class YamlFileLoader extends FileLoader 'calls' => 'calls', 'tags' => 'tags', 'autowire' => 'autowire', + 'bind' => 'bind', ); private static $defaultsKeywords = array( diff --git a/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd b/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd index 21e3b593105d2..c7f344fd8340c 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd +++ b/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd @@ -141,6 +141,7 @@ + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInstanceofConditionalsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInstanceofConditionalsPassTest.php index cc96c5a517849..84bfa6a655f19 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInstanceofConditionalsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInstanceofConditionalsPassTest.php @@ -17,6 +17,7 @@ use Symfony\Component\DependencyInjection\Compiler\ResolveInstanceofConditionalsPass; use Symfony\Component\DependencyInjection\Compiler\ResolveChildDefinitionsPass; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; class ResolveInstanceofConditionalsPassTest extends TestCase { @@ -270,7 +271,30 @@ public function testMergeReset() $this->assertTrue($abstract->isAbstract()); } - public function testBindings() + public function testProcessForAutoconfiguredBindings() + { + $container = new ContainerBuilder(); + + $container->registerForAutoconfiguration(self::class) + ->setBindings(array( + '$foo' => new BoundArgument(234, false), + parent::class => new BoundArgument(new Reference('foo'), false), + )); + + $container->register('foo', self::class) + ->setAutoconfigured(true) + ->setBindings(array('$foo' => new BoundArgument(123, false))); + + (new ResolveInstanceofConditionalsPass())->process($container); + + $expected = array( + '$foo' => new BoundArgument(123, false), + parent::class => new BoundArgument(new Reference('foo'), false), + ); + $this->assertEquals($expected, $container->findDefinition('foo')->getBindings()); + } + + public function testBindingsOnInstanceofConditionals() { $container = new ContainerBuilder(); $def = $container->register('foo', self::class)->setBindings(array('$toto' => 123));