From 5d4e3a2d57c1ea1be3a12e4695ac8eadf1a8209d Mon Sep 17 00:00:00 2001 From: Amrouche Hamza Date: Sat, 6 Apr 2019 14:30:12 +0200 Subject: [PATCH] [WIP] [DependencyInjection] Fix a wrong error when using a factory and a call --- .../Compiler/AutowirePass.php | 10 ++++- .../Compiler/ResolveBindingsPass.php | 9 +++- .../Tests/Compiler/AutowirePassTest.php | 13 ++++++ .../Compiler/ResolveBindingsPassTest.php | 44 +++++++++++++++++++ 4 files changed, 74 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index 252b304f11..c8e7a0f575 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -181,7 +181,15 @@ class AutowirePass extends AbstractRecursivePass if ($method instanceof \ReflectionFunctionAbstract) { $reflectionMethod = $method; } else { - $reflectionMethod = $this->getReflectionMethod(new Definition($reflectionClass->name), $method); + $definition = new Definition($reflectionClass->name); + try { + $reflectionMethod = $this->getReflectionMethod($definition, $method); + } catch (RuntimeException $e) { + if ($definition->getFactory()) { + continue; + } + throw $e; + } } $arguments = $this->autowireMethod($reflectionMethod, $arguments); diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php index 20b262b6d4..bb67eb1679 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php @@ -115,7 +115,14 @@ class ResolveBindingsPass extends AbstractRecursivePass if ($method instanceof \ReflectionFunctionAbstract) { $reflectionMethod = $method; } else { - $reflectionMethod = $this->getReflectionMethod($value, $method); + try { + $reflectionMethod = $this->getReflectionMethod($value, $method); + } catch (RuntimeException $e) { + if ($value->getFactory()) { + continue; + } + throw $e; + } } foreach ($reflectionMethod->getParameters() as $key => $parameter) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php index 6bd49fa5c6..6235ed50be 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -23,6 +23,7 @@ use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Tests\Fixtures\includes\FooVariadic; use Symfony\Component\DependencyInjection\TypedReference; +use Symfony\Component\HttpKernel\HttpKernelInterface; require_once __DIR__.'/../Fixtures/includes/autowiring_classes.php'; @@ -605,6 +606,18 @@ class AutowirePassTest extends TestCase ); } + public function testWithNonExistingSetterAndAutowiring() + { + $container = new ContainerBuilder(); + + $definition = $container->register(HttpKernelInterface::class, HttpKernelInterface::class)->setAutowired(true); + $definition->addMethodCall('setLogger'); + $this->expectException(RuntimeException::class); + (new ResolveClassPass())->process($container); + (new AutowireRequiredMethodsPass())->process($container); + (new AutowirePass())->process($container); + } + public function testExplicitMethodInjection() { $container = new ContainerBuilder(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php index 5118b416f9..84b3d6c652 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php @@ -16,11 +16,14 @@ use Symfony\Component\DependencyInjection\Argument\BoundArgument; use Symfony\Component\DependencyInjection\Compiler\AutowireRequiredMethodsPass; use Symfony\Component\DependencyInjection\Compiler\ResolveBindingsPass; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Tests\Fixtures\CaseSensitiveClass; use Symfony\Component\DependencyInjection\Tests\Fixtures\NamedArgumentsDummy; use Symfony\Component\DependencyInjection\Tests\Fixtures\ParentNotExists; use Symfony\Component\DependencyInjection\TypedReference; +use Symfony\Component\HttpKernel\HttpKernelInterface; require_once __DIR__.'/../Fixtures/includes/autowiring_classes.php'; @@ -111,4 +114,45 @@ class ResolveBindingsPassTest extends TestCase $this->assertEquals([['setDefaultLocale', ['fr']]], $definition->getMethodCalls()); } + + public function testWithNonExistingSetterAndBinding() + { + $container = new ContainerBuilder(); + + $bindings = [ + '$c' => (new Definition('logger'))->setFactory('logger'), + ]; + + $definition = $container->register(HttpKernelInterface::class, HttpKernelInterface::class); + $definition->addMethodCall('setLogger'); + $definition->setBindings($bindings); + $this->expectException(RuntimeException::class); + + $pass = new ResolveBindingsPass(); + $pass->process($container); + } + + public function testTupleBinding() + { + $container = new ContainerBuilder(); + + $bindings = [ + '$c' => new BoundArgument(new Reference('bar')), + CaseSensitiveClass::class.'$c' => new BoundArgument(new Reference('foo')), + ]; + + $definition = $container->register(NamedArgumentsDummy::class, NamedArgumentsDummy::class); + $definition->addMethodCall('setSensitiveClass'); + $definition->addMethodCall('setAnotherC'); + $definition->setBindings($bindings); + + $pass = new ResolveBindingsPass(); + $pass->process($container); + + $expected = [ + ['setSensitiveClass', [new Reference('foo')]], + ['setAnotherC', [new Reference('bar')]], + ]; + $this->assertEquals($expected, $definition->getMethodCalls()); + } }