Exemple #1
0
 public static function valueFromAST($valueAST, InputType $type, $variables = null)
 {
     if ($type instanceof NonNull) {
         return self::valueFromAST($valueAST, $type->getWrappedType(), $variables);
     }
     if (!$valueAST) {
         return null;
     }
     if ($valueAST instanceof Variable) {
         $variableName = $valueAST->name->value;
         if (!$variables || !isset($variables[$variableName])) {
             return null;
         }
         return $variables[$variableName];
     }
     if ($type instanceof ListOfType) {
         $itemType = $type->getWrappedType();
         if ($valueAST instanceof ListValue) {
             return array_map(function ($itemAST) use($itemType, $variables) {
                 return Values::valueFromAST($itemAST, $itemType, $variables);
             }, $valueAST->values);
         } else {
             return [self::valueFromAST($valueAST, $itemType, $variables)];
         }
     }
     if ($type instanceof InputObjectType) {
         $fields = $type->getFields();
         if (!$valueAST instanceof ObjectValue) {
             return null;
         }
         $fieldASTs = Utils::keyMap($valueAST->fields, function ($field) {
             return $field->name->value;
         });
         $values = [];
         foreach ($fields as $field) {
             $fieldAST = isset($fieldASTs[$field->name]) ? $fieldASTs[$field->name] : null;
             $fieldValue = self::valueFromAST($fieldAST ? $fieldAST->value : null, $field->getType(), $variables);
             if (null === $fieldValue) {
                 $fieldValue = $field->defaultValue;
             }
             if (null !== $fieldValue) {
                 $values[$field->name] = $fieldValue;
             }
         }
         return $values;
     }
     Utils::invariant($type instanceof ScalarType || $type instanceof EnumType, 'Must be input type');
     return $type->parseLiteral($valueAST);
 }
Exemple #2
0
 /**
  * Produces a PHP value given a GraphQL Value AST.
  *
  * A GraphQL type must be provided, which will be used to interpret different
  * GraphQL Value literals.
  *
  * | GraphQL Value        | PHP Value     |
  * | -------------------- | ------------- |
  * | Input Object         | Assoc Array   |
  * | List                 | Array         |
  * | Boolean              | Boolean       |
  * | String               | String        |
  * | Int / Float          | Int / Float   |
  * | Enum Value           | Mixed         |
  *
  * @param $valueAST
  * @param InputType $type
  * @param null $variables
  * @return array|null
  * @throws \Exception
  */
 public static function valueFromAST($valueAST, InputType $type, $variables = null)
 {
     if ($type instanceof NonNull) {
         // Note: we're not checking that the result of valueFromAST is non-null.
         // We're assuming that this query has been validated and the value used
         // here is of the correct type.
         return self::valueFromAST($valueAST, $type->getWrappedType(), $variables);
     }
     if (!$valueAST) {
         return null;
     }
     if ($valueAST instanceof Variable) {
         $variableName = $valueAST->name->value;
         if (!$variables || !isset($variables[$variableName])) {
             return null;
         }
         // Note: we're not doing any checking that this variable is correct. We're
         // assuming that this query has been validated and the variable usage here
         // is of the correct type.
         return $variables[$variableName];
     }
     if ($type instanceof ListOfType) {
         $itemType = $type->getWrappedType();
         if ($valueAST instanceof ListValue) {
             return array_map(function ($itemAST) use($itemType, $variables) {
                 return self::valueFromAST($itemAST, $itemType, $variables);
             }, $valueAST->values);
         } else {
             return [self::valueFromAST($valueAST, $itemType, $variables)];
         }
     }
     if ($type instanceof InputObjectType) {
         $fields = $type->getFields();
         if (!$valueAST instanceof ObjectValue) {
             return null;
         }
         $fieldASTs = Utils::keyMap($valueAST->fields, function ($field) {
             return $field->name->value;
         });
         $values = [];
         foreach ($fields as $field) {
             $fieldAST = isset($fieldASTs[$field->name]) ? $fieldASTs[$field->name] : null;
             $fieldValue = self::valueFromAST($fieldAST ? $fieldAST->value : null, $field->getType(), $variables);
             if (null === $fieldValue) {
                 $fieldValue = $field->defaultValue;
             }
             if (null !== $fieldValue) {
                 $values[$field->name] = $fieldValue;
             }
         }
         return $values;
     }
     if ($type instanceof LeafType) {
         return $type->parseLiteral($valueAST);
     }
     throw new InvariantViolation('Must be input type');
 }
Exemple #3
0
 /**
  * Produces a PHP value given a GraphQL Value AST.
  *
  * A GraphQL type must be provided, which will be used to interpret different
  * GraphQL Value literals.
  *
  * Returns `null` when the value could not be validly coerced according to
  * the provided type.
  *
  * | GraphQL Value        | PHP Value     |
  * | -------------------- | ------------- |
  * | Input Object         | Assoc Array   |
  * | List                 | Array         |
  * | Boolean              | Boolean       |
  * | String               | String        |
  * | Int / Float          | Int / Float   |
  * | Enum Value           | Mixed         |
  * | Null Value           | stdClass      | instance of NullValue::getNullValue()
  *
  * @param $valueNode
  * @param InputType $type
  * @param null $variables
  * @return array|null|\stdClass
  * @throws \Exception
  */
 public static function valueFromAST($valueNode, InputType $type, $variables = null)
 {
     $undefined = Utils::undefined();
     if (!$valueNode) {
         // When there is no AST, then there is also no value.
         // Importantly, this is different from returning the GraphQL null value.
         return $undefined;
     }
     if ($type instanceof NonNull) {
         if ($valueNode instanceof NullValueNode) {
             // Invalid: intentionally return no value.
             return $undefined;
         }
         return self::valueFromAST($valueNode, $type->getWrappedType(), $variables);
     }
     if ($valueNode instanceof NullValueNode) {
         // This is explicitly returning the value null.
         return null;
     }
     if ($valueNode instanceof VariableNode) {
         $variableName = $valueNode->name->value;
         if (!$variables || !array_key_exists($variableName, $variables)) {
             // No valid return value.
             return $undefined;
         }
         // Note: we're not doing any checking that this variable is correct. We're
         // assuming that this query has been validated and the variable usage here
         // is of the correct type.
         return $variables[$variableName];
     }
     if ($type instanceof ListOfType) {
         $itemType = $type->getWrappedType();
         if ($valueNode instanceof ListValueNode) {
             $coercedValues = [];
             $itemNodes = $valueNode->values;
             foreach ($itemNodes as $itemNode) {
                 if (self::isMissingVariable($itemNode, $variables)) {
                     // If an array contains a missing variable, it is either coerced to
                     // null or if the item type is non-null, it considered invalid.
                     if ($itemType instanceof NonNull) {
                         // Invalid: intentionally return no value.
                         return $undefined;
                     }
                     $coercedValues[] = null;
                 } else {
                     $itemValue = self::valueFromAST($itemNode, $itemType, $variables);
                     if ($undefined === $itemValue) {
                         // Invalid: intentionally return no value.
                         return $undefined;
                     }
                     $coercedValues[] = $itemValue;
                 }
             }
             return $coercedValues;
         }
         $coercedValue = self::valueFromAST($valueNode, $itemType, $variables);
         if ($undefined === $coercedValue) {
             // Invalid: intentionally return no value.
             return $undefined;
         }
         return [$coercedValue];
     }
     if ($type instanceof InputObjectType) {
         if (!$valueNode instanceof ObjectValueNode) {
             // Invalid: intentionally return no value.
             return $undefined;
         }
         $coercedObj = [];
         $fields = $type->getFields();
         $fieldNodes = Utils::keyMap($valueNode->fields, function ($field) {
             return $field->name->value;
         });
         foreach ($fields as $field) {
             /** @var ValueNode $fieldNode */
             $fieldName = $field->name;
             $fieldNode = isset($fieldNodes[$fieldName]) ? $fieldNodes[$fieldName] : null;
             if (!$fieldNode || self::isMissingVariable($fieldNode->value, $variables)) {
                 if ($field->defaultValueExists()) {
                     $coercedObj[$fieldName] = $field->defaultValue;
                 } else {
                     if ($field->getType() instanceof NonNull) {
                         // Invalid: intentionally return no value.
                         return $undefined;
                     }
                 }
                 continue;
             }
             $fieldValue = self::valueFromAST($fieldNode ? $fieldNode->value : null, $field->getType(), $variables);
             if ($undefined === $fieldValue) {
                 // Invalid: intentionally return no value.
                 return $undefined;
             }
             $coercedObj[$fieldName] = $fieldValue;
         }
         return $coercedObj;
     }
     if ($type instanceof LeafType) {
         $parsed = $type->parseLiteral($valueNode);
         if (null === $parsed) {
             // null represent a failure to parse correctly,
             // in which case no value is returned.
             return $undefined;
         }
         return $parsed;
     }
     throw new InvariantViolation('Must be input type');
 }
Exemple #4
0
 /**
  * Given a PHP value and a GraphQL type, determine if the value will be
  * accepted for that type. This is primarily useful for validating the
  * runtime values of query variables.
  *
  * @param $value
  * @param InputType $type
  * @return array
  */
 private static function isValidPHPValue($value, InputType $type)
 {
     // A value must be provided if the type is non-null.
     if ($type instanceof NonNull) {
         $ofType = $type->getWrappedType();
         if (null === $value) {
             if ($ofType->name) {
                 return ["Expected \"{$ofType->name}!\", found null."];
             }
             return ['Expected non-null value, found null.'];
         }
         return self::isValidPHPValue($value, $ofType);
     }
     if (null === $value) {
         return [];
     }
     // Lists accept a non-list value as a list of one.
     if ($type instanceof ListOfType) {
         $itemType = $type->getWrappedType();
         if (is_array($value)) {
             $tmp = [];
             foreach ($value as $index => $item) {
                 $errors = self::isValidPHPValue($item, $itemType);
                 $tmp = array_merge($tmp, Utils::map($errors, function ($error) use($index) {
                     return "In element #{$index}: {$error}";
                 }));
             }
             return $tmp;
         }
         return self::isValidPHPValue($value, $itemType);
     }
     // Input objects check each defined field.
     if ($type instanceof InputObjectType) {
         if (!is_object($value) && !is_array($value)) {
             return ["Expected \"{$type->name}\", found not an object."];
         }
         $fields = $type->getFields();
         $errors = [];
         // Ensure every provided field is defined.
         $props = is_object($value) ? get_object_vars($value) : $value;
         foreach ($props as $providedField => $tmp) {
             if (!isset($fields[$providedField])) {
                 $errors[] = "In field \"{$providedField}\": Unknown field.";
             }
         }
         // Ensure every defined field is valid.
         foreach ($fields as $fieldName => $tmp) {
             $newErrors = self::isValidPHPValue(isset($value[$fieldName]) ? $value[$fieldName] : null, $fields[$fieldName]->getType());
             $errors = array_merge($errors, Utils::map($newErrors, function ($error) use($fieldName) {
                 return "In field \"{$fieldName}\": {$error}";
             }));
         }
         return $errors;
     }
     if ($type instanceof LeafType) {
         // Scalar/Enum input checks to ensure the type can parse the value to
         // a non-null value.
         $parseResult = $type->parseValue($value);
         if (null === $parseResult) {
             $v = json_encode($value);
             return ["Expected type \"{$type->name}\", found {$v}."];
         }
         return [];
     }
     throw new InvariantViolation('Must be input type');
 }