public function __invoke(ValidationContext $context) { $visitedFragmentNames = new \stdClass(); $variableDefs = []; $variableNameUsed = new \stdClass(); return ['visitSpreadFragments' => true, Node::OPERATION_DEFINITION => ['enter' => function () use(&$visitedFragmentNames, &$variableDefs, &$variableNameUsed) { $visitedFragmentNames = new \stdClass(); $variableDefs = []; $variableNameUsed = new \stdClass(); }, 'leave' => function () use(&$visitedFragmentNames, &$variableDefs, &$variableNameUsed) { $errors = []; foreach ($variableDefs as $def) { if (empty($variableNameUsed->{$def->variable->name->value})) { $errors[] = new Error(Messages::unusedVariableMessage($def->variable->name->value), [$def]); } } return !empty($errors) ? $errors : null; }], Node::VARIABLE_DEFINITION => function ($def) use(&$variableDefs) { $variableDefs[] = $def; return Visitor::skipNode(); }, Node::VARIABLE => function ($variable) use(&$variableNameUsed) { $variableNameUsed->{$variable->name->value} = true; }, Node::FRAGMENT_SPREAD => function ($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; }]; }
public function __invoke(ValidationContext $context) { return [Node::DIRECTIVE => function (Directive $node, $key, $parent, $path, $ancestors) use($context) { $directiveDef = null; foreach ($context->getSchema()->getDirectives() as $def) { if ($def->name === $node->name->value) { $directiveDef = $def; break; } } if (!$directiveDef) { return new Error(Messages::unknownDirectiveMessage($node->name->value), [$node]); } $appliedTo = $ancestors[count($ancestors) - 1]; if ($appliedTo instanceof OperationDefinition && !$directiveDef->onOperation) { return new Error(Messages::misplacedDirectiveMessage($node->name->value, 'operation'), [$node]); } if ($appliedTo instanceof Field && !$directiveDef->onField) { return new Error(Messages::misplacedDirectiveMessage($node->name->value, 'field'), [$node]); } $fragmentKind = $appliedTo instanceof FragmentSpread || $appliedTo instanceof InlineFragment || $appliedTo instanceof FragmentDefinition; if ($fragmentKind && !$directiveDef->onFragment) { return new Error(Messages::misplacedDirectiveMessage($node->name->value, 'fragment'), [$node]); } }]; }
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]); } }]; }
public function __invoke(ValidationContext $context) { return [Node::FIELD => function (Field $fieldAST) use($context) { $fieldDef = $context->getFieldDef(); if (!$fieldDef) { return Visitor::skipNode(); } $errors = []; $argASTs = $fieldAST->arguments ?: []; $argASTMap = Utils::keyMap($argASTs, function (Argument $arg) { return $arg->name->value; }); foreach ($fieldDef->args as $argDef) { $argAST = isset($argASTMap[$argDef->name]) ? $argASTMap[$argDef->name] : null; if (!$argAST && $argDef->getType() instanceof NonNull) { $errors[] = new Error(Messages::missingArgMessage($fieldAST->name->value, $argDef->name, $argDef->getType()), [$fieldAST]); } } $argDefMap = Utils::keyMap($fieldDef->args, function ($def) { return $def->name; }); foreach ($argASTs as $argAST) { $argDef = $argDefMap[$argAST->name->value]; if ($argDef && !DocumentValidator::isValidLiteralValue($argAST->value, $argDef->getType())) { $errors[] = new Error(Messages::badValueMessage($argAST->name->value, $argDef->getType(), Printer::doPrint($argAST->value)), [$argAST->value]); } } return !empty($errors) ? $errors : null; }]; }
private function detectCycleRecursive($fragmentName, array $spreadsInFragment, \SplObjectStorage $knownToLeadToCycle, $initialName, array &$spreadPath, &$errors) { $spreadNodes = $spreadsInFragment[$fragmentName]; for ($i = 0; $i < count($spreadNodes); ++$i) { $spreadNode = $spreadNodes[$i]; if (isset($knownToLeadToCycle[$spreadNode])) { continue; } if ($spreadNode->name->value === $initialName) { $cyclePath = array_merge($spreadPath, [$spreadNode]); foreach ($cyclePath as $spread) { $knownToLeadToCycle[$spread] = true; } $errors[] = new Error(Messages::cycleErrorMessage($initialName, array_map(function ($s) { return $s->name->value; }, $spreadPath)), $cyclePath); continue; } foreach ($spreadPath as $spread) { if ($spread === $spreadNode) { continue 2; } } $spreadPath[] = $spreadNode; $this->detectCycleRecursive($spreadNode->name->value, $spreadsInFragment, $knownToLeadToCycle, $initialName, $spreadPath, $errors); array_pop($spreadPath); } }
public function __invoke(ValidationContext $context) { $operation = null; $visitedFragmentNames = []; $definedVariableNames = []; return ['visitSpreadFragments' => true, Node::OPERATION_DEFINITION => function (OperationDefinition $node, $key, $parent, $path, $ancestors) use(&$operation, &$visitedFragmentNames, &$definedVariableNames) { $operation = $node; $visitedFragmentNames = []; $definedVariableNames = []; }, Node::VARIABLE_DEFINITION => function (VariableDefinition $def) use(&$definedVariableNames) { $definedVariableNames[$def->variable->name->value] = true; }, Node::VARIABLE => function (Variable $variable, $key, $parent, $path, $ancestors) use(&$definedVariableNames, &$visitedFragmentNames, &$operation) { $varName = $variable->name->value; if (empty($definedVariableNames[$varName])) { $withinFragment = false; foreach ($ancestors as $ancestor) { if ($ancestor instanceof FragmentDefinition) { $withinFragment = true; break; } } if ($withinFragment && $operation && $operation->name) { return new Error(Messages::undefinedVarByOpMessage($varName, $operation->name->value), [$variable, $operation]); } return new Error(Messages::undefinedVarMessage($varName), [$variable]); } }, 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; }]; }
public function __invoke(ValidationContext $context) { $fragmentDefs = []; $spreadsWithinOperation = []; $fragAdjacencies = new \stdClass(); $spreadNames = new \stdClass(); return [Node::OPERATION_DEFINITION => function () use(&$spreadNames, &$spreadsWithinOperation) { $spreadNames = new \stdClass(); $spreadsWithinOperation[] = $spreadNames; }, Node::FRAGMENT_DEFINITION => function (FragmentDefinition $def) use(&$fragmentDefs, &$spreadNames, &$fragAdjacencies) { $fragmentDefs[] = $def; $spreadNames = new \stdClass(); $fragAdjacencies->{$def->name->value} = $spreadNames; }, Node::FRAGMENT_SPREAD => function (FragmentSpread $spread) use(&$spreadNames) { $spreadNames->{$spread->name->value} = true; }, Node::DOCUMENT => ['leave' => function () use(&$fragAdjacencies, &$spreadsWithinOperation, &$fragmentDefs) { $fragmentNameUsed = []; foreach ($spreadsWithinOperation as $spreads) { $this->reduceSpreadFragments($spreads, $fragmentNameUsed, $fragAdjacencies); } $errors = []; foreach ($fragmentDefs as $def) { if (empty($fragmentNameUsed[$def->name->value])) { $errors[] = new Error(Messages::unusedFragMessage($def->name->value), [$def]); } } return !empty($errors) ? $errors : null; }]]; }
public function testOutputTypesAreInvalid() { $this->expectFailsRule(new VariablesAreInputTypes(), ' query Foo($a: Dog, $b: [[DogOrCat!]]!, $c: Pet) { field(a: $a, b: $b, c: $c) } ', [new FormattedError(Messages::nonInputTypeOnVarMessage('a', 'Dog'), [new SourceLocation(2, 21)]), new FormattedError(Messages::nonInputTypeOnVarMessage('b', '[[DogOrCat!]]!'), [new SourceLocation(2, 30)]), new FormattedError(Messages::nonInputTypeOnVarMessage('c', 'Pet'), [new SourceLocation(2, 50)])]); }
public function __invoke(ValidationContext $context) { return [Node::VARIABLE_DEFINITION => function (VariableDefinition $node) use($context) { $typeName = $this->getTypeASTName($node->type); $type = $context->getSchema()->getType($typeName); if (!$type instanceof InputType) { $variableName = $node->variable->name->value; return new Error(Messages::nonInputTypeOnVarMessage($variableName, Printer::doPrint($node->type)), [$node->type]); } }]; }
public function __invoke(ValidationContext $context) { return [Node::NAME => function (Name $node, $key) use($context) { if ($key === 'type' || $key === 'typeCondition') { $typeName = $node->value; $type = $context->getSchema()->getType($typeName); if (!$type) { return new Error(Messages::unknownTypeMessage($typeName), [$node]); } } }]; }
public function __invoke(ValidationContext $context) { return [Node::FIELD => function (Field $node) use($context) { $type = $context->getParentType(); if ($type) { $fieldDef = $context->getFieldDef(); if (!$fieldDef) { return new Error(Messages::undefinedFieldMessage($node->name->value, $type->name), [$node]); } } }]; }
public function __invoke(ValidationContext $context) { $comparedSet = new PairSet(); return [Node::SELECTION_SET => ['leave' => function (SelectionSet $selectionSet) use($context, $comparedSet) { $fieldMap = $this->collectFieldASTsAndDefs($context, $context->getType(), $selectionSet); $conflicts = $this->findConflicts($fieldMap, $context, $comparedSet); if (!empty($conflicts)) { return array_map(function ($conflict) { $responseName = $conflict[0][0]; $reason = $conflict[0][1]; $blameNodes = $conflict[1]; return new Error(Messages::fieldsConflictMessage($responseName, $reason), $blameNodes); }, $conflicts); } }]]; }
public function __invoke(ValidationContext $context) { return [Node::INLINE_FRAGMENT => function (InlineFragment $node) use($context) { $fragType = Type::getUnmodifiedType($context->getType()); $parentType = $context->getParentType(); if ($fragType && $parentType && !$this->doTypesOverlap($fragType, $parentType)) { return new Error(Messages::typeIncompatibleAnonSpreadMessage($parentType, $fragType), [$node]); } }, Node::FRAGMENT_SPREAD => function (FragmentSpread $node) use($context) { $fragName = $node->name->value; $fragType = Type::getUnmodifiedType($this->getFragmentType($context, $fragName)); $parentType = $context->getParentType(); if ($fragType && $parentType && !$this->doTypesOverlap($fragType, $parentType)) { return new Error(Messages::typeIncompatibleSpreadMessage($fragName, $parentType, $fragType), [$node]); } }]; }
public function __invoke(ValidationContext $context) { return [Node::FIELD => function (Field $node) use($context) { $type = $context->getType(); if ($type) { if (Type::isLeafType($type)) { if ($node->selectionSet) { return new Error(Messages::noSubselectionAllowedMessage($node->name->value, $type), [$node->selectionSet]); } } else { if (!$node->selectionSet) { return new Error(Messages::requiredSubselectionMessage($node->name->value, $type), [$node]); } } } }]; }
public function __invoke(ValidationContext $context) { return [Node::INLINE_FRAGMENT => function (InlineFragment $node) use($context) { $typeName = $node->typeCondition->value; $type = $context->getSchema()->getType($typeName); $isCompositeType = $type instanceof CompositeType; if (!$isCompositeType) { return new Error("Fragment cannot condition on non composite type \"{$typeName}\".", [$node->typeCondition]); } }, Node::FRAGMENT_DEFINITION => function (FragmentDefinition $node) use($context) { $typeName = $node->typeCondition->value; $type = $context->getSchema()->getType($typeName); $isCompositeType = $type instanceof CompositeType; if (!$isCompositeType) { return new Error(Messages::fragmentOnNonCompositeErrorMessage($node->name->value, $typeName), [$node->typeCondition]); } }]; }
public function __invoke(ValidationContext $context) { return [Node::ARGUMENT => function (Argument $node) use($context) { $fieldDef = $context->getFieldDef(); if ($fieldDef) { $argDef = null; foreach ($fieldDef->args as $arg) { if ($arg->name === $node->name->value) { $argDef = $arg; break; } } if (!$argDef) { $parentType = $context->getParentType(); Utils::invariant($parentType); return new Error(Messages::unknownArgMessage($node->name->value, $fieldDef->name, $parentType->name), [$node]); } } }]; }
private function missingObjSubselection($field, $type, $line, $column) { return new FormattedError(Messages::requiredSubselectionMessage($field, $type), [new SourceLocation($line, $column)]); }
private function unknownType($typeName, $line, $column) { return new FormattedError(Messages::unknownTypeMessage($typeName), [new SourceLocation($line, $column)]); }
public function testStringXBooleanNonNullInDirective() { // String => Boolean! in directive $this->expectFailsRule(new VariablesInAllowedPosition(), ' query Query($stringVar: String) { dog @include(if: $stringVar) } ', [FormattedError::create(Messages::badVarPosMessage('stringVar', 'String', 'Boolean!'), [new SourceLocation(4, 26)])]); }
function badValue($argName, $typeName, $value, $line, $column) { return new FormattedError(Messages::badValueMessage($argName, $typeName, $value), [new SourceLocation($line, $column)]); }
private function undefVarByOp($varName, $l1, $c1, $opName, $l2, $c2) { return new FormattedError(Messages::undefinedVarByOpMessage($varName, $opName), [new SourceLocation($l1, $c1), new SourceLocation($l2, $c2)]); }
public function testFailsAsExpectedOnThe__typeRootFieldWithoutAnArg() { $TestType = new ObjectType(['name' => 'TestType', 'fields' => ['testField' => ['type' => Type::string()]]]); $schema = new Schema($TestType); $request = ' { __type { name } } '; $expected = ['errors' => [new FormattedError(Messages::missingArgMessage('__type', 'name', 'String!'), [new SourceLocation(3, 9)])]]; $this->assertEquals($expected, GraphQL::execute($schema, $request)); }
function misplacedDirective($directiveName, $placement, $line, $column) { return new FormattedError(Messages::misplacedDirectiveMessage($directiveName, $placement), [new SourceLocation($line, $column)]); }
private function badValue($varName, $typeName, $val, $line, $column) { return new FormattedError(Messages::badValueForDefaultArgMessage($varName, $typeName, $val), [new SourceLocation($line, $column)]); }
private function errorAnon($parentType, $fragType, $line, $column) { return new FormattedError(Messages::typeIncompatibleAnonSpreadMessage($parentType, $fragType), [new SourceLocation($line, $column)]); }
private function unknownArg($argName, $fieldName, $typeName, $line, $column) { return new FormattedError(Messages::unknownArgMessage($argName, $fieldName, $typeName), [new SourceLocation($line, $column)]); }
public function testConflictingScalarReturnTypes() { $this->expectFailsRuleWithSchema($this->getTestSchema(), new OverlappingFieldsCanBeMerged(), ' { boxUnion { ...on IntBox { scalar } ...on StringBox { scalar } } } ', [new FormattedError(Messages::fieldsConflictMessage('scalar', 'they return differing types Int and String'), [new SourceLocation(5, 15), new SourceLocation(8, 15)])]); }
private function undefinedField($field, $type, $line, $column) { return new FormattedError(Messages::undefinedFieldMessage($field, $type), [new SourceLocation($line, $column)]); }
private function error($fragName, $typeName, $line, $column) { return new FormattedError(Messages::fragmentOnNonCompositeErrorMessage($fragName, $typeName), [new SourceLocation($line, $column)]); }
private function unusedVar($varName, $line, $column) { return new FormattedError(Messages::unusedVariableMessage($varName), [new SourceLocation($line, $column)]); }