mirror of
https://github.com/retailcrm/graphql-php.git
synced 2024-11-25 22:36:02 +03:00
More definition tests (for type validation)
This commit is contained in:
parent
392b567f23
commit
39df711eac
@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace GraphQL\Type\Definition;
|
namespace GraphQL\Type\Definition;
|
||||||
|
use GraphQL\Error\Error;
|
||||||
use GraphQL\Error\InvariantViolation;
|
use GraphQL\Error\InvariantViolation;
|
||||||
use GraphQL\Language\AST\FieldDefinitionNode;
|
use GraphQL\Language\AST\FieldDefinitionNode;
|
||||||
use GraphQL\Language\AST\TypeDefinitionNode;
|
use GraphQL\Language\AST\TypeDefinitionNode;
|
||||||
@ -82,8 +83,15 @@ class FieldDefinition
|
|||||||
$map = [];
|
$map = [];
|
||||||
foreach ($fields as $name => $field) {
|
foreach ($fields as $name => $field) {
|
||||||
if (is_array($field)) {
|
if (is_array($field)) {
|
||||||
if (!isset($field['name']) && is_string($name)) {
|
if (!isset($field['name'])) {
|
||||||
|
if (is_string($name)) {
|
||||||
$field['name'] = $name;
|
$field['name'] = $name;
|
||||||
|
} else {
|
||||||
|
throw new InvariantViolation(
|
||||||
|
"{$type->name} fields must be an associative array with field names as keys or a " .
|
||||||
|
"function which returns such an array."
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (isset($field['args']) && !is_array($field['args'])) {
|
if (isset($field['args']) && !is_array($field['args'])) {
|
||||||
throw new InvariantViolation(
|
throw new InvariantViolation(
|
||||||
@ -185,7 +193,7 @@ class FieldDefinition
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
Utils::assertValidName($this->name);
|
Utils::assertValidName($this->name);
|
||||||
} catch (InvariantViolation $e) {
|
} catch (Error $e) {
|
||||||
throw new InvariantViolation("{$parentType->name}.{$this->name}: {$e->getMessage()}");
|
throw new InvariantViolation("{$parentType->name}.{$this->name}: {$e->getMessage()}");
|
||||||
}
|
}
|
||||||
Utils::invariant(
|
Utils::invariant(
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace GraphQL\Type\Definition;
|
namespace GraphQL\Type\Definition;
|
||||||
|
use GraphQL\Error\Error;
|
||||||
|
use GraphQL\Error\InvariantViolation;
|
||||||
use GraphQL\Language\AST\InputValueDefinitionNode;
|
use GraphQL\Language\AST\InputValueDefinitionNode;
|
||||||
|
use GraphQL\Utils\Utils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class InputObjectField
|
* Class InputObjectField
|
||||||
@ -81,4 +84,30 @@ class InputObjectField
|
|||||||
{
|
{
|
||||||
return $this->defaultValueExists;
|
return $this->defaultValueExists;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Type $parentType
|
||||||
|
* @throws InvariantViolation
|
||||||
|
*/
|
||||||
|
public function assertValid(Type $parentType)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Utils::assertValidName($this->name);
|
||||||
|
} catch (Error $e) {
|
||||||
|
throw new InvariantViolation("{$parentType->name}.{$this->name}: {$e->getMessage()}");
|
||||||
|
}
|
||||||
|
$type = $this->type;
|
||||||
|
if ($type instanceof WrappingType) {
|
||||||
|
$type = $type->getWrappedType(true);
|
||||||
|
}
|
||||||
|
Utils::invariant(
|
||||||
|
$type instanceof InputType,
|
||||||
|
"{$parentType->name}.{$this->name} field type must be Input Type but got: " . Utils::printSafe($this->type)
|
||||||
|
);
|
||||||
|
Utils::invariant(
|
||||||
|
empty($this->config['resolve']),
|
||||||
|
"{$parentType->name}.{$this->name} field type has a resolve property, " .
|
||||||
|
'but Input Types cannot define resolvers.'
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,4 +80,25 @@ class InputObjectType extends Type implements InputType, NamedType
|
|||||||
Utils::invariant(isset($this->fields[$name]), "Field '%s' is not defined for type '%s'", $name, $this->name);
|
Utils::invariant(isset($this->fields[$name]), "Field '%s' is not defined for type '%s'", $name, $this->name);
|
||||||
return $this->fields[$name];
|
return $this->fields[$name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates type config and throws if one of type options is invalid.
|
||||||
|
* Note: this method is shallow, it won't validate object fields and their arguments.
|
||||||
|
*
|
||||||
|
* @throws InvariantViolation
|
||||||
|
*/
|
||||||
|
public function assertValid()
|
||||||
|
{
|
||||||
|
parent::assertValid();
|
||||||
|
|
||||||
|
Utils::invariant(
|
||||||
|
!empty($this->getFields()),
|
||||||
|
"{$this->name} fields must be an associative array with field names as keys or a " .
|
||||||
|
"callable which returns such an array."
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($this->getFields() as $field) {
|
||||||
|
$field->assertValid($this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,9 +110,11 @@ class InterfaceType extends Type implements AbstractType, OutputType, CompositeT
|
|||||||
{
|
{
|
||||||
parent::assertValid();
|
parent::assertValid();
|
||||||
|
|
||||||
|
$resolveType = $this->config['resolveType'] ?? null;
|
||||||
|
|
||||||
Utils::invariant(
|
Utils::invariant(
|
||||||
!isset($this->config['resolveType']) || is_callable($this->config['resolveType']),
|
!isset($resolveType) || is_callable($resolveType),
|
||||||
"{$this->name} must provide \"resolveType\" as a function."
|
"{$this->name} must provide \"resolveType\" as a function, but got: " . Utils::printSafe($resolveType)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,9 +207,15 @@ class ObjectType extends Type implements OutputType, CompositeType, NamedType
|
|||||||
"{$this->name} description must be string if set, but it is: " . Utils::printSafe($this->description)
|
"{$this->name} description must be string if set, but it is: " . Utils::printSafe($this->description)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$isTypeOf = $this->config['isTypeOf'] ?? null;
|
||||||
|
|
||||||
Utils::invariant(
|
Utils::invariant(
|
||||||
!isset($this->config['isTypeOf']) || is_callable($this->config['isTypeOf']),
|
!isset($isTypeOf) || is_callable($isTypeOf),
|
||||||
"{$this->name} must provide 'isTypeOf' as a function"
|
"{$this->name} must provide \"isTypeOf\" as a function, but got: " . Utils::printSafe($isTypeOf)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
foreach ($this->getFields() as $field) {
|
||||||
|
$field->assertValid($this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -216,16 +216,7 @@ abstract class Type implements \JsonSerializable
|
|||||||
*/
|
*/
|
||||||
public static function isType($type)
|
public static function isType($type)
|
||||||
{
|
{
|
||||||
return (
|
return $type instanceof Type;
|
||||||
$type instanceof ScalarType ||
|
|
||||||
$type instanceof ObjectType ||
|
|
||||||
$type instanceof InterfaceType ||
|
|
||||||
$type instanceof UnionType ||
|
|
||||||
$type instanceof EnumType ||
|
|
||||||
$type instanceof InputObjectType ||
|
|
||||||
$type instanceof ListOfType ||
|
|
||||||
$type instanceof NonNull
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -121,7 +121,7 @@ class UnionType extends Type implements AbstractType, OutputType, CompositeType,
|
|||||||
if (isset($this->config['resolveType'])) {
|
if (isset($this->config['resolveType'])) {
|
||||||
Utils::invariant(
|
Utils::invariant(
|
||||||
is_callable($this->config['resolveType']),
|
is_callable($this->config['resolveType']),
|
||||||
"{$this->name} must provide \"resolveType\" as a function."
|
"{$this->name} must provide \"resolveType\" as a function, but got: " . Utils::printSafe($this->config['resolveType'])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -406,7 +406,8 @@ class Schema
|
|||||||
* @api
|
* @api
|
||||||
* @return InvariantViolation[]|Error[]
|
* @return InvariantViolation[]|Error[]
|
||||||
*/
|
*/
|
||||||
public function validate() {
|
public function validate()
|
||||||
|
{
|
||||||
// If this Schema has already been validated, return the previous results.
|
// If this Schema has already been validated, return the previous results.
|
||||||
if ($this->validationErrors !== null) {
|
if ($this->validationErrors !== null) {
|
||||||
return $this->validationErrors;
|
return $this->validationErrors;
|
||||||
|
@ -49,11 +49,13 @@ class SchemaValidationContext
|
|||||||
/**
|
/**
|
||||||
* @return Error[]
|
* @return Error[]
|
||||||
*/
|
*/
|
||||||
public function getErrors() {
|
public function getErrors()
|
||||||
|
{
|
||||||
return $this->errors;
|
return $this->errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function validateRootTypes() {
|
public function validateRootTypes()
|
||||||
|
{
|
||||||
$queryType = $this->schema->getQueryType();
|
$queryType = $this->schema->getQueryType();
|
||||||
if (!$queryType) {
|
if (!$queryType) {
|
||||||
$this->reportError(
|
$this->reportError(
|
||||||
@ -208,7 +210,8 @@ class SchemaValidationContext
|
|||||||
/**
|
/**
|
||||||
* @param ObjectType|InterfaceType $type
|
* @param ObjectType|InterfaceType $type
|
||||||
*/
|
*/
|
||||||
private function validateFields($type) {
|
private function validateFields($type)
|
||||||
|
{
|
||||||
$fieldMap = $type->getFields();
|
$fieldMap = $type->getFields();
|
||||||
|
|
||||||
// Objects and Interfaces both must define one or more fields.
|
// Objects and Interfaces both must define one or more fields.
|
||||||
@ -271,7 +274,8 @@ class SchemaValidationContext
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function validateObjectInterfaces(ObjectType $object) {
|
private function validateObjectInterfaces(ObjectType $object)
|
||||||
|
{
|
||||||
$implementedTypeNames = [];
|
$implementedTypeNames = [];
|
||||||
foreach($object->getInterfaces() as $iface) {
|
foreach($object->getInterfaces() as $iface) {
|
||||||
if (isset($implementedTypeNames[$iface->name])) {
|
if (isset($implementedTypeNames[$iface->name])) {
|
||||||
@ -714,7 +718,8 @@ class SchemaValidationContext
|
|||||||
* @param string $message
|
* @param string $message
|
||||||
* @param array|Node|TypeNode|TypeDefinitionNode $nodes
|
* @param array|Node|TypeNode|TypeDefinitionNode $nodes
|
||||||
*/
|
*/
|
||||||
private function reportError($message, $nodes = null) {
|
private function reportError($message, $nodes = null)
|
||||||
|
{
|
||||||
$nodes = array_filter($nodes && is_array($nodes) ? $nodes : [$nodes]);
|
$nodes = array_filter($nodes && is_array($nodes) ? $nodes : [$nodes]);
|
||||||
$this->addError(new Error($message, $nodes));
|
$this->addError(new Error($message, $nodes));
|
||||||
}
|
}
|
||||||
@ -722,7 +727,8 @@ class SchemaValidationContext
|
|||||||
/**
|
/**
|
||||||
* @param Error $error
|
* @param Error $error
|
||||||
*/
|
*/
|
||||||
private function addError($error) {
|
private function addError($error)
|
||||||
|
{
|
||||||
$this->errors[] = $error;
|
$this->errors[] = $error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user