From 9828da296f6f2f45a741fffc8acd28e85f14a0e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Mon, 24 Aug 2015 03:36:41 +0200 Subject: [PATCH 01/19] [DependencyInjection] Add autowiring capabilities --- .../Compiler/AutowiringPass.php | 233 +++++++++++++++++ .../Compiler/PassConfig.php | 1 + .../DependencyInjection/Definition.php | 68 +++++ .../Loader/XmlFileLoader.php | 4 + .../Loader/YamlFileLoader.php | 14 + .../schema/dic/services/services-1.0.xsd | 1 + .../Tests/Compiler/AutowiringPassTest.php | 239 ++++++++++++++++++ .../Tests/ContainerBuilderTest.php | 23 ++ .../Tests/DefinitionTest.php | 13 + .../Tests/Fixtures/xml/services22.xml | 9 + .../Tests/Fixtures/yaml/bad_types1.yml | 5 + .../Tests/Fixtures/yaml/bad_types2.yml | 5 + .../Tests/Fixtures/yaml/services22.yml | 4 + .../Tests/Loader/XmlFileLoaderTest.php | 9 + .../Tests/Loader/YamlFileLoaderTest.php | 27 ++ 15 files changed, 655 insertions(+) create mode 100644 src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowiringPassTest.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services22.xml create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_types1.yml create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_types2.yml create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services22.yml diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php new file mode 100644 index 0000000000000..bae46b85ac88c --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php @@ -0,0 +1,233 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Guesses constructor arguments of services definitions and try to instantiate services if necessary. + * + * @author Kévin Dunglas + */ +class AutowiringPass implements CompilerPassInterface +{ + private $container; + private $definitions; + private $reflectionClassesToId = array(); + private $definedTypes = array(); + private $typesToId; + private $notGuessableTypesToId = array(); + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $this->container = $container; + $this->definitions = $container->getDefinitions(); + foreach ($this->definitions as $id => $definition) { + $this->completeDefinition($id, $definition, $container); + } + } + + /** + * Wires the given definition. + * + * @param string $id + * @param Definition $definition + * + * @throws RuntimeException + */ + private function completeDefinition($id, Definition $definition) + { + if (!($reflectionClass = $this->getReflectionClass($id, $definition))) { + return; + } + + if (!($constructor = $reflectionClass->getConstructor())) { + return; + } + + $arguments = $definition->getArguments(); + foreach ($constructor->getParameters() as $index => $parameter) { + if (!($typeHint = $parameter->getClass()) || $parameter->isOptional()) { + continue; + } + + $argumentExist = array_key_exists($index, $arguments); + if ($argumentExist && '' !== $arguments[$index]) { + continue; + } + + if (null === $this->typesToId) { + $this->populateAvailableTypes(); + } + + if (isset($this->typesToId[$typeHint->name])) { + $reference = new Reference($this->typesToId[$typeHint->name]); + } else { + $reference = $this->createAutowiredDefinition($typeHint); + } + + if ($argumentExist) { + $definition->replaceArgument($index, $reference); + } else { + $definition->addArgument($reference); + } + } + } + + /** + * Populates the list of available types. + */ + private function populateAvailableTypes() + { + $this->typesToId = array(); + + foreach ($this->definitions as $id => $definition) { + $this->populateAvailableType($id, $definition); + } + } + + /** + * Populates the of available types for a given definition. + * + * @param string $id + * @param Definition $definition + */ + private function populateAvailableType($id, Definition $definition) { + if (!($class = $definition->getClass())) { + return; + } + + foreach ($definition->getTypes() as $type) { + $this->definedTypes[$type] = true; + $this->typesToId[$type] = $id; + } + + if ($reflectionClass = $this->getReflectionClass($id, $definition)) { + $this->extractInterfaces($id, $reflectionClass); + $this->extractAncestors($id, $reflectionClass); + } + } + + /** + * Extracts the list of all interfaces implemented by a class. + * + * @param string $id + * @param \ReflectionClass $reflectionClass + */ + private function extractInterfaces($id, \ReflectionClass $reflectionClass) + { + foreach ($reflectionClass->getInterfaces() as $interfaceName => $reflectionInterface) { + $this->set($interfaceName, $id); + + $this->extractInterfaces($id, $reflectionInterface); + } + } + + /** + * Extracts all inherited types of a class. + * + * @param string $id + * @param \ReflectionClass $reflectionClass + */ + private function extractAncestors($id, \ReflectionClass $reflectionClass) + { + $this->set($reflectionClass->name, $id); + + if ($reflectionParentClass = $reflectionClass->getParentClass()) { + $this->extractAncestors($id, $reflectionParentClass); + } + } + + /** + * Associates if applicable a type and a service id or a class. + * + * @param string $type + * @param string $value A service id or a class name depending of the value of $class + */ + private function set($type, $value) + { + if (isset($this->definedTypes[$type]) || isset($this->notGuessableTypesToId[$type])) { + return; + } + + if (isset($this->typesToId[$type])) { + if ($this->typesToId[$type] === $value) { + return; + } + + unset($this->typesToId[$type]); + + $this->notGuessableTypesToId[$type] = true; + return; + } + + $this->typesToId[$type] = $value; + } + + /** + * Registers a definition for the type if possible or throws an exception. + * + * @param \ReflectionClass $typeHint + * + * @return Reference A reference to the registered definition + * + * @throws RuntimeException + */ + private function createAutowiredDefinition(\ReflectionClass $typeHint) + { + if (!$typeHint->isInstantiable()) { + throw new RuntimeException(sprintf('Unable to autowire type "%s".', $typeHint->name)); + } + + $argumentId = sprintf('autowired.%s', $typeHint->name); + + $argumentDefinition = $this->container->register($argumentId, $typeHint->name); + $argumentDefinition->setPublic(false); + + $this->definitions = $this->container->getDefinitions(); + $this->populateAvailableType($argumentId, $argumentDefinition); + $this->completeDefinition($argumentId, $argumentDefinition); + + return new Reference($argumentId); + } + + /** + * Retrieves the reflection class associated with the given service. + * + * @param string $id + * @param Definition $definition + * + * @return \ReflectionClass|null + */ + private function getReflectionClass($id, Definition $definition) + { + if (isset($this->reflectionClassesToId[$id])) { + return $this->reflectionClassesToId[$id]; + } + + if (!$class = $definition->getClass()) { + return; + } + + try { + return $this->reflectionClassesToId[$id] = new \ReflectionClass($class); + } catch (\ReflectionException $e) { + // Skip invalid classes definitions to keep BC + } + } +} diff --git a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php index 2849dfe129a78..e89a00bb4d19e 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php @@ -51,6 +51,7 @@ public function __construct() new ResolveReferencesToAliasesPass(), new ResolveInvalidReferencesPass(), new AnalyzeServiceReferencesPass(true), + new AutowiringPass(), new CheckCircularReferencesPass(), new CheckReferenceValidityPass(), ); diff --git a/src/Symfony/Component/DependencyInjection/Definition.php b/src/Symfony/Component/DependencyInjection/Definition.php index 9ce81e3a12cfa..0bcd11b0263c7 100644 --- a/src/Symfony/Component/DependencyInjection/Definition.php +++ b/src/Symfony/Component/DependencyInjection/Definition.php @@ -41,6 +41,7 @@ class Definition private $synchronized = false; private $lazy = false; private $decoratedService; + private $types = array(); protected $arguments; @@ -818,4 +819,71 @@ public function getConfigurator() { return $this->configurator; } + + /** + * Sets types that will default to this definition. + * + * @param string[] $types + * + * @return Definition The current instance + */ + public function setTypes(array $types) + { + $this->types = array(); + + foreach ($types as $type) { + $this->types[$type] = true; + } + + return $this; + } + + /** + * Gets types that will default to this definition. + * + * @return string[] + */ + public function getTypes() + { + return array_keys($this->types); + } + + /** + * Adds a type that will default to this definition. + * + * @param string $type + * + * @return Definition The current instance + */ + public function addType($type) + { + $this->types[$type] = true; + + return $this; + } + + /** + * Removes a type. + * + * @param string $type + * + * @return Definition The current instance + */ + public function removeType($type) + { + unset($this->types[$type]); + + return $this; + } + + /** + * Will this definition default for the given type? + * + * @param string $type + * + * @return bool + */ + public function hasType($type) { + return isset($this->types[$type]); + } } diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index 8a0e4ac24a65a..fa2c3f9234f6b 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -247,6 +247,10 @@ private function parseDefinition(\DOMElement $service, $file) $definition->addTag($tag->getAttribute('name'), $parameters); } + foreach ($this->getChildren($service, 'type') as $type) { + $definition->addType($type->textContent); + } + if ($value = $service->getAttribute('decorates')) { $renameId = $service->hasAttribute('decoration-inner-name') ? $service->getAttribute('decoration-inner-name') : null; $priority = $service->hasAttribute('decoration-priority') ? $service->getAttribute('decoration-priority') : 0; diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index 19191a760c6cd..508c65144b7c6 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -299,6 +299,20 @@ private function parseDefinition($id, $service, $file) $definition->setDecoratedService($service['decorates'], $renameId, $priority); } + if (isset($service['types'])) { + if (!is_array($service['types'])) { + throw new InvalidArgumentException(sprintf('Parameter "types" must be an array for service "%s" in %s. Check your YAML syntax.', $id, $file)); + } + + foreach ($service['types'] as $type) { + if (!is_string($type)) { + throw new InvalidArgumentException(sprintf('A "types" attribute must be of type string for service "%s" in %s. Check your YAML syntax.', $id, $file)); + } + + $definition->addType($type); + } + } + $this->container->setDefinition($id, $definition); } 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 cbaa3606f7a04..1bf4eb5bc0859 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 @@ -85,6 +85,7 @@ + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowiringPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowiringPassTest.php new file mode 100644 index 0000000000000..f656cc3526674 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowiringPassTest.php @@ -0,0 +1,239 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Compiler; + +use Symfony\Component\DependencyInjection\Compiler\AutowiringPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * @author Kévin Dunglas + */ +class AutowiringPassTest extends \PHPUnit_Framework_TestCase +{ + public function testProcess() + { + $container = new ContainerBuilder(); + + $container->register('foo', __NAMESPACE__.'\Foo'); + $container->register('bar', __NAMESPACE__.'\Bar'); + + $pass = new AutowiringPass(); + $pass->process($container); + + $this->assertCount(1, $container->getDefinition('bar')->getArguments()); + $this->assertEquals('foo', (string) $container->getDefinition('bar')->getArgument(0)); + } + + public function testProcessAutowireParent() + { + $container = new ContainerBuilder(); + + $container->register('b', __NAMESPACE__.'\B'); + $container->register('c', __NAMESPACE__.'\C'); + + $pass = new AutowiringPass(); + $pass->process($container); + + $this->assertCount(1, $container->getDefinition('c')->getArguments()); + $this->assertEquals('b', (string) $container->getDefinition('c')->getArgument(0)); + } + + public function testProcessAutowireInterface() + { + $container = new ContainerBuilder(); + + $container->register('f', __NAMESPACE__.'\F'); + $container->register('g', __NAMESPACE__.'\G'); + + $pass = new AutowiringPass(); + $pass->process($container); + + $this->assertCount(2, $container->getDefinition('g')->getArguments()); + $this->assertEquals('f', (string) $container->getDefinition('g')->getArgument(0)); + $this->assertEquals('f', (string) $container->getDefinition('g')->getArgument(1)); + } + + public function testCompleteExistingDefinition() + { + $container = new ContainerBuilder(); + + $container->register('b', __NAMESPACE__.'\B'); + $container->register('f', __NAMESPACE__.'\F'); + $container->register('h', __NAMESPACE__.'\H')->addArgument(new Reference('b')); + + $pass = new AutowiringPass(); + $pass->process($container); + + $this->assertCount(2, $container->getDefinition('h')->getArguments()); + $this->assertEquals('b', (string) $container->getDefinition('h')->getArgument(0)); + $this->assertEquals('f', (string) $container->getDefinition('h')->getArgument(1)); + } + + public function testCompleteExistingDefinitionWithNotDefinedArguments() + { + $container = new ContainerBuilder(); + + $container->register('b', __NAMESPACE__.'\B'); + $container->register('f', __NAMESPACE__.'\F'); + $container->register('h', __NAMESPACE__.'\H')->addArgument('')->addArgument(''); + + $pass = new AutowiringPass(); + $pass->process($container); + + $this->assertCount(2, $container->getDefinition('h')->getArguments()); + $this->assertEquals('b', (string) $container->getDefinition('h')->getArgument(0)); + $this->assertEquals('f', (string) $container->getDefinition('h')->getArgument(1)); + } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedExceptionMessage Unable to autowire type "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface". + */ + public function testTypeCollision() + { + $container = new ContainerBuilder(); + + $container->register('c1', __NAMESPACE__.'\CollisionA'); + $container->register('c2', __NAMESPACE__.'\CollisionB'); + $container->register('a', __NAMESPACE__.'\CannotBeAutowired'); + + $pass = new AutowiringPass(); + $pass->process($container); + } + + public function testWithTypeSet() + { + $container = new ContainerBuilder(); + + $container->register('c1', __NAMESPACE__.'\CollisionA'); + $container->register('c2', __NAMESPACE__.'\CollisionB')->addType(__NAMESPACE__.'\CollisionInterface'); + $container->register('a', __NAMESPACE__.'\CannotBeAutowired'); + + $pass = new AutowiringPass(); + $pass->process($container); + + $this->assertCount(1, $container->getDefinition('a')->getArguments()); + $this->assertEquals('c2', (string) $container->getDefinition('a')->getArgument(0)); + } + + public function testCreateDefinition() + { + $container = new ContainerBuilder(); + + $container->register('coop_tilleuls', __NAMESPACE__.'\LesTilleuls'); + + $pass = new AutowiringPass(); + $pass->process($container); + + $this->assertCount(1, $container->getDefinition('coop_tilleuls')->getArguments()); + $this->assertEquals('autowired.symfony\component\dependencyinjection\tests\compiler\dunglas', $container->getDefinition('coop_tilleuls')->getArgument(0)); + + $dunglasDefinition = $container->getDefinition('autowired.symfony\component\dependencyinjection\tests\compiler\dunglas'); + $this->assertEquals(__NAMESPACE__.'\Dunglas', $dunglasDefinition->getClass()); + $this->assertFalse($dunglasDefinition->isPublic()); + $this->assertCount(1, $dunglasDefinition->getArguments()); + $this->assertEquals('autowired.symfony\component\dependencyinjection\tests\compiler\lille', $dunglasDefinition->getArgument(0)); + + $lilleDefinition = $container->getDefinition('autowired.symfony\component\dependencyinjection\tests\compiler\lille'); + $this->assertEquals(__NAMESPACE__.'\Lille', $lilleDefinition->getClass()); + } +} + +class Foo +{ +} + +class Bar +{ + public function __construct(Foo $foo) + { + } +} + +class A +{ +} + +class B extends A +{ +} + +class C +{ + public function __construct(A $a) + { + } +} + +interface DInterface +{ +} + +interface EInterface extends DInterface +{ +} + +class F implements EInterface +{ +} + +class G +{ + public function __construct(DInterface $d, EInterface $e) + { + } +} + +class H +{ + public function __construct(B $b, DInterface $d) + { + } +} + +interface CollisionInterface +{ +} + +class CollisionA implements CollisionInterface +{ +} + +class CollisionB implements CollisionInterface +{ +} + +class CannotBeAutowired +{ + public function __construct(CollisionInterface $collision) + { + } +} + +class Lille +{ +} + +class Dunglas +{ + public function __construct(Lille $l) + { + } +} + +class LesTilleuls +{ + public function __construct(Dunglas $k) + { + } +} diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index 047a7cf3347f4..1a4c810239810 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -890,6 +890,18 @@ public function testLazyLoadedService() $this->assertTrue($classInList); } + + public function testAutowiring() + { + $container = new ContainerBuilder(); + + $container->register('a', __NAMESPACE__.'\A'); + $container->register('b', __NAMESPACE__.'\B'); + + $container->compile(); + + $this->assertEquals('a', (string) $container->getDefinition('b')->getArgument(0)); + } } class FooClass @@ -903,3 +915,14 @@ public function getFoobazService() throw new InactiveScopeException('foo', 'request'); } } + +class A +{ +} + +class B +{ + public function __construct(A $a) + { + } +} diff --git a/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php b/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php index ea3045df1acbc..fab48f50c746b 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php @@ -394,4 +394,17 @@ public function testSetProperty() $this->assertSame($def, $def->setProperty('foo', 'bar')); $this->assertEquals(array('foo' => 'bar'), $def->getProperties()); } + + public function testTypes() + { + $def = new Definition('stdClass'); + + $this->assertEquals(array(), $def->getTypes()); + $this->assertSame($def, $def->setTypes(array('Foo'))); + $this->assertEquals(array('Foo'), $def->getTypes()); + $this->assertSame($def, $def->addType('Bar')); + $this->assertTrue($def->hasType('Bar')); + $this->assertSame($def, $def->removeType('Foo')); + $this->assertEquals(array('Bar'), $def->getTypes()); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services22.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services22.xml new file mode 100644 index 0000000000000..7b5ffe7c3ca67 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services22.xml @@ -0,0 +1,9 @@ + + + + + Bar + Baz + + + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_types1.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_types1.yml new file mode 100644 index 0000000000000..79d676f2bf569 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_types1.yml @@ -0,0 +1,5 @@ +services: + foo_service: + class: FooClass + # types is not an array + types: string diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_types2.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_types2.yml new file mode 100644 index 0000000000000..c26e077185723 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_types2.yml @@ -0,0 +1,5 @@ +services: + foo_service: + class: FooClass + # type is not a string + types: [ 1 ] diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services22.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services22.yml new file mode 100644 index 0000000000000..9fa7d0c57b900 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services22.yml @@ -0,0 +1,4 @@ +services: + foo_service: + class: FooClass + types: [ Foo, Bar ] diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php index b717113bb436a..512af94b9ae49 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php @@ -494,4 +494,13 @@ public function testLoadInlinedServices() $this->assertSame('Baz', $barConfigurator[0]->getClass()); $this->assertSame('configureBar', $barConfigurator[1]); } + + public function testType() + { + $container = new ContainerBuilder(); + $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); + $loader->load('services22.xml'); + + $this->assertEquals(array('Bar', 'Baz'), $container->getDefinition('foo')->getTypes()); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php index 2d1b0b6956f73..6bfaa5996a72e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php @@ -282,4 +282,31 @@ public function testLoadYamlOnlyWithKeys() $this->assertEquals(array(true), $definition->getArguments()); $this->assertEquals(array('manager' => array(array('alias' => 'user'))), $definition->getTags()); } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + */ + public function testTypesNotArray() + { + $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml')); + $loader->load('bad_types1.yml'); + } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + */ + public function testTypeNotString() + { + $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml')); + $loader->load('bad_types2.yml'); + } + + public function testTypes() + { + $container = new ContainerBuilder(); + $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); + $loader->load('services22.yml'); + + $this->assertEquals(array('Foo', 'Bar'), $container->getDefinition('foo_service')->getTypes()); + } } From 195f6c0abc0ff15ef7cfddf3e14d0283737abdd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 25 Aug 2015 14:54:58 +0200 Subject: [PATCH 02/19] Fix CS --- .../DependencyInjection/Compiler/AutowiringPass.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php index bae46b85ac88c..4dfc06e11c930 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php @@ -45,7 +45,7 @@ public function process(ContainerBuilder $container) /** * Wires the given definition. * - * @param string $id + * @param string $id * @param Definition $definition * * @throws RuntimeException @@ -171,8 +171,8 @@ private function set($type, $value) } unset($this->typesToId[$type]); - $this->notGuessableTypesToId[$type] = true; + return; } @@ -209,7 +209,7 @@ private function createAutowiredDefinition(\ReflectionClass $typeHint) /** * Retrieves the reflection class associated with the given service. * - * @param string $id + * @param string $id * @param Definition $definition * * @return \ReflectionClass|null From 8d23c9d52e40bc04b1bfd37067ce1f3bdd592e7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 25 Aug 2015 15:04:14 +0200 Subject: [PATCH 03/19] Remove unused argument --- .../Component/DependencyInjection/Compiler/AutowiringPass.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php index 4dfc06e11c930..0f6a49492f2f1 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php @@ -38,7 +38,7 @@ public function process(ContainerBuilder $container) $this->container = $container; $this->definitions = $container->getDefinitions(); foreach ($this->definitions as $id => $definition) { - $this->completeDefinition($id, $definition, $container); + $this->completeDefinition($id, $definition); } } From 27f4de83de82d90b19d31d4997deac7caa1eb09d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 25 Aug 2015 17:11:08 +0200 Subject: [PATCH 04/19] Fix CS --- .../Component/DependencyInjection/Compiler/AutowiringPass.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php index 0f6a49492f2f1..d9cc26c3c4c8a 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php @@ -107,7 +107,8 @@ private function populateAvailableTypes() * @param string $id * @param Definition $definition */ - private function populateAvailableType($id, Definition $definition) { + private function populateAvailableType($id, Definition $definition) + { if (!($class = $definition->getClass())) { return; } From 5575ec1d9537fd35c0ad736542f1ed4dd53aac47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 25 Aug 2015 22:31:37 +0200 Subject: [PATCH 05/19] Fix issues raised by @stof --- .../Compiler/AutowiringPass.php | 66 +++++++++++-------- .../Compiler/PassConfig.php | 2 +- .../Tests/Compiler/AutowiringPassTest.php | 38 +++++++++++ 3 files changed, 79 insertions(+), 27 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php index d9cc26c3c4c8a..30205ad72f962 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php @@ -24,11 +24,10 @@ class AutowiringPass implements CompilerPassInterface { private $container; - private $definitions; - private $reflectionClassesToId = array(); + private $reflectionClasses = array(); private $definedTypes = array(); - private $typesToId; - private $notGuessableTypesToId = array(); + private $types; + private $notGuessableTypes = array(); /** * {@inheritdoc} @@ -36,10 +35,16 @@ class AutowiringPass implements CompilerPassInterface public function process(ContainerBuilder $container) { $this->container = $container; - $this->definitions = $container->getDefinitions(); - foreach ($this->definitions as $id => $definition) { + foreach ($container->getDefinitions() as $id => $definition) { $this->completeDefinition($id, $definition); } + + // Free memory and remove circular reference to container + $this->container = null; + $this->reflectionClasses = array(); + $this->definedTypes = array(); + $this->types = null; + $this->notGuessableTypes = array(); } /** @@ -62,7 +67,7 @@ private function completeDefinition($id, Definition $definition) $arguments = $definition->getArguments(); foreach ($constructor->getParameters() as $index => $parameter) { - if (!($typeHint = $parameter->getClass()) || $parameter->isOptional()) { + if (!($typeHint = $parameter->getClass())) { continue; } @@ -71,20 +76,28 @@ private function completeDefinition($id, Definition $definition) continue; } - if (null === $this->typesToId) { + if (null === $this->types) { $this->populateAvailableTypes(); } - if (isset($this->typesToId[$typeHint->name])) { - $reference = new Reference($this->typesToId[$typeHint->name]); + if (isset($this->types[$typeHint->name])) { + $value = new Reference($this->types[$typeHint->name]); } else { - $reference = $this->createAutowiredDefinition($typeHint); + try { + $value = $this->createAutowiredDefinition($typeHint); + } catch (RuntimeException $e) { + if (!$parameter->isDefaultValueAvailable()) { + throw $e; + } + + $value = $parameter->getDefaultValue(); + } } if ($argumentExist) { - $definition->replaceArgument($index, $reference); + $definition->replaceArgument($index, $value); } else { - $definition->addArgument($reference); + $definition->addArgument($value); } } } @@ -94,9 +107,9 @@ private function completeDefinition($id, Definition $definition) */ private function populateAvailableTypes() { - $this->typesToId = array(); + $this->types = array(); - foreach ($this->definitions as $id => $definition) { + foreach ($this->container->getDefinitions() as $id => $definition) { $this->populateAvailableType($id, $definition); } } @@ -115,7 +128,7 @@ private function populateAvailableType($id, Definition $definition) foreach ($definition->getTypes() as $type) { $this->definedTypes[$type] = true; - $this->typesToId[$type] = $id; + $this->types[$type] = $id; } if ($reflectionClass = $this->getReflectionClass($id, $definition)) { @@ -162,22 +175,22 @@ private function extractAncestors($id, \ReflectionClass $reflectionClass) */ private function set($type, $value) { - if (isset($this->definedTypes[$type]) || isset($this->notGuessableTypesToId[$type])) { + if (isset($this->definedTypes[$type]) || isset($this->notGuessableTypes[$type])) { return; } - if (isset($this->typesToId[$type])) { - if ($this->typesToId[$type] === $value) { + if (isset($this->types[$type])) { + if ($this->types[$type] === $value) { return; } - unset($this->typesToId[$type]); - $this->notGuessableTypesToId[$type] = true; + unset($this->types[$type]); + $this->notGuessableTypes[$type] = true; return; } - $this->typesToId[$type] = $value; + $this->types[$type] = $value; } /** @@ -200,7 +213,6 @@ private function createAutowiredDefinition(\ReflectionClass $typeHint) $argumentDefinition = $this->container->register($argumentId, $typeHint->name); $argumentDefinition->setPublic(false); - $this->definitions = $this->container->getDefinitions(); $this->populateAvailableType($argumentId, $argumentDefinition); $this->completeDefinition($argumentId, $argumentDefinition); @@ -217,16 +229,18 @@ private function createAutowiredDefinition(\ReflectionClass $typeHint) */ private function getReflectionClass($id, Definition $definition) { - if (isset($this->reflectionClassesToId[$id])) { - return $this->reflectionClassesToId[$id]; + if (isset($this->reflectionClasses[$id])) { + return $this->reflectionClasses[$id]; } if (!$class = $definition->getClass()) { return; } + $class = $this->container->getParameterBag()->resolveValue($class); + try { - return $this->reflectionClassesToId[$id] = new \ReflectionClass($class); + return $this->reflectionClasses[$id] = new \ReflectionClass($class); } catch (\ReflectionException $e) { // Skip invalid classes definitions to keep BC } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php index e89a00bb4d19e..efbf8f8023b66 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php @@ -50,8 +50,8 @@ public function __construct() new CheckDefinitionValidityPass(), new ResolveReferencesToAliasesPass(), new ResolveInvalidReferencesPass(), - new AnalyzeServiceReferencesPass(true), new AutowiringPass(), + new AnalyzeServiceReferencesPass(true), new CheckCircularReferencesPass(), new CheckReferenceValidityPass(), ); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowiringPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowiringPassTest.php index f656cc3526674..76c71cc7f1190 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowiringPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowiringPassTest.php @@ -147,6 +147,37 @@ public function testCreateDefinition() $lilleDefinition = $container->getDefinition('autowired.symfony\component\dependencyinjection\tests\compiler\lille'); $this->assertEquals(__NAMESPACE__.'\Lille', $lilleDefinition->getClass()); } + + public function testResolveParameter() + { + $container = new ContainerBuilder(); + + $container->setParameter('class_name', __NAMESPACE__.'\Foo'); + $container->register('foo', '%class_name%'); + $container->register('bar', __NAMESPACE__.'\Bar'); + + $pass = new AutowiringPass(); + $pass->process($container); + + $this->assertEquals('foo', $container->getDefinition('bar')->getArgument(0)); + } + + public function testOptionalParameter() + { + $container = new ContainerBuilder(); + + $container->register('a', __NAMESPACE__.'\A'); + $container->register('foo', __NAMESPACE__.'\Foo'); + $container->register('opt', __NAMESPACE__.'\OptionalParameter'); + + $pass = new AutowiringPass(); + $pass->process($container); + + $definition = $container->getDefinition('opt'); + $this->assertNull($definition->getArgument(0)); + $this->assertEquals('a', $definition->getArgument(1)); + $this->assertEquals('foo', $definition->getArgument(2)); + } } class Foo @@ -237,3 +268,10 @@ public function __construct(Dunglas $k) { } } + +class OptionalParameter +{ + public function __construct(CollisionInterface $c = null, A $a, Foo $f = null) + { + } +} From edce23da281bcf5bc9bcdb6d4ef37e5096eb7f86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Wed, 26 Aug 2015 09:56:03 +0200 Subject: [PATCH 06/19] Better RunTime exception error. --- .../DependencyInjection/Compiler/AutowiringPass.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php index 30205ad72f962..a62e1827424ec 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php @@ -84,7 +84,7 @@ private function completeDefinition($id, Definition $definition) $value = new Reference($this->types[$typeHint->name]); } else { try { - $value = $this->createAutowiredDefinition($typeHint); + $value = $this->createAutowiredDefinition($typeHint, $id); } catch (RuntimeException $e) { if (!$parameter->isDefaultValueAvailable()) { throw $e; @@ -197,15 +197,15 @@ private function set($type, $value) * Registers a definition for the type if possible or throws an exception. * * @param \ReflectionClass $typeHint - * + * @param string $id * @return Reference A reference to the registered definition * * @throws RuntimeException */ - private function createAutowiredDefinition(\ReflectionClass $typeHint) + private function createAutowiredDefinition(\ReflectionClass $typeHint, $id) { if (!$typeHint->isInstantiable()) { - throw new RuntimeException(sprintf('Unable to autowire type "%s".', $typeHint->name)); + throw new RuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s".', $typeHint->name, $id)); } $argumentId = sprintf('autowired.%s', $typeHint->name); From 07d475ec2941c6808e580d52901fc7f8b49a59a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Wed, 26 Aug 2015 10:20:44 +0200 Subject: [PATCH 07/19] Fix CS --- .../DependencyInjection/Compiler/AutowiringPass.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php index a62e1827424ec..35d4637ba4d06 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php @@ -71,8 +71,8 @@ private function completeDefinition($id, Definition $definition) continue; } - $argumentExist = array_key_exists($index, $arguments); - if ($argumentExist && '' !== $arguments[$index]) { + $argumentExists = array_key_exists($index, $arguments); + if ($argumentExists && '' !== $arguments[$index]) { continue; } @@ -94,7 +94,7 @@ private function completeDefinition($id, Definition $definition) } } - if ($argumentExist) { + if ($argumentExists) { $definition->replaceArgument($index, $value); } else { $definition->addArgument($value); @@ -198,6 +198,7 @@ private function set($type, $value) * * @param \ReflectionClass $typeHint * @param string $id + * * @return Reference A reference to the registered definition * * @throws RuntimeException From afe009ad399442b3d1b12c40fb8da6eb1ef036bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 27 Aug 2015 23:26:51 +0200 Subject: [PATCH 08/19] Flag to enable/disable autowiring. no_autowiring tag. --- .../Resources/config/annotations.xml | 2 ++ .../FrameworkBundle/Resources/config/session.xml | 4 +++- .../Compiler/AutowiringPass.php | 6 +++++- .../DependencyInjection/Compiler/Compiler.php | 6 ++++-- .../DependencyInjection/Compiler/PassConfig.php | 14 +++++++++++--- .../DependencyInjection/ContainerBuilder.php | 2 +- .../Tests/Compiler/AutowiringPassTest.php | 16 +++++++++++++++- src/Symfony/Component/HttpKernel/Kernel.php | 2 ++ 8 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.xml index 1c0c312dc2673..e3b121c418687 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.xml @@ -17,6 +17,8 @@ + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml index 591f92e456ddc..59061036669a8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml @@ -55,7 +55,9 @@ %session.save_path% - + + + diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php index 35d4637ba4d06..ac14984864359 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php @@ -23,6 +23,8 @@ */ class AutowiringPass implements CompilerPassInterface { + const NO_AUTOWIRING = 'no_autowiring'; + private $container; private $reflectionClasses = array(); private $definedTypes = array(); @@ -36,7 +38,9 @@ public function process(ContainerBuilder $container) { $this->container = $container; foreach ($container->getDefinitions() as $id => $definition) { - $this->completeDefinition($id, $definition); + if (!$definition->hasTag(self::NO_AUTOWIRING)) { + $this->completeDefinition($id, $definition); + } } // Free memory and remove circular reference to container diff --git a/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php b/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php index 4e4c2cdaba5b9..3617b7ab91b29 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php @@ -27,10 +27,12 @@ class Compiler /** * Constructor. + * + * @param bool $autowiring Enable the autowiring */ - public function __construct() + public function __construct($autowiring = false) { - $this->passConfig = new PassConfig(); + $this->passConfig = new PassConfig($autowiring); $this->serviceReferenceGraph = new ServiceReferenceGraph(); $this->loggingFormatter = new LoggingFormatter(); } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php index efbf8f8023b66..ecfb52ee81ba4 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php @@ -37,8 +37,10 @@ class PassConfig /** * Constructor. + * + * @param bool $autowiring Enable the autowiring */ - public function __construct() + public function __construct($autowiring = false) { $this->mergePass = new MergeExtensionConfigurationPass(); @@ -50,11 +52,17 @@ public function __construct() new CheckDefinitionValidityPass(), new ResolveReferencesToAliasesPass(), new ResolveInvalidReferencesPass(), - new AutowiringPass(), + ); + + if ($autowiring) { + $this->optimizationPasses[] = new AutowiringPass(); + } + + $this->optimizationPasses = array_merge($this->optimizationPasses, array( new AnalyzeServiceReferencesPass(true), new CheckCircularReferencesPass(), new CheckReferenceValidityPass(), - ); + )); $this->removingPasses = array( new RemovePrivateAliasesPass(), diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 0f893e66e9885..7a1402f7d67e2 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -325,7 +325,7 @@ public function getCompilerPassConfig() public function getCompiler() { if (null === $this->compiler) { - $this->compiler = new Compiler(); + $this->compiler = new Compiler($this->hasParameter('container.autowiring') ? $this->getParameter('container.autowiring') : false); } return $this->compiler; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowiringPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowiringPassTest.php index 76c71cc7f1190..d3b801ee916d8 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowiringPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowiringPassTest.php @@ -97,7 +97,7 @@ public function testCompleteExistingDefinitionWithNotDefinedArguments() /** * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException - * @expectedExceptionMessage Unable to autowire type "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface". + * @expectedExceptionMessage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" for the service "a". */ public function testTypeCollision() { @@ -178,6 +178,20 @@ public function testOptionalParameter() $this->assertEquals('a', $definition->getArgument(1)); $this->assertEquals('foo', $definition->getArgument(2)); } + + public function testNoAutowiringTag() + { + $container = new ContainerBuilder(); + + $container->register('foo', __NAMESPACE__.'\Foo'); + $barDefintion = $container->register('bar', __NAMESPACE__.'\Bar'); + $barDefintion->addTag(AutowiringPass::NO_AUTOWIRING); + + $pass = new AutowiringPass(); + $pass->process($container); + + $this->assertCount(0, $container->getDefinition('bar')->getArguments()); + } } class Foo diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 7c55172d395ae..8acb507d32efa 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -59,6 +59,7 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $name; protected $startTime; protected $loadClassCache; + protected $containerAutowiring = true; const VERSION = '2.8.0-DEV'; const VERSION_ID = 20800; @@ -552,6 +553,7 @@ protected function getKernelParameters() 'kernel.bundles' => $bundles, 'kernel.charset' => $this->getCharset(), 'kernel.container_class' => $this->getContainerClass(), + 'container.autowiring' => $this->containerAutowiring, ), $this->getEnvParameters() ); From 7ab5b0873ed24ec42a5e29455c97140c70966d65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 27 Aug 2015 23:55:23 +0200 Subject: [PATCH 09/19] Fix some tests --- .../SecurityBundle/Resources/config/security_listeners.xml | 2 ++ src/Symfony/Component/DependencyInjection/Compiler/Compiler.php | 2 +- .../Component/DependencyInjection/Compiler/PassConfig.php | 2 +- src/Symfony/Component/DependencyInjection/ContainerBuilder.php | 2 +- .../DependencyInjection/Tests/ContainerBuilderTest.php | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml index 948286bb5a857..de134ecffcbb4 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml @@ -127,6 +127,8 @@ + + diff --git a/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php b/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php index 3617b7ab91b29..f121bff2772e5 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php @@ -30,7 +30,7 @@ class Compiler * * @param bool $autowiring Enable the autowiring */ - public function __construct($autowiring = false) + public function __construct($autowiring = true) { $this->passConfig = new PassConfig($autowiring); $this->serviceReferenceGraph = new ServiceReferenceGraph(); diff --git a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php index ecfb52ee81ba4..1a97ea063ec2f 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php @@ -40,7 +40,7 @@ class PassConfig * * @param bool $autowiring Enable the autowiring */ - public function __construct($autowiring = false) + public function __construct($autowiring = true) { $this->mergePass = new MergeExtensionConfigurationPass(); diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 7a1402f7d67e2..d9d7d46b770b7 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -325,7 +325,7 @@ public function getCompilerPassConfig() public function getCompiler() { if (null === $this->compiler) { - $this->compiler = new Compiler($this->hasParameter('container.autowiring') ? $this->getParameter('container.autowiring') : false); + $this->compiler = new Compiler($this->hasParameter('container.autowiring') ? $this->getParameter('container.autowiring') : true); } return $this->compiler; diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index 1a4c810239810..aee8adeb24521 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -893,7 +893,7 @@ public function testLazyLoadedService() public function testAutowiring() { - $container = new ContainerBuilder(); + $container = new ContainerBuilder(new ParameterBag(array('container.autowiring' => true))); $container->register('a', __NAMESPACE__.'\A'); $container->register('b', __NAMESPACE__.'\B'); From a7ca3f231bc426d1f21b86e3e65c37e948b6ee9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 28 Aug 2015 08:41:33 +0200 Subject: [PATCH 10/19] Fix @meyerbaptiste comments --- .../Compiler/AutowiringPass.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php index ac14984864359..9ece267493c4b 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php @@ -119,14 +119,14 @@ private function populateAvailableTypes() } /** - * Populates the of available types for a given definition. + * Populates the list of available types for a given definition. * * @param string $id * @param Definition $definition */ private function populateAvailableType($id, Definition $definition) { - if (!($class = $definition->getClass())) { + if (!$definition->getClass()) { return; } @@ -172,19 +172,19 @@ private function extractAncestors($id, \ReflectionClass $reflectionClass) } /** - * Associates if applicable a type and a service id or a class. + * Associates a type and a service id if applicable. * * @param string $type - * @param string $value A service id or a class name depending of the value of $class + * @param string $id */ - private function set($type, $value) + private function set($type, $id) { if (isset($this->definedTypes[$type]) || isset($this->notGuessableTypes[$type])) { return; } if (isset($this->types[$type])) { - if ($this->types[$type] === $value) { + if ($this->types[$type] === $id) { return; } @@ -194,7 +194,7 @@ private function set($type, $value) return; } - $this->types[$type] = $value; + $this->types[$type] = $id; } /** From 57c494c1fb72836ab12a363cccba1a2c9c2de1e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 28 Aug 2015 09:00:37 +0200 Subject: [PATCH 11/19] Move the autowiring parameter to a setter --- .../DependencyInjection/ContainerBuilder.php | 24 ++++++++++++++++++- src/Symfony/Component/HttpKernel/Kernel.php | 4 +++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index d9d7d46b770b7..bed732ec2ddaa 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -88,6 +88,8 @@ class ContainerBuilder extends Container implements TaggedContainerInterface */ private $expressionLanguageProviders = array(); + private $autowiring = true; + /** * @var string[] with tag names used by findTaggedServiceIds */ @@ -126,6 +128,26 @@ public function setProxyInstantiator(InstantiatorInterface $proxyInstantiator) $this->proxyInstantiator = $proxyInstantiator; } + /** + * Sets if the autowiring must be enabled or not. + * + * @param bool $autowiring + */ + public function setAutowiring($autowiring) + { + $this->autowiring = (bool) $autowiring; + } + + /** + * Checks if the autowiring is enabled. + * + * @return bool + */ + public function isAutowiring() + { + return $this->autowiring; + } + /** * Registers an extension. * @@ -325,7 +347,7 @@ public function getCompilerPassConfig() public function getCompiler() { if (null === $this->compiler) { - $this->compiler = new Compiler($this->hasParameter('container.autowiring') ? $this->getParameter('container.autowiring') : true); + $this->compiler = new Compiler($this->autowiring); } return $this->compiler; diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 8acb507d32efa..b45373f0df13b 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -553,7 +553,6 @@ protected function getKernelParameters() 'kernel.bundles' => $bundles, 'kernel.charset' => $this->getCharset(), 'kernel.container_class' => $this->getContainerClass(), - 'container.autowiring' => $this->containerAutowiring, ), $this->getEnvParameters() ); @@ -645,6 +644,9 @@ protected function prepareContainer(ContainerBuilder $container) protected function getContainerBuilder() { $container = new ContainerBuilder(new ParameterBag($this->getKernelParameters())); + if (!$this->containerAutowiring) { + $container->setAutowiring(false); + } if (class_exists('ProxyManager\Configuration') && class_exists('Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator')) { $container->setProxyInstantiator(new RuntimeInstantiator()); From e642aa8dd3c182c3edc4d83ce52410212faab09b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 28 Aug 2015 09:04:55 +0200 Subject: [PATCH 12/19] Fix SecurityBundle test --- .../SecurityBundle/Resources/config/security_listeners.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml index de134ecffcbb4..278c29b2dba85 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml @@ -139,6 +139,8 @@ + + From d00c7e30ff99cdadaf2088873ae6c3b28f818e13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 28 Aug 2015 22:29:22 +0200 Subject: [PATCH 13/19] Optin. Removed config flag. --- .../Resources/config/annotations.xml | 2 -- .../Resources/config/session.xml | 4 +-- .../Resources/config/security_listeners.xml | 4 --- .../Compiler/AutowiringPass.php | 10 ++---- .../DependencyInjection/Compiler/Compiler.php | 6 ++-- .../Compiler/PassConfig.php | 14 ++------ .../DependencyInjection/ContainerBuilder.php | 24 +------------ .../Tests/Compiler/AutowiringPassTest.php | 35 ++++++++++++------- .../Tests/ContainerBuilderTest.php | 5 +-- src/Symfony/Component/HttpKernel/Kernel.php | 4 --- 10 files changed, 35 insertions(+), 73 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.xml index e3b121c418687..1c0c312dc2673 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.xml @@ -17,8 +17,6 @@ - - diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml index 59061036669a8..591f92e456ddc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml @@ -55,9 +55,7 @@ %session.save_path% - - - + diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml index 278c29b2dba85..948286bb5a857 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml @@ -127,8 +127,6 @@ - - @@ -139,8 +137,6 @@ - - diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php index 9ece267493c4b..3d828b9fd5b22 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php @@ -23,7 +23,7 @@ */ class AutowiringPass implements CompilerPassInterface { - const NO_AUTOWIRING = 'no_autowiring'; + const AUTOWIRING = 'autowiring'; private $container; private $reflectionClasses = array(); @@ -38,7 +38,7 @@ public function process(ContainerBuilder $container) { $this->container = $container; foreach ($container->getDefinitions() as $id => $definition) { - if (!$definition->hasTag(self::NO_AUTOWIRING)) { + if ($definition->hasTag(self::AUTOWIRING)) { $this->completeDefinition($id, $definition); } } @@ -244,10 +244,6 @@ private function getReflectionClass($id, Definition $definition) $class = $this->container->getParameterBag()->resolveValue($class); - try { - return $this->reflectionClasses[$id] = new \ReflectionClass($class); - } catch (\ReflectionException $e) { - // Skip invalid classes definitions to keep BC - } + return $this->reflectionClasses[$id] = new \ReflectionClass($class); } } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php b/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php index f121bff2772e5..4e4c2cdaba5b9 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php @@ -27,12 +27,10 @@ class Compiler /** * Constructor. - * - * @param bool $autowiring Enable the autowiring */ - public function __construct($autowiring = true) + public function __construct() { - $this->passConfig = new PassConfig($autowiring); + $this->passConfig = new PassConfig(); $this->serviceReferenceGraph = new ServiceReferenceGraph(); $this->loggingFormatter = new LoggingFormatter(); } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php index 1a97ea063ec2f..efbf8f8023b66 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php @@ -37,10 +37,8 @@ class PassConfig /** * Constructor. - * - * @param bool $autowiring Enable the autowiring */ - public function __construct($autowiring = true) + public function __construct() { $this->mergePass = new MergeExtensionConfigurationPass(); @@ -52,17 +50,11 @@ public function __construct($autowiring = true) new CheckDefinitionValidityPass(), new ResolveReferencesToAliasesPass(), new ResolveInvalidReferencesPass(), - ); - - if ($autowiring) { - $this->optimizationPasses[] = new AutowiringPass(); - } - - $this->optimizationPasses = array_merge($this->optimizationPasses, array( + new AutowiringPass(), new AnalyzeServiceReferencesPass(true), new CheckCircularReferencesPass(), new CheckReferenceValidityPass(), - )); + ); $this->removingPasses = array( new RemovePrivateAliasesPass(), diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index bed732ec2ddaa..0f893e66e9885 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -88,8 +88,6 @@ class ContainerBuilder extends Container implements TaggedContainerInterface */ private $expressionLanguageProviders = array(); - private $autowiring = true; - /** * @var string[] with tag names used by findTaggedServiceIds */ @@ -128,26 +126,6 @@ public function setProxyInstantiator(InstantiatorInterface $proxyInstantiator) $this->proxyInstantiator = $proxyInstantiator; } - /** - * Sets if the autowiring must be enabled or not. - * - * @param bool $autowiring - */ - public function setAutowiring($autowiring) - { - $this->autowiring = (bool) $autowiring; - } - - /** - * Checks if the autowiring is enabled. - * - * @return bool - */ - public function isAutowiring() - { - return $this->autowiring; - } - /** * Registers an extension. * @@ -347,7 +325,7 @@ public function getCompilerPassConfig() public function getCompiler() { if (null === $this->compiler) { - $this->compiler = new Compiler($this->autowiring); + $this->compiler = new Compiler(); } return $this->compiler; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowiringPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowiringPassTest.php index d3b801ee916d8..b0c98763754cc 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowiringPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowiringPassTest.php @@ -25,7 +25,8 @@ public function testProcess() $container = new ContainerBuilder(); $container->register('foo', __NAMESPACE__.'\Foo'); - $container->register('bar', __NAMESPACE__.'\Bar'); + $barDefinition = $container->register('bar', __NAMESPACE__.'\Bar'); + $barDefinition->addTag(AutowiringPass::AUTOWIRING); $pass = new AutowiringPass(); $pass->process($container); @@ -39,7 +40,8 @@ public function testProcessAutowireParent() $container = new ContainerBuilder(); $container->register('b', __NAMESPACE__.'\B'); - $container->register('c', __NAMESPACE__.'\C'); + $cDefinition = $container->register('c', __NAMESPACE__.'\C'); + $cDefinition->addTag(AutowiringPass::AUTOWIRING); $pass = new AutowiringPass(); $pass->process($container); @@ -53,7 +55,8 @@ public function testProcessAutowireInterface() $container = new ContainerBuilder(); $container->register('f', __NAMESPACE__.'\F'); - $container->register('g', __NAMESPACE__.'\G'); + $gDefinition = $container->register('g', __NAMESPACE__.'\G'); + $gDefinition->addTag(AutowiringPass::AUTOWIRING); $pass = new AutowiringPass(); $pass->process($container); @@ -69,7 +72,8 @@ public function testCompleteExistingDefinition() $container->register('b', __NAMESPACE__.'\B'); $container->register('f', __NAMESPACE__.'\F'); - $container->register('h', __NAMESPACE__.'\H')->addArgument(new Reference('b')); + $hDefinition = $container->register('h', __NAMESPACE__.'\H')->addArgument(new Reference('b')); + $hDefinition->addTag(AutowiringPass::AUTOWIRING); $pass = new AutowiringPass(); $pass->process($container); @@ -85,7 +89,8 @@ public function testCompleteExistingDefinitionWithNotDefinedArguments() $container->register('b', __NAMESPACE__.'\B'); $container->register('f', __NAMESPACE__.'\F'); - $container->register('h', __NAMESPACE__.'\H')->addArgument('')->addArgument(''); + $hDefinition = $container->register('h', __NAMESPACE__.'\H')->addArgument('')->addArgument(''); + $hDefinition->addTag(AutowiringPass::AUTOWIRING); $pass = new AutowiringPass(); $pass->process($container); @@ -105,7 +110,8 @@ public function testTypeCollision() $container->register('c1', __NAMESPACE__.'\CollisionA'); $container->register('c2', __NAMESPACE__.'\CollisionB'); - $container->register('a', __NAMESPACE__.'\CannotBeAutowired'); + $aDefinition = $container->register('a', __NAMESPACE__.'\CannotBeAutowired'); + $aDefinition->addTag(AutowiringPass::AUTOWIRING); $pass = new AutowiringPass(); $pass->process($container); @@ -117,7 +123,8 @@ public function testWithTypeSet() $container->register('c1', __NAMESPACE__.'\CollisionA'); $container->register('c2', __NAMESPACE__.'\CollisionB')->addType(__NAMESPACE__.'\CollisionInterface'); - $container->register('a', __NAMESPACE__.'\CannotBeAutowired'); + $aDefinition = $container->register('a', __NAMESPACE__.'\CannotBeAutowired'); + $aDefinition->addTag(AutowiringPass::AUTOWIRING); $pass = new AutowiringPass(); $pass->process($container); @@ -130,7 +137,8 @@ public function testCreateDefinition() { $container = new ContainerBuilder(); - $container->register('coop_tilleuls', __NAMESPACE__.'\LesTilleuls'); + $coopTilleulsDefinition = $container->register('coop_tilleuls', __NAMESPACE__.'\LesTilleuls'); + $coopTilleulsDefinition->addTag(AutowiringPass::AUTOWIRING); $pass = new AutowiringPass(); $pass->process($container); @@ -154,7 +162,8 @@ public function testResolveParameter() $container->setParameter('class_name', __NAMESPACE__.'\Foo'); $container->register('foo', '%class_name%'); - $container->register('bar', __NAMESPACE__.'\Bar'); + $barDefinition = $container->register('bar', __NAMESPACE__.'\Bar'); + $barDefinition->addTag(AutowiringPass::AUTOWIRING); $pass = new AutowiringPass(); $pass->process($container); @@ -168,7 +177,8 @@ public function testOptionalParameter() $container->register('a', __NAMESPACE__.'\A'); $container->register('foo', __NAMESPACE__.'\Foo'); - $container->register('opt', __NAMESPACE__.'\OptionalParameter'); + $optDefinition = $container->register('opt', __NAMESPACE__.'\OptionalParameter'); + $optDefinition->addTag(AutowiringPass::AUTOWIRING); $pass = new AutowiringPass(); $pass->process($container); @@ -179,13 +189,12 @@ public function testOptionalParameter() $this->assertEquals('foo', $definition->getArgument(2)); } - public function testNoAutowiringTag() + public function testDontTriggeruAutowiring() { $container = new ContainerBuilder(); $container->register('foo', __NAMESPACE__.'\Foo'); - $barDefintion = $container->register('bar', __NAMESPACE__.'\Bar'); - $barDefintion->addTag(AutowiringPass::NO_AUTOWIRING); + $container->register('bar', __NAMESPACE__.'\Bar'); $pass = new AutowiringPass(); $pass->process($container); diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index aee8adeb24521..f301e7b3d6fc0 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -893,10 +893,11 @@ public function testLazyLoadedService() public function testAutowiring() { - $container = new ContainerBuilder(new ParameterBag(array('container.autowiring' => true))); + $container = new ContainerBuilder(); $container->register('a', __NAMESPACE__.'\A'); - $container->register('b', __NAMESPACE__.'\B'); + $bDefinition = $container->register('b', __NAMESPACE__.'\B'); + $bDefinition->addTag('autowiring'); $container->compile(); diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index b45373f0df13b..7c55172d395ae 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -59,7 +59,6 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $name; protected $startTime; protected $loadClassCache; - protected $containerAutowiring = true; const VERSION = '2.8.0-DEV'; const VERSION_ID = 20800; @@ -644,9 +643,6 @@ protected function prepareContainer(ContainerBuilder $container) protected function getContainerBuilder() { $container = new ContainerBuilder(new ParameterBag($this->getKernelParameters())); - if (!$this->containerAutowiring) { - $container->setAutowiring(false); - } if (class_exists('ProxyManager\Configuration') && class_exists('Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator')) { $container->setProxyInstantiator(new RuntimeInstantiator()); From 55bb42c15d688d6c202a0e296699e994e8008487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Sun, 30 Aug 2015 15:18:11 +0200 Subject: [PATCH 14/19] Fix CS --- src/Symfony/Component/DependencyInjection/Definition.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Definition.php b/src/Symfony/Component/DependencyInjection/Definition.php index 0bcd11b0263c7..b2a80902347ef 100644 --- a/src/Symfony/Component/DependencyInjection/Definition.php +++ b/src/Symfony/Component/DependencyInjection/Definition.php @@ -883,7 +883,8 @@ public function removeType($type) * * @return bool */ - public function hasType($type) { + public function hasType($type) + { return isset($this->types[$type]); } } From 7806487bbb3455ee1518f8b9f37ac160f2f014be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 24 Sep 2015 19:45:33 +0200 Subject: [PATCH 15/19] [DependencyInjection] Rename types to autowiring_types --- .../Compiler/AutowiringPass.php | 2 +- .../DependencyInjection/Definition.php | 24 +++++++++---------- .../Loader/XmlFileLoader.php | 4 ++-- .../Loader/YamlFileLoader.php | 14 +++++------ .../schema/dic/services/services-1.0.xsd | 2 +- .../Tests/Compiler/AutowiringPassTest.php | 2 +- .../Tests/DefinitionTest.php | 12 +++++----- .../Tests/Fixtures/xml/services22.xml | 4 ++-- .../Tests/Fixtures/yaml/bad_types1.yml | 4 ++-- .../Tests/Fixtures/yaml/bad_types2.yml | 6 ++--- .../Tests/Fixtures/yaml/services22.yml | 4 ++-- .../Tests/Loader/XmlFileLoaderTest.php | 2 +- .../Tests/Loader/YamlFileLoaderTest.php | 2 +- 13 files changed, 41 insertions(+), 41 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php index 3d828b9fd5b22..b570225148939 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php @@ -130,7 +130,7 @@ private function populateAvailableType($id, Definition $definition) return; } - foreach ($definition->getTypes() as $type) { + foreach ($definition->getAutowiringTypes() as $type) { $this->definedTypes[$type] = true; $this->types[$type] = $id; } diff --git a/src/Symfony/Component/DependencyInjection/Definition.php b/src/Symfony/Component/DependencyInjection/Definition.php index b2a80902347ef..8c8212711c686 100644 --- a/src/Symfony/Component/DependencyInjection/Definition.php +++ b/src/Symfony/Component/DependencyInjection/Definition.php @@ -41,7 +41,7 @@ class Definition private $synchronized = false; private $lazy = false; private $decoratedService; - private $types = array(); + private $autowiringTypes = array(); protected $arguments; @@ -829,23 +829,23 @@ public function getConfigurator() */ public function setTypes(array $types) { - $this->types = array(); + $this->autowiringTypes = array(); foreach ($types as $type) { - $this->types[$type] = true; + $this->autowiringTypes[$type] = true; } return $this; } /** - * Gets types that will default to this definition. + * Gets autowiring types that will default to this definition. * * @return string[] */ - public function getTypes() + public function getAutowiringTypes() { - return array_keys($this->types); + return array_keys($this->autowiringTypes); } /** @@ -855,9 +855,9 @@ public function getTypes() * * @return Definition The current instance */ - public function addType($type) + public function addAutowiringType($type) { - $this->types[$type] = true; + $this->autowiringTypes[$type] = true; return $this; } @@ -869,9 +869,9 @@ public function addType($type) * * @return Definition The current instance */ - public function removeType($type) + public function removeAutowiringType($type) { - unset($this->types[$type]); + unset($this->autowiringTypes[$type]); return $this; } @@ -883,8 +883,8 @@ public function removeType($type) * * @return bool */ - public function hasType($type) + public function hasAutowiringType($type) { - return isset($this->types[$type]); + return isset($this->autowiringTypes[$type]); } } diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index fa2c3f9234f6b..20ab3688019dd 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -247,8 +247,8 @@ private function parseDefinition(\DOMElement $service, $file) $definition->addTag($tag->getAttribute('name'), $parameters); } - foreach ($this->getChildren($service, 'type') as $type) { - $definition->addType($type->textContent); + foreach ($this->getChildren($service, 'autowiring-type') as $type) { + $definition->addAutowiringType($type->textContent); } if ($value = $service->getAttribute('decorates')) { diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index 508c65144b7c6..7d49f708de7f1 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -299,17 +299,17 @@ private function parseDefinition($id, $service, $file) $definition->setDecoratedService($service['decorates'], $renameId, $priority); } - if (isset($service['types'])) { - if (!is_array($service['types'])) { - throw new InvalidArgumentException(sprintf('Parameter "types" must be an array for service "%s" in %s. Check your YAML syntax.', $id, $file)); + if (isset($service['autowiring_types'])) { + if (!is_array($service['autowiring_types'])) { + throw new InvalidArgumentException(sprintf('Parameter "autowiring_types" must be an array for service "%s" in %s. Check your YAML syntax.', $id, $file)); } - foreach ($service['types'] as $type) { - if (!is_string($type)) { - throw new InvalidArgumentException(sprintf('A "types" attribute must be of type string for service "%s" in %s. Check your YAML syntax.', $id, $file)); + foreach ($service['autowiring_types'] as $autowiringType) { + if (!is_string($autowiringType)) { + throw new InvalidArgumentException(sprintf('A "autowiring_types" attribute must be of type string for service "%s" in %s. Check your YAML syntax.', $id, $file)); } - $definition->addType($type); + $definition->addAutowiringType($autowiringType); } } 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 1bf4eb5bc0859..95fb3cfbd3fb1 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 @@ -85,7 +85,7 @@ - + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowiringPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowiringPassTest.php index b0c98763754cc..69751695792ad 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowiringPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowiringPassTest.php @@ -122,7 +122,7 @@ public function testWithTypeSet() $container = new ContainerBuilder(); $container->register('c1', __NAMESPACE__.'\CollisionA'); - $container->register('c2', __NAMESPACE__.'\CollisionB')->addType(__NAMESPACE__.'\CollisionInterface'); + $container->register('c2', __NAMESPACE__.'\CollisionB')->addAutowiringType(__NAMESPACE__.'\CollisionInterface'); $aDefinition = $container->register('a', __NAMESPACE__.'\CannotBeAutowired'); $aDefinition->addTag(AutowiringPass::AUTOWIRING); diff --git a/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php b/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php index fab48f50c746b..ccc4ecfbb99de 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php @@ -399,12 +399,12 @@ public function testTypes() { $def = new Definition('stdClass'); - $this->assertEquals(array(), $def->getTypes()); + $this->assertEquals(array(), $def->getAutowiringTypes()); $this->assertSame($def, $def->setTypes(array('Foo'))); - $this->assertEquals(array('Foo'), $def->getTypes()); - $this->assertSame($def, $def->addType('Bar')); - $this->assertTrue($def->hasType('Bar')); - $this->assertSame($def, $def->removeType('Foo')); - $this->assertEquals(array('Bar'), $def->getTypes()); + $this->assertEquals(array('Foo'), $def->getAutowiringTypes()); + $this->assertSame($def, $def->addAutowiringType('Bar')); + $this->assertTrue($def->hasAutowiringType('Bar')); + $this->assertSame($def, $def->removeAutowiringType('Foo')); + $this->assertEquals(array('Bar'), $def->getAutowiringTypes()); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services22.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services22.xml index 7b5ffe7c3ca67..fa79d389489fb 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services22.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services22.xml @@ -2,8 +2,8 @@ - Bar - Baz + Bar + Baz diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_types1.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_types1.yml index 79d676f2bf569..a9572c4d00a53 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_types1.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_types1.yml @@ -1,5 +1,5 @@ services: foo_service: - class: FooClass + class: FooClass # types is not an array - types: string + autowiring_types: string diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_types2.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_types2.yml index c26e077185723..fb1d53e151014 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_types2.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_types2.yml @@ -1,5 +1,5 @@ services: foo_service: - class: FooClass - # type is not a string - types: [ 1 ] + class: FooClass + # autowiring_types is not a string + autowiring_types: [ 1 ] diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services22.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services22.yml index 9fa7d0c57b900..ed61ad50ac559 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services22.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services22.yml @@ -1,4 +1,4 @@ services: foo_service: - class: FooClass - types: [ Foo, Bar ] + class: FooClass + autowiring_types: [ Foo, Bar ] diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php index 512af94b9ae49..f0e3d7b99c243 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php @@ -501,6 +501,6 @@ public function testType() $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); $loader->load('services22.xml'); - $this->assertEquals(array('Bar', 'Baz'), $container->getDefinition('foo')->getTypes()); + $this->assertEquals(array('Bar', 'Baz'), $container->getDefinition('foo')->getAutowiringTypes()); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php index 6bfaa5996a72e..a29fb1f69b7dd 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php @@ -307,6 +307,6 @@ public function testTypes() $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); $loader->load('services22.yml'); - $this->assertEquals(array('Foo', 'Bar'), $container->getDefinition('foo_service')->getTypes()); + $this->assertEquals(array('Foo', 'Bar'), $container->getDefinition('foo_service')->getAutowiringTypes()); } } From 585616dc4189614d92d3fcc1d64e20dad25452f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Mon, 28 Sep 2015 09:34:28 +0200 Subject: [PATCH 16/19] [DependencyInjection] Add the new 'autowire' syntax. --- .../{AutowiringPass.php => AutowirePass.php} | 7 ++- .../Compiler/PassConfig.php | 2 +- .../DependencyInjection/Definition.php | 25 ++++++++++ .../Loader/XmlFileLoader.php | 4 ++ .../Loader/YamlFileLoader.php | 4 ++ .../schema/dic/services/services-1.0.xsd | 1 + ...iringPassTest.php => AutowirePassTest.php} | 46 +++++++++---------- .../Tests/DefinitionTest.php | 8 ++++ .../Tests/Fixtures/xml/services23.xml | 6 +++ .../Tests/Fixtures/yaml/services23.yml | 4 ++ .../Tests/Loader/XmlFileLoaderTest.php | 9 ++++ .../Tests/Loader/YamlFileLoaderTest.php | 9 ++++ 12 files changed, 97 insertions(+), 28 deletions(-) rename src/Symfony/Component/DependencyInjection/Compiler/{AutowiringPass.php => AutowirePass.php} (97%) rename src/Symfony/Component/DependencyInjection/Tests/Compiler/{AutowiringPassTest.php => AutowirePassTest.php} (87%) create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services23.xml create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services23.yml diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php similarity index 97% rename from src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php rename to src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index b570225148939..bc268845191f4 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowiringPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -21,10 +21,8 @@ * * @author Kévin Dunglas */ -class AutowiringPass implements CompilerPassInterface +class AutowirePass implements CompilerPassInterface { - const AUTOWIRING = 'autowiring'; - private $container; private $reflectionClasses = array(); private $definedTypes = array(); @@ -38,7 +36,7 @@ public function process(ContainerBuilder $container) { $this->container = $container; foreach ($container->getDefinitions() as $id => $definition) { - if ($definition->hasTag(self::AUTOWIRING)) { + if ($definition->isAutowired()) { $this->completeDefinition($id, $definition); } } @@ -64,6 +62,7 @@ private function completeDefinition($id, Definition $definition) if (!($reflectionClass = $this->getReflectionClass($id, $definition))) { return; } + $this->container->addClassResource($reflectionClass); if (!($constructor = $reflectionClass->getConstructor())) { return; diff --git a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php index efbf8f8023b66..246529d865cd3 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php @@ -50,7 +50,7 @@ public function __construct() new CheckDefinitionValidityPass(), new ResolveReferencesToAliasesPass(), new ResolveInvalidReferencesPass(), - new AutowiringPass(), + new AutowirePass(), new AnalyzeServiceReferencesPass(true), new CheckCircularReferencesPass(), new CheckReferenceValidityPass(), diff --git a/src/Symfony/Component/DependencyInjection/Definition.php b/src/Symfony/Component/DependencyInjection/Definition.php index 8c8212711c686..30fc9c99655fd 100644 --- a/src/Symfony/Component/DependencyInjection/Definition.php +++ b/src/Symfony/Component/DependencyInjection/Definition.php @@ -41,6 +41,7 @@ class Definition private $synchronized = false; private $lazy = false; private $decoratedService; + private $autowired = false; private $autowiringTypes = array(); protected $arguments; @@ -838,6 +839,30 @@ public function setTypes(array $types) return $this; } + /** + * Is the definition autowired? + * + * @return bool + */ + public function isAutowired() + { + return $this->autowired; + } + + /** + * Sets autowired. + * + * @param $autowired + * + * @return Definition The current instance + */ + public function setAutowired($autowired) + { + $this->autowired = $autowired; + + return $this; + } + /** * Gets autowiring types that will default to this definition. * diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index 20ab3688019dd..7fb98972c0c6e 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -157,6 +157,10 @@ private function parseDefinition(\DOMElement $service, $file) } } + if ($value = $service->getAttribute('autowire')) { + $definition->setAutowired(XmlUtils::phpize($value)); + } + if ($value = $service->getAttribute('scope')) { $triggerDeprecation = 'request' !== (string) $service->getAttribute('id'); diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index 7d49f708de7f1..3811644dc69c0 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -299,6 +299,10 @@ private function parseDefinition($id, $service, $file) $definition->setDecoratedService($service['decorates'], $renameId, $priority); } + if (isset($service['autowire'])) { + $definition->setAutowired($service['autowire']); + } + if (isset($service['autowiring_types'])) { if (!is_array($service['autowiring_types'])) { throw new InvalidArgumentException(sprintf('Parameter "autowiring_types" must be an array for service "%s" in %s. Check your YAML syntax.', $id, $file)); 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 95fb3cfbd3fb1..3241c43c40994 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 @@ -104,6 +104,7 @@ + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowiringPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php similarity index 87% rename from src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowiringPassTest.php rename to src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php index 69751695792ad..3639a2138fad7 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowiringPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -11,14 +11,14 @@ namespace Symfony\Component\DependencyInjection\Tests\Compiler; -use Symfony\Component\DependencyInjection\Compiler\AutowiringPass; +use Symfony\Component\DependencyInjection\Compiler\AutowirePass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; /** * @author Kévin Dunglas */ -class AutowiringPassTest extends \PHPUnit_Framework_TestCase +class AutowirePassTest extends \PHPUnit_Framework_TestCase { public function testProcess() { @@ -26,9 +26,9 @@ public function testProcess() $container->register('foo', __NAMESPACE__.'\Foo'); $barDefinition = $container->register('bar', __NAMESPACE__.'\Bar'); - $barDefinition->addTag(AutowiringPass::AUTOWIRING); + $barDefinition->setAutowired(true); - $pass = new AutowiringPass(); + $pass = new AutowirePass(); $pass->process($container); $this->assertCount(1, $container->getDefinition('bar')->getArguments()); @@ -41,9 +41,9 @@ public function testProcessAutowireParent() $container->register('b', __NAMESPACE__.'\B'); $cDefinition = $container->register('c', __NAMESPACE__.'\C'); - $cDefinition->addTag(AutowiringPass::AUTOWIRING); + $cDefinition->setAutowired(true); - $pass = new AutowiringPass(); + $pass = new AutowirePass(); $pass->process($container); $this->assertCount(1, $container->getDefinition('c')->getArguments()); @@ -56,9 +56,9 @@ public function testProcessAutowireInterface() $container->register('f', __NAMESPACE__.'\F'); $gDefinition = $container->register('g', __NAMESPACE__.'\G'); - $gDefinition->addTag(AutowiringPass::AUTOWIRING); + $gDefinition->setAutowired(true); - $pass = new AutowiringPass(); + $pass = new AutowirePass(); $pass->process($container); $this->assertCount(2, $container->getDefinition('g')->getArguments()); @@ -73,9 +73,9 @@ public function testCompleteExistingDefinition() $container->register('b', __NAMESPACE__.'\B'); $container->register('f', __NAMESPACE__.'\F'); $hDefinition = $container->register('h', __NAMESPACE__.'\H')->addArgument(new Reference('b')); - $hDefinition->addTag(AutowiringPass::AUTOWIRING); + $hDefinition->setAutowired(true); - $pass = new AutowiringPass(); + $pass = new AutowirePass(); $pass->process($container); $this->assertCount(2, $container->getDefinition('h')->getArguments()); @@ -90,9 +90,9 @@ public function testCompleteExistingDefinitionWithNotDefinedArguments() $container->register('b', __NAMESPACE__.'\B'); $container->register('f', __NAMESPACE__.'\F'); $hDefinition = $container->register('h', __NAMESPACE__.'\H')->addArgument('')->addArgument(''); - $hDefinition->addTag(AutowiringPass::AUTOWIRING); + $hDefinition->setAutowired(true); - $pass = new AutowiringPass(); + $pass = new AutowirePass(); $pass->process($container); $this->assertCount(2, $container->getDefinition('h')->getArguments()); @@ -111,9 +111,9 @@ public function testTypeCollision() $container->register('c1', __NAMESPACE__.'\CollisionA'); $container->register('c2', __NAMESPACE__.'\CollisionB'); $aDefinition = $container->register('a', __NAMESPACE__.'\CannotBeAutowired'); - $aDefinition->addTag(AutowiringPass::AUTOWIRING); + $aDefinition->setAutowired(true); - $pass = new AutowiringPass(); + $pass = new AutowirePass(); $pass->process($container); } @@ -124,9 +124,9 @@ public function testWithTypeSet() $container->register('c1', __NAMESPACE__.'\CollisionA'); $container->register('c2', __NAMESPACE__.'\CollisionB')->addAutowiringType(__NAMESPACE__.'\CollisionInterface'); $aDefinition = $container->register('a', __NAMESPACE__.'\CannotBeAutowired'); - $aDefinition->addTag(AutowiringPass::AUTOWIRING); + $aDefinition->setAutowired(true); - $pass = new AutowiringPass(); + $pass = new AutowirePass(); $pass->process($container); $this->assertCount(1, $container->getDefinition('a')->getArguments()); @@ -138,9 +138,9 @@ public function testCreateDefinition() $container = new ContainerBuilder(); $coopTilleulsDefinition = $container->register('coop_tilleuls', __NAMESPACE__.'\LesTilleuls'); - $coopTilleulsDefinition->addTag(AutowiringPass::AUTOWIRING); + $coopTilleulsDefinition->setAutowired(true); - $pass = new AutowiringPass(); + $pass = new AutowirePass(); $pass->process($container); $this->assertCount(1, $container->getDefinition('coop_tilleuls')->getArguments()); @@ -163,9 +163,9 @@ public function testResolveParameter() $container->setParameter('class_name', __NAMESPACE__.'\Foo'); $container->register('foo', '%class_name%'); $barDefinition = $container->register('bar', __NAMESPACE__.'\Bar'); - $barDefinition->addTag(AutowiringPass::AUTOWIRING); + $barDefinition->setAutowired(true); - $pass = new AutowiringPass(); + $pass = new AutowirePass(); $pass->process($container); $this->assertEquals('foo', $container->getDefinition('bar')->getArgument(0)); @@ -178,9 +178,9 @@ public function testOptionalParameter() $container->register('a', __NAMESPACE__.'\A'); $container->register('foo', __NAMESPACE__.'\Foo'); $optDefinition = $container->register('opt', __NAMESPACE__.'\OptionalParameter'); - $optDefinition->addTag(AutowiringPass::AUTOWIRING); + $optDefinition->setAutowired(true); - $pass = new AutowiringPass(); + $pass = new AutowirePass(); $pass->process($container); $definition = $container->getDefinition('opt'); @@ -196,7 +196,7 @@ public function testDontTriggeruAutowiring() $container->register('foo', __NAMESPACE__.'\Foo'); $container->register('bar', __NAMESPACE__.'\Bar'); - $pass = new AutowiringPass(); + $pass = new AutowirePass(); $pass->process($container); $this->assertCount(0, $container->getDefinition('bar')->getArguments()); diff --git a/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php b/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php index ccc4ecfbb99de..47288af7686ea 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php @@ -395,6 +395,14 @@ public function testSetProperty() $this->assertEquals(array('foo' => 'bar'), $def->getProperties()); } + public function testAutowired() + { + $def = new Definition('stdClass'); + $this->assertFalse($def->isAutowired()); + $def->setAutowired(true); + $this->assertTrue($def->isAutowired()); + } + public function testTypes() { $def = new Definition('stdClass'); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services23.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services23.xml new file mode 100644 index 0000000000000..3f9e15fd499da --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services23.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services23.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services23.yml new file mode 100644 index 0000000000000..1984c17714633 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services23.yml @@ -0,0 +1,4 @@ +services: + bar_service: + class: BarClass + autowire: true diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php index f0e3d7b99c243..723d30605ea4e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php @@ -503,4 +503,13 @@ public function testType() $this->assertEquals(array('Bar', 'Baz'), $container->getDefinition('foo')->getAutowiringTypes()); } + + public function testAutowire() + { + $container = new ContainerBuilder(); + $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); + $loader->load('services23.xml'); + + $this->assertTrue($container->getDefinition('bar')->isAutowired()); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php index a29fb1f69b7dd..8b1004f1552bb 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php @@ -309,4 +309,13 @@ public function testTypes() $this->assertEquals(array('Foo', 'Bar'), $container->getDefinition('foo_service')->getAutowiringTypes()); } + + public function testAutowire() + { + $container = new ContainerBuilder(); + $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); + $loader->load('services23.yml'); + + $this->assertTrue($container->getDefinition('bar_service')->isAutowired()); + } } From c717c694287b20c85febe14aef29847adb101e5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Mon, 28 Sep 2015 14:11:59 +0200 Subject: [PATCH 17/19] Fix tests. --- .../DependencyInjection/Tests/ContainerBuilderTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index f301e7b3d6fc0..ad83f8e0d13f3 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -897,7 +897,7 @@ public function testAutowiring() $container->register('a', __NAMESPACE__.'\A'); $bDefinition = $container->register('b', __NAMESPACE__.'\B'); - $bDefinition->addTag('autowiring'); + $bDefinition->setAutowired(true); $container->compile(); From 3b7f5538643a5b25e8e5c4060a50826fc34d59f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 2 Oct 2015 11:50:40 +0200 Subject: [PATCH 18/19] Fix @fabpot and @stof comments. --- .../Compiler/AutowirePass.php | 13 ++++++++---- .../DependencyInjection/Definition.php | 2 +- .../Loader/YamlFileLoader.php | 20 +++++++++++-------- .../Tests/DefinitionTest.php | 2 +- .../Tests/Fixtures/yaml/bad_types1.yml | 2 +- .../Tests/Fixtures/yaml/services22.yml | 4 ++++ .../Tests/Loader/YamlFileLoaderTest.php | 1 + 7 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index bc268845191f4..45951ab9df7da 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -59,18 +59,19 @@ public function process(ContainerBuilder $container) */ private function completeDefinition($id, Definition $definition) { - if (!($reflectionClass = $this->getReflectionClass($id, $definition))) { + if (!$reflectionClass = $this->getReflectionClass($id, $definition)) { return; } + $this->container->addClassResource($reflectionClass); - if (!($constructor = $reflectionClass->getConstructor())) { + if (!$constructor = $reflectionClass->getConstructor()) { return; } $arguments = $definition->getArguments(); foreach ($constructor->getParameters() as $index => $parameter) { - if (!($typeHint = $parameter->getClass())) { + if (!$typeHint = $parameter->getClass()) { continue; } @@ -243,6 +244,10 @@ private function getReflectionClass($id, Definition $definition) $class = $this->container->getParameterBag()->resolveValue($class); - return $this->reflectionClasses[$id] = new \ReflectionClass($class); + try { + return $this->reflectionClasses[$id] = new \ReflectionClass($class); + } catch (\ReflectionException $reflectionException) { + // return null + } } } diff --git a/src/Symfony/Component/DependencyInjection/Definition.php b/src/Symfony/Component/DependencyInjection/Definition.php index 30fc9c99655fd..66ea2cc0e4146 100644 --- a/src/Symfony/Component/DependencyInjection/Definition.php +++ b/src/Symfony/Component/DependencyInjection/Definition.php @@ -828,7 +828,7 @@ public function getConfigurator() * * @return Definition The current instance */ - public function setTypes(array $types) + public function setAutowiringTypes(array $types) { $this->autowiringTypes = array(); diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index 3811644dc69c0..3039885ec2fc9 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -304,16 +304,20 @@ private function parseDefinition($id, $service, $file) } if (isset($service['autowiring_types'])) { - if (!is_array($service['autowiring_types'])) { - throw new InvalidArgumentException(sprintf('Parameter "autowiring_types" must be an array for service "%s" in %s. Check your YAML syntax.', $id, $file)); - } - - foreach ($service['autowiring_types'] as $autowiringType) { - if (!is_string($autowiringType)) { - throw new InvalidArgumentException(sprintf('A "autowiring_types" attribute must be of type string for service "%s" in %s. Check your YAML syntax.', $id, $file)); + if (is_string($service['autowiring_types'])) { + $definition->addAutowiringType($service['autowiring_types']); + } else { + if (!is_array($service['autowiring_types'])) { + throw new InvalidArgumentException(sprintf('Parameter "autowiring_types" must be a string or an array for service "%s" in %s. Check your YAML syntax.', $id, $file)); } - $definition->addAutowiringType($autowiringType); + foreach ($service['autowiring_types'] as $autowiringType) { + if (!is_string($autowiringType)) { + throw new InvalidArgumentException(sprintf('A "autowiring_types" attribute must be of type string for service "%s" in %s. Check your YAML syntax.', $id, $file)); + } + + $definition->addAutowiringType($autowiringType); + } } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php b/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php index 47288af7686ea..cb6344e49578a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php @@ -408,7 +408,7 @@ public function testTypes() $def = new Definition('stdClass'); $this->assertEquals(array(), $def->getAutowiringTypes()); - $this->assertSame($def, $def->setTypes(array('Foo'))); + $this->assertSame($def, $def->setAutowiringTypes(array('Foo'))); $this->assertEquals(array('Foo'), $def->getAutowiringTypes()); $this->assertSame($def, $def->addAutowiringType('Bar')); $this->assertTrue($def->hasAutowiringType('Bar')); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_types1.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_types1.yml index a9572c4d00a53..891e01497cadf 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_types1.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_types1.yml @@ -2,4 +2,4 @@ services: foo_service: class: FooClass # types is not an array - autowiring_types: string + autowiring_types: 1 diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services22.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services22.yml index ed61ad50ac559..55d015baea0fb 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services22.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services22.yml @@ -2,3 +2,7 @@ services: foo_service: class: FooClass autowiring_types: [ Foo, Bar ] + + baz_service: + class: Baz + autowiring_types: Foo diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php index 8b1004f1552bb..8ab714e43a2c4 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php @@ -308,6 +308,7 @@ public function testTypes() $loader->load('services22.yml'); $this->assertEquals(array('Foo', 'Bar'), $container->getDefinition('foo_service')->getAutowiringTypes()); + $this->assertEquals(array('Foo'), $container->getDefinition('baz_service')->getAutowiringTypes()); } public function testAutowire() From 936a16a3809bc5a8dddc849c0ff09b389faf93b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 2 Oct 2015 12:08:24 +0200 Subject: [PATCH 19/19] Typehint against a non-existing class --- .../Compiler/AutowirePass.php | 42 ++++++++++++------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index 45951ab9df7da..3b85543b8b956 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -71,31 +71,41 @@ private function completeDefinition($id, Definition $definition) $arguments = $definition->getArguments(); foreach ($constructor->getParameters() as $index => $parameter) { - if (!$typeHint = $parameter->getClass()) { - continue; - } - $argumentExists = array_key_exists($index, $arguments); if ($argumentExists && '' !== $arguments[$index]) { continue; } - if (null === $this->types) { - $this->populateAvailableTypes(); - } + try { + if (!$typeHint = $parameter->getClass()) { + continue; + } - if (isset($this->types[$typeHint->name])) { - $value = new Reference($this->types[$typeHint->name]); - } else { - try { - $value = $this->createAutowiredDefinition($typeHint, $id); - } catch (RuntimeException $e) { - if (!$parameter->isDefaultValueAvailable()) { - throw $e; + if (null === $this->types) { + $this->populateAvailableTypes(); + } + + if (isset($this->types[$typeHint->name])) { + $value = new Reference($this->types[$typeHint->name]); + } else { + try { + $value = $this->createAutowiredDefinition($typeHint, $id); + } catch (RuntimeException $e) { + if (!$parameter->isDefaultValueAvailable()) { + throw $e; + } + + $value = $parameter->getDefaultValue(); } + } + } catch (\ReflectionException $reflectionException) { + // Typehint against a non-existing class - $value = $parameter->getDefaultValue(); + if (!$parameter->isDefaultValueAvailable()) { + continue; } + + $value = $parameter->getDefaultValue(); } if ($argumentExists) { 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