Fully load all schema types in constructor when type loader is not set

This commit is contained in:
Vladimir Razuvaev 2017-08-14 19:44:16 +07:00
parent 884a8967f3
commit f47db61907
7 changed files with 321 additions and 334 deletions

View File

@ -226,6 +226,20 @@ EOD;
return $includeDescription ? $withDescription : $withoutDescription;
}
public static function getTypes()
{
return [
'__Schema' => self::_schema(),
'__Type' => self::_type(),
'__Directive' => self::_directive(),
'__Field' => self::_field(),
'__InputValue' => self::_inputValue(),
'__EnumValue' => self::_enumValue(),
'__TypeKind' => self::_typeKind(),
'__DirectiveLocation' => self::_directiveLocation(),
];
}
public static function _schema()
{
if (!isset(self::$map['__Schema'])) {

View File

@ -122,6 +122,9 @@ class Schema
if ($config->subscription) {
$this->resolvedTypes[$config->subscription->name] = $config->subscription;
}
if (!$this->config->typeLoader) {
$this->getTypeMap();
}
}
/**

View File

@ -57,7 +57,7 @@ class SchemaConfig
Utils::invariant(
$options['query'] instanceof ObjectType,
'Schema query must be Object Type if provided but got: %s',
Utils::getVariableType($options['query'])
Utils::printSafe($options['query'])
);
$config->setQuery($options['query']);
}
@ -66,7 +66,7 @@ class SchemaConfig
Utils::invariant(
$options['mutation'] instanceof ObjectType,
'Schema mutation must be Object Type if provided but got: %s',
Utils::getVariableType($options['mutation'])
Utils::printSafe($options['mutation'])
);
$config->setMutation($options['mutation']);
}
@ -75,7 +75,7 @@ class SchemaConfig
Utils::invariant(
$options['subscription'] instanceof ObjectType,
'Schema subscription must be Object Type if provided but got: %s',
Utils::getVariableType($options['subscription'])
Utils::printSafe($options['subscription'])
);
$config->setSubscription($options['subscription']);
}
@ -84,7 +84,7 @@ class SchemaConfig
Utils::invariant(
is_array($options['types']) || is_callable($options['types']),
'Schema types must be array or callable if provided but got: %s',
Utils::getVariableType($options['types'])
Utils::printSafe($options['types'])
);
$config->setTypes($options['types']);
}
@ -93,7 +93,7 @@ class SchemaConfig
Utils::invariant(
is_array($options['directives']),
'Schema directives must be array if provided but got: %s',
Utils::getVariableType($options['directives'])
Utils::printSafe($options['directives'])
);
$config->setDirectives($options['directives']);
}
@ -116,7 +116,7 @@ class SchemaConfig
Utils::invariant(
is_callable($options['typeLoader']),
'Schema type loader must be callable if provided but got: %s',
Utils::getVariableType($options['typeLoader'])
Utils::printSafe($options['typeLoader'])
);
$config->setTypeLoader($options['typeLoader']);
}
@ -184,7 +184,7 @@ class SchemaConfig
*/
public function getTypes()
{
return $this->types;
return $this->types ?: [];
}
/**

View File

@ -32,18 +32,18 @@ class StarWarsIntrospectionTest extends \PHPUnit_Framework_TestCase
['name' => 'String'],
['name' => 'Human'],
['name' => 'Droid'],
['name' => 'ID'],
['name' => 'Float'],
['name' => 'Int'],
['name' => 'Boolean'],
['name' => '__Schema'],
['name' => '__Type'],
['name' => '__TypeKind'],
['name' => 'Boolean'],
['name' => '__Directive'],
['name' => '__Field'],
['name' => '__InputValue'],
['name' => '__EnumValue'],
['name' => '__Directive'],
['name' => '__TypeKind'],
['name' => '__DirectiveLocation'],
['name' => 'ID'],
['name' => 'Float'],
['name' => 'Int']
]
]
];

View File

@ -576,9 +576,8 @@ class DefinitionTest extends \PHPUnit_Framework_TestCase
'types' => [$user, $blog]
]);
$this->assertFalse($called);
$schema->getType('Blog');
$this->assertTrue($called);
$schema->getType('Blog');
$this->assertEquals([$node], $blog->getInterfaces());
$this->assertEquals([$node], $user->getInterfaces());

View File

@ -74,6 +74,42 @@ class IntrospectionTest extends \PHPUnit_Framework_TestCase
'enumValues' => NULL,
'possibleTypes' => NULL,
),
array (
'kind' => 'SCALAR',
'name' => 'ID',
'fields' => NULL,
'inputFields' => NULL,
'interfaces' => NULL,
'enumValues' => NULL,
'possibleTypes' => NULL,
),
array (
'kind' => 'SCALAR',
'name' => 'Float',
'fields' => NULL,
'inputFields' => NULL,
'interfaces' => NULL,
'enumValues' => NULL,
'possibleTypes' => NULL,
),
array (
'kind' => 'SCALAR',
'name' => 'Int',
'fields' => NULL,
'inputFields' => NULL,
'interfaces' => NULL,
'enumValues' => NULL,
'possibleTypes' => NULL,
),
array (
'kind' => 'SCALAR',
'name' => 'Boolean',
'fields' => NULL,
'inputFields' => NULL,
'interfaces' => NULL,
'enumValues' => NULL,
'possibleTypes' => NULL,
),
array (
'kind' => 'OBJECT',
'name' => '__Schema',
@ -127,60 +163,60 @@ class IntrospectionTest extends \PHPUnit_Framework_TestCase
'isDeprecated' => false,
'deprecationReason' => NULL,
),
array (
'name' => 'mutationType',
'args' =>
array (
),
'type' =>
array (
'kind' => 'OBJECT',
'name' => '__Type',
),
'isDeprecated' => false,
'deprecationReason' => NULL,
),
array (
'name' => 'subscriptionType',
'args' =>
array (
),
'type' =>
array (
'kind' => 'OBJECT',
'name' => '__Type',
),
'isDeprecated' => false,
'deprecationReason' => NULL,
),
array (
'name' => 'directives',
'args' =>
array (
),
'type' =>
array (
'kind' => 'NON_NULL',
'name' => NULL,
'ofType' =>
array (
'kind' => 'LIST',
'name' => NULL,
'ofType' =>
array (
'kind' => 'NON_NULL',
'name' => NULL,
'ofType' =>
array (
'kind' => 'OBJECT',
'name' => '__Directive',
),
),
),
),
'isDeprecated' => false,
'deprecationReason' => NULL,
),
array (
'name' => 'mutationType',
'args' =>
array (
),
'type' =>
array (
'kind' => 'OBJECT',
'name' => '__Type',
),
'isDeprecated' => false,
'deprecationReason' => NULL,
),
array (
'name' => 'subscriptionType',
'args' =>
array (
),
'type' =>
array (
'kind' => 'OBJECT',
'name' => '__Type',
),
'isDeprecated' => false,
'deprecationReason' => NULL,
),
array (
'name' => 'directives',
'args' =>
array (
),
'type' =>
array (
'kind' => 'NON_NULL',
'name' => NULL,
'ofType' =>
array (
'kind' => 'LIST',
'name' => NULL,
'ofType' =>
array (
'kind' => 'NON_NULL',
'name' => NULL,
'ofType' =>
array (
'kind' => 'OBJECT',
'name' => '__Directive',
),
),
),
),
'isDeprecated' => false,
'deprecationReason' => NULL,
),
),
'inputFields' => NULL,
'interfaces' =>
@ -404,70 +440,164 @@ class IntrospectionTest extends \PHPUnit_Framework_TestCase
'possibleTypes' => NULL,
),
array (
'kind' => 'ENUM',
'name' => '__TypeKind',
'fields' => NULL,
'inputFields' => NULL,
'interfaces' => NULL,
'enumValues' =>
'kind' => 'OBJECT',
'name' => '__Directive',
'fields' =>
array (
0 =>
array (
'name' => 'SCALAR',
'name' => 'name',
'args' =>
array (
),
'type' =>
array (
'kind' => 'NON_NULL',
'name' => NULL,
'ofType' =>
array (
'kind' => 'SCALAR',
'name' => 'String',
),
),
'isDeprecated' => false,
'deprecationReason' => NULL,
),
1 =>
array (
'name' => 'OBJECT',
'name' => 'description',
'args' =>
array (
),
'type' =>
array (
'kind' => 'SCALAR',
'name' => 'String',
),
'isDeprecated' => false,
'deprecationReason' => NULL,
),
2 =>
array (
'name' => 'INTERFACE',
'name' => 'locations',
'args' =>
array (
),
'type' =>
array (
'kind' => 'NON_NULL',
'name' => NULL,
'ofType' =>
array (
'kind' => 'LIST',
'name' => NULL,
'ofType' =>
array (
'kind' => 'NON_NULL',
'name' => NULL,
'ofType' =>
array (
'kind' => 'ENUM',
'name' => '__DirectiveLocation',
),
),
),
),
'isDeprecated' => false,
'deprecationReason' => NULL,
),
3 =>
array (
'name' => 'UNION',
'name' => 'args',
'args' =>
array (
),
'type' =>
array (
'kind' => 'NON_NULL',
'name' => NULL,
'ofType' =>
array (
'kind' => 'LIST',
'name' => NULL,
'ofType' =>
array (
'kind' => 'NON_NULL',
'name' => NULL,
'ofType' =>
array (
'kind' => 'OBJECT',
'name' => '__InputValue',
),
),
),
),
'isDeprecated' => false,
'deprecationReason' => NULL,
),
4 =>
array (
'name' => 'ENUM',
'isDeprecated' => false,
'deprecationReason' => NULL,
'name' => 'onOperation',
'args' =>
array (
),
'type' =>
array (
'kind' => 'NON_NULL',
'name' => NULL,
'ofType' =>
array (
'kind' => 'SCALAR',
'name' => 'Boolean',
),
),
'isDeprecated' => true,
'deprecationReason' => 'Use `locations`.',
),
5 =>
array (
'name' => 'INPUT_OBJECT',
'isDeprecated' => false,
'deprecationReason' => NULL,
'name' => 'onFragment',
'args' =>
array (
),
'type' =>
array (
'kind' => 'NON_NULL',
'name' => NULL,
'ofType' =>
array (
'kind' => 'SCALAR',
'name' => 'Boolean',
),
),
'isDeprecated' => true,
'deprecationReason' => 'Use `locations`.',
),
6 =>
array (
'name' => 'LIST',
'isDeprecated' => false,
'deprecationReason' => NULL,
),
7 =>
array (
'name' => 'NON_NULL',
'isDeprecated' => false,
'deprecationReason' => NULL,
'name' => 'onField',
'args' =>
array (
),
'type' =>
array (
'kind' => 'NON_NULL',
'name' => NULL,
'ofType' =>
array (
'kind' => 'SCALAR',
'name' => 'Boolean',
),
),
'isDeprecated' => true,
'deprecationReason' => 'Use `locations`.',
),
),
'possibleTypes' => NULL,
),
array (
'kind' => 'SCALAR',
'name' => 'Boolean',
'fields' => NULL,
'inputFields' => NULL,
'interfaces' => NULL,
'interfaces' =>
array (
),
'enumValues' => NULL,
'possibleTypes' => NULL,
),
@ -757,165 +887,62 @@ class IntrospectionTest extends \PHPUnit_Framework_TestCase
'possibleTypes' => NULL,
),
array (
'kind' => 'OBJECT',
'name' => '__Directive',
'fields' =>
'kind' => 'ENUM',
'name' => '__TypeKind',
'fields' => NULL,
'inputFields' => NULL,
'interfaces' => NULL,
'enumValues' =>
array (
0 =>
array (
'name' => 'name',
'args' =>
array (
),
'type' =>
array (
'kind' => 'NON_NULL',
'name' => NULL,
'ofType' =>
array (
'kind' => 'SCALAR',
'name' => 'String',
),
),
'name' => 'SCALAR',
'isDeprecated' => false,
'deprecationReason' => NULL,
),
1 =>
array (
'name' => 'description',
'args' =>
array (
),
'type' =>
array (
'kind' => 'SCALAR',
'name' => 'String',
),
'name' => 'OBJECT',
'isDeprecated' => false,
'deprecationReason' => NULL,
),
2 =>
array (
'name' => 'locations',
'args' =>
array (
),
'type' =>
array (
'kind' => 'NON_NULL',
'name' => NULL,
'ofType' =>
array (
'kind' => 'LIST',
'name' => NULL,
'ofType' =>
array (
'kind' => 'NON_NULL',
'name' => NULL,
'ofType' =>
array (
'kind' => 'ENUM',
'name' => '__DirectiveLocation',
),
),
),
),
'name' => 'INTERFACE',
'isDeprecated' => false,
'deprecationReason' => NULL,
),
3 =>
array (
'name' => 'args',
'args' =>
array (
),
'type' =>
array (
'kind' => 'NON_NULL',
'name' => NULL,
'ofType' =>
array (
'kind' => 'LIST',
'name' => NULL,
'ofType' =>
array (
'kind' => 'NON_NULL',
'name' => NULL,
'ofType' =>
array (
'kind' => 'OBJECT',
'name' => '__InputValue',
),
),
),
),
'name' => 'UNION',
'isDeprecated' => false,
'deprecationReason' => NULL,
),
4 =>
array (
'name' => 'onOperation',
'args' =>
array (
),
'type' =>
array (
'kind' => 'NON_NULL',
'name' => NULL,
'ofType' =>
array (
'kind' => 'SCALAR',
'name' => 'Boolean',
),
),
'isDeprecated' => true,
'deprecationReason' => 'Use `locations`.',
'name' => 'ENUM',
'isDeprecated' => false,
'deprecationReason' => NULL,
),
5 =>
array (
'name' => 'onFragment',
'args' =>
array (
),
'type' =>
array (
'kind' => 'NON_NULL',
'name' => NULL,
'ofType' =>
array (
'kind' => 'SCALAR',
'name' => 'Boolean',
),
),
'isDeprecated' => true,
'deprecationReason' => 'Use `locations`.',
'name' => 'INPUT_OBJECT',
'isDeprecated' => false,
'deprecationReason' => NULL,
),
6 =>
array (
'name' => 'onField',
'args' =>
array (
),
'type' =>
array (
'kind' => 'NON_NULL',
'name' => NULL,
'ofType' =>
array (
'kind' => 'SCALAR',
'name' => 'Boolean',
),
),
'isDeprecated' => true,
'deprecationReason' => 'Use `locations`.',
'name' => 'LIST',
'isDeprecated' => false,
'deprecationReason' => NULL,
),
7 =>
array (
'name' => 'NON_NULL',
'isDeprecated' => false,
'deprecationReason' => NULL,
),
),
'inputFields' => NULL,
'interfaces' =>
array (
),
'enumValues' => NULL,
'possibleTypes' => NULL,
),
array (
@ -971,33 +998,6 @@ class IntrospectionTest extends \PHPUnit_Framework_TestCase
),
'possibleTypes' => NULL,
),
array (
'kind' => 'SCALAR',
'name' => 'ID',
'fields' => NULL,
'inputFields' => NULL,
'interfaces' => NULL,
'enumValues' => NULL,
'possibleTypes' => NULL,
),
array (
'kind' => 'SCALAR',
'name' => 'Float',
'fields' => NULL,
'inputFields' => NULL,
'interfaces' => NULL,
'enumValues' => NULL,
'possibleTypes' => NULL,
),
array (
'kind' => 'SCALAR',
'name' => 'Int',
'fields' => NULL,
'inputFields' => NULL,
'interfaces' => NULL,
'enumValues' => NULL,
'possibleTypes' => NULL,
)
),
'directives' =>
array (

View File

@ -230,7 +230,7 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
}
/**
* @it TODO: accepts a Schema whose query and mutation types are object types
* @it accepts a Schema whose query and mutation types are object types
*/
public function testAcceptsASchemaWhoseQueryAndMutationTypesAreObjectTypes()
{
@ -357,13 +357,11 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
]
]);
$schema = new Schema(['query' => $QueryType]);
$this->setExpectedException(
InvariantViolation::class,
'Schema must contain unique named types but contains multiple types named "String".'
);
$schema->assertValid();
new Schema(['query' => $QueryType]);
}
/**
@ -389,14 +387,12 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
]
]);
$schema = new Schema([ 'query' => $QueryType ]);
$this->setExpectedException(
InvariantViolation::class,
'Schema must contain unique named types but contains multiple types named "SameName".'
);
$schema->assertValid();
new Schema([ 'query' => $QueryType ]);
}
/**
@ -429,17 +425,15 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
]
]);
$schema = new Schema([
'query' => $QueryType,
'types' => [ $FirstBadObject, $SecondBadObject ]
]);
$this->setExpectedException(
InvariantViolation::class,
'Schema must contain unique named types but contains multiple types named "BadObject".'
);
$schema->assertValid();
new Schema([
'query' => $QueryType,
'types' => [ $FirstBadObject, $SecondBadObject ]
]);
}
@ -498,17 +492,16 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
*/
public function testRejectsAnObjectTypeFieldWithUndefinedConfig()
{
$schema = $this->schemaWithFieldType(new ObjectType([
$this->setExpectedException(
InvariantViolation::class,
'SomeObject.f field config must be an array, but got'
);
$this->schemaWithFieldType(new ObjectType([
'name' => 'SomeObject',
'fields' => [
'f' => null
]
]));
$this->setExpectedException(
InvariantViolation::class,
'SomeObject.f field config must be an array, but got'
);
$schema->assertValid();
}
/**
@ -609,16 +602,14 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
*/
public function testRejectsAnObjectTypeWithAFieldFunctionThatReturnsNothing()
{
$schema = $this->schemaWithFieldType(new ObjectType([
'name' => 'SomeObject',
'fields' => function() {}
]));
$this->setExpectedException(
InvariantViolation::class,
'SomeObject fields must be an array or a callable which returns such an array.'
);
$schema->assertValid();
$this->schemaWithFieldType(new ObjectType([
'name' => 'SomeObject',
'fields' => function() {}
]));
}
/**
@ -782,17 +773,15 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
*/
public function testRejectsAnObjectTypeWithIncorrectlyTypedInterfaces()
{
$this->setExpectedException(
InvariantViolation::class,
'SomeObject interfaces must be an Array or a callable which returns an Array.'
);
$schema = $this->schemaWithFieldType(new ObjectType([
'name' => 'SomeObject',
'interfaces' => new \stdClass(),
'fields' => ['f' => ['type' => Type::string()]]
]));
$this->setExpectedException(
InvariantViolation::class,
'SomeObject interfaces must be an Array or a callable which returns an Array.'
);
$schema->assertValid();
}
@ -837,20 +826,17 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
*/
public function testRejectsAnObjectTypeWithInterfacesAsAFunctionReturningAnIncorrectType()
{
$schema = $this->schemaWithFieldType(new ObjectType([
$this->setExpectedException(
InvariantViolation::class,
'SomeObject interfaces must be an Array or a callable which returns an Array.'
);
$this->schemaWithFieldType(new ObjectType([
'name' => 'SomeObject',
'interfaces' => function () {
return new \stdClass();
},
'fields' => ['f' => ['type' => Type::string()]]
]));
$this->setExpectedException(
InvariantViolation::class,
'SomeObject interfaces must be an Array or a callable which returns an Array.'
);
$schema->assertValid();
}
// DESCRIBE: Type System: Union types must be array
@ -892,17 +878,14 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
*/
public function testRejectsAUnionTypeWithoutTypes()
{
$schema = $this->schemaWithFieldType(new UnionType([
'name' => 'SomeUnion',
'resolveType' => function() {return null;}
]));
$this->setExpectedException(
InvariantViolation::class,
'SomeUnion types must be an Array or a callable which returns an Array.'
);
$schema->assertValid();
$this->schemaWithFieldType(new UnionType([
'name' => 'SomeUnion',
'resolveType' => function() {return null;}
]));
}
/**
@ -929,18 +912,16 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
*/
public function testRejectsAUnionTypeWithIncorrectlyTypedTypes()
{
$schema = $this->schemaWithFieldType(new UnionType([
$this->setExpectedException(
InvariantViolation::class,
'SomeUnion types must be an Array or a callable which returns an Array.'
);
$this->schemaWithFieldType(new UnionType([
'name' => 'SomeUnion',
'resolveType' => function () {
},
'types' => $this->SomeObjectType
]));
$this->setExpectedException(
InvariantViolation::class,
'SomeUnion types must be an Array or a callable which returns an Array.'
);
$schema->assertValid();
}
/**
@ -1038,16 +1019,14 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
*/
public function testRejectsAnInputObjectTypeWithEmptyFields()
{
$schema = $this->schemaWithInputObject(new InputObjectType([
'name' => 'SomeInputObject',
'fields' => new \stdClass()
]));
$this->setExpectedException(
InvariantViolation::class,
'SomeInputObject fields must be an array or a callable which returns such an array.'
);
$schema->assertValid();
$this->schemaWithInputObject(new InputObjectType([
'name' => 'SomeInputObject',
'fields' => new \stdClass()
]));
}
/**
@ -1055,18 +1034,15 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
*/
public function testRejectsAnInputObjectTypeWithAFieldFunctionThatReturnsNothing()
{
$schema = $this->schemaWithInputObject(new ObjectType([
'name' => 'SomeInputObject',
'fields' => function () {
}
]));
$this->setExpectedException(
InvariantViolation::class,
'SomeInputObject fields must be an array or a callable which returns such an array.'
);
$schema->assertValid();
$this->schemaWithInputObject(new ObjectType([
'name' => 'SomeInputObject',
'fields' => function () {
}
]));
}
/**
@ -1074,19 +1050,16 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
*/
public function testRejectsAnInputObjectTypeWithAFieldFunctionThatReturnsEmpty()
{
$schema = $this->schemaWithInputObject(new InputObjectType([
$this->setExpectedException(
InvariantViolation::class,
'SomeInputObject fields must be an array or a callable which returns such an array.'
);
$this->schemaWithInputObject(new InputObjectType([
'name' => 'SomeInputObject',
'fields' => function () {
return new \stdClass();
}
]));
$this->setExpectedException(
InvariantViolation::class,
'SomeInputObject fields must be an array or a callable which returns such an array.'
);
$schema->assertValid();
}
// DESCRIBE: Type System: Input Object fields must not have resolvers
@ -1222,12 +1195,11 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
'fields' => ['f' => ['type' => Type::string()]]
]);
$schema = $this->schemaWithFieldType(new ObjectType([
$this->schemaWithFieldType(new ObjectType([
'name' => 'SomeObject',
'interfaces' => [$AnotherInterfaceType],
'fields' => ['f' => ['type' => Type::string()]]
]));
$schema->assertValid();
}
/**
@ -1322,7 +1294,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
}
// DESCRIBE: Type System: Union types must be resolvable
// TODO: accepts a Union type defining resolveType
/**
* @it accepts a Union type defining resolveType