From 504e338c0bae6be8e402c8d84f8aa24973aa5b6f Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 23 Mar 2015 19:17:24 +0100 Subject: [PATCH] make it possible to dump inlined services to XML --- .../Compiler/InlineServiceDefinitionsPass.php | 6 +++ .../DependencyInjection/Dumper/XmlDumper.php | 12 ++++- .../Loader/XmlFileLoader.php | 32 +++++++---- .../schema/dic/services/services-1.0.xsd | 3 ++ .../InlineServiceDefinitionsPassTest.php | 34 ------------ .../Tests/Dumper/XmlDumperTest.php | 8 +++ .../Tests/Fixtures/containers/container21.php | 20 +++++++ .../Tests/Fixtures/php/services9_compiled.php | 54 +++---------------- .../Tests/Fixtures/xml/services21.xml | 21 ++++++++ .../Tests/Loader/XmlFileLoaderTest.php | 29 ++++++++++ 10 files changed, 127 insertions(+), 92 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container21.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services21.xml diff --git a/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php index 30da0347c4fe..026700d2263d 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php @@ -62,6 +62,12 @@ public function process(ContainerBuilder $container) $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]); } } diff --git a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php index 0a7310062289..40486c459554 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php @@ -178,7 +178,11 @@ private function addService($definition, $id, \DOMElement $parent) if ($callable = $definition->getFactory()) { $factory = $this->document->createElement('factory'); - if (is_array($callable)) { + + if (is_array($callable) && $callable[0] instanceof Definition) { + $this->addService($callable[0], null, $factory); + $factory->setAttribute('method', $callable[1]); + } elseif (is_array($callable)) { $factory->setAttribute($callable[0] instanceof Reference ? 'service' : 'class', $callable[0]); $factory->setAttribute('method', $callable[1]); } else { @@ -189,7 +193,11 @@ private function addService($definition, $id, \DOMElement $parent) if ($callable = $definition->getConfigurator()) { $configurator = $this->document->createElement('configurator'); - if (is_array($callable)) { + + if (is_array($callable) && $callable[0] instanceof Definition) { + $this->addService($callable[0], null, $configurator); + $configurator->setAttribute('method', $callable[1]); + } elseif (is_array($callable)) { $configurator->setAttribute($callable[0] instanceof Reference ? 'service' : 'class', $callable[0]); $configurator->setAttribute('method', $callable[1]); } else { diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index 52328ddd540a..f81d8d693197 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -116,25 +116,27 @@ private function parseDefinitions(\DOMDocument $xml, $file) } foreach ($services as $service) { - $this->parseDefinition((string) $service->getAttribute('id'), $service, $file); + if (null !== $definition = $this->parseDefinition($service, $file)) { + $this->container->setDefinition((string) $service->getAttribute('id'), $definition); + } } } /** * Parses an individual Definition. * - * @param string $id * @param \DOMElement $service - * @param string $file + * + * @return Definition|null */ - private function parseDefinition($id, \DOMElement $service, $file) + private function parseDefinition(\DOMElement $service) { if ($alias = $service->getAttribute('alias')) { $public = true; if ($publicAttr = $service->getAttribute('public')) { $public = XmlUtils::phpize($publicAttr); } - $this->container->setAlias($id, new Alias($alias, $public)); + $this->container->setAlias((string) $service->getAttribute('id'), new Alias($alias, $public)); return; } @@ -153,7 +155,7 @@ private function parseDefinition($id, \DOMElement $service, $file) } if ($value = $service->getAttribute('synchronized')) { - $definition->setSynchronized(XmlUtils::phpize($value), 'request' !== $id); + $definition->setSynchronized(XmlUtils::phpize($value), 'request' !== (string) $service->getAttribute('id')); } if ($files = $this->getChildren($service, 'file')) { @@ -168,7 +170,11 @@ private function parseDefinition($id, \DOMElement $service, $file) if ($function = $factory->getAttribute('function')) { $definition->setFactory($function); } else { - if ($childService = $factory->getAttribute('service')) { + $factoryService = $this->getChildren($factory, 'service'); + + if (isset($factoryService[0])) { + $class = $this->parseDefinition($factoryService[0]); + } elseif ($childService = $factory->getAttribute('service')) { $class = new Reference($childService, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false); } else { $class = $factory->getAttribute('class'); @@ -183,7 +189,11 @@ private function parseDefinition($id, \DOMElement $service, $file) if ($function = $configurator->getAttribute('function')) { $definition->setConfigurator($function); } else { - if ($childService = $configurator->getAttribute('service')) { + $configuratorService = $this->getChildren($configurator, 'service'); + + if (isset($configuratorService[0])) { + $class = $this->parseDefinition($configuratorService[0]); + } elseif ($childService = $configurator->getAttribute('service')) { $class = new Reference($childService, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false); } else { $class = $configurator->getAttribute('class'); @@ -219,7 +229,7 @@ private function parseDefinition($id, \DOMElement $service, $file) $definition->setDecoratedService($value, $renameId); } - $this->container->setDefinition($id, $definition); + return $definition; } /** @@ -295,7 +305,9 @@ private function processAnonymousServices(\DOMDocument $xml, $file) // we could not use the constant false here, because of XML parsing $domElement->setAttribute('public', 'false'); - $this->parseDefinition($id, $domElement, $file); + if (null !== $definition = $this->parseDefinition($domElement, $file)) { + $this->container->setDefinition($id, $definition); + } if (true === $wild) { $tmpDomElement = new \DOMElement('_services', null, self::NS); 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 966f4de07fe4..ac2cba7a80ce 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 @@ -65,6 +65,9 @@ + + + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php index baefa1d0fff9..590ca4cfae2f 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php @@ -237,40 +237,6 @@ public function testProcessDoesNotInlineWhenServiceReferencesItself() $this->assertSame($ref, $calls[0][1][0]); } - public function testProcessDoesNotInlineFactories() - { - $container = new ContainerBuilder(); - $container - ->register('foo.factory') - ->setPublic(false) - ; - $container - ->register('foo') - ->setFactory(array(new Reference('foo.factory'), 'getFoo')) - ; - $this->process($container); - - $factory = $container->getDefinition('foo')->getFactory(); - $this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $factory[0]); - } - - public function testProcessDoesNotInlineConfigurators() - { - $container = new ContainerBuilder(); - $container - ->register('foo.configurator') - ->setPublic(false) - ; - $container - ->register('foo') - ->setConfigurator(array(new Reference('foo.configurator'), 'getFoo')) - ; - $this->process($container); - - $configurator = $container->getDefinition('foo')->getConfigurator(); - $this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $configurator[0]); - } - protected function process(ContainerBuilder $container) { $repeatedPass = new RepeatedPass(array(new AnalyzeServiceReferencesPass(), new InlineServiceDefinitionsPass())); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php index d0ffaefd0435..fe253f918cbc 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php @@ -175,4 +175,12 @@ public function provideCompiledContainerData() array('container14'), ); } + + public function testDumpInlinedServices() + { + $container = include self::$fixturesPath.'/containers/container21.php'; + $dumper = new XmlDumper($container); + + $this->assertEquals(file_get_contents(self::$fixturesPath.'/xml/services21.xml'), $dumper->dump()); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container21.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container21.php new file mode 100644 index 000000000000..d0467386140a --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container21.php @@ -0,0 +1,20 @@ +setConfigurator(array(new Definition('Baz'), 'configureBar')); + +$fooFactory = new Definition('FooFactory'); +$fooFactory->setFactory(array(new Definition('Foobar'), 'createFooFactory')); + +$container + ->register('foo', 'Foo') + ->setFactory(array($fooFactory, 'createFoo')) + ->setConfigurator(array($bar, 'configureFoo')) +; + +return $container; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php index ed5f1fdcc586..7c1a49d46f88 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php @@ -37,7 +37,6 @@ public function __construct() $this->methodMap = array( 'bar' => 'getBarService', 'baz' => 'getBazService', - 'configurator_service' => 'getConfiguratorServiceService', 'configured_service' => 'getConfiguredServiceService', 'decorator_service' => 'getDecoratorServiceService', 'decorator_service_with_name' => 'getDecoratorServiceWithNameService', @@ -47,7 +46,6 @@ public function __construct() 'foo_bar' => 'getFooBarService', 'foo_with_inline' => 'getFooWithInlineService', 'method_call1' => 'getMethodCall1Service', - 'new_factory' => 'getNewFactoryService', 'new_factory_service' => 'getNewFactoryServiceService', 'request' => 'getRequestService', 'service_from_static_method' => 'getServiceFromStaticMethodService', @@ -113,9 +111,12 @@ protected function getBazService() */ protected function getConfiguredServiceService() { + $a = new \ConfClass(); + $a->setFoo($this->get('baz')); + $this->services['configured_service'] = $instance = new \stdClass(); - $this->get('configurator_service')->configureStdClass($instance); + $a->configureStdClass($instance); return $instance; } @@ -263,7 +264,10 @@ protected function getMethodCall1Service() */ protected function getNewFactoryServiceService() { - $this->services['new_factory_service'] = $instance = $this->get('new_factory')->getInstance(); + $a = new \FactoryClass(); + $a->foo = 'bar'; + + $this->services['new_factory_service'] = $instance = $a->getInstance(); $instance->foo = 'bar'; @@ -296,48 +300,6 @@ protected function getServiceFromStaticMethodService() return $this->services['service_from_static_method'] = \Bar\FooClass::getInstance(); } - /** - * Gets the 'configurator_service' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * This service is private. - * If you want to be able to request this service from the container directly, - * make it public, otherwise you might end up with broken code. - * - * @return \ConfClass A ConfClass instance. - */ - protected function getConfiguratorServiceService() - { - $this->services['configurator_service'] = $instance = new \ConfClass(); - - $instance->setFoo($this->get('baz')); - - return $instance; - } - - /** - * Gets the 'new_factory' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * This service is private. - * If you want to be able to request this service from the container directly, - * make it public, otherwise you might end up with broken code. - * - * @return \FactoryClass A FactoryClass instance. - */ - protected function getNewFactoryService() - { - $this->services['new_factory'] = $instance = new \FactoryClass(); - - $instance->foo = 'bar'; - - return $instance; - } - /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services21.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services21.xml new file mode 100644 index 000000000000..329bc3d72a25 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services21.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php index 50546ed519f2..c9b454c4e084 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php @@ -467,4 +467,33 @@ public function testLoadIndexedArguments() $this->assertEquals(array('index_0' => 'app'), $container->findDefinition('logger')->getArguments()); } + + public function testLoadInlinedServices() + { + $container = new ContainerBuilder(); + $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); + $loader->load('services21.xml'); + + $foo = $container->getDefinition('foo'); + + $fooFactory = $foo->getFactory(); + $this->assertInstanceOf('Symfony\Component\DependencyInjection\Definition', $fooFactory[0]); + $this->assertSame('FooFactory', $fooFactory[0]->getClass()); + $this->assertSame('createFoo', $fooFactory[1]); + + $fooFactoryFactory = $fooFactory[0]->getFactory(); + $this->assertInstanceOf('Symfony\Component\DependencyInjection\Definition', $fooFactoryFactory[0]); + $this->assertSame('Foobar', $fooFactoryFactory[0]->getClass()); + $this->assertSame('createFooFactory', $fooFactoryFactory[1]); + + $fooConfigurator = $foo->getConfigurator(); + $this->assertInstanceOf('Symfony\Component\DependencyInjection\Definition', $fooConfigurator[0]); + $this->assertSame('Bar', $fooConfigurator[0]->getClass()); + $this->assertSame('configureFoo', $fooConfigurator[1]); + + $barConfigurator = $fooConfigurator[0]->getConfigurator(); + $this->assertInstanceOf('Symfony\Component\DependencyInjection\Definition', $barConfigurator[0]); + $this->assertSame('Baz', $barConfigurator[0]->getClass()); + $this->assertSame('configureBar', $barConfigurator[1]); + } }