public function __invoke(ValidationContext $context)
{
$varDefMap = new \ArrayObject();
$visitedFragmentNames = new \ArrayObject();
return ['visitSpreadFragments' => true, Node::OPERATION_DEFINITION => function () use(&$varDefMap, &$visitedFragmentNames) {
$varDefMap = new \ArrayObject();
$visitedFragmentNames = new \ArrayObject();
}, Node::VARIABLE_DEFINITION => function (VariableDefinition $varDefAST) use($varDefMap) {
$varDefMap[$varDefAST->variable->name->value] = $varDefAST;
}, Node::FRAGMENT_SPREAD => function (FragmentSpread $spreadAST) use($visitedFragmentNames) {
// Only visit fragments of a particular name once per operation
if (!empty($visitedFragmentNames[$spreadAST->name->value])) {
return Visitor::skipNode();
}
$visitedFragmentNames[$spreadAST->name->value] = true;
}, Node::VARIABLE => function (Variable $variableAST) use($context, $varDefMap) {
$varName = $variableAST->name->value;
$varDef = isset($varDefMap[$varName]) ? $varDefMap[$varName] : null;
$varType = $varDef ? TypeInfo::typeFromAST($context->getSchema(), $varDef->type) : null;
$inputType = $context->getInputType();
if ($varType && $inputType && !$this->varTypeAllowedForType($this->effectiveType($varType, $varDef), $inputType)) {
return new Error(Messages::badVarPosMessage($varName, $varType, $inputType), [$variableAST]);
}
}];
}