public function __invoke(ValidationContext $context)
 {
     return [NodeKind::OPERATION_DEFINITION => ['enter' => function () {
         $this->varDefMap = [];
     }, 'leave' => function (OperationDefinitionNode $operation) use($context) {
         $usages = $context->getRecursiveVariableUsages($operation);
         foreach ($usages as $usage) {
             $node = $usage['node'];
             $type = $usage['type'];
             $varName = $node->name->value;
             $varDef = isset($this->varDefMap[$varName]) ? $this->varDefMap[$varName] : null;
             if ($varDef && $type) {
                 // A var type is allowed if it is the same or more strict (e.g. is
                 // a subtype of) than the expected type. It can be more strict if
                 // the variable type is non-null when the expected type is nullable.
                 // If both are list types, the variable item type can be more strict
                 // than the expected item type (contravariant).
                 $schema = $context->getSchema();
                 $varType = TypeInfo::typeFromAST($schema, $varDef->type);
                 if ($varType && !TypeInfo::isTypeSubTypeOf($schema, $this->effectiveType($varType, $varDef), $type)) {
                     $context->reportError(new Error(self::badVarPosMessage($varName, $varType, $type), [$varDef, $node]));
                 }
             }
         }
     }], NodeKind::VARIABLE_DEFINITION => function (VariableDefinitionNode $varDefNode) {
         $this->varDefMap[$varDefNode->variable->name->value] = $varDefNode;
     }];
 }
 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]);
         }
     }];
 }
Exemplo n.º 3
0
 public function __invoke(ValidationContext $context)
 {
     $this->operationDefs = [];
     $this->fragmentDefs = [];
     return [NodeKind::OPERATION_DEFINITION => function ($node) {
         $this->operationDefs[] = $node;
         return Visitor::skipNode();
     }, NodeKind::FRAGMENT_DEFINITION => function (FragmentDefinitionNode $def) {
         $this->fragmentDefs[] = $def;
         return Visitor::skipNode();
     }, NodeKind::DOCUMENT => ['leave' => function () use($context) {
         $fragmentNameUsed = [];
         foreach ($this->operationDefs as $operation) {
             foreach ($context->getRecursivelyReferencedFragments($operation) as $fragment) {
                 $fragmentNameUsed[$fragment->name->value] = true;
             }
         }
         foreach ($this->fragmentDefs as $fragmentDef) {
             $fragName = $fragmentDef->name->value;
             if (empty($fragmentNameUsed[$fragName])) {
                 $context->reportError(new Error(self::unusedFragMessage($fragName), [$fragmentDef]));
             }
         }
     }]];
 }
Exemplo n.º 4
0
 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]);
         }
     }];
 }
Exemplo n.º 5
0
 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;
     }];
 }
Exemplo n.º 6
0
 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) {
             $context->reportError(new Error(self::unknownDirectiveMessage($node->name->value), [$node]));
             return;
         }
         $appliedTo = $ancestors[count($ancestors) - 1];
         $candidateLocation = $this->getLocationForAppliedNode($appliedTo);
         if (!$candidateLocation) {
             $context->reportError(new Error(self::misplacedDirectiveMessage($node->name->value, $node->type), [$node]));
         } else {
             if (!in_array($candidateLocation, $directiveDef->locations)) {
                 $context->reportError(new Error(self::misplacedDirectiveMessage($node->name->value, $candidateLocation), [$node]));
             }
         }
     }];
 }
Exemplo n.º 7
0
 public function __invoke(ValidationContext $context)
 {
     // Gather all the fragment spreads ASTs for each fragment definition.
     // Importantly this does not include inline fragments.
     $definitions = $context->getDocument()->definitions;
     $spreadsInFragment = [];
     foreach ($definitions as $node) {
         if ($node instanceof FragmentDefinition) {
             $spreadsInFragment[$node->name->value] = $this->gatherSpreads($node);
         }
     }
     // Tracks spreads known to lead to cycles to ensure that cycles are not
     // redundantly reported.
     $knownToLeadToCycle = new \SplObjectStorage();
     return [Node::FRAGMENT_DEFINITION => function (FragmentDefinition $node) use($spreadsInFragment, $knownToLeadToCycle) {
         $errors = [];
         $initialName = $node->name->value;
         // Array of AST nodes used to produce meaningful errors
         $spreadPath = [];
         $this->detectCycleRecursive($initialName, $spreadsInFragment, $knownToLeadToCycle, $initialName, $spreadPath, $errors);
         if (!empty($errors)) {
             return $errors;
         }
     }];
 }
 public function __invoke(ValidationContext $context)
 {
     return [Node::ARGUMENT => function (Argument $argAST) use($context) {
         $argDef = $context->getArgument();
         if ($argDef && !DocumentValidator::isValidLiteralValue($argAST->value, $argDef->getType())) {
             return new Error(self::badValueMessage($argAST->name->value, $argDef->getType(), Printer::doPrint($argAST->value)), [$argAST->value]);
         }
     }];
 }
Exemplo n.º 9
0
 public function __invoke(ValidationContext $context)
 {
     return [Node::FRAGMENT_SPREAD => function (FragmentSpread $node) use($context) {
         $fragmentName = $node->name->value;
         $fragment = $context->getFragment($fragmentName);
         if (!$fragment) {
             $context->reportError(new Error(self::unknownFragmentMessage($fragmentName), [$node->name]));
         }
     }];
 }
Exemplo n.º 10
0
 public function __invoke(ValidationContext $context)
 {
     return [Node::FRAGMENT_SPREAD => function (FragmentSpread $node) use($context) {
         $fragmentName = $node->name->value;
         $fragment = $context->getFragment($fragmentName);
         if (!$fragment) {
             return new Error("Undefined fragment {$fragmentName}.", [$node->name]);
         }
     }];
 }
Exemplo n.º 11
0
 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]);
         }
     }];
 }
Exemplo n.º 12
0
 public function __invoke(ValidationContext $context)
 {
     return [NodeKind::VARIABLE_DEFINITION => function (VariableDefinitionNode $node) use($context) {
         $type = Utils\TypeInfo::typeFromAST($context->getSchema(), $node->type);
         // If the variable type is not an input type, return an error.
         if ($type && !Type::isInputType($type)) {
             $variableName = $node->variable->name->value;
             $context->reportError(new Error(self::nonInputTypeOnVarMessage($variableName, Printer::doPrint($node->type)), [$node->type]));
         }
     }];
 }
Exemplo n.º 13
0
 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]);
             }
         }
     }];
 }
Exemplo n.º 14
0
 public function __invoke(ValidationContext $context)
 {
     return [Node::NAMED_TYPE => function (NamedType $node, $key) use($context) {
         if ($key === 'type' || $key === 'typeCondition') {
             $typeName = $node->name->value;
             $type = $context->getSchema()->getType($typeName);
             if (!$type) {
                 return new Error(self::unknownTypeMessage($typeName), [$node]);
             }
         }
     }];
 }
Exemplo n.º 15
0
 public function __invoke(ValidationContext $context)
 {
     return [Node::ARGUMENT => function (Argument $argAST) use($context) {
         $argDef = $context->getArgument();
         if ($argDef) {
             $errors = DocumentValidator::isValidLiteralValue($argDef->getType(), $argAST->value);
             if (!empty($errors)) {
                 $context->reportError(new Error(self::badValueMessage($argAST->name->value, $argDef->getType(), Printer::doPrint($argAST->value), $errors), [$argAST->value]));
             }
         }
         return Visitor::skipNode();
     }];
 }
Exemplo n.º 16
0
 public function __invoke(ValidationContext $context)
 {
     $skip = function () {
         return Visitor::skipNode();
     };
     return [Node::OBJECT_TYPE_DEFINITION => $skip, Node::INTERFACE_TYPE_DEFINITION => $skip, Node::UNION_TYPE_DEFINITION => $skip, Node::INPUT_OBJECT_TYPE_DEFINITION => $skip, Node::NAMED_TYPE => function (NamedType $node, $key) use($context) {
         $typeName = $node->name->value;
         $type = $context->getSchema()->getType($typeName);
         if (!$type) {
             $context->reportError(new Error(self::unknownTypeMessage($typeName), [$node]));
         }
     }];
 }
Exemplo n.º 17
0
 public function __invoke(ValidationContext $context)
 {
     $operationCount = 0;
     return [NodeKind::DOCUMENT => function (DocumentNode $node) use(&$operationCount) {
         $tmp = Utils::filter($node->definitions, function ($definition) {
             return $definition->kind === NodeKind::OPERATION_DEFINITION;
         });
         $operationCount = count($tmp);
     }, NodeKind::OPERATION_DEFINITION => function (OperationDefinitionNode $node) use(&$operationCount, $context) {
         if (!$node->name && $operationCount > 1) {
             $context->reportError(new Error(self::anonOperationNotAloneMessage(), [$node]));
         }
     }];
 }
Exemplo n.º 18
0
 public function __invoke(ValidationContext $context)
 {
     $this->knownVariableNames = [];
     return [NodeKind::OPERATION_DEFINITION => function () {
         $this->knownVariableNames = [];
     }, NodeKind::VARIABLE_DEFINITION => function (VariableDefinitionNode $node) use($context) {
         $variableName = $node->variable->name->value;
         if (!empty($this->knownVariableNames[$variableName])) {
             $context->reportError(new Error(self::duplicateVariableMessage($variableName), [$this->knownVariableNames[$variableName], $node->variable->name]));
         } else {
             $this->knownVariableNames[$variableName] = $node->variable->name;
         }
     }];
 }
Exemplo n.º 19
0
 public function __invoke(ValidationContext $context)
 {
     return [Node::INLINE_FRAGMENT => function (InlineFragment $node) use($context) {
         $type = $context->getType();
         if ($node->typeCondition && $type && !Type::isCompositeType($type)) {
             $context->reportError(new Error(static::inlineFragmentOnNonCompositeErrorMessage($type), [$node->typeCondition]));
         }
     }, Node::FRAGMENT_DEFINITION => function (FragmentDefinition $node) use($context) {
         $type = $context->getType();
         if ($type && !Type::isCompositeType($type)) {
             $context->reportError(new Error(static::fragmentOnNonCompositeErrorMessage($node->name->value, Printer::doPrint($node->typeCondition)), [$node->typeCondition]));
         }
     }];
 }
Exemplo n.º 20
0
 public function __invoke(ValidationContext $context)
 {
     $this->knownFragmentNames = [];
     return [Node::OPERATION_DEFINITION => function () {
         return Visitor::skipNode();
     }, Node::FRAGMENT_DEFINITION => function (FragmentDefinition $node) use($context) {
         $fragmentName = $node->name->value;
         if (!empty($this->knownFragmentNames[$fragmentName])) {
             $context->reportError(new Error(self::duplicateFragmentNameMessage($fragmentName), [$this->knownFragmentNames[$fragmentName], $node->name]));
         } else {
             $this->knownFragmentNames[$fragmentName] = $node->name;
         }
         return Visitor::skipNode();
     }];
 }
 public function __invoke(ValidationContext $context)
 {
     return ['enter' => function (Node $node) use($context) {
         if (isset($node->directives)) {
             $knownDirectives = [];
             foreach ($node->directives as $directive) {
                 /** @var DirectiveNode $directive */
                 $directiveName = $directive->name->value;
                 if (isset($knownDirectives[$directiveName])) {
                     $context->reportError(new Error(self::duplicateDirectiveMessage($directiveName), [$knownDirectives[$directiveName], $directive]));
                 } else {
                     $knownDirectives[$directiveName] = $directive;
                 }
             }
         }
     }];
 }
Exemplo n.º 22
0
 public function __invoke(ValidationContext $context)
 {
     $this->knownOperationNames = [];
     return [NodeKind::OPERATION_DEFINITION => function (OperationDefinitionNode $node) use($context) {
         $operationName = $node->name;
         if ($operationName) {
             if (!empty($this->knownOperationNames[$operationName->value])) {
                 $context->reportError(new Error(self::duplicateOperationNameMessage($operationName->value), [$this->knownOperationNames[$operationName->value], $operationName]));
             } else {
                 $this->knownOperationNames[$operationName->value] = $operationName;
             }
         }
         return Visitor::skipNode();
     }, NodeKind::FRAGMENT_DEFINITION => function () {
         return Visitor::skipNode();
     }];
 }
Exemplo n.º 23
0
 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]);
                 }
             }
         }
     }];
 }
Exemplo n.º 24
0
 public function __invoke(ValidationContext $context)
 {
     $this->knownArgNames = [];
     return [Node::FIELD => function () {
         $this->knownArgNames = [];
     }, Node::DIRECTIVE => function () {
         $this->knownArgNames = [];
     }, Node::ARGUMENT => function (Argument $node) use($context) {
         $argName = $node->name->value;
         if (!empty($this->knownArgNames[$argName])) {
             $context->reportError(new Error(self::duplicateArgMessage($argName), [$this->knownArgNames[$argName], $node->name]));
         } else {
             $this->knownArgNames[$argName] = $node->name;
         }
         return Visitor::skipNode();
     }];
 }
Exemplo n.º 25
0
 public function __invoke(ValidationContext $context)
 {
     $variableNameDefined = [];
     return [NodeKind::OPERATION_DEFINITION => ['enter' => function () use(&$variableNameDefined) {
         $variableNameDefined = [];
     }, 'leave' => function (OperationDefinitionNode $operation) use(&$variableNameDefined, $context) {
         $usages = $context->getRecursiveVariableUsages($operation);
         foreach ($usages as $usage) {
             $node = $usage['node'];
             $varName = $node->name->value;
             if (empty($variableNameDefined[$varName])) {
                 $context->reportError(new Error(self::undefinedVarMessage($varName, $operation->name ? $operation->name->value : null), [$node, $operation]));
             }
         }
     }], NodeKind::VARIABLE_DEFINITION => function (VariableDefinitionNode $def) use(&$variableNameDefined) {
         $variableNameDefined[$def->variable->name->value] = true;
     }];
 }
Exemplo n.º 26
0
 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::FIELD => ['leave' => function (Field $fieldAST) use($context) {
         $fieldDef = $context->getFieldDef();
         if (!$fieldDef) {
             return Visitor::skipNode();
         }
         $errors = [];
         $argASTs = $fieldAST->arguments ?: [];
         $argASTMap = [];
         foreach ($argASTs as $argAST) {
             $argASTMap[$argAST->name->value] = $argASTs;
         }
         foreach ($fieldDef->args as $argDef) {
             $argAST = isset($argASTMap[$argDef->name]) ? $argASTMap[$argDef->name] : null;
             if (!$argAST && $argDef->getType() instanceof NonNull) {
                 $errors[] = new Error(self::missingFieldArgMessage($fieldAST->name->value, $argDef->name, $argDef->getType()), [$fieldAST]);
             }
         }
         if (!empty($errors)) {
             return $errors;
         }
     }], Node::DIRECTIVE => ['leave' => function (Directive $directiveAST) use($context) {
         $directiveDef = $context->getDirective();
         if (!$directiveDef) {
             return Visitor::skipNode();
         }
         $errors = [];
         $argASTs = $directiveAST->arguments ?: [];
         $argASTMap = [];
         foreach ($argASTs as $argAST) {
             $argASTMap[$argAST->name->value] = $argASTs;
         }
         foreach ($directiveDef->args as $argDef) {
             $argAST = isset($argASTMap[$argDef->name]) ? $argASTMap[$argDef->name] : null;
             if (!$argAST && $argDef->getType() instanceof NonNull) {
                 $errors[] = new Error(self::missingDirectiveArgMessage($directiveAST->name->value, $argDef->name, $argDef->getType()), [$directiveAST]);
             }
         }
         if (!empty($errors)) {
             return $errors;
         }
     }]];
 }
Exemplo n.º 28
0
 public function __invoke(ValidationContext $context)
 {
     $this->knownNames = [];
     $this->knownNameStack = [];
     return [NodeKind::OBJECT => ['enter' => function () {
         $this->knownNameStack[] = $this->knownNames;
         $this->knownNames = [];
     }, 'leave' => function () {
         $this->knownNames = array_pop($this->knownNameStack);
     }], NodeKind::OBJECT_FIELD => function (ObjectFieldNode $node) use($context) {
         $fieldName = $node->name->value;
         if (!empty($this->knownNames[$fieldName])) {
             $context->reportError(new Error(self::duplicateInputFieldMessage($fieldName), [$this->knownNames[$fieldName], $node->name]));
         } else {
             $this->knownNames[$fieldName] = $node->name;
         }
         return Visitor::skipNode();
     }];
 }
Exemplo n.º 29
0
 public function __invoke(ValidationContext $context)
 {
     return [Node::FIELD => function (Field $node) use($context) {
         $type = $context->getParentType();
         if ($type) {
             $fieldDef = $context->getFieldDef();
             if (!$fieldDef) {
                 // This isn't valid. Let's find suggestions, if any.
                 $suggestedTypes = [];
                 if ($type instanceof AbstractType) {
                     $schema = $context->getSchema();
                     $suggestedTypes = self::getSiblingInterfacesIncludingField($schema, $type, $node->name->value);
                     $suggestedTypes = array_merge($suggestedTypes, self::getImplementationsIncludingField($schema, $type, $node->name->value));
                 }
                 $context->reportError(new Error(static::undefinedFieldMessage($node->name->value, $type->name, $suggestedTypes), [$node]));
             }
         }
     }];
 }
Exemplo n.º 30
0
 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]);
             }
         }
     }];
 }