4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\DependencyInjection\Compiler;
14 use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
15 use Symfony\Component\DependencyInjection\ContainerBuilder;
18 * Checks your services for circular references.
20 * References from method calls are ignored since we might be able to resolve
21 * these references depending on the order in which services are called.
23 * Circular reference from method calls will only be detected at run-time.
25 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
27 class CheckCircularReferencesPass implements CompilerPassInterface
30 private $checkedNodes;
33 * Checks the ContainerBuilder object for circular references.
35 * @param ContainerBuilder $container The ContainerBuilder instances
37 public function process(ContainerBuilder $container)
39 $graph = $container->getCompiler()->getServiceReferenceGraph();
41 $this->checkedNodes = array();
42 foreach ($graph->getNodes() as $id => $node) {
43 $this->currentPath = array($id);
45 $this->checkOutEdges($node->getOutEdges());
50 * Checks for circular references.
52 * @param ServiceReferenceGraphEdge[] $edges An array of Edges
54 * @throws ServiceCircularReferenceException When a circular reference is found.
56 private function checkOutEdges(array $edges)
58 foreach ($edges as $edge) {
59 $node = $edge->getDestNode();
62 if (empty($this->checkedNodes[$id])) {
63 // don't check circular dependencies for lazy services
64 if (!$node->getValue() || !$node->getValue()->isLazy()) {
65 $searchKey = array_search($id, $this->currentPath);
66 $this->currentPath[] = $id;
68 if (false !== $searchKey) {
69 throw new ServiceCircularReferenceException($id, array_slice($this->currentPath, $searchKey));
72 $this->checkOutEdges($node->getOutEdges());
75 $this->checkedNodes[$id] = true;
76 array_pop($this->currentPath);