コード例 #1
0
 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;
     }];
 }
コード例 #2
0
ファイル: KnownDirectives.php プロジェクト: rtuin/graphql-php
 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]);
         }
     }];
 }
コード例 #3
0
 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]);
         }
     }];
 }
コード例 #4
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;
     }];
 }
コード例 #5
0
 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);
     }
 }
コード例 #6
0
 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;
     }];
 }
コード例 #7
0
 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;
     }]];
 }
コード例 #8
0
 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)])]);
 }
コード例 #9
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]);
         }
     }];
 }
コード例 #10
0
ファイル: KnownTypeNames.php プロジェクト: rtuin/graphql-php
 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]);
             }
         }
     }];
 }
コード例 #11
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]);
             }
         }
     }];
 }
コード例 #12
0
 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);
         }
     }]];
 }
コード例 #13
0
 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]);
         }
     }];
 }
コード例 #14
0
ファイル: ScalarLeafs.php プロジェクト: rtuin/graphql-php
 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]);
                 }
             }
         }
     }];
 }
コード例 #15
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]);
         }
     }];
 }
コード例 #16
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]);
             }
         }
     }];
 }
コード例 #17
0
ファイル: ScalarLeafsTest.php プロジェクト: rtuin/graphql-php
 private function missingObjSubselection($field, $type, $line, $column)
 {
     return new FormattedError(Messages::requiredSubselectionMessage($field, $type), [new SourceLocation($line, $column)]);
 }
コード例 #18
0
 private function unknownType($typeName, $line, $column)
 {
     return new FormattedError(Messages::unknownTypeMessage($typeName), [new SourceLocation($line, $column)]);
 }
コード例 #19
0
 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)])]);
 }
コード例 #20
0
 function badValue($argName, $typeName, $value, $line, $column)
 {
     return new FormattedError(Messages::badValueMessage($argName, $typeName, $value), [new SourceLocation($line, $column)]);
 }
コード例 #21
0
 private function undefVarByOp($varName, $l1, $c1, $opName, $l2, $c2)
 {
     return new FormattedError(Messages::undefinedVarByOpMessage($varName, $opName), [new SourceLocation($l1, $c1), new SourceLocation($l2, $c2)]);
 }
コード例 #22
0
 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));
 }
コード例 #23
0
 function misplacedDirective($directiveName, $placement, $line, $column)
 {
     return new FormattedError(Messages::misplacedDirectiveMessage($directiveName, $placement), [new SourceLocation($line, $column)]);
 }
コード例 #24
0
 private function badValue($varName, $typeName, $val, $line, $column)
 {
     return new FormattedError(Messages::badValueForDefaultArgMessage($varName, $typeName, $val), [new SourceLocation($line, $column)]);
 }
コード例 #25
0
 private function errorAnon($parentType, $fragType, $line, $column)
 {
     return new FormattedError(Messages::typeIncompatibleAnonSpreadMessage($parentType, $fragType), [new SourceLocation($line, $column)]);
 }
コード例 #26
0
 private function unknownArg($argName, $fieldName, $typeName, $line, $column)
 {
     return new FormattedError(Messages::unknownArgMessage($argName, $fieldName, $typeName), [new SourceLocation($line, $column)]);
 }
コード例 #27
0
 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)])]);
 }
コード例 #28
0
 private function undefinedField($field, $type, $line, $column)
 {
     return new FormattedError(Messages::undefinedFieldMessage($field, $type), [new SourceLocation($line, $column)]);
 }
コード例 #29
0
 private function error($fragName, $typeName, $line, $column)
 {
     return new FormattedError(Messages::fragmentOnNonCompositeErrorMessage($fragName, $typeName), [new SourceLocation($line, $column)]);
 }
コード例 #30
0
 private function unusedVar($varName, $line, $column)
 {
     return new FormattedError(Messages::unusedVariableMessage($varName), [new SourceLocation($line, $column)]);
 }