diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index 3039885ec2fc9..f3923789ca43d 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -26,8 +26,6 @@ /** * YamlFileLoader loads YAML files service definitions. * - * The YAML format does not support anonymous services (cf. the XML loader). - * * @author Fabien Potencier */ class YamlFileLoader extends FileLoader @@ -50,6 +48,9 @@ public function load($resource, $type = null) return; } + // anonymous services + $this->processAnonymousServices($content, $path); + // imports $this->parseImports($content, $path); @@ -360,6 +361,63 @@ protected function loadFile($file) return $this->validate($configuration, $file); } + /** + * Processes anonymous services. + * + * @param array $content + * @param string $path + */ + private function processAnonymousServices(array &$content, $path) + { + $definitions = array(); + $count = 0; + + if (false === array_key_exists('services', $content) || false === is_array($content['services'])) + { + return; + } + + foreach ($content['services'] as $id => &$service) + { + if (false === is_array($service)) + { + continue; + } + + // TODO covert "properties" key also + if (false === array_key_exists('arguments', (array) $service)) + { + continue; + } + + foreach ($service['arguments'] as &$argument) + { + if (false === is_array($argument)) + { + continue; + } + + if (false === array_key_exists('type', $argument) || 'service' !== $argument['type']) + { + continue; + } + + $id = sprintf('%s_%d', hash('sha256', $path), ++$count); + $argument['id'] = $id; + $definitions[$id] = array(&$argument, $path); + } + } + + // resolve definitions + ksort($definitions); + foreach ($definitions as $id => $def) { + $serviceDef = &$def[0]; + $serviceDef['public'] = false; + $this->parseDefinition($id, (array) $def[0], $def[1]); + $serviceDef = '@'.$id; + } + } + /** * Validates a YAML file. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/anonymous_services.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/anonymous_services.yml new file mode 100644 index 0000000000000..6d7b717a3abf8 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/anonymous_services.yml @@ -0,0 +1,11 @@ +services: + service_with_anonymous_services: + class: FooClass + arguments: [{type: service, class: BazClass}] + another_service_with_anonymous_services: + class: FooClass + arguments: + - type: service + class: BazClass + - type: service + class: BarClass diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php index 8ab714e43a2c4..6d2542ea22a83 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php @@ -177,6 +177,24 @@ public function testLoadServices() $this->assertEquals(array('decorated', 'decorated.pif-pouf', 5), $services['decorator_service_with_name_and_priority']->getDecoratedService()); } + public function testAnonymousServices() + { + $container = new ContainerBuilder(); + $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); + $loader->load('anonymous_services.yml'); + $services = $container->getDefinitions(); + $arguments = $services['service_with_anonymous_services']->getArguments(); + $arguments2 = $services['another_service_with_anonymous_services']->getArguments(); + $this->assertCount(1, $arguments); + $this->assertCount(2, $arguments2); + $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Reference', $arguments[0]); + $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Reference', $arguments2[0]); + $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Reference', $arguments2[1]); + $this->assertEquals('BazClass', $services[(string) $arguments[0]]->getClass()); + $this->assertEquals('BazClass', $services[(string) $arguments2[0]]->getClass()); + $this->assertEquals('BarClass', $services[(string) $arguments2[1]]->getClass()); + } + public function testLoadFactoryShortSyntax() { $container = new ContainerBuilder();