Chris@0: Chris@0: * Chris@0: * For the full copyright and license information, please view the LICENSE Chris@0: * file that was distributed with this source code. Chris@0: */ Chris@0: Chris@0: namespace Symfony\Component\DependencyInjection\Compiler; Chris@0: Chris@17: use Symfony\Component\DependencyInjection\ContainerBuilder; Chris@0: use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; Chris@0: Chris@0: /** Chris@0: * Checks your services for circular references. Chris@0: * Chris@0: * References from method calls are ignored since we might be able to resolve Chris@0: * these references depending on the order in which services are called. Chris@0: * Chris@0: * Circular reference from method calls will only be detected at run-time. Chris@0: * Chris@0: * @author Johannes M. Schmitt Chris@0: */ Chris@0: class CheckCircularReferencesPass implements CompilerPassInterface Chris@0: { Chris@0: private $currentPath; Chris@0: private $checkedNodes; Chris@0: Chris@0: /** Chris@0: * Checks the ContainerBuilder object for circular references. Chris@0: */ Chris@0: public function process(ContainerBuilder $container) Chris@0: { Chris@0: $graph = $container->getCompiler()->getServiceReferenceGraph(); Chris@0: Chris@17: $this->checkedNodes = []; Chris@0: foreach ($graph->getNodes() as $id => $node) { Chris@17: $this->currentPath = [$id]; Chris@0: Chris@0: $this->checkOutEdges($node->getOutEdges()); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Checks for circular references. Chris@0: * Chris@0: * @param ServiceReferenceGraphEdge[] $edges An array of Edges Chris@0: * Chris@14: * @throws ServiceCircularReferenceException when a circular reference is found Chris@0: */ Chris@0: private function checkOutEdges(array $edges) Chris@0: { Chris@0: foreach ($edges as $edge) { Chris@0: $node = $edge->getDestNode(); Chris@0: $id = $node->getId(); Chris@0: Chris@0: if (empty($this->checkedNodes[$id])) { Chris@14: // Don't check circular references for lazy edges Chris@14: if (!$node->getValue() || (!$edge->isLazy() && !$edge->isWeak())) { Chris@0: $searchKey = array_search($id, $this->currentPath); Chris@0: $this->currentPath[] = $id; Chris@0: Chris@0: if (false !== $searchKey) { Chris@17: throw new ServiceCircularReferenceException($id, \array_slice($this->currentPath, $searchKey)); Chris@0: } Chris@0: Chris@0: $this->checkOutEdges($node->getOutEdges()); Chris@0: } Chris@0: Chris@0: $this->checkedNodes[$id] = true; Chris@0: array_pop($this->currentPath); Chris@0: } Chris@0: } Chris@0: } Chris@0: }