graphql-php/tests/StarWarsSchema.php

297 lines
10 KiB
PHP
Raw Normal View History

2015-07-15 20:05:46 +03:00
<?php
2016-04-09 10:36:53 +03:00
namespace GraphQL\Tests;
2015-07-15 20:05:46 +03:00
/**
* This is designed to be an end-to-end test, demonstrating
* the full GraphQL stack.
*
* We will create a GraphQL schema that describes the major
* characters in the original Star Wars trilogy.
*
* NOTE: This may contain spoilers for the original Star
* Wars trilogy.
*/
2016-04-09 10:36:53 +03:00
use GraphQL\Schema;
2015-07-15 20:05:46 +03:00
use GraphQL\Type\Definition\EnumType;
use GraphQL\Type\Definition\InterfaceType;
use GraphQL\Type\Definition\NonNull;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\ResolveInfo;
2015-07-15 20:05:46 +03:00
use GraphQL\Type\Definition\Type;
/**
* Using our shorthand to describe type systems, the type system for our
* Star Wars example is:
*
* enum Episode { NEWHOPE, EMPIRE, JEDI }
*
* interface Character {
* id: String!
* name: String
* friends: [Character]
* appearsIn: [Episode]
* }
*
* type Human : Character {
* id: String!
* name: String
* friends: [Character]
* appearsIn: [Episode]
* homePlanet: String
* }
*
* type Droid : Character {
* id: String!
* name: String
* friends: [Character]
* appearsIn: [Episode]
* primaryFunction: String
* }
*
* type Query {
2015-08-16 13:17:35 +03:00
* hero(episode: Episode): Character
2015-07-15 20:05:46 +03:00
* human(id: String!): Human
* droid(id: String!): Droid
* }
*
* We begin by setting up our schema.
*/
class StarWarsSchema
{
public static function build()
{
/**
* The original trilogy consists of three movies.
*
* This implements the following type system shorthand:
* enum Episode { NEWHOPE, EMPIRE, JEDI }
*/
$episodeEnum = new EnumType([
'name' => 'Episode',
'description' => 'One of the films in the Star Wars Trilogy',
'values' => [
'NEWHOPE' => [
'value' => 4,
'description' => 'Released in 1977.'
],
'EMPIRE' => [
'value' => 5,
'description' => 'Released in 1980.'
],
'JEDI' => [
'value' => 6,
'description' => 'Released in 1983.'
],
]
]);
$humanType = null;
$droidType = null;
/**
* Characters in the Star Wars trilogy are either humans or droids.
*
* This implements the following type system shorthand:
* interface Character {
* id: String!
* name: String
* friends: [Character]
* appearsIn: [Episode]
* }
*/
$characterInterface = new InterfaceType([
'name' => 'Character',
'description' => 'A character in the Star Wars Trilogy',
'fields' => [
'id' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The id of the character.',
],
'name' => [
'type' => Type::string(),
'description' => 'The name of the character.'
],
'friends' => [
'type' => function () use (&$characterInterface) {
return Type::listOf($characterInterface);
},
'description' => 'The friends of the character, or an empty list if they have none.',
],
'appearsIn' => [
'type' => Type::listOf($episodeEnum),
'description' => 'Which movies they appear in.'
]
],
'resolveType' => function ($obj) use (&$humanType, &$droidType) {
$humans = StarWarsData::humans();
$droids = StarWarsData::droids();
if (isset($humans[$obj['id']])) {
return $humanType;
}
if (isset($droids[$obj['id']])) {
return $droidType;
}
return null;
},
]);
/**
* We define our human type, which implements the character interface.
*
* This implements the following type system shorthand:
* type Human : Character {
* id: String!
* name: String
* friends: [Character]
* appearsIn: [Episode]
* }
*/
$humanType = new ObjectType([
'name' => 'Human',
'description' => 'A humanoid creature in the Star Wars universe.',
'fields' => [
'id' => [
'type' => new NonNull(Type::string()),
'description' => 'The id of the human.',
],
'name' => [
'type' => Type::string(),
'description' => 'The name of the human.',
],
'friends' => [
'type' => Type::listOf($characterInterface),
'description' => 'The friends of the human, or an empty list if they have none.',
'resolve' => function ($human, $args, ResolveInfo $info) {
$fieldSelection = $info->getFieldSelection();
$fieldSelection['id'] = true;
$friends = array_map(
function($friend) use ($fieldSelection) {
return array_intersect_key($friend, $fieldSelection);
},
StarWarsData::getFriends($human)
);
return $friends;
2015-07-15 20:05:46 +03:00
},
],
'appearsIn' => [
'type' => Type::listOf($episodeEnum),
'description' => 'Which movies they appear in.'
],
'homePlanet' => [
'type' => Type::string(),
'description' => 'The home planet of the human, or null if unknown.'
],
],
'interfaces' => [$characterInterface]
]);
/**
* The other type of character in Star Wars is a droid.
*
* This implements the following type system shorthand:
* type Droid : Character {
* id: String!
* name: String
* friends: [Character]
* appearsIn: [Episode]
* primaryFunction: String
* }
*/
$droidType = new ObjectType([
'name' => 'Droid',
'description' => 'A mechanical creature in the Star Wars universe.',
'fields' => [
'id' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The id of the droid.',
],
'name' => [
'type' => Type::string(),
'description' => 'The name of the droid.'
],
'friends' => [
'type' => Type::listOf($characterInterface),
'description' => 'The friends of the droid, or an empty list if they have none.',
'resolve' => function ($droid) {
return StarWarsData::getFriends($droid);
},
],
'appearsIn' => [
'type' => Type::listOf($episodeEnum),
'description' => 'Which movies they appear in.'
],
'primaryFunction' => [
'type' => Type::string(),
'description' => 'The primary function of the droid.'
]
],
'interfaces' => [$characterInterface]
]);
/**
* This is the type that will be the root of our query, and the
* entry point into our schema. It gives us the ability to fetch
* objects by their IDs, as well as to fetch the undisputed hero
* of the Star Wars trilogy, R2-D2, directly.
*
* This implements the following type system shorthand:
* type Query {
2015-08-16 13:17:35 +03:00
* hero(episode: Episode): Character
2015-07-15 20:05:46 +03:00
* human(id: String!): Human
* droid(id: String!): Droid
* }
*
*/
$queryType = new ObjectType([
'name' => 'Query',
'fields' => [
'hero' => [
'type' => $characterInterface,
2015-08-16 13:17:35 +03:00
'args' => [
'episode' => [
'description' => 'If omitted, returns the hero of the whole saga. If provided, returns the hero of that particular episode.',
'type' => $episodeEnum
]
],
'resolve' => function ($root, $args) {
return StarWarsData::getHero(isset($args['episode']) ? $args['episode'] : null);
2015-07-15 20:05:46 +03:00
},
],
'human' => [
'type' => $humanType,
2015-08-16 13:17:35 +03:00
'args' => [
'id' => [
'name' => 'id',
'description' => 'id of the human',
'type' => Type::nonNull(Type::string())
]
],
2015-07-15 20:05:46 +03:00
'resolve' => function ($root, $args) {
$humans = StarWarsData::humans();
return isset($humans[$args['id']]) ? $humans[$args['id']] : null;
}
],
'droid' => [
'type' => $droidType,
2015-08-16 13:17:35 +03:00
'args' => [
'id' => [
'name' => 'id',
'description' => 'id of the droid',
'type' => Type::nonNull(Type::string())
]
],
2015-07-15 20:05:46 +03:00
'resolve' => function ($root, $args) {
$droids = StarWarsData::droids();
return isset($droids[$args['id']]) ? $droids[$args['id']] : null;
}
]
]
]);
return new Schema($queryType);
}
}