Skip to content

Commit 15bbba4

Browse files
[DI] Add ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_DEFINITION
1 parent 07a2f6c commit 15bbba4

21 files changed

+679
-13
lines changed

src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,15 @@ private function doProcessValue($value, $isRoot = false)
8888
if ($ref = $this->getAutowiredReference($value, $value->getRequiringClass() ? sprintf('for "%s" in "%s"', $value->getType(), $value->getRequiringClass()) : '')) {
8989
return $ref;
9090
}
91-
$this->container->log($this, $this->createTypeNotFoundMessage($value, 'it'));
91+
$message = $this->createTypeNotFoundMessage($value, 'it');
92+
93+
if (ContainerBuilder::RUNTIME_EXCEPTION_ON_INVALID_DEFINITION === $value->getInvalidBehavior()) {
94+
$this->container->register((string) $value, $value->getType())
95+
->addError($message);
96+
97+
return $value;
98+
}
99+
$this->container->log($this, $message);
92100
}
93101
$value = parent::processValue($value, $isRoot);
94102

@@ -376,7 +384,8 @@ private function createTypeNotFoundMessage(TypedReference $reference, $label)
376384
}
377385
}
378386

379-
$message = sprintf('Cannot autowire service "%s": %s %s', $this->currentId, $label, $message);
387+
$id = $reference->getRequiringClass() && $this->container->getDefinition($this->currentId)->hasTag('container.service_locator') ? sprintf('class "%s"', $reference->getRequiringClass()) : sprintf('service "%s"', $this->currentId);
388+
$message = sprintf('Cannot autowire %s: %s %s', $id, $label, $message);
380389

381390
if (null !== $this->lastFailure) {
382391
$message = $this->lastFailure."\n".$message;

src/Symfony/Component/DependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ protected function processValue($value, $isRoot = false)
2828
if (!$value instanceof Reference) {
2929
return parent::processValue($value, $isRoot);
3030
}
31-
if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $value->getInvalidBehavior() && !$this->container->has($id = (string) $value)) {
31+
if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $value->getInvalidBehavior() && !$this->container->has($id = (string) $value)) {
3232
throw new ServiceNotFoundException($id, $this->currentId);
3333
}
3434
if (ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior() && $this->container->has($id = (string) $value) && !$this->container->findDefinition($id)->isShared()) {

src/Symfony/Component/DependencyInjection/Compiler/DefinitionErrorExceptionPass.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
1111

1212
namespace Symfony\Component\DependencyInjection\Compiler;
1313

14+
use Symfony\Component\DependencyInjection\ContainerInterface;
1415
use Symfony\Component\DependencyInjection\Definition;
1516
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
17+
use Symfony\Component\DependencyInjection\Reference;
1618

1719
/**
1820
* Throws an exception for any Definitions that have errors and still exist.
@@ -30,6 +32,21 @@ protected function processValue($value, $isRoot = false)
3032
return parent::processValue($value, $isRoot);
3133
}
3234

35+
if ($isRoot && !$value->isPublic()) {
36+
$graph = $this->container->getCompiler()->getServiceReferenceGraph();
37+
$runtimeException = false;
38+
foreach ($graph->getNode($this->currentId)->getInEdges() as $edge) {
39+
if (!$edge->getValue() instanceof Reference || ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_DEFINITION !== $edge->getValue()->getInvalidBehavior()) {
40+
$runtimeException = false;
41+
break;
42+
}
43+
$runtimeException = true;
44+
}
45+
if ($runtimeException) {
46+
return parent::processValue($value, $isRoot);
47+
}
48+
}
49+
3350
// only show the first error so the user can focus on it
3451
$errors = $value->getErrors();
3552
$message = reset($errors);

src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ private function isInlineableDefinition($id, Definition $definition, ServiceRefe
9292
return true;
9393
}
9494

95-
if ($definition->isDeprecated() || $definition->isPublic() || $definition->isLazy()) {
95+
if ($definition->isDeprecated() || $definition->isPublic() || $definition->isLazy() || $definition->getErrors()) {
9696
return false;
9797
}
9898

src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,10 @@ private function doResolveDefinition(ChildDefinition $definition)
163163
$def->setMethodCalls(array_merge($def->getMethodCalls(), $calls));
164164
}
165165

166+
foreach (array_merge($parentDef->getErrors(), $definition->getErrors()) as $v) {
167+
$def->addError($v);
168+
}
169+
166170
// these attributes are always taken from the child
167171
$def->setAbstract($definition->isAbstract());
168172
$def->setTags($definition->getTags());

src/Symfony/Component/DependencyInjection/ContainerBuilder.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,7 @@ public function has($id)
529529
*/
530530
public function get($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE)
531531
{
532-
if ($this->isCompiled() && isset($this->removedIds[$id = (string) $id]) && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior) {
532+
if ($this->isCompiled() && isset($this->removedIds[$id = (string) $id]) && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $invalidBehavior) {
533533
return parent::get($id);
534534
}
535535

@@ -555,13 +555,17 @@ private function doGet($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_
555555
try {
556556
$definition = $this->getDefinition($id);
557557
} catch (ServiceNotFoundException $e) {
558-
if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) {
558+
if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE < $invalidBehavior) {
559559
return;
560560
}
561561

562562
throw $e;
563563
}
564564

565+
if ($e = $definition->getErrors()) {
566+
throw new RuntimeException(reset($e));
567+
}
568+
565569
$loading = isset($this->alreadyLoading[$id]) ? 'loading' : 'alreadyLoading';
566570
$this->{$loading}[$id] = true;
567571

src/Symfony/Component/DependencyInjection/ContainerInterface.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
*/
2525
interface ContainerInterface extends PsrContainerInterface
2626
{
27+
const RUNTIME_EXCEPTION_ON_INVALID_DEFINITION = 0;
2728
const EXCEPTION_ON_INVALID_REFERENCE = 1;
2829
const NULL_ON_INVALID_REFERENCE = 2;
2930
const IGNORE_ON_INVALID_REFERENCE = 3;

src/Symfony/Component/DependencyInjection/Definition.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -873,10 +873,14 @@ public function setBindings(array $bindings)
873873
* Add an error that occurred when building this Definition.
874874
*
875875
* @param string $error
876+
*
877+
* @return $this
876878
*/
877879
public function addError($error)
878880
{
879881
$this->errors[] = $error;
882+
883+
return $this;
880884
}
881885

882886
/**

src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ public function dump(array $options = array())
187187
<?php
188188
189189
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
190+
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
190191
191192
// This file has been auto-generated by the Symfony Dependency Injection Component for internal use.
192193
@@ -320,7 +321,7 @@ private function addServiceLocalTempVariables(string $cId, Definition $definitio
320321
$name = $this->getNextVariableName();
321322
$this->referenceVariables[$id] = new Variable($name);
322323

323-
$reference = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $behavior[$id] ? new Reference($id, $behavior[$id]) : null;
324+
$reference = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $behavior[$id] ? new Reference($id, $behavior[$id]) : null;
324325
$code .= sprintf(" \$%s = %s;\n", $name, $this->getServiceCall($id, $reference));
325326
}
326327

@@ -552,7 +553,7 @@ private function isTrivialInstance(Definition $definition): bool
552553
if ($definition->isSynthetic() || $definition->getFile() || $definition->getMethodCalls() || $definition->getProperties() || $definition->getConfigurator()) {
553554
return false;
554555
}
555-
if ($definition->isDeprecated() || $definition->isLazy() || $definition->getFactory() || 3 < count($definition->getArguments())) {
556+
if ($definition->isDeprecated() || $definition->isLazy() || $definition->getFactory() || 3 < count($definition->getArguments()) || $definition->getErrors()) {
556557
return false;
557558
}
558559

@@ -738,6 +739,12 @@ protected function {$methodName}($lazyInitialization)
738739
EOF;
739740
}
740741

742+
if ($e = $definition->getErrors()) {
743+
$e = sprintf("throw new RuntimeException(%s);\n", $this->export(reset($e)));
744+
745+
return $asFile ? substr($code, 8).$e : $code.' '.$e." }\n";
746+
}
747+
741748
$inlinedDefinitions = $this->getDefinitionsFromArguments(array($definition));
742749
$constructorDefinitions = $this->getDefinitionsFromArguments(array($definition->getArguments(), $definition->getFactory()));
743750
$otherDefinitions = new \SplObjectStorage();
@@ -1470,7 +1477,7 @@ private function dumpValue($value, bool $interpolate = true): string
14701477

14711478
$returnedType = '';
14721479
if ($value instanceof TypedReference) {
1473-
$returnedType = sprintf(': %s\%s', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $value->getInvalidBehavior() ? '' : '?', $value->getType());
1480+
$returnedType = sprintf(': %s\%s', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $value->getInvalidBehavior() ? '' : '?', $value->getType());
14741481
}
14751482

14761483
$code = sprintf('return %s;', $code);
@@ -1675,7 +1682,7 @@ private function getServiceCall(string $id, Reference $reference = null): string
16751682
if (null !== $reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $reference->getInvalidBehavior()) {
16761683
return 'null';
16771684
}
1678-
if (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) {
1685+
if (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE < $reference->getInvalidBehavior()) {
16791686
$code = sprintf('$this->get(\'%s\', /* ContainerInterface::NULL_ON_INVALID_REFERENCE */ %d)', $id, ContainerInterface::NULL_ON_INVALID_REFERENCE);
16801687
} else {
16811688
$code = sprintf('$this->get(\'%s\')', $id);

src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ private function getServiceCall(string $id, Reference $reference = null): string
266266
{
267267
if (null !== $reference) {
268268
switch ($reference->getInvalidBehavior()) {
269+
case ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_DEFINITION:
269270
case ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE: break;
270271
case ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE: return sprintf('@!%s', $id);
271272
default: return sprintf('@?%s', $id);

0 commit comments

Comments
 (0)