From e5763cea5474be708a331e77b6f208bd12779703 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 24 Jun 2015 10:29:42 +0200 Subject: [PATCH] [DependencyInjection] Allow anonymous DefinitionDecorator resolving --- .../Compiler/InlineServiceDefinitionsPass.php | 34 +++------ .../ResolveDefinitionTemplatesPass.php | 74 ++++++++++++++----- .../ResolveDefinitionTemplatesPassTest.php | 36 +++++++++ 3 files changed, 102 insertions(+), 42 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php index c3c4ef5fd6540..1beaaf0c53ce0 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php @@ -48,27 +48,7 @@ public function process(ContainerBuilder $container) $this->formatter = $this->compiler->getLoggingFormatter(); $this->graph = $this->compiler->getServiceReferenceGraph(); - foreach ($container->getDefinitions() as $id => $definition) { - $this->currentId = $id; - - $definition->setArguments( - $this->inlineArguments($container, $definition->getArguments()) - ); - - $definition->setMethodCalls( - $this->inlineArguments($container, $definition->getMethodCalls()) - ); - - $definition->setProperties( - $this->inlineArguments($container, $definition->getProperties()) - ); - - $configurator = $this->inlineArguments($container, array($definition->getConfigurator())); - $definition->setConfigurator($configurator[0]); - - $factory = $this->inlineArguments($container, array($definition->getFactory())); - $definition->setFactory($factory[0]); - } + $container->setDefinitions($this->inlineArguments($container, $container->getDefinitions(), true)); } /** @@ -76,12 +56,16 @@ public function process(ContainerBuilder $container) * * @param ContainerBuilder $container The ContainerBuilder * @param array $arguments An array of arguments + * @param bool $isRoot If we are processing the root definitions or not * * @return array */ - private function inlineArguments(ContainerBuilder $container, array $arguments) + private function inlineArguments(ContainerBuilder $container, array $arguments, $isRoot = false) { foreach ($arguments as $k => $argument) { + if ($isRoot) { + $this->currentId = $k; + } if (is_array($argument)) { $arguments[$k] = $this->inlineArguments($container, $argument); } elseif ($argument instanceof Reference) { @@ -102,6 +86,12 @@ private function inlineArguments(ContainerBuilder $container, array $arguments) $argument->setArguments($this->inlineArguments($container, $argument->getArguments())); $argument->setMethodCalls($this->inlineArguments($container, $argument->getMethodCalls())); $argument->setProperties($this->inlineArguments($container, $argument->getProperties())); + + $configurator = $this->inlineArguments($container, array($argument->getConfigurator())); + $argument->setConfigurator($configurator[0]); + + $factory = $this->inlineArguments($container, array($argument->getFactory())); + $argument->setFactory($factory[0]); } } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php index daaee8159d488..2d5711cdf2e42 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php @@ -21,12 +21,13 @@ * merged Definition instance. * * @author Johannes M. Schmitt + * @author Nicolas Grekas */ class ResolveDefinitionTemplatesPass implements CompilerPassInterface { - private $container; private $compiler; private $formatter; + private $currentId; /** * Process the ContainerBuilder to replace DefinitionDecorator instances with their real Definition instances. @@ -35,44 +36,80 @@ class ResolveDefinitionTemplatesPass implements CompilerPassInterface */ public function process(ContainerBuilder $container) { - $this->container = $container; $this->compiler = $container->getCompiler(); $this->formatter = $this->compiler->getLoggingFormatter(); - foreach ($container->getDefinitions() as $id => $definition) { - // yes, we are specifically fetching the definition from the - // container to ensure we are not operating on stale data - $definition = $container->getDefinition($id); - if (!$definition instanceof DefinitionDecorator || $definition->isAbstract()) { - continue; - } + $container->setDefinitions($this->resolveArguments($container, $container->getDefinitions(), true)); + } - $this->resolveDefinition($id, $definition); + /** + * Resolves definition decorator arguments. + * + * @param ContainerBuilder $container The ContainerBuilder + * @param array $arguments An array of arguments + * @param bool $isRoot If we are processing the root definitions or not + * + * @return array + */ + private function resolveArguments(ContainerBuilder $container, array $arguments, $isRoot = false) + { + foreach ($arguments as $k => $argument) { + if ($isRoot) { + // yes, we are specifically fetching the definition from the + // container to ensure we are not operating on stale data + $arguments[$k] = $argument = $container->getDefinition($k); + $this->currentId = $k; + } + if (is_array($argument)) { + $arguments[$k] = $this->resolveArguments($container, $argument); + } elseif ($argument instanceof Definition) { + if ($argument instanceof DefinitionDecorator) { + $arguments[$k] = $argument = $this->resolveDefinition($container, $argument); + if ($isRoot) { + $container->setDefinition($k, $argument); + } + } + $argument->setArguments($this->resolveArguments($container, $argument->getArguments())); + $argument->setMethodCalls($this->resolveArguments($container, $argument->getMethodCalls())); + $argument->setProperties($this->resolveArguments($container, $argument->getProperties())); + + $configurator = $this->resolveArguments($container, array($argument->getConfigurator())); + $argument->setConfigurator($configurator[0]); + + $factory = $this->resolveArguments($container, array($argument->getFactory())); + $argument->setFactory($factory[0]); + } } + + return $arguments; } /** * Resolves the definition. * - * @param string $id The definition identifier + * @param ContainerBuilder $container The ContainerBuilder * @param DefinitionDecorator $definition * * @return Definition * * @throws \RuntimeException When the definition is invalid */ - private function resolveDefinition($id, DefinitionDecorator $definition) + private function resolveDefinition(ContainerBuilder $container, DefinitionDecorator $definition) { - if (!$this->container->hasDefinition($parent = $definition->getParent())) { - throw new RuntimeException(sprintf('The parent definition "%s" defined for definition "%s" does not exist.', $parent, $id)); + if (!$container->hasDefinition($parent = $definition->getParent())) { + throw new RuntimeException(sprintf('The parent definition "%s" defined for definition "%s" does not exist.', $parent, $this->currentId)); } - $parentDef = $this->container->getDefinition($parent); + $parentDef = $container->getDefinition($parent); if ($parentDef instanceof DefinitionDecorator) { - $parentDef = $this->resolveDefinition($parent, $parentDef); + $id = $this->currentId; + $this->currentId = $parent; + $parentDef = $this->resolveDefinition($container, $parentDef); + $container->setDefinition($parent, $parentDef); + $this->currentId = $id; } - $this->compiler->addLogMessage($this->formatter->formatResolveInheritance($this, $id, $parent)); + $this->compiler->addLogMessage($this->formatter->formatResolveInheritance($this, $this->currentId, $parent)); $def = new Definition(); // merge in parent definition @@ -156,9 +193,6 @@ private function resolveDefinition($id, DefinitionDecorator $definition) $def->setScope($definition->getScope(false), false); $def->setTags($definition->getTags()); - // set new definition on container - $this->container->setDefinition($id, $def); - return $def; } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php index 0060b35e9a595..1487d94f51473 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php @@ -176,6 +176,42 @@ public function testSetLazyOnServiceIsParent() $this->assertTrue($container->getDefinition('child1')->isLazy()); } + public function testDeepDefinitionsResolving() + { + $container = new ContainerBuilder(); + + $container->register('parent', 'parentClass'); + $container->register('sibling', 'siblingClass') + ->setConfigurator(new DefinitionDecorator('parent'), 'foo') + ->setFactory(array(new DefinitionDecorator('parent'), 'foo')) + ->addArgument(new DefinitionDecorator('parent')) + ->setProperty('prop', new DefinitionDecorator('parent')) + ->addMethodCall('meth', array(new DefinitionDecorator('parent'))) + ; + + $this->process($container); + + $configurator = $container->getDefinition('sibling')->getConfigurator(); + $this->assertSame('Symfony\Component\DependencyInjection\Definition', get_class($configurator)); + $this->assertSame('parentClass', $configurator->getClass()); + + $factory = $container->getDefinition('sibling')->getFactory(); + $this->assertSame('Symfony\Component\DependencyInjection\Definition', get_class($factory[0])); + $this->assertSame('parentClass', $factory[0]->getClass()); + + $argument = $container->getDefinition('sibling')->getArgument(0); + $this->assertSame('Symfony\Component\DependencyInjection\Definition', get_class($argument)); + $this->assertSame('parentClass', $argument->getClass()); + + $properties = $container->getDefinition('sibling')->getProperties(); + $this->assertSame('Symfony\Component\DependencyInjection\Definition', get_class($properties['prop'])); + $this->assertSame('parentClass', $properties['prop']->getClass()); + + $methodCalls = $container->getDefinition('sibling')->getMethodCalls(); + $this->assertSame('Symfony\Component\DependencyInjection\Definition', get_class($methodCalls[0][1][0])); + $this->assertSame('parentClass', $methodCalls[0][1][0]->getClass()); + } + protected function process(ContainerBuilder $container) { $pass = new ResolveDefinitionTemplatesPass(); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy