private function collectFieldNodesAndDefs(ValidationContext $context, $parentType, SelectionSetNode $selectionSet, \ArrayObject $visitedFragmentNames = null, \ArrayObject $astAndDefs = null)
{
$_visitedFragmentNames = $visitedFragmentNames ?: new \ArrayObject();
$_astAndDefs = $astAndDefs ?: new \ArrayObject();
for ($i = 0; $i < count($selectionSet->selections); $i++) {
$selection = $selectionSet->selections[$i];
switch ($selection->kind) {
case NodeKind::FIELD:
$fieldName = $selection->name->value;
$fieldDef = null;
if ($parentType && method_exists($parentType, 'getFields')) {
$tmp = $parentType->getFields();
if (isset($tmp[$fieldName])) {
$fieldDef = $tmp[$fieldName];
}
}
$responseName = $selection->alias ? $selection->alias->value : $fieldName;
if (!isset($_astAndDefs[$responseName])) {
$_astAndDefs[$responseName] = new \ArrayObject();
}
$_astAndDefs[$responseName][] = [$parentType, $selection, $fieldDef];
break;
case NodeKind::INLINE_FRAGMENT:
$typeCondition = $selection->typeCondition;
$inlineFragmentType = $typeCondition ? TypeInfo::typeFromAST($context->getSchema(), $typeCondition) : $parentType;
$_astAndDefs = $this->collectFieldNodesAndDefs($context, $inlineFragmentType, $selection->selectionSet, $_visitedFragmentNames, $_astAndDefs);
break;
case NodeKind::FRAGMENT_SPREAD:
/** @var FragmentSpreadNode $selection */
$fragName = $selection->name->value;
if (!empty($_visitedFragmentNames[$fragName])) {
continue;
}
$_visitedFragmentNames[$fragName] = true;
$fragment = $context->getFragment($fragName);
if (!$fragment) {
continue;
}
$fragmentType = TypeInfo::typeFromAST($context->getSchema(), $fragment->typeCondition);
$_astAndDefs = $this->collectFieldNodesAndDefs($context, $fragmentType, $fragment->selectionSet, $_visitedFragmentNames, $_astAndDefs);
break;
}
}
return $_astAndDefs;
}