typeFromAST() public static méthode

public static typeFromAST ( Schema $schema, $inputTypeNode ) : Type
$schema GraphQL\Schema
Résultat GraphQL\Type\Definition\Type
 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]);
         }
     }];
 }
Exemple #2
0
 /**
  * Prepares an object map of variables of the correct type based on the provided
  * variable definitions and arbitrary input. If the input cannot be coerced
  * to match the variable definitions, a Error will be thrown.
  *
  * @param Schema $schema
  * @param VariableDefinitionNode[] $definitionNodes
  * @param array $inputs
  * @return array
  * @throws Error
  */
 public static function getVariableValues(Schema $schema, $definitionNodes, array $inputs)
 {
     $coercedValues = [];
     foreach ($definitionNodes as $definitionNode) {
         $varName = $definitionNode->variable->name->value;
         $varType = Utils\TypeInfo::typeFromAST($schema, $definitionNode->type);
         if (!Type::isInputType($varType)) {
             throw new Error('Variable "$' . $varName . '" expected value of type ' . '"' . Printer::doPrint($definitionNode->type) . '" which cannot be used as an input type.', [$definitionNode->type]);
         }
         if (!array_key_exists($varName, $inputs)) {
             $defaultValue = $definitionNode->defaultValue;
             if ($defaultValue) {
                 $coercedValues[$varName] = Utils\AST::valueFromAST($defaultValue, $varType);
             }
             if ($varType instanceof NonNull) {
                 throw new Error('Variable "$' . $varName . '" of required type ' . '"' . Utils::printSafe($varType) . '" was not provided.', [$definitionNode]);
             }
         } else {
             $value = $inputs[$varName];
             $errors = self::isValidPHPValue($value, $varType);
             if (!empty($errors)) {
                 $message = "\n" . implode("\n", $errors);
                 throw new Error('Variable "$' . $varName . '" got invalid value ' . json_encode($value) . '.' . $message, [$definitionNode]);
             }
             $coercedValue = self::coerceValue($varType, $value);
             Utils::invariant($coercedValue !== Utils::undefined(), 'Should have reported error.');
             $coercedValues[$varName] = $coercedValue;
         }
     }
     return $coercedValues;
 }
Exemple #3
0
 /**
  * Given a variable definition, and any value of input, return a value which
  * adheres to the variable definition, or throw an error.
  */
 private static function getVariableValue(Schema $schema, VariableDefinition $definitionAST, $input)
 {
     $type = Utils\TypeInfo::typeFromAST($schema, $definitionAST->type);
     $variable = $definitionAST->variable;
     if (!$type || !Type::isInputType($type)) {
         $printed = Printer::doPrint($definitionAST->type);
         throw new Error("Variable \"\${$variable->name->value}\" expected value of type " . "\"{$printed}\" which cannot be used as an input type.", [$definitionAST]);
     }
     $inputType = $type;
     $errors = self::isValidPHPValue($input, $inputType);
     if (empty($errors)) {
         if (null === $input) {
             $defaultValue = $definitionAST->defaultValue;
             if ($defaultValue) {
                 return Utils\AST::valueFromAST($defaultValue, $inputType);
             }
         }
         return self::coerceValue($inputType, $input);
     }
     if (null === $input) {
         $printed = Printer::doPrint($definitionAST->type);
         throw new Error("Variable \"\${$variable->name->value}\" of required type " . "\"{$printed}\" was not provided.", [$definitionAST]);
     }
     $message = $errors ? "\n" . implode("\n", $errors) : '';
     $val = json_encode($input);
     throw new Error("Variable \"\${$variable->name->value}\" got invalid value " . "{$val}.{$message}", [$definitionAST]);
 }
 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)
 {
     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]));
         }
     }];
 }
Exemple #6
0
 /**
  * Given a variable definition, and any value of input, return a value which
  * adheres to the variable definition, or throw an error.
  */
 private static function getVariableValue(Schema $schema, VariableDefinition $definitionAST, $input)
 {
     $type = Utils\TypeInfo::typeFromAST($schema, $definitionAST->type);
     if (!$type) {
         return null;
     }
     if (self::isValidValue($type, $input)) {
         if (null === $input) {
             $defaultValue = $definitionAST->defaultValue;
             if ($defaultValue) {
                 return self::coerceValueAST($type, $defaultValue);
             }
         }
         return self::coerceValue($type, $input);
     }
     throw new Error("Variable \${$definitionAST->variable->name->value} expected value of type " . Printer::doPrint($definitionAST->type) . " but got: " . json_encode($input) . '.', [$definitionAST]);
 }
 /**
  * Given a selectionSet, adds all of the fields in that selection to
  * the passed in map of fields, and returns it at the end.
  *
  * Note: This is not the same as execution's collectFields because at static
  * time we do not know what object type will be used, so we unconditionally
  * spread in all fragments.
  *
  * @param ValidationContext $context
  * @param mixed $parentType
  * @param SelectionSetNode $selectionSet
  * @param \ArrayObject $visitedFragmentNames
  * @param \ArrayObject $astAndDefs
  * @return mixed
  */
 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;
 }
Exemple #8
0
 /**
  * Determines if a fragment is applicable to the given type.
  *
  * @param ExecutionContext $exeContext
  * @param $fragment
  * @param ObjectType $type
  * @return bool
  */
 private static function doesFragmentConditionMatch(ExecutionContext $exeContext, $fragment, ObjectType $type)
 {
     $typeConditionNode = $fragment->typeCondition;
     if (!$typeConditionNode) {
         return true;
     }
     $conditionalType = Utils\TypeInfo::typeFromAST($exeContext->schema, $typeConditionNode);
     if ($conditionalType === $type) {
         return true;
     }
     if ($conditionalType instanceof AbstractType) {
         return $exeContext->schema->isPossibleType($conditionalType, $type);
     }
     return false;
 }
Exemple #9
0
 /**
  * Determines if a fragment is applicable to the given type.
  */
 private static function doesFragmentConditionMatch(ExecutionContext $exeContext, $fragment, ObjectType $type)
 {
     $conditionalType = Utils\TypeInfo::typeFromAST($exeContext->schema, $fragment->typeCondition);
     if ($conditionalType === $type) {
         return true;
     }
     if ($conditionalType instanceof InterfaceType || $conditionalType instanceof UnionType) {
         return $conditionalType->isPossibleType($type);
     }
     return false;
 }
Exemple #10
0
 /**
  * Given a variable definition, and any value of input, return a value which
  * adheres to the variable definition, or throw an error.
  */
 private static function getVariableValue(Schema $schema, VariableDefinition $definitionAST, $input)
 {
     $type = Utils\TypeInfo::typeFromAST($schema, $definitionAST->type);
     $variable = $definitionAST->variable;
     if (!$type || !Type::isInputType($type)) {
         $printed = Printer::doPrint($definitionAST->type);
         throw new Error("Variable \"\${$variable->name->value}\" expected value of type " . "\"{$printed}\" which cannot be used as an input type.", [$definitionAST]);
     }
     if (self::isValidValue($input, $type)) {
         if (null === $input) {
             $defaultValue = $definitionAST->defaultValue;
             if ($defaultValue) {
                 return self::valueFromAST($defaultValue, $type);
             }
         }
         return self::coerceValue($type, $input);
     }
     throw new Error("Variable \${$definitionAST->variable->name->value} expected value of type " . Printer::doPrint($definitionAST->type) . " but got: " . json_encode($input) . '.', [$definitionAST]);
 }
 /**
  * Given a selectionSet, adds all of the fields in that selection to
  * the passed in map of fields, and returns it at the end.
  *
  * Note: This is not the same as execution's collectFields because at static
  * time we do not know what object type will be used, so we unconditionally
  * spread in all fragments.
  *
  * @see GraphQL\Validator\Rules\OverlappingFieldsCanBeMerged
  *
  * @param ValidationContext $context
  * @param Type|null         $parentType
  * @param SelectionSetNode      $selectionSet
  * @param \ArrayObject      $visitedFragmentNames
  * @param \ArrayObject      $astAndDefs
  *
  * @return \ArrayObject
  */
 protected function collectFieldASTsAndDefs(ValidationContext $context, $parentType, SelectionSetNode $selectionSet, \ArrayObject $visitedFragmentNames = null, \ArrayObject $astAndDefs = null)
 {
     $_visitedFragmentNames = $visitedFragmentNames ?: new \ArrayObject();
     $_astAndDefs = $astAndDefs ?: new \ArrayObject();
     foreach ($selectionSet->selections as $selection) {
         switch ($selection->kind) {
             case NodeKind::FIELD:
                 /* @var FieldNode $selection */
                 $fieldName = $selection->name->value;
                 $fieldDef = null;
                 if ($parentType && method_exists($parentType, 'getFields')) {
                     $tmp = $parentType->getFields();
                     $schemaMetaFieldDef = Introspection::schemaMetaFieldDef();
                     $typeMetaFieldDef = Introspection::typeMetaFieldDef();
                     $typeNameMetaFieldDef = Introspection::typeNameMetaFieldDef();
                     if ($fieldName === $schemaMetaFieldDef->name && $context->getSchema()->getQueryType() === $parentType) {
                         $fieldDef = $schemaMetaFieldDef;
                     } elseif ($fieldName === $typeMetaFieldDef->name && $context->getSchema()->getQueryType() === $parentType) {
                         $fieldDef = $typeMetaFieldDef;
                     } elseif ($fieldName === $typeNameMetaFieldDef->name) {
                         $fieldDef = $typeNameMetaFieldDef;
                     } elseif (isset($tmp[$fieldName])) {
                         $fieldDef = $tmp[$fieldName];
                     }
                 }
                 $responseName = $this->getFieldName($selection);
                 if (!isset($_astAndDefs[$responseName])) {
                     $_astAndDefs[$responseName] = new \ArrayObject();
                 }
                 // create field context
                 $_astAndDefs[$responseName][] = [$selection, $fieldDef];
                 break;
             case NodeKind::INLINE_FRAGMENT:
                 /* @var InlineFragmentNode $selection */
                 $_astAndDefs = $this->collectFieldASTsAndDefs($context, TypeInfo::typeFromAST($context->getSchema(), $selection->typeCondition), $selection->selectionSet, $_visitedFragmentNames, $_astAndDefs);
                 break;
             case NodeKind::FRAGMENT_SPREAD:
                 /* @var FragmentSpreadNode $selection */
                 $fragName = $selection->name->value;
                 if (empty($_visitedFragmentNames[$fragName])) {
                     $_visitedFragmentNames[$fragName] = true;
                     $fragment = $context->getFragment($fragName);
                     if ($fragment) {
                         $_astAndDefs = $this->collectFieldASTsAndDefs($context, TypeInfo::typeFromAST($context->getSchema(), $fragment->typeCondition), $fragment->selectionSet, $_visitedFragmentNames, $_astAndDefs);
                     }
                 }
                 break;
         }
     }
     return $_astAndDefs;
 }
 private function getFragmentType(ValidationContext $context, $name)
 {
     $frag = $context->getFragment($name);
     return $frag ? TypeInfo::typeFromAST($context->getSchema(), $frag->typeCondition) : null;
 }