Skip to content

Commit

Permalink
Container: detects circular reference for parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed Sep 22, 2023
1 parent e821d83 commit 45f7d27
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 14 deletions.
33 changes: 21 additions & 12 deletions src/DI/Container.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ public function getParameters(): array
public function getParameter($key)
{
if (!array_key_exists($key, $this->parameters)) {
$this->parameters[$key] = $this->getDynamicParameter($key);
$this->parameters[$key] = $this->criticalSection("%$key%", function () use ($key) {
return $this->getDynamicParameter($key);
});
}
return $this->parameters[$key];
}
Expand Down Expand Up @@ -211,22 +213,15 @@ public function createService(string $name, array $args = []): object
$name = $this->aliases[$name] ?? $name;
$method = self::getMethodName($name);
$cb = $this->methods[$method] ?? null;
if (isset($this->creating[$name])) {
throw new Nette\InvalidStateException(sprintf('Circular reference detected for services: %s.', implode(', ', array_keys($this->creating))));

} elseif ($cb === null) {
if ($cb === null) {
throw new MissingServiceException(sprintf("Service '%s' not found.", $name));
}

try {
$this->creating[$name] = true;
$service = $cb instanceof \Closure
$service = $this->criticalSection($name, function () use ($cb, $args, $method) {
return $cb instanceof \Closure
? $cb(...$args)
: $this->$method(...$args);

} finally {
unset($this->creating[$name]);
}
});

if (!is_object($service)) {
throw new Nette\UnexpectedValueException(sprintf(
Expand Down Expand Up @@ -317,6 +312,20 @@ public function findByTag(string $tag): array
}


private function criticalSection(string $key, \Closure $closure)
{
if (isset($this->creating[$key])) {
throw new Nette\InvalidStateException(sprintf('Circular reference detected for: %s.', implode(', ', array_keys($this->creating))));
}
try {
$this->creating[$key] = true;
return $closure();
} finally {
unset($this->creating[$key]);
}
}


/********************* autowiring ****************d*g**/


Expand Down
2 changes: 1 addition & 1 deletion tests/DI/Compiler.parameters.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,6 @@ test('', function () {
$container->getParameter('bar');
},
Nette\InvalidStateException::class,
'Circular reference detected for services: one.'
'Circular reference detected for: %bar%, one.'
);
});
2 changes: 1 addition & 1 deletion tests/DI/Container.circular.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@ $container = new MyContainer;

Assert::exception(function () use ($container) {
$container->getService('one');
}, Nette\InvalidStateException::class, 'Circular reference detected for services: one, two.');
}, Nette\InvalidStateException::class, 'Circular reference detected for: one, two.');

0 comments on commit 45f7d27

Please sign in to comment.