diff --git a/UPGRADE-4.4.md b/UPGRADE-4.4.md index 6a2eaea10d327..3aeac10b29bda 100644 --- a/UPGRADE-4.4.md +++ b/UPGRADE-4.4.md @@ -16,41 +16,37 @@ Debug DependencyInjection ------------------- + * Made singly-implemented interfaces detection be scoped by file * Deprecated support for short factories and short configurators in Yaml Before: ```yaml services: - my_service: - factory: factory_service:method + my_service: + factory: factory_service:method ``` After: ```yaml services: - my_service: - factory: ['@factory_service', method] + my_service: + factory: ['@factory_service', method] ``` + * Deprecated `tagged` in favor of `tagged_iterator` Before: ```yaml services: - App\Handler: - tags: ['app.handler'] - App\HandlerCollection: - arguments: [!tagged app.handler] + arguments: [!tagged my_tag] ``` After: ```yaml services: - App\Handler: - tags: ['app.handler'] - - App\HandlerCollection: - arguments: [!tagged_iterator app.handler] + App\HandlerCollection: + arguments: [!tagged_iterator my_tag] ``` * Passing an instance of `Symfony\Component\DependencyInjection\Parameter` as class name to `Symfony\Component\DependencyInjection\Definition` is deprecated. @@ -143,6 +139,7 @@ HttpKernel As many bundles must be compatible with a range of Symfony versions, the current directory convention is not deprecated yet, but it will be in the future. + * Deprecated the second and third argument of `KernelInterface::locateResource` * Deprecated the second and third argument of `FileLocator::__construct` * Deprecated loading resources from `%kernel.root_dir%/Resources` and `%kernel.root_dir%` as @@ -244,13 +241,13 @@ TwigBundle Before (`templates/bundles/TwigBundle/Exception/error.jsonld.twig`): ```twig { - "@id": "https://example.com", - "@type": "error", - "@context": { - "title": "{{ status_text }}", - "code": {{ status_code }}, - "message": "{{ exception.message }}" - } + "@id": "https://example.com", + "@type": "error", + "@context": { + "title": "{{ status_text }}", + "code": {{ status_code }}, + "message": "{{ exception.message }}" + } } ``` @@ -258,23 +255,23 @@ TwigBundle ```php class JsonLdErrorRenderer implements ErrorRendererInterface { - public static function getFormat(): string - { - return 'jsonld'; - } + public static function getFormat(): string + { + return 'jsonld'; + } - public function render(FlattenException $exception): string - { - return json_encode([ - '@id' => 'https://example.com', - '@type' => 'error', - '@context' => [ - 'title' => $exception->getTitle(), - 'code' => $exception->getStatusCode(), - 'message' => $exception->getMessage(), - ], - ]); - } + public function render(FlattenException $exception): string + { + return json_encode([ + '@id' => 'https://example.com', + '@type' => 'error', + '@context' => [ + 'title' => $exception->getTitle(), + 'code' => $exception->getStatusCode(), + 'message' => $exception->getMessage(), + ], + ]); + } } ``` diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index bbe164bacf575..6f56c7610363f 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -8,6 +8,7 @@ CHANGELOG * deprecated support for short factories and short configurators in Yaml * deprecated `tagged` in favor of `tagged_iterator` * deprecated passing an instance of `Symfony\Component\DependencyInjection\Parameter` as class name to `Symfony\Component\DependencyInjection\Definition` + * made singly-implemented interfaces detection be scoped by file 4.3.0 ----- diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/ServicesConfigurator.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/ServicesConfigurator.php index b693fc2d66e7e..f0fdde81c33a4 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/Configurator/ServicesConfigurator.php +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/ServicesConfigurator.php @@ -139,4 +139,9 @@ final public function __invoke(string $id, string $class = null): ServiceConfigu { return $this->set($id, $class); } + + public function __destruct() + { + $this->loader->registerAliasesForSinglyImplementedInterfaces(); + } } diff --git a/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php index cb204164857c3..b522a31382a5e 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php @@ -29,6 +29,8 @@ abstract class FileLoader extends BaseFileLoader protected $container; protected $isLoadingInstanceof = false; protected $instanceof = []; + protected $interfaces = []; + protected $singlyImplemented = []; public function __construct(ContainerBuilder $container, FileLocatorInterface $locator) { @@ -57,12 +59,10 @@ public function registerClasses(Definition $prototype, $namespace, $resource, $e $classes = $this->findClasses($namespace, $resource, (array) $exclude); // prepare for deep cloning $serializedPrototype = serialize($prototype); - $interfaces = []; - $singlyImplemented = []; foreach ($classes as $class => $errorMessage) { if (interface_exists($class, false)) { - $interfaces[] = $class; + $this->interfaces[] = $class; } else { $this->setDefinition($class, $definition = unserialize($serializedPrototype)); if (null !== $errorMessage) { @@ -71,16 +71,21 @@ public function registerClasses(Definition $prototype, $namespace, $resource, $e continue; } foreach (class_implements($class, false) as $interface) { - $singlyImplemented[$interface] = isset($singlyImplemented[$interface]) ? false : $class; + $this->singlyImplemented[$interface] = isset($this->singlyImplemented[$interface]) ? false : $class; } } } - foreach ($interfaces as $interface) { - if (!empty($singlyImplemented[$interface])) { - $this->container->setAlias($interface, $singlyImplemented[$interface]) - ->setPublic(false); + } + + public function registerAliasesForSinglyImplementedInterfaces() + { + foreach ($this->interfaces as $interface) { + if (!empty($this->singlyImplemented[$interface]) && !$this->container->hasAlias($interface)) { + $this->container->setAlias($interface, $this->singlyImplemented[$interface])->setPublic(false); } } + + $this->interfaces = $this->singlyImplemented = []; } /** diff --git a/src/Symfony/Component/DependencyInjection/Loader/PhpFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/PhpFileLoader.php index 033798f6813f7..0efa1239f0705 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/PhpFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/PhpFileLoader.php @@ -41,10 +41,15 @@ public function load($resource, $type = null) return include $path; }, $this, ProtectedPhpFileLoader::class); - $callback = $load($path); + try { + $callback = $load($path); - if (\is_object($callback) && \is_callable($callback)) { - $callback(new ContainerConfigurator($this->container, $this, $this->instanceof, $path, $resource), $this->container, $this); + if (\is_object($callback) && \is_callable($callback)) { + $callback(new ContainerConfigurator($this->container, $this, $this->instanceof, $path, $resource), $this->container, $this); + } + } finally { + $this->instanceof = []; + $this->registerAliasesForSinglyImplementedInterfaces(); } } diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index 50b90a81aabad..06100a46d7ffb 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -66,6 +66,7 @@ public function load($resource, $type = null) $this->parseDefinitions($xml, $path, $defaults); } finally { $this->instanceof = []; + $this->registerAliasesForSinglyImplementedInterfaces(); } } diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index bb3868bdead35..03daeaeff3fa2 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -150,6 +150,7 @@ public function load($resource, $type = null) $this->parseDefinitions($content, $path); } finally { $this->instanceof = []; + $this->registerAliasesForSinglyImplementedInterfaces(); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/Prototype/SinglyImplementedInterface/Adapter/Adapter.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/Prototype/SinglyImplementedInterface/Adapter/Adapter.php new file mode 100644 index 0000000000000..3450f0da87962 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/Prototype/SinglyImplementedInterface/Adapter/Adapter.php @@ -0,0 +1,9 @@ +tag('baz'); $di->load(Prototype::class.'\\', '../Prototype') ->autoconfigure() - ->exclude('../Prototype/{OtherDir,BadClasses}') + ->exclude('../Prototype/{OtherDir,BadClasses,SinglyImplementedInterface}') ->factory('f') ->deprecate('%service_id%') ->args([0]) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/prototype_array.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/prototype_array.php index 819a3fa11c15f..501baa3c10ab7 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/prototype_array.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/prototype_array.php @@ -9,7 +9,7 @@ ->tag('baz'); $di->load(Prototype::class.'\\', '../Prototype') ->autoconfigure() - ->exclude(['../Prototype/OtherDir', '../Prototype/BadClasses']) + ->exclude(['../Prototype/OtherDir', '../Prototype/BadClasses', '../Prototype/SinglyImplementedInterface']) ->factory('f') ->deprecate('%service_id%') ->args([0]) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/not_singly_implemented_interface_in_multiple_resources.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/not_singly_implemented_interface_in_multiple_resources.xml new file mode 100644 index 0000000000000..ed533e917b37b --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/not_singly_implemented_interface_in_multiple_resources.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/not_singly_implemented_interface_in_multiple_resources_with_previously_registered_alias.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/not_singly_implemented_interface_in_multiple_resources_with_previously_registered_alias.xml new file mode 100644 index 0000000000000..e463cfc424ce2 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/not_singly_implemented_interface_in_multiple_resources_with_previously_registered_alias.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/not_singly_implemented_interface_in_multiple_resources_with_previously_registered_alias2.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/not_singly_implemented_interface_in_multiple_resources_with_previously_registered_alias2.xml new file mode 100644 index 0000000000000..29486267fcf6b --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/not_singly_implemented_interface_in_multiple_resources_with_previously_registered_alias2.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_prototype.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_prototype.xml index 9d1d622d4aad3..1aa28bf341f27 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_prototype.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_prototype.xml @@ -1,6 +1,6 @@ - + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_prototype_array.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_prototype_array.xml index a62fd06eee7ac..b24b3af5777aa 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_prototype_array.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_prototype_array.xml @@ -4,6 +4,7 @@ ../Prototype/OtherDir ../Prototype/BadClasses + ../Prototype/SinglyImplementedInterface diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/singly_implemented_interface_in_multiple_resources.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/singly_implemented_interface_in_multiple_resources.xml new file mode 100644 index 0000000000000..d4af42d52525d --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/singly_implemented_interface_in_multiple_resources.xml @@ -0,0 +1,14 @@ + + + + + + + + + + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/not_singly_implemented_interface_in_multiple_resources.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/not_singly_implemented_interface_in_multiple_resources.yml new file mode 100644 index 0000000000000..ba8cf0d63fc85 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/not_singly_implemented_interface_in_multiple_resources.yml @@ -0,0 +1,12 @@ +services: + _defaults: + autowire: true + + Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\Adapter\: + resource: ../Prototype/SinglyImplementedInterface/Adapter/* + + Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\AnotherAdapter\: + resource: ../Prototype/SinglyImplementedInterface/AnotherAdapter/* + + Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\Port\: + resource: ../Prototype/SinglyImplementedInterface/Port/* diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/not_singly_implemented_interface_in_multiple_resources_with_previously_registered_alias.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/not_singly_implemented_interface_in_multiple_resources_with_previously_registered_alias.yml new file mode 100644 index 0000000000000..76643879a212b --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/not_singly_implemented_interface_in_multiple_resources_with_previously_registered_alias.yml @@ -0,0 +1,15 @@ +services: + _defaults: + autowire: true + + Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\Port\PortInterface: + alias: Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\Adapter\Adapter + + Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\Port\: + resource: ../Prototype/SinglyImplementedInterface/Port/* + + Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\Adapter\: + resource: ../Prototype/SinglyImplementedInterface/Adapter/* + + Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\AnotherAdapter\: + resource: ../Prototype/SinglyImplementedInterface/AnotherAdapter/* diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/not_singly_implemented_interface_in_multiple_resources_with_previously_registered_alias2.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/not_singly_implemented_interface_in_multiple_resources_with_previously_registered_alias2.yml new file mode 100644 index 0000000000000..2c9a9ccd485a1 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/not_singly_implemented_interface_in_multiple_resources_with_previously_registered_alias2.yml @@ -0,0 +1,15 @@ +services: + _defaults: + autowire: true + + Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\Port\: + resource: ../Prototype/SinglyImplementedInterface/Port/* + + Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\Adapter\: + resource: ../Prototype/SinglyImplementedInterface/Adapter/* + + Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\Port\PortInterface: + alias: Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\Adapter\Adapter + + Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\AnotherAdapter\: + resource: ../Prototype/SinglyImplementedInterface/AnotherAdapter/* diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_prototype.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_prototype.yml index 8c0b202aab2b7..43f8d51e04246 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_prototype.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_prototype.yml @@ -1,4 +1,4 @@ services: Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\: resource: ../Prototype - exclude: '../Prototype/{OtherDir,BadClasses}' + exclude: '../Prototype/{OtherDir,BadClasses,SinglyImplementedInterface}' diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/singly_implemented_interface_in_multiple_resources.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/singly_implemented_interface_in_multiple_resources.yml new file mode 100644 index 0000000000000..bc0eb0398c7e9 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/singly_implemented_interface_in_multiple_resources.yml @@ -0,0 +1,9 @@ +services: + _defaults: + autowire: true + + Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\Port\: + resource: ../Prototype/SinglyImplementedInterface/Port/* + + Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\Adapter\: + resource: ../Prototype/SinglyImplementedInterface/Adapter/* diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/FileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/FileLoaderTest.php index d2800def2a55e..d4446cbe4e60c 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/FileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/FileLoaderTest.php @@ -260,4 +260,10 @@ public function supports($resource, $type = null): bool { return false; } + + public function registerClasses(Definition $prototype, $namespace, $resource, $exclude = null) + { + parent::registerClasses($prototype, $namespace, $resource, $exclude); + $this->registerAliasesForSinglyImplementedInterfaces(); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php index dafa0464edd21..3e00103aed97e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php @@ -652,6 +652,7 @@ public function testPrototype() [ str_replace(\DIRECTORY_SEPARATOR, '/', $prototypeRealPath.\DIRECTORY_SEPARATOR.'OtherDir') => true, str_replace(\DIRECTORY_SEPARATOR, '/', $prototypeRealPath.\DIRECTORY_SEPARATOR.'BadClasses') => true, + str_replace(\DIRECTORY_SEPARATOR, '/', $prototypeRealPath.\DIRECTORY_SEPARATOR.'SinglyImplementedInterface') => true, ] ); $this->assertContains((string) $globResource, $resources); @@ -684,6 +685,7 @@ public function testPrototypeExcludeWithArray() [ str_replace(\DIRECTORY_SEPARATOR, '/', $prototypeRealPath.\DIRECTORY_SEPARATOR.'BadClasses') => true, str_replace(\DIRECTORY_SEPARATOR, '/', $prototypeRealPath.\DIRECTORY_SEPARATOR.'OtherDir') => true, + str_replace(\DIRECTORY_SEPARATOR, '/', $prototypeRealPath.\DIRECTORY_SEPARATOR.'SinglyImplementedInterface') => true, ] ); $this->assertContains((string) $globResource, $resources); @@ -901,4 +903,50 @@ public function testOverriddenDefaultsBindings() $this->assertSame('overridden', $container->get('bar')->quz); } + + public function testSinglyImplementedInterfacesInMultipleResources() + { + $container = new ContainerBuilder(); + + $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); + $loader->load('singly_implemented_interface_in_multiple_resources.xml'); + + $alias = $container->getAlias(Prototype\SinglyImplementedInterface\Port\PortInterface::class); + + $this->assertSame(Prototype\SinglyImplementedInterface\Adapter\Adapter::class, (string) $alias); + } + + public function testNotSinglyImplementedInterfacesInMultipleResources() + { + $container = new ContainerBuilder(); + + $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); + $loader->load('not_singly_implemented_interface_in_multiple_resources.xml'); + + $this->assertFalse($container->hasAlias(Prototype\SinglyImplementedInterface\Port\PortInterface::class)); + } + + public function testNotSinglyImplementedInterfacesInMultipleResourcesWithPreviouslyRegisteredAlias() + { + $container = new ContainerBuilder(); + + $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); + $loader->load('not_singly_implemented_interface_in_multiple_resources_with_previously_registered_alias.xml'); + + $alias = $container->getAlias(Prototype\SinglyImplementedInterface\Port\PortInterface::class); + + $this->assertSame(Prototype\SinglyImplementedInterface\Adapter\Adapter::class, (string) $alias); + } + + public function testNotSinglyImplementedInterfacesInMultipleResourcesWithPreviouslyRegisteredAlias2() + { + $container = new ContainerBuilder(); + + $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); + $loader->load('not_singly_implemented_interface_in_multiple_resources_with_previously_registered_alias2.xml'); + + $alias = $container->getAlias(Prototype\SinglyImplementedInterface\Port\PortInterface::class); + + $this->assertSame(Prototype\SinglyImplementedInterface\Adapter\Adapter::class, (string) $alias); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php index a7e56e68420a1..bc34b17428738 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php @@ -415,6 +415,7 @@ public function testPrototype() false, [ str_replace(\DIRECTORY_SEPARATOR, '/', $prototypeRealPath.\DIRECTORY_SEPARATOR.'BadClasses') => true, str_replace(\DIRECTORY_SEPARATOR, '/', $prototypeRealPath.\DIRECTORY_SEPARATOR.'OtherDir') => true, + str_replace(\DIRECTORY_SEPARATOR, '/', $prototypeRealPath.\DIRECTORY_SEPARATOR.'SinglyImplementedInterface') => true, ] ); $this->assertContains((string) $globResource, $resources); @@ -834,4 +835,50 @@ public function testDefaultValueOfTagged() $this->assertInstanceOf(TaggedIteratorArgument::class, $iteratorArgument); $this->assertNull($iteratorArgument->getIndexAttribute()); } + + public function testSinglyImplementedInterfacesInMultipleResources() + { + $container = new ContainerBuilder(); + + $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); + $loader->load('singly_implemented_interface_in_multiple_resources.yml'); + + $alias = $container->getAlias(Prototype\SinglyImplementedInterface\Port\PortInterface::class); + + $this->assertSame(Prototype\SinglyImplementedInterface\Adapter\Adapter::class, (string) $alias); + } + + public function testNotSinglyImplementedInterfacesInMultipleResources() + { + $container = new ContainerBuilder(); + + $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); + $loader->load('not_singly_implemented_interface_in_multiple_resources.yml'); + + $this->assertFalse($container->hasAlias(Prototype\SinglyImplementedInterface\Port\PortInterface::class)); + } + + public function testNotSinglyImplementedInterfacesInMultipleResourcesWithPreviouslyRegisteredAlias() + { + $container = new ContainerBuilder(); + + $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); + $loader->load('not_singly_implemented_interface_in_multiple_resources_with_previously_registered_alias.yml'); + + $alias = $container->getAlias(Prototype\SinglyImplementedInterface\Port\PortInterface::class); + + $this->assertSame(Prototype\SinglyImplementedInterface\Adapter\Adapter::class, (string) $alias); + } + + public function testNotSinglyImplementedInterfacesInMultipleResourcesWithPreviouslyRegisteredAlias2() + { + $container = new ContainerBuilder(); + + $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); + $loader->load('not_singly_implemented_interface_in_multiple_resources_with_previously_registered_alias2.yml'); + + $alias = $container->getAlias(Prototype\SinglyImplementedInterface\Port\PortInterface::class); + + $this->assertSame(Prototype\SinglyImplementedInterface\Adapter\Adapter::class, (string) $alias); + } }