bug #33350 [DI] scope singly-implemented interfaces detection by file (daniel-iwaniec, nicolas-grekas)
This PR was merged into the 4.4 branch. Discussion ---------- [DI] scope singly-implemented interfaces detection by file | Q | A | ------------- | --- | Branch? | 4.4 | Bug fix? | yes | New feature? | no | BC breaks? | yes | Deprecations? | no | Tests pass? | yes | License | MIT [DependencyInjection] fixed handling singly implemented interfaces when importing multiple resources for example: ```yaml App\Adapter\: resource: '../src/Adapter/*' App\Port\: resource: '../src/Port/*' ``` this configuration wont create service for interface (in other words singly implemented interface wont be autowired) and this chage fixes it **Also** this will prevent false positives - for example if I had one implementation in \App\Port namespace and another in \App\Adapter then interface service would still be registered but that could potentially break exisitng code not aware of this bug Commits -------c1f39709ff
[DI] add FileLoader::registerAliasesForSinglyImplementedInterfaces()bec38900d8
[DI] scope singly-implemented interfaces detection by file
This commit is contained in:
commit
db5cf1a83e
|
@ -16,41 +16,37 @@ Debug
|
||||||
DependencyInjection
|
DependencyInjection
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
* Made singly-implemented interfaces detection be scoped by file
|
||||||
* Deprecated support for short factories and short configurators in Yaml
|
* Deprecated support for short factories and short configurators in Yaml
|
||||||
|
|
||||||
Before:
|
Before:
|
||||||
```yaml
|
```yaml
|
||||||
services:
|
services:
|
||||||
my_service:
|
my_service:
|
||||||
factory: factory_service:method
|
factory: factory_service:method
|
||||||
```
|
```
|
||||||
|
|
||||||
After:
|
After:
|
||||||
```yaml
|
```yaml
|
||||||
services:
|
services:
|
||||||
my_service:
|
my_service:
|
||||||
factory: ['@factory_service', method]
|
factory: ['@factory_service', method]
|
||||||
```
|
```
|
||||||
|
|
||||||
* Deprecated `tagged` in favor of `tagged_iterator`
|
* Deprecated `tagged` in favor of `tagged_iterator`
|
||||||
|
|
||||||
Before:
|
Before:
|
||||||
```yaml
|
```yaml
|
||||||
services:
|
services:
|
||||||
App\Handler:
|
|
||||||
tags: ['app.handler']
|
|
||||||
|
|
||||||
App\HandlerCollection:
|
App\HandlerCollection:
|
||||||
arguments: [!tagged app.handler]
|
arguments: [!tagged my_tag]
|
||||||
```
|
```
|
||||||
|
|
||||||
After:
|
After:
|
||||||
```yaml
|
```yaml
|
||||||
services:
|
services:
|
||||||
App\Handler:
|
App\HandlerCollection:
|
||||||
tags: ['app.handler']
|
arguments: [!tagged_iterator my_tag]
|
||||||
|
|
||||||
App\HandlerCollection:
|
|
||||||
arguments: [!tagged_iterator app.handler]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
* Passing an instance of `Symfony\Component\DependencyInjection\Parameter` as class name to `Symfony\Component\DependencyInjection\Definition` is deprecated.
|
* Passing an instance of `Symfony\Component\DependencyInjection\Parameter` as class name to `Symfony\Component\DependencyInjection\Definition` is deprecated.
|
||||||
|
@ -145,6 +141,7 @@ HttpKernel
|
||||||
|
|
||||||
As many bundles must be compatible with a range of Symfony versions, the current
|
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.
|
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 `KernelInterface::locateResource`
|
||||||
* Deprecated the second and third argument of `FileLocator::__construct`
|
* Deprecated the second and third argument of `FileLocator::__construct`
|
||||||
* Deprecated loading resources from `%kernel.root_dir%/Resources` and `%kernel.root_dir%` as
|
* Deprecated loading resources from `%kernel.root_dir%/Resources` and `%kernel.root_dir%` as
|
||||||
|
@ -283,13 +280,13 @@ TwigBundle
|
||||||
Before (`templates/bundles/TwigBundle/Exception/error.jsonld.twig`):
|
Before (`templates/bundles/TwigBundle/Exception/error.jsonld.twig`):
|
||||||
```twig
|
```twig
|
||||||
{
|
{
|
||||||
"@id": "https://example.com",
|
"@id": "https://example.com",
|
||||||
"@type": "error",
|
"@type": "error",
|
||||||
"@context": {
|
"@context": {
|
||||||
"title": "{{ status_text }}",
|
"title": "{{ status_text }}",
|
||||||
"code": {{ status_code }},
|
"code": {{ status_code }},
|
||||||
"message": "{{ exception.message }}"
|
"message": "{{ exception.message }}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -297,23 +294,23 @@ TwigBundle
|
||||||
```php
|
```php
|
||||||
class JsonLdErrorRenderer implements ErrorRendererInterface
|
class JsonLdErrorRenderer implements ErrorRendererInterface
|
||||||
{
|
{
|
||||||
public static function getFormat(): string
|
public static function getFormat(): string
|
||||||
{
|
{
|
||||||
return 'jsonld';
|
return 'jsonld';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render(FlattenException $exception): string
|
public function render(FlattenException $exception): string
|
||||||
{
|
{
|
||||||
return json_encode([
|
return json_encode([
|
||||||
'@id' => 'https://example.com',
|
'@id' => 'https://example.com',
|
||||||
'@type' => 'error',
|
'@type' => 'error',
|
||||||
'@context' => [
|
'@context' => [
|
||||||
'title' => $exception->getTitle(),
|
'title' => $exception->getTitle(),
|
||||||
'code' => $exception->getStatusCode(),
|
'code' => $exception->getStatusCode(),
|
||||||
'message' => $exception->getMessage(),
|
'message' => $exception->getMessage(),
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ CHANGELOG
|
||||||
* deprecated `tagged` in favor of `tagged_iterator`
|
* deprecated `tagged` in favor of `tagged_iterator`
|
||||||
* deprecated passing an instance of `Symfony\Component\DependencyInjection\Parameter` as class name to `Symfony\Component\DependencyInjection\Definition`
|
* deprecated passing an instance of `Symfony\Component\DependencyInjection\Parameter` as class name to `Symfony\Component\DependencyInjection\Definition`
|
||||||
* added support for binding iterable and tagged services
|
* added support for binding iterable and tagged services
|
||||||
|
* made singly-implemented interfaces detection be scoped by file
|
||||||
|
|
||||||
4.3.0
|
4.3.0
|
||||||
-----
|
-----
|
||||||
|
|
|
@ -139,4 +139,9 @@ class ServicesConfigurator extends AbstractConfigurator
|
||||||
{
|
{
|
||||||
return $this->set($id, $class);
|
return $this->set($id, $class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function __destruct()
|
||||||
|
{
|
||||||
|
$this->loader->registerAliasesForSinglyImplementedInterfaces();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,8 @@ abstract class FileLoader extends BaseFileLoader
|
||||||
protected $container;
|
protected $container;
|
||||||
protected $isLoadingInstanceof = false;
|
protected $isLoadingInstanceof = false;
|
||||||
protected $instanceof = [];
|
protected $instanceof = [];
|
||||||
|
protected $interfaces = [];
|
||||||
|
protected $singlyImplemented = [];
|
||||||
|
|
||||||
public function __construct(ContainerBuilder $container, FileLocatorInterface $locator)
|
public function __construct(ContainerBuilder $container, FileLocatorInterface $locator)
|
||||||
{
|
{
|
||||||
|
@ -57,12 +59,10 @@ abstract class FileLoader extends BaseFileLoader
|
||||||
$classes = $this->findClasses($namespace, $resource, (array) $exclude);
|
$classes = $this->findClasses($namespace, $resource, (array) $exclude);
|
||||||
// prepare for deep cloning
|
// prepare for deep cloning
|
||||||
$serializedPrototype = serialize($prototype);
|
$serializedPrototype = serialize($prototype);
|
||||||
$interfaces = [];
|
|
||||||
$singlyImplemented = [];
|
|
||||||
|
|
||||||
foreach ($classes as $class => $errorMessage) {
|
foreach ($classes as $class => $errorMessage) {
|
||||||
if (interface_exists($class, false)) {
|
if (interface_exists($class, false)) {
|
||||||
$interfaces[] = $class;
|
$this->interfaces[] = $class;
|
||||||
} else {
|
} else {
|
||||||
$this->setDefinition($class, $definition = unserialize($serializedPrototype));
|
$this->setDefinition($class, $definition = unserialize($serializedPrototype));
|
||||||
if (null !== $errorMessage) {
|
if (null !== $errorMessage) {
|
||||||
|
@ -71,16 +71,21 @@ abstract class FileLoader extends BaseFileLoader
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
foreach (class_implements($class, false) as $interface) {
|
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])
|
public function registerAliasesForSinglyImplementedInterfaces()
|
||||||
->setPublic(false);
|
{
|
||||||
|
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 = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -41,10 +41,15 @@ class PhpFileLoader extends FileLoader
|
||||||
return include $path;
|
return include $path;
|
||||||
}, $this, ProtectedPhpFileLoader::class);
|
}, $this, ProtectedPhpFileLoader::class);
|
||||||
|
|
||||||
$callback = $load($path);
|
try {
|
||||||
|
$callback = $load($path);
|
||||||
|
|
||||||
if (\is_object($callback) && \is_callable($callback)) {
|
if (\is_object($callback) && \is_callable($callback)) {
|
||||||
$callback(new ContainerConfigurator($this->container, $this, $this->instanceof, $path, $resource), $this->container, $this);
|
$callback(new ContainerConfigurator($this->container, $this, $this->instanceof, $path, $resource), $this->container, $this);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
$this->instanceof = [];
|
||||||
|
$this->registerAliasesForSinglyImplementedInterfaces();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,7 @@ class XmlFileLoader extends FileLoader
|
||||||
$this->parseDefinitions($xml, $path, $defaults);
|
$this->parseDefinitions($xml, $path, $defaults);
|
||||||
} finally {
|
} finally {
|
||||||
$this->instanceof = [];
|
$this->instanceof = [];
|
||||||
|
$this->registerAliasesForSinglyImplementedInterfaces();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -150,6 +150,7 @@ class YamlFileLoader extends FileLoader
|
||||||
$this->parseDefinitions($content, $path);
|
$this->parseDefinitions($content, $path);
|
||||||
} finally {
|
} finally {
|
||||||
$this->instanceof = [];
|
$this->instanceof = [];
|
||||||
|
$this->registerAliasesForSinglyImplementedInterfaces();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\Adapter;
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\Port\PortInterface;
|
||||||
|
|
||||||
|
class Adapter implements PortInterface
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\AnotherAdapter;
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\Port\PortInterface;
|
||||||
|
|
||||||
|
class Adapter implements PortInterface
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\Port;
|
||||||
|
|
||||||
|
interface PortInterface
|
||||||
|
{
|
||||||
|
}
|
|
@ -9,7 +9,7 @@ return function (ContainerConfigurator $c) {
|
||||||
->tag('baz');
|
->tag('baz');
|
||||||
$di->load(Prototype::class.'\\', '../Prototype')
|
$di->load(Prototype::class.'\\', '../Prototype')
|
||||||
->autoconfigure()
|
->autoconfigure()
|
||||||
->exclude('../Prototype/{OtherDir,BadClasses}')
|
->exclude('../Prototype/{OtherDir,BadClasses,SinglyImplementedInterface}')
|
||||||
->factory('f')
|
->factory('f')
|
||||||
->deprecate('%service_id%')
|
->deprecate('%service_id%')
|
||||||
->args([0])
|
->args([0])
|
||||||
|
|
|
@ -9,7 +9,7 @@ return function (ContainerConfigurator $c) {
|
||||||
->tag('baz');
|
->tag('baz');
|
||||||
$di->load(Prototype::class.'\\', '../Prototype')
|
$di->load(Prototype::class.'\\', '../Prototype')
|
||||||
->autoconfigure()
|
->autoconfigure()
|
||||||
->exclude(['../Prototype/OtherDir', '../Prototype/BadClasses'])
|
->exclude(['../Prototype/OtherDir', '../Prototype/BadClasses', '../Prototype/SinglyImplementedInterface'])
|
||||||
->factory('f')
|
->factory('f')
|
||||||
->deprecate('%service_id%')
|
->deprecate('%service_id%')
|
||||||
->args([0])
|
->args([0])
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<container xmlns="http://symfony.com/schema/dic/services"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd">
|
||||||
|
<services>
|
||||||
|
<defaults autowire="true" />
|
||||||
|
|
||||||
|
<prototype namespace="Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\Adapter\"
|
||||||
|
resource="../Prototype/SinglyImplementedInterface/Adapter/*" />
|
||||||
|
<prototype namespace="Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\AnotherAdapter\"
|
||||||
|
resource="../Prototype/SinglyImplementedInterface/AnotherAdapter/*" />
|
||||||
|
<prototype namespace="Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\Port\"
|
||||||
|
resource="../Prototype/SinglyImplementedInterface/Port/*" />
|
||||||
|
</services>
|
||||||
|
</container>
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<container xmlns="http://symfony.com/schema/dic/services"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd">
|
||||||
|
<services>
|
||||||
|
<defaults autowire="true" />
|
||||||
|
|
||||||
|
<service id="Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\Port\PortInterface"
|
||||||
|
alias="Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\Adapter\Adapter" />
|
||||||
|
<prototype namespace="Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\Port\"
|
||||||
|
resource="../Prototype/SinglyImplementedInterface/Port/*" />
|
||||||
|
<prototype namespace="Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\Adapter\"
|
||||||
|
resource="../Prototype/SinglyImplementedInterface/Adapter/*" />
|
||||||
|
<prototype namespace="Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\AnotherAdapter\"
|
||||||
|
resource="../Prototype/SinglyImplementedInterface/AnotherAdapter/*" />
|
||||||
|
</services>
|
||||||
|
</container>
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<container xmlns="http://symfony.com/schema/dic/services"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd">
|
||||||
|
<services>
|
||||||
|
<defaults autowire="true" />
|
||||||
|
|
||||||
|
<prototype namespace="Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\Port\"
|
||||||
|
resource="../Prototype/SinglyImplementedInterface/Port/*" />
|
||||||
|
<prototype namespace="Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\Adapter\"
|
||||||
|
resource="../Prototype/SinglyImplementedInterface/Adapter/*" />
|
||||||
|
<service id="Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\Port\PortInterface"
|
||||||
|
alias="Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\Adapter\Adapter" />
|
||||||
|
<prototype namespace="Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\AnotherAdapter\"
|
||||||
|
resource="../Prototype/SinglyImplementedInterface/AnotherAdapter/*" />
|
||||||
|
</services>
|
||||||
|
</container>
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd">
|
<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd">
|
||||||
<services>
|
<services>
|
||||||
<prototype namespace="Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\" resource="../Prototype/*" exclude="../Prototype/{OtherDir,BadClasses}" />
|
<prototype namespace="Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\" resource="../Prototype/*" exclude="../Prototype/{OtherDir,BadClasses,SinglyImplementedInterface}" />
|
||||||
</services>
|
</services>
|
||||||
</container>
|
</container>
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
<prototype namespace="Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\" resource="../Prototype/*">
|
<prototype namespace="Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\" resource="../Prototype/*">
|
||||||
<exclude>../Prototype/OtherDir</exclude>
|
<exclude>../Prototype/OtherDir</exclude>
|
||||||
<exclude>../Prototype/BadClasses</exclude>
|
<exclude>../Prototype/BadClasses</exclude>
|
||||||
|
<exclude>../Prototype/SinglyImplementedInterface</exclude>
|
||||||
</prototype>
|
</prototype>
|
||||||
</services>
|
</services>
|
||||||
</container>
|
</container>
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<container xmlns="http://symfony.com/schema/dic/services"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd">
|
||||||
|
<services>
|
||||||
|
<defaults autowire="true" />
|
||||||
|
|
||||||
|
<prototype namespace="Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\Port\"
|
||||||
|
resource="../Prototype/SinglyImplementedInterface/Port/*" />
|
||||||
|
<prototype namespace="Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\SinglyImplementedInterface\Adapter\"
|
||||||
|
resource="../Prototype/SinglyImplementedInterface/Adapter/*" />
|
||||||
|
</services>
|
||||||
|
</container>
|
|
@ -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/*
|
|
@ -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/*
|
|
@ -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/*
|
|
@ -1,4 +1,4 @@
|
||||||
services:
|
services:
|
||||||
Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\:
|
Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\:
|
||||||
resource: ../Prototype
|
resource: ../Prototype
|
||||||
exclude: '../Prototype/{OtherDir,BadClasses}'
|
exclude: '../Prototype/{OtherDir,BadClasses,SinglyImplementedInterface}'
|
||||||
|
|
|
@ -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/*
|
|
@ -240,4 +240,10 @@ class TestFileLoader extends FileLoader
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function registerClasses(Definition $prototype, $namespace, $resource, $exclude = null)
|
||||||
|
{
|
||||||
|
parent::registerClasses($prototype, $namespace, $resource, $exclude);
|
||||||
|
$this->registerAliasesForSinglyImplementedInterfaces();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -652,6 +652,7 @@ class XmlFileLoaderTest extends TestCase
|
||||||
[
|
[
|
||||||
str_replace(\DIRECTORY_SEPARATOR, '/', $prototypeRealPath.\DIRECTORY_SEPARATOR.'OtherDir') => true,
|
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.'BadClasses') => true,
|
||||||
|
str_replace(\DIRECTORY_SEPARATOR, '/', $prototypeRealPath.\DIRECTORY_SEPARATOR.'SinglyImplementedInterface') => true,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
$this->assertContains((string) $globResource, $resources);
|
$this->assertContains((string) $globResource, $resources);
|
||||||
|
@ -684,6 +685,7 @@ class XmlFileLoaderTest extends TestCase
|
||||||
[
|
[
|
||||||
str_replace(\DIRECTORY_SEPARATOR, '/', $prototypeRealPath.\DIRECTORY_SEPARATOR.'BadClasses') => true,
|
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.'OtherDir') => true,
|
||||||
|
str_replace(\DIRECTORY_SEPARATOR, '/', $prototypeRealPath.\DIRECTORY_SEPARATOR.'SinglyImplementedInterface') => true,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
$this->assertContains((string) $globResource, $resources);
|
$this->assertContains((string) $globResource, $resources);
|
||||||
|
@ -901,4 +903,50 @@ class XmlFileLoaderTest extends TestCase
|
||||||
|
|
||||||
$this->assertSame('overridden', $container->get('bar')->quz);
|
$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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -421,6 +421,7 @@ class YamlFileLoaderTest extends TestCase
|
||||||
false, [
|
false, [
|
||||||
str_replace(\DIRECTORY_SEPARATOR, '/', $prototypeRealPath.\DIRECTORY_SEPARATOR.'BadClasses') => true,
|
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.'OtherDir') => true,
|
||||||
|
str_replace(\DIRECTORY_SEPARATOR, '/', $prototypeRealPath.\DIRECTORY_SEPARATOR.'SinglyImplementedInterface') => true,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
$this->assertContains((string) $globResource, $resources);
|
$this->assertContains((string) $globResource, $resources);
|
||||||
|
@ -840,4 +841,50 @@ class YamlFileLoaderTest extends TestCase
|
||||||
$this->assertInstanceOf(TaggedIteratorArgument::class, $iteratorArgument);
|
$this->assertInstanceOf(TaggedIteratorArgument::class, $iteratorArgument);
|
||||||
$this->assertNull($iteratorArgument->getIndexAttribute());
|
$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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in New Issue