protected function detectFragmentCycle(FragmentDefinitionNode $fragment): void
    {
        $fragmentName = $fragment->getNameValue();

        $this->visitedFragments[$fragmentName] = true;

        $spreadNodes = $this->context->getFragmentSpreads($fragment->getSelectionSet());

        if (empty($spreadNodes)) {
            return;
        }

        $this->spreadPathIndexByName[$fragmentName] = \count($this->spreadPath);

        foreach ($spreadNodes as $spreadNode) {
            $spreadName = $spreadNode->getNameValue();
            $cycleIndex = $this->spreadPathIndexByName[$spreadName] ?? null;

            if (null === $cycleIndex) {
                $this->spreadPath[] = $spreadNode;

                if (!isset($this->visitedFragments[$spreadName])) {
                    $spreadFragment = $this->context->getFragment($spreadName);

                    if (null !== $spreadFragment) {
                        $this->detectFragmentCycle($spreadFragment);
                    }
                }

                \array_pop($this->spreadPath);
            } else {
                $cyclePath = \array_slice($this->spreadPath, $cycleIndex);

                $this->context->reportError(
                    new ValidationException(
                        fragmentCycleMessage($spreadName, \array_map(function (FragmentSpreadNode $spread) {
                            return $spread->getNameValue();
                        }, $cyclePath)),
                        \array_merge($cyclePath, [$spreadNode])
                    )
                );
            }
        }

        $this->spreadPathIndexByName[$fragmentName] = null;
    }
protected function detectFragmentCycle(FragmentDefinitionNode $fragment): void
    {
        $fragmentName = $fragment->getNameValue();

        $this->visitedFragments[$fragmentName] = true;

        $spreadNodes = $this->context->getFragmentSpreads($fragment->getSelectionSet());

        if (empty($spreadNodes)) {
            return;
        }

        $this->spreadPathIndexByName[$fragmentName] = \count($this->spreadPath);

        foreach ($spreadNodes as $spreadNode) {
            $spreadName = $spreadNode->getNameValue();
            $cycleIndex = $this->spreadPathIndexByName[$spreadName] ?? null;

            if (null === $cycleIndex) {
                $this->spreadPath[] = $spreadNode;

                if (!isset($this->visitedFragments[$spreadName])) {
                    $spreadFragment = $this->context->getFragment($spreadName);

                    if (null !== $spreadFragment) {
                        $this->detectFragmentCycle($spreadFragment);
                    }
                }

                \array_pop($this->spreadPath);
            } else {
                $cyclePath = \array_slice($this->spreadPath, $cycleIndex);

                $this->context->reportError(
                    new ValidationException(
                        fragmentCycleMessage($spreadName, \array_map(function (FragmentSpreadNode $spread) {
                            return $spread->getNameValue();
                        }, $cyclePath)),
                        \array_merge($cyclePath, [$spreadNode])
                    )
                );
            }
        }

        $this->spreadPathIndexByName[$fragmentName] = null;
    }
protected function detectFragmentCycle ( FragmentDefinitionNode $ fragment ) : void { $ fragmentName = $ fragment -> getNameValue ( ) ; $ this -> visitedFragments [ $ fragmentName ] = true ; $ spreadNodes = $ this -> context -> getFragmentSpreads ( $ fragment -> getSelectionSet ( ) ) ; if ( empty ( $ spreadNodes ) ) { return ; } $ this -> spreadPathIndexByName [ $ fragmentName ] = \ count ( $ this -> spreadPath ) ; foreach ( $ spreadNodes as $ spreadNode ) { $ spreadName = $ spreadNode -> getNameValue ( ) ; $ cycleIndex = $ this -> spreadPathIndexByName [ $ spreadName ] ?? null ; if ( null === $ cycleIndex ) { $ this -> spreadPath [ ] = $ spreadNode ; if ( ! isset ( $ this -> visitedFragments [ $ spreadName ] ) ) { $ spreadFragment = $ this -> context -> getFragment ( $ spreadName ) ; if ( null !== $ spreadFragment ) { $ this -> detectFragmentCycle ( $ spreadFragment ) ; } } \ array_pop ( $ this -> spreadPath ) ; } else { $ cyclePath = \ array_slice ( $ this -> spreadPath , $ cycleIndex ) ; $ this -> context -> reportError ( new ValidationException ( fragmentCycleMessage ( $ spreadName , \ array_map ( function ( FragmentSpreadNode $ spread ) { return $ spread -> getNameValue ( ) ; } , $ cyclePath ) ) , \ array_merge ( $ cyclePath , [ $ spreadNode ] ) ) ) ; } } $ this -> spreadPathIndexByName [ $ fragmentName ] = null ; }
This does a straight-forward DFS to find cycles.
It does not terminate when a cycle was found but continues to explore
the graph to find all possible cycles.

@param FragmentDefinitionNode $fragment
This does a straight - forward DFS to find cycles . It does not terminate when a cycle was found but continues to explore the graph to find all possible cycles .