From 9e8e0630a98167651cd03e883670a85e0d4c72d1 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 21 Mar 2018 22:48:27 +0100 Subject: [PATCH] [DI] Add ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE --- .../Compiler/AutowirePass.php | 11 +- ...xceptionOnInvalidReferenceBehaviorPass.php | 2 +- .../Compiler/DefinitionErrorExceptionPass.php | 17 + .../Compiler/InlineServiceDefinitionsPass.php | 2 +- .../Compiler/ResolveChildDefinitionsPass.php | 4 + .../Compiler/ResolveInvalidReferencesPass.php | 18 +- .../DependencyInjection/ContainerBuilder.php | 8 +- .../ContainerInterface.php | 1 + .../DependencyInjection/Definition.php | 4 + .../DependencyInjection/Dumper/PhpDumper.php | 15 +- .../DependencyInjection/Dumper/YamlDumper.php | 1 + .../Tests/Compiler/AutowirePassTest.php | 15 + .../Tests/ContainerBuilderTest.php | 15 + .../Tests/Dumper/PhpDumperTest.php | 18 + .../Tests/Fixtures/config/services9.php | 7 + .../Tests/Fixtures/containers/container9.php | 7 + .../Tests/Fixtures/graphviz/services9.dot | 3 + .../Tests/Fixtures/php/services9_as_files.txt | 46 ++ .../Tests/Fixtures/php/services9_compiled.php | 22 + .../php/services_errored_definition.php | 504 ++++++++++++++++++ .../Tests/Fixtures/xml/services9.xml | 4 + .../Tests/Fixtures/yaml/services9.yml | 6 + .../Tests/Loader/PhpFileLoaderTest.php | 1 + .../ArgumentResolver/ServiceValueResolver.php | 18 +- ...RegisterControllerArgumentLocatorsPass.php | 4 +- ...sterControllerArgumentLocatorsPassTest.php | 4 +- ...mptyControllerArgumentLocatorsPassTest.php | 4 +- 27 files changed, 745 insertions(+), 16 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_errored_definition.php diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index 9d44bde35bd8c..7ed6988c62d71 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -86,7 +86,16 @@ private function doProcessValue($value, $isRoot = false) if ($ref = $this->getAutowiredReference($value)) { return $ref; } - $this->container->log($this, $this->createTypeNotFoundMessage($value, 'it')); + $message = $this->createTypeNotFoundMessage($value, 'it'); + + if (ContainerBuilder::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE === $value->getInvalidBehavior()) { + // since the error message varies by referenced id and $this->currentId, so should the id of the dummy errored definition + $this->container->register($id = sprintf('_errored.%s.%s', $this->currentId, (string) $value), $value->getType()) + ->addError($message); + + return new TypedReference($id, $value->getType(), $value->getInvalidBehavior()); + } + $this->container->log($this, $message); } $value = parent::processValue($value, $isRoot); diff --git a/src/Symfony/Component/DependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php b/src/Symfony/Component/DependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php index 7ffedd3dc0523..1bae24c10b458 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php @@ -28,7 +28,7 @@ protected function processValue($value, $isRoot = false) if (!$value instanceof Reference) { return parent::processValue($value, $isRoot); } - if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $value->getInvalidBehavior() && !$this->container->has($id = (string) $value)) { + if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $value->getInvalidBehavior() && !$this->container->has($id = (string) $value)) { throw new ServiceNotFoundException($id, $this->currentId); } if (ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior() && $this->container->has($id = (string) $value) && !$this->container->findDefinition($id)->isShared()) { diff --git a/src/Symfony/Component/DependencyInjection/Compiler/DefinitionErrorExceptionPass.php b/src/Symfony/Component/DependencyInjection/Compiler/DefinitionErrorExceptionPass.php index 73b5d1d57d582..509011247c1c2 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/DefinitionErrorExceptionPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/DefinitionErrorExceptionPass.php @@ -11,8 +11,10 @@ namespace Symfony\Component\DependencyInjection\Compiler; +use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\Reference; /** * Throws an exception for any Definitions that have errors and still exist. @@ -30,6 +32,21 @@ protected function processValue($value, $isRoot = false) return parent::processValue($value, $isRoot); } + if ($isRoot && !$value->isPublic()) { + $graph = $this->container->getCompiler()->getServiceReferenceGraph(); + $runtimeException = false; + foreach ($graph->getNode($this->currentId)->getInEdges() as $edge) { + if (!$edge->getValue() instanceof Reference || ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE !== $edge->getValue()->getInvalidBehavior()) { + $runtimeException = false; + break; + } + $runtimeException = true; + } + if ($runtimeException) { + return parent::processValue($value, $isRoot); + } + } + // only show the first error so the user can focus on it $errors = $value->getErrors(); $message = reset($errors); diff --git a/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php index 00a1e1f99fced..d3b379034bd7f 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php @@ -92,7 +92,7 @@ private function isInlineableDefinition($id, Definition $definition, ServiceRefe return true; } - if ($definition->isDeprecated() || $definition->isPublic() || $definition->isLazy()) { + if ($definition->isDeprecated() || $definition->isPublic() || $definition->isLazy() || $definition->getErrors()) { return false; } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php index 0ad3fe1dcd509..62d0e7c680cb0 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php @@ -163,6 +163,10 @@ private function doResolveDefinition(ChildDefinition $definition) $def->setMethodCalls(array_merge($def->getMethodCalls(), $calls)); } + foreach (array_merge($parentDef->getErrors(), $definition->getErrors()) as $v) { + $def->addError($v); + } + // these attributes are always taken from the child $def->setAbstract($definition->isAbstract()); $def->setTags($definition->getTags()); diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.php index d60272b276558..d894a2f99008b 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.php @@ -15,7 +15,9 @@ use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\TypedReference; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\RuntimeException; @@ -29,6 +31,7 @@ class ResolveInvalidReferencesPass implements CompilerPassInterface { private $container; private $signalingException; + private $currentId; /** * Process the ContainerBuilder to resolve invalid references. @@ -67,6 +70,9 @@ private function processValue($value, $rootLevel = 0, $level = 0) $i = 0; foreach ($value as $k => $v) { + if (!$rootLevel) { + $this->currentId = $k; + } try { if (false !== $i && $k !== $i++) { $i = false; @@ -90,11 +96,21 @@ private function processValue($value, $rootLevel = 0, $level = 0) $value = array_values($value); } } elseif ($value instanceof Reference) { - if ($this->container->has($value)) { + if ($this->container->has($id = (string) $value)) { return $value; } $invalidBehavior = $value->getInvalidBehavior(); + if (ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior && $value instanceof TypedReference && !$this->container->has($id)) { + $e = new ServiceNotFoundException($id, $this->currentId); + + // since the error message varies by $id and $this->currentId, so should the id of the dummy errored definition + $this->container->register($id = sprintf('_errored.%s.%s', $this->currentId, $id), $value->getType()) + ->addError($e->getMessage()); + + return new TypedReference($id, $value->getType(), $value->getInvalidBehavior()); + } + // resolve invalid behavior if (ContainerInterface::NULL_ON_INVALID_REFERENCE === $invalidBehavior) { $value = null; diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index f28726c11a55f..16d6854340fd5 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -529,7 +529,7 @@ public function has($id) */ public function get($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) { - if ($this->isCompiled() && isset($this->removedIds[$id = (string) $id]) && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior) { + if ($this->isCompiled() && isset($this->removedIds[$id = (string) $id]) && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $invalidBehavior) { return parent::get($id); } @@ -555,13 +555,17 @@ private function doGet($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_ try { $definition = $this->getDefinition($id); } catch (ServiceNotFoundException $e) { - if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) { + if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE < $invalidBehavior) { return; } throw $e; } + if ($e = $definition->getErrors()) { + throw new RuntimeException(reset($e)); + } + $loading = isset($this->alreadyLoading[$id]) ? 'loading' : 'alreadyLoading'; $this->{$loading}[$id] = true; diff --git a/src/Symfony/Component/DependencyInjection/ContainerInterface.php b/src/Symfony/Component/DependencyInjection/ContainerInterface.php index 2274ec7bb3266..f859b020314e5 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerInterface.php +++ b/src/Symfony/Component/DependencyInjection/ContainerInterface.php @@ -24,6 +24,7 @@ */ interface ContainerInterface extends PsrContainerInterface { + const RUNTIME_EXCEPTION_ON_INVALID_REFERENCE = 0; const EXCEPTION_ON_INVALID_REFERENCE = 1; const NULL_ON_INVALID_REFERENCE = 2; const IGNORE_ON_INVALID_REFERENCE = 3; diff --git a/src/Symfony/Component/DependencyInjection/Definition.php b/src/Symfony/Component/DependencyInjection/Definition.php index 6f2e94bf5bd1d..2116505895636 100644 --- a/src/Symfony/Component/DependencyInjection/Definition.php +++ b/src/Symfony/Component/DependencyInjection/Definition.php @@ -873,10 +873,14 @@ public function setBindings(array $bindings) * Add an error that occurred when building this Definition. * * @param string $error + * + * @return $this */ public function addError($error) { $this->errors[] = $error; + + return $this; } /** diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 9a109e8a1cc85..f503786789234 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -187,6 +187,7 @@ public function dump(array $options = array()) getNextVariableName(); $this->referenceVariables[$id] = new Variable($name); - $reference = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $behavior[$id] ? new Reference($id, $behavior[$id]) : null; + $reference = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $behavior[$id] ? new Reference($id, $behavior[$id]) : null; $code .= sprintf(" \$%s = %s;\n", $name, $this->getServiceCall($id, $reference)); } @@ -552,7 +553,7 @@ private function isTrivialInstance(Definition $definition): bool if ($definition->isSynthetic() || $definition->getFile() || $definition->getMethodCalls() || $definition->getProperties() || $definition->getConfigurator()) { return false; } - if ($definition->isDeprecated() || $definition->isLazy() || $definition->getFactory() || 3 < count($definition->getArguments())) { + if ($definition->isDeprecated() || $definition->isLazy() || $definition->getFactory() || 3 < count($definition->getArguments()) || $definition->getErrors()) { return false; } @@ -738,6 +739,12 @@ protected function {$methodName}($lazyInitialization) EOF; } + if ($e = $definition->getErrors()) { + $e = sprintf("throw new RuntimeException(%s);\n", $this->export(reset($e))); + + return $asFile ? substr($code, 8).$e : $code.' '.$e." }\n"; + } + $inlinedDefinitions = $this->getDefinitionsFromArguments(array($definition)); $constructorDefinitions = $this->getDefinitionsFromArguments(array($definition->getArguments(), $definition->getFactory())); $otherDefinitions = new \SplObjectStorage(); @@ -1470,7 +1477,7 @@ private function dumpValue($value, bool $interpolate = true): string $returnedType = ''; if ($value instanceof TypedReference) { - $returnedType = sprintf(': %s\%s', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $value->getInvalidBehavior() ? '' : '?', $value->getType()); + $returnedType = sprintf(': %s\%s', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $value->getInvalidBehavior() ? '' : '?', $value->getType()); } $code = sprintf('return %s;', $code); @@ -1675,7 +1682,7 @@ private function getServiceCall(string $id, Reference $reference = null): string if (null !== $reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $reference->getInvalidBehavior()) { return 'null'; } - if (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) { + if (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE < $reference->getInvalidBehavior()) { $code = sprintf('$this->get(\'%s\', /* ContainerInterface::NULL_ON_INVALID_REFERENCE */ %d)', $id, ContainerInterface::NULL_ON_INVALID_REFERENCE); } else { $code = sprintf('$this->get(\'%s\')', $id); diff --git a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php index 25830e0bc506b..8fa341bcadac4 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php @@ -266,6 +266,7 @@ private function getServiceCall(string $id, Reference $reference = null): string { if (null !== $reference) { switch ($reference->getInvalidBehavior()) { + case ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE: break; case ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE: break; case ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE: return sprintf('@!%s', $id); default: return sprintf('@?%s', $id); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php index a78ea122c2c77..b5673e92a638e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -20,6 +20,7 @@ use Symfony\Component\DependencyInjection\Compiler\DecoratorServicePass; use Symfony\Component\DependencyInjection\Compiler\ResolveClassPass; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\DependencyInjection\Reference; @@ -845,4 +846,18 @@ public function testDoNotAutowireDecoratorWhenSeveralArgumentOfTheType() (new DecoratorServicePass())->process($container); (new AutowirePass())->process($container); } + + public function testErroredServiceLocator() + { + $container = new ContainerBuilder(); + $container->register('some_locator', 'stdClass') + ->addArgument(new TypedReference(MissingClass::class, MissingClass::class, ContainerBuilder::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE)) + ->addTag('container.service_locator'); + + (new AutowirePass())->process($container); + + $erroredDefinition = new Definition(MissingClass::class); + + $this->assertEquals($erroredDefinition->addError('Cannot autowire service "some_locator": it has type "Symfony\Component\DependencyInjection\Tests\Compiler\MissingClass" but this class was not found.'), $container->getDefinition('_errored.some_locator.'.MissingClass::class)); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index 1b719938a9d0f..acc8480f31c27 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -1367,6 +1367,21 @@ public function testIdCanBeAnObjectAsLongAsItCanBeCastToString() $container->removeAlias($aliasId); $container->removeDefinition($id); } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedExceptionMessage Service "errored_definition" is broken. + */ + public function testErroredDefinition() + { + $container = new ContainerBuilder(); + + $container->register('errored_definition', 'stdClass') + ->addError('Service "errored_definition" is broken.') + ->setPublic(true); + + $container->get('errored_definition'); + } } class FooClass diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index cdeaac72cf787..897647f4c1d41 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -946,6 +946,24 @@ public function testParameterWithMixedCase() $this->assertSame('bar', $container->getParameter('Foo')); $this->assertSame('foo', $container->getParameter('BAR')); } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedExceptionMessage Service "errored_definition" is broken. + */ + public function testErroredDefinition() + { + $container = include self::$fixturesPath.'/containers/container9.php'; + $container->setParameter('foo_bar', 'foo_bar'); + $container->compile(); + $dumper = new PhpDumper($container); + $dump = $dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Errored_Definition')); + $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_errored_definition.php', str_replace(str_replace('\\', '\\\\', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR), '%path%', $dump)); + eval('?>'.$dump); + + $container = new \Symfony_DI_PhpDumper_Errored_Definition(); + $container->get('runtime_error'); + } } class Rot13EnvVarProcessor implements EnvVarProcessorInterface diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services9.php index 4bf3b89d8e3e0..8055f8ce7d8ac 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services9.php @@ -3,6 +3,8 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator; use Bar\FooClass; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Parameter; require_once __DIR__.'/../includes/classes.php'; @@ -128,6 +130,11 @@ ->public() ->args(array(tagged('foo'))); + $s->set('runtime_error', 'stdClass') + ->args(array(new Reference('errored_definition', ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE))) + ->public(); + $s->set('errored_definition', 'stdClass')->private(); + $s->alias('alias_for_foo', 'foo')->private()->public(); $s->alias('alias_for_alias', ref('alias_for_foo')); }; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php index 06789bd350fe1..c403a3af40638 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php @@ -180,4 +180,11 @@ $container->setAlias('alias_for_foo', 'foo')->setPublic(true); $container->setAlias('alias_for_alias', 'alias_for_foo')->setPublic(true); +$container->register('runtime_error', 'stdClass') + ->addArgument(new Reference('errored_definition', ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE)) + ->setPublic(true); + +$container->register('errored_definition', 'stdClass') + ->addError('Service "errored_definition" is broken.'); + return $container; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot index 2c116979e4b6f..5cf170fddb8c3 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot @@ -34,6 +34,8 @@ digraph sc { node_BAR2 [label="BAR2\nstdClass\n", shape=record, fillcolor="#eeeeee", style="filled"]; node_tagged_iterator_foo [label="tagged_iterator_foo\nBar\n", shape=record, fillcolor="#eeeeee", style="filled"]; node_tagged_iterator [label="tagged_iterator\nBar\n", shape=record, fillcolor="#eeeeee", style="filled"]; + node_runtime_error [label="runtime_error\nstdClass\n", shape=record, fillcolor="#eeeeee", style="filled"]; + node_errored_definition [label="errored_definition\nstdClass\n", shape=record, fillcolor="#eeeeee", style="filled"]; node_foo2 [label="foo2\n\n", shape=record, fillcolor="#ff9999", style="filled"]; node_foo3 [label="foo3\n\n", shape=record, fillcolor="#ff9999", style="filled"]; node_foobaz [label="foobaz\n\n", shape=record, fillcolor="#ff9999", style="filled"]; @@ -57,4 +59,5 @@ digraph sc { node_lazy_context_ignore_invalid_ref -> node_foo_baz [label="" style="filled" color="#9999ff"]; node_lazy_context_ignore_invalid_ref -> node_invalid [label="" style="filled" color="#9999ff"]; node_BAR -> node_bar [label="" style="dashed"]; + node_runtime_error -> node_errored_definition [label="" style="filled"]; } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt index 6cea40ce0624e..ad14fd95345f2 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt @@ -9,6 +9,7 @@ return array( 'configurator_service_simple' => true, 'decorated.pif-pouf' => true, 'decorator_service.inner' => true, + 'errored_definition' => true, 'factory_simple' => true, 'inlined' => true, 'new_factory' => true, @@ -18,6 +19,7 @@ return array( [Container%s/getBAR2Service.php] => services['BAR2'] = new \stdClass(); [Container%s/getBar23Service.php] => services['bar2'] = new \stdClass(); [Container%s/getBazService.php] => services['decorator_service'] = new \stdClass(); [Container%s/getDecoratorServiceWithNameService.php] => services['decorator_service_with_name'] = new \stdClass(); [Container%s/getDeprecatedServiceService.php] => services['deprecated_service'] = new \stdClass(); + [Container%s/getErroredDefinitionService.php] => services['factory_service'] = ($this->services['foo.baz'] ?? $this [Container%s/getFactoryServiceSimpleService.php] => services['factory_service_simple'] = ($this->privates['factory_sim [Container%s/getFactorySimpleService.php] => privates['factory_simple'] = new \SimpleFactoryClass('foo'); [Container%s/getFooService.php] => factories['foo_bar'](); [Container%s/getFooWithInlineService.php] => services['lazy_context'] = new \LazyContext(new RewindableGenerato [Container%s/getLazyContextIgnoreInvalidRefService.php] => services['lazy_context_ignore_invalid_ref'] = new \LazyContext(new [Container%s/getMethodCall1Service.php] => factories['non_shared_foo'] = function () { return $this->factories['non_shared_foo'](); + [Container%s/getRuntimeErrorService.php] => services['runtime_error'] = new \stdClass(($this->privates['errored_definition'] ?? $this->load(__DIR__.'/getErroredDefinitionService.php'))); + [Container%s/getServiceFromStaticMethodService.php] => services['service_from_static_method'] = \Bar\FooClass::getInstanc [Container%s/getTaggedIteratorService.php] => services['tagged_iterator'] = new \Bar(new RewindableGenerator(fun [Container%s/getTaggedIteratorFooService.php] => __DIR__.'/getMethodCall1Service.php', 'new_factory_service' => __DIR__.'/getNewFactoryServiceService.php', 'non_shared_foo' => __DIR__.'/getNonSharedFooService.php', + 'runtime_error' => __DIR__.'/getRuntimeErrorService.php', 'service_from_static_method' => __DIR__.'/getServiceFromStaticMethodService.php', 'tagged_iterator' => __DIR__.'/getTaggedIteratorService.php', ); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php index a45456163f796..6231dab53aac9 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php @@ -53,6 +53,7 @@ public function __construct() 'lazy_context_ignore_invalid_ref' => 'getLazyContextIgnoreInvalidRefService', 'method_call1' => 'getMethodCall1Service', 'new_factory_service' => 'getNewFactoryServiceService', + 'runtime_error' => 'getRuntimeErrorService', 'service_from_static_method' => 'getServiceFromStaticMethodService', 'tagged_iterator' => 'getTaggedIteratorService', ); @@ -88,6 +89,7 @@ public function getRemovedIds() 'configurator_service_simple' => true, 'decorated.pif-pouf' => true, 'decorator_service.inner' => true, + 'errored_definition' => true, 'factory_simple' => true, 'inlined' => true, 'new_factory' => true, @@ -372,6 +374,16 @@ protected function getNewFactoryServiceService() return $instance; } + /** + * Gets the public 'runtime_error' shared service. + * + * @return \stdClass + */ + protected function getRuntimeErrorService() + { + return $this->services['runtime_error'] = new \stdClass(($this->privates['errored_definition'] ?? $this->getErroredDefinitionService())); + } + /** * Gets the public 'service_from_static_method' shared service. * @@ -395,6 +407,16 @@ protected function getTaggedIteratorService() }, 2)); } + /** + * Gets the private 'errored_definition' shared service. + * + * @return \stdClass + */ + protected function getErroredDefinitionService() + { + throw new RuntimeException('Service "errored_definition" is broken.'); + } + /** * Gets the private 'factory_simple' shared service. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_errored_definition.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_errored_definition.php new file mode 100644 index 0000000000000..34a38dfc40274 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_errored_definition.php @@ -0,0 +1,504 @@ +parameters = $this->getDefaultParameters(); + + $this->services = $this->privates = array(); + $this->syntheticIds = array( + 'request' => true, + ); + $this->methodMap = array( + 'BAR' => 'getBARService', + 'BAR2' => 'getBAR2Service', + 'bar' => 'getBar3Service', + 'bar2' => 'getBar22Service', + 'baz' => 'getBazService', + 'configured_service' => 'getConfiguredServiceService', + 'configured_service_simple' => 'getConfiguredServiceSimpleService', + 'decorator_service' => 'getDecoratorServiceService', + 'decorator_service_with_name' => 'getDecoratorServiceWithNameService', + 'deprecated_service' => 'getDeprecatedServiceService', + 'factory_service' => 'getFactoryServiceService', + 'factory_service_simple' => 'getFactoryServiceSimpleService', + 'foo' => 'getFooService', + 'foo.baz' => 'getFoo_BazService', + 'foo_bar' => 'getFooBarService', + 'foo_with_inline' => 'getFooWithInlineService', + 'lazy_context' => 'getLazyContextService', + 'lazy_context_ignore_invalid_ref' => 'getLazyContextIgnoreInvalidRefService', + 'method_call1' => 'getMethodCall1Service', + 'new_factory_service' => 'getNewFactoryServiceService', + 'runtime_error' => 'getRuntimeErrorService', + 'service_from_static_method' => 'getServiceFromStaticMethodService', + 'tagged_iterator' => 'getTaggedIteratorService', + ); + $this->aliases = array( + 'alias_for_alias' => 'foo', + 'alias_for_foo' => 'foo', + 'decorated' => 'decorator_service_with_name', + ); + } + + public function reset() + { + $this->privates = array(); + parent::reset(); + } + + public function compile() + { + throw new LogicException('You cannot compile a dumped container that was already compiled.'); + } + + public function isCompiled() + { + return true; + } + + public function getRemovedIds() + { + return array( + 'Psr\\Container\\ContainerInterface' => true, + 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, + 'configurator_service' => true, + 'configurator_service_simple' => true, + 'decorated.pif-pouf' => true, + 'decorator_service.inner' => true, + 'errored_definition' => true, + 'factory_simple' => true, + 'inlined' => true, + 'new_factory' => true, + 'tagged_iterator_foo' => true, + ); + } + + /** + * Gets the public 'BAR' shared service. + * + * @return \stdClass + */ + protected function getBARService() + { + $this->services['BAR'] = $instance = new \stdClass(); + + $instance->bar = ($this->services['bar'] ?? $this->getBar3Service()); + + return $instance; + } + + /** + * Gets the public 'BAR2' shared service. + * + * @return \stdClass + */ + protected function getBAR2Service() + { + return $this->services['BAR2'] = new \stdClass(); + } + + /** + * Gets the public 'bar' shared service. + * + * @return \Bar\FooClass + */ + protected function getBar3Service() + { + $a = ($this->services['foo.baz'] ?? $this->getFoo_BazService()); + + $this->services['bar'] = $instance = new \Bar\FooClass('foo', $a, 'foo_bar'); + + $a->configure($instance); + + return $instance; + } + + /** + * Gets the public 'bar2' shared service. + * + * @return \stdClass + */ + protected function getBar22Service() + { + return $this->services['bar2'] = new \stdClass(); + } + + /** + * Gets the public 'baz' shared service. + * + * @return \Baz + */ + protected function getBazService() + { + $this->services['baz'] = $instance = new \Baz(); + + $instance->setFoo(($this->services['foo_with_inline'] ?? $this->getFooWithInlineService())); + + return $instance; + } + + /** + * Gets the public 'configured_service' shared service. + * + * @return \stdClass + */ + protected function getConfiguredServiceService() + { + $this->services['configured_service'] = $instance = new \stdClass(); + + $a = new \ConfClass(); + $a->setFoo(($this->services['baz'] ?? $this->getBazService())); + + $a->configureStdClass($instance); + + return $instance; + } + + /** + * Gets the public 'configured_service_simple' shared service. + * + * @return \stdClass + */ + protected function getConfiguredServiceSimpleService() + { + $this->services['configured_service_simple'] = $instance = new \stdClass(); + + (new \ConfClass('bar'))->configureStdClass($instance); + + return $instance; + } + + /** + * Gets the public 'decorator_service' shared service. + * + * @return \stdClass + */ + protected function getDecoratorServiceService() + { + return $this->services['decorator_service'] = new \stdClass(); + } + + /** + * Gets the public 'decorator_service_with_name' shared service. + * + * @return \stdClass + */ + protected function getDecoratorServiceWithNameService() + { + return $this->services['decorator_service_with_name'] = new \stdClass(); + } + + /** + * Gets the public 'deprecated_service' shared service. + * + * @return \stdClass + * + * @deprecated The "deprecated_service" service is deprecated. You should stop using it, as it will soon be removed. + */ + protected function getDeprecatedServiceService() + { + @trigger_error('The "deprecated_service" service is deprecated. You should stop using it, as it will soon be removed.', E_USER_DEPRECATED); + + return $this->services['deprecated_service'] = new \stdClass(); + } + + /** + * Gets the public 'factory_service' shared service. + * + * @return \Bar + */ + protected function getFactoryServiceService() + { + return $this->services['factory_service'] = ($this->services['foo.baz'] ?? $this->getFoo_BazService())->getInstance(); + } + + /** + * Gets the public 'factory_service_simple' shared service. + * + * @return \Bar + */ + protected function getFactoryServiceSimpleService() + { + return $this->services['factory_service_simple'] = ($this->privates['factory_simple'] ?? $this->getFactorySimpleService())->getInstance(); + } + + /** + * Gets the public 'foo' shared service. + * + * @return \Bar\FooClass + */ + protected function getFooService() + { + $a = ($this->services['foo.baz'] ?? $this->getFoo_BazService()); + + $this->services['foo'] = $instance = \Bar\FooClass::getInstance('foo', $a, array('bar' => 'foo is bar', 'foobar' => 'bar'), true, $this); + + $instance->foo = 'bar'; + $instance->moo = $a; + $instance->qux = array('bar' => 'foo is bar', 'foobar' => 'bar'); + $instance->setBar(($this->services['bar'] ?? $this->getBar3Service())); + $instance->initialize(); + sc_configure($instance); + + return $instance; + } + + /** + * Gets the public 'foo.baz' shared service. + * + * @return \BazClass + */ + protected function getFoo_BazService() + { + $this->services['foo.baz'] = $instance = \BazClass::getInstance(); + + \BazClass::configureStatic1($instance); + + return $instance; + } + + /** + * Gets the public 'foo_bar' service. + * + * @return \Bar\FooClass + */ + protected function getFooBarService() + { + return new \Bar\FooClass(($this->services['deprecated_service'] ?? $this->getDeprecatedServiceService())); + } + + /** + * Gets the public 'foo_with_inline' shared service. + * + * @return \Foo + */ + protected function getFooWithInlineService() + { + $this->services['foo_with_inline'] = $instance = new \Foo(); + + $a = new \Bar(); + + $a->pub = 'pub'; + $a->setBaz(($this->services['baz'] ?? $this->getBazService())); + + $instance->setBar($a); + + return $instance; + } + + /** + * Gets the public 'lazy_context' shared service. + * + * @return \LazyContext + */ + protected function getLazyContextService() + { + return $this->services['lazy_context'] = new \LazyContext(new RewindableGenerator(function () { + yield 'k1' => ($this->services['foo.baz'] ?? $this->getFoo_BazService()); + yield 'k2' => $this; + }, 2), new RewindableGenerator(function () { + return new \EmptyIterator(); + }, 0)); + } + + /** + * Gets the public 'lazy_context_ignore_invalid_ref' shared service. + * + * @return \LazyContext + */ + protected function getLazyContextIgnoreInvalidRefService() + { + return $this->services['lazy_context_ignore_invalid_ref'] = new \LazyContext(new RewindableGenerator(function () { + yield 0 => ($this->services['foo.baz'] ?? $this->getFoo_BazService()); + }, 1), new RewindableGenerator(function () { + return new \EmptyIterator(); + }, 0)); + } + + /** + * Gets the public 'method_call1' shared service. + * + * @return \Bar\FooClass + */ + protected function getMethodCall1Service() + { + include_once '%path%foo.php'; + + $this->services['method_call1'] = $instance = new \Bar\FooClass(); + + $instance->setBar(($this->services['foo'] ?? $this->getFooService())); + $instance->setBar(NULL); + $instance->setBar((($this->services['foo'] ?? $this->getFooService())->foo() . (($this->hasParameter("foo")) ? ($this->getParameter("foo")) : ("default")))); + + return $instance; + } + + /** + * Gets the public 'new_factory_service' shared service. + * + * @return \FooBarBaz + */ + protected function getNewFactoryServiceService() + { + $a = new \FactoryClass(); + $a->foo = 'bar'; + + $this->services['new_factory_service'] = $instance = $a->getInstance(); + + $instance->foo = 'bar'; + + return $instance; + } + + /** + * Gets the public 'runtime_error' shared service. + * + * @return \stdClass + */ + protected function getRuntimeErrorService() + { + return $this->services['runtime_error'] = new \stdClass(($this->privates['errored_definition'] ?? $this->getErroredDefinitionService())); + } + + /** + * Gets the public 'service_from_static_method' shared service. + * + * @return \Bar\FooClass + */ + protected function getServiceFromStaticMethodService() + { + return $this->services['service_from_static_method'] = \Bar\FooClass::getInstance(); + } + + /** + * Gets the public 'tagged_iterator' shared service. + * + * @return \Bar + */ + protected function getTaggedIteratorService() + { + return $this->services['tagged_iterator'] = new \Bar(new RewindableGenerator(function () { + yield 0 => ($this->services['foo'] ?? $this->getFooService()); + yield 1 => ($this->privates['tagged_iterator_foo'] ?? $this->privates['tagged_iterator_foo'] = new \Bar()); + }, 2)); + } + + /** + * Gets the private 'errored_definition' shared service. + * + * @return \stdClass + */ + protected function getErroredDefinitionService() + { + throw new RuntimeException('Service "errored_definition" is broken.'); + } + + /** + * Gets the private 'factory_simple' shared service. + * + * @return \SimpleFactoryClass + * + * @deprecated The "factory_simple" service is deprecated. You should stop using it, as it will soon be removed. + */ + protected function getFactorySimpleService() + { + @trigger_error('The "factory_simple" service is deprecated. You should stop using it, as it will soon be removed.', E_USER_DEPRECATED); + + return $this->privates['factory_simple'] = new \SimpleFactoryClass('foo'); + } + + public function getParameter($name) + { + $name = (string) $name; + + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); + } + if (isset($this->loadedDynamicParameters[$name])) { + return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); + } + + return $this->parameters[$name]; + } + + public function hasParameter($name) + { + $name = (string) $name; + + return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); + } + + public function setParameter($name, $value) + { + throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); + } + + public function getParameterBag() + { + if (null === $this->parameterBag) { + $parameters = $this->parameters; + foreach ($this->loadedDynamicParameters as $name => $loaded) { + $parameters[$name] = $loaded ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); + } + $this->parameterBag = new FrozenParameterBag($parameters); + } + + return $this->parameterBag; + } + + private $loadedDynamicParameters = array(); + private $dynamicParameters = array(); + + /** + * Computes a dynamic parameter. + * + * @param string The name of the dynamic parameter to load + * + * @return mixed The value of the dynamic parameter + * + * @throws InvalidArgumentException When the dynamic parameter does not exist + */ + private function getDynamicParameter($name) + { + throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name)); + } + + /** + * Gets the default parameters. + * + * @return array An array of the default parameters + */ + protected function getDefaultParameters() + { + return array( + 'baz_class' => 'BazClass', + 'foo_class' => 'Bar\\FooClass', + 'foo' => 'bar', + 'foo_bar' => 'foo_bar', + ); + } +} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml index 3848a83dbd463..e4a3ac4bbed11 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml @@ -144,6 +144,10 @@ + + + + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml index dbe59ed9e56a2..52de888b05581 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml @@ -171,3 +171,9 @@ services: alias_for_alias: alias: 'foo' public: true + runtime_error: + class: stdClass + arguments: ['@errored_definition'] + public: true + errored_definition: + class: stdClass diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php index f4c8d36e6249e..d4149f0301d3d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php @@ -43,6 +43,7 @@ public function testConfigServices() $fixtures = realpath(__DIR__.'/../Fixtures'); $loader = new PhpFileLoader($container = new ContainerBuilder(), new FileLocator()); $loader->load($fixtures.'/config/services9.php'); + $container->getDefinition('errored_definition')->addError('Service "errored_definition" is broken.'); $container->compile(); $dumper = new PhpDumper($container); diff --git a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/ServiceValueResolver.php b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/ServiceValueResolver.php index c55564c0467ef..dd145b3af810b 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/ServiceValueResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/ServiceValueResolver.php @@ -12,6 +12,7 @@ namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; use Psr\Container\ContainerInterface; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; @@ -53,6 +54,21 @@ public function resolve(Request $request, ArgumentMetadata $argument) $controller = $controller[0].'::'.$controller[1]; } - yield $this->container->get($controller)->get($argument->getName()); + try { + yield $this->container->get($controller)->get($argument->getName()); + } catch (RuntimeException $e) { + $what = sprintf('argument $%s of "%s()"', $argument->getName(), $controller); + $message = preg_replace('/service "service_locator\.[^"]++"/', $what, $e->getMessage()); + + if ($e->getMessage() === $message) { + $message = sprintf('Cannot resolve %s: %s', $what, $message); + } + + $r = new \ReflectionProperty($e, 'message'); + $r->setAccessible(true); + $r->setValue($e, $message); + + throw $e; + } } } diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php b/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php index e5cc3facf6759..ffd74c711135a 100644 --- a/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php +++ b/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php @@ -126,7 +126,7 @@ public function process(ContainerBuilder $container) if (isset($arguments[$r->name][$p->name])) { $target = $arguments[$r->name][$p->name]; if ('?' !== $target[0]) { - $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; + $invalidBehavior = ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE; } elseif ('' === $target = (string) substr($target, 1)) { throw new InvalidArgumentException(sprintf('A "%s" tag must have non-empty "id" attributes for service "%s".', $this->controllerTag, $id)); } elseif ($p->allowsNull() && !$p->isOptional()) { @@ -147,6 +147,8 @@ public function process(ContainerBuilder $container) continue; } elseif (!$type || !$autowire) { continue; + } elseif (!$p->allowsNull()) { + $invalidBehavior = ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE; } if (Request::class === $type) { diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php index 383a86a61f0da..faf76d35ebb9e 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php @@ -148,7 +148,7 @@ public function testAllActions() $this->assertSame(ServiceLocator::class, $locator->getClass()); $this->assertFalse($locator->isPublic()); - $expected = array('bar' => new ServiceClosureArgument(new TypedReference(ControllerDummy::class, ControllerDummy::class, ContainerInterface::IGNORE_ON_INVALID_REFERENCE))); + $expected = array('bar' => new ServiceClosureArgument(new TypedReference(ControllerDummy::class, ControllerDummy::class, ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE))); $this->assertEquals($expected, $locator->getArgument(0)); } @@ -168,7 +168,7 @@ public function testExplicitArgument() $locator = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0); $locator = $container->getDefinition((string) $locator['foo::fooAction']->getValues()[0]); - $expected = array('bar' => new ServiceClosureArgument(new TypedReference('bar', ControllerDummy::class))); + $expected = array('bar' => new ServiceClosureArgument(new TypedReference('bar', ControllerDummy::class, ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE))); $this->assertEquals($expected, $locator->getArgument(0)); } diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPassTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPassTest.php index 36e9310ae783f..dfec38347d6cc 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPassTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPassTest.php @@ -81,7 +81,7 @@ public function testInvoke() class RemoveTestController1 { - public function fooAction(\stdClass $bar, ClassNotInContainer $baz) + public function fooAction(\stdClass $bar, ClassNotInContainer $baz = null) { } } @@ -92,7 +92,7 @@ public function setTestCase(TestCase $test) { } - public function fooAction(ClassNotInContainer $bar) + public function fooAction(ClassNotInContainer $bar = null) { } }