Example #1
0
 protected function setUp()
 {
     $namedType = new InterfaceType('Named', ['name' => ['type' => Type::stringType()]]);
     $dogType = new ObjectType('Dog', ['name' => ['type' => Type::stringType()], 'barks' => ['type' => Type::booleanType()]], [$namedType], function ($value) {
         return $value instanceof Dog;
     });
     $catType = new ObjectType('Cat', ['name' => ['type' => Type::stringType()], 'meows' => ['type' => Type::booleanType()]], [$namedType], function ($value) {
         return $value instanceof Cat;
     });
     $petType = new UnionType('Pet', [$dogType, $catType], function ($value) use($dogType, $catType) {
         if ($value instanceof Dog) {
             return $dogType;
         }
         if ($value instanceof Cat) {
             return $catType;
         }
         return NULL;
     });
     $personType = new ObjectType('Person', ['name' => ['type' => Type::stringType()], 'pets' => ['type' => new ListModifier($petType)], 'friends' => ['type' => new ListModifier($namedType)]], [$namedType], function ($value) {
         return $value instanceof Person;
     });
     $this->schema = new Schema($personType);
     $this->garfield = new Cat('Garfield', FALSE);
     $this->odie = new Dog('Odie', TRUE);
     $this->liz = new Person('Liz');
     $this->john = new Person('John', [$this->garfield, $this->odie], [$this->liz, $this->odie]);
 }
Example #2
0
 /**
  * {@inheritdoc}
  */
 public function getType()
 {
     if (!isset($this->type)) {
         $this->type = new NonNullModifier(Type::booleanType());
     }
     return $this->type;
 }
Example #3
0
 protected function setUp()
 {
     $this->syncError = new \Exception('sync');
     $this->nonNullSyncError = new \Exception('nonNullSync');
     $this->throwingData = ['sync' => function () {
         throw $this->syncError;
     }, 'nonNullSync' => function () {
         throw $this->nonNullSyncError;
     }, 'nest' => function () {
         return $this->throwingData;
     }, 'nonNullNest' => function () {
         return $this->throwingData;
     }];
     $this->NULLingData = ['sync' => function () {
         return NULL;
     }, 'nonNullSync' => function () {
         return NULL;
     }, 'nest' => function () {
         return $this->NULLingData;
     }, 'nonNullNest' => function () {
         return $this->NULLingData;
     }];
     $dataType = new ObjectType('DataType', ['sync' => ['type' => Type::stringType()], 'nonNullSync' => ['type' => new NonNullModifier(Type::stringType())], 'nest' => ['type' => function () use(&$dataType) {
         return $dataType;
     }], 'nonNullNest' => ['type' => function () use(&$dataType) {
         return new NonNullModifier($dataType);
     }]]);
     $this->schema = new Schema($dataType);
 }
Example #4
0
 /**
  * Constructor.
  *
  * @param string $name
  * @param array $fields
  * @param \Fubhy\GraphQL\Type\Definition\Types\InterfaceType[] $interfaces
  * @param callable|null $isTypeOf
  * @param string|null $description
  */
 public function __construct($name, array $fields = [], array $interfaces = [], callable $isTypeOf = NULL, $description = NULL)
 {
     parent::__construct($name, $description);
     $this->fields = $fields;
     $this->interfaces = $interfaces;
     $this->isTypeOf = $isTypeOf;
     foreach ($this->interfaces as $interface) {
         $interface->addPossibleType($this);
     }
 }
Example #5
0
    public function testExecutesUsingASchema()
    {
        $blogArticle = NULL;
        $blogImage = new ObjectType('Image', ['url' => ['type' => Type::stringType()], 'width' => ['type' => Type::intType()], 'height' => ['type' => Type::intType()]]);
        $blogAuthor = new ObjectType('Author', ['id' => ['type' => Type::stringType()], 'name' => ['type' => Type::stringType()], 'pic' => ['args' => ['width' => ['type' => Type::intType()], 'height' => ['type' => Type::intType()]], 'type' => $blogImage, 'resolve' => function ($obj, $args) {
            return $obj['pic']($args['width'], $args['height']);
        }], 'recentArticle' => ['type' => function () use(&$blogArticle) {
            return $blogArticle;
        }]]);
        $blogArticle = new ObjectType('Article', ['id' => ['type' => new NonNullModifier(Type::stringType())], 'isPublished' => ['type' => Type::booleanType()], 'author' => ['type' => $blogAuthor], 'title' => ['type' => Type::stringType()], 'body' => ['type' => Type::stringType()], 'keywords' => ['type' => new ListModifier(Type::stringType())]]);
        $blogQuery = new ObjectType('Query', ['article' => ['type' => $blogArticle, 'args' => ['id' => ['type' => Type::idType()]], 'resolve' => function ($_, $args) {
            return $this->article($args['id']);
        }], 'feed' => ['type' => new ListModifier($blogArticle), 'resolve' => function () {
            return [$this->article(1), $this->article(2), $this->article(3), $this->article(4), $this->article(5), $this->article(6), $this->article(7), $this->article(8), $this->article(9), $this->article(10)];
        }]]);
        $blogSchema = new Schema($blogQuery);
        $request = '
            {
                feed {
                    id,
                    title
                },
                article(id: "1") {
                    ...articleFields,
                    author {
                        id,
                        name,
                        pic(width: 640, height: 480) {
                            url,
                            width,
                            height
                        },
                        recentArticle {
                            ...articleFields,
                            keywords
                        }
                    }
                }
            }

            fragment articleFields on Article {
                id,
                isPublished,
                title,
                body,
                hidden,
                notdefined
            }
        ';
        $expected = ['data' => ['feed' => [['id' => '1', 'title' => 'My Article 1'], ['id' => '2', 'title' => 'My Article 2'], ['id' => '3', 'title' => 'My Article 3'], ['id' => '4', 'title' => 'My Article 4'], ['id' => '5', 'title' => 'My Article 5'], ['id' => '6', 'title' => 'My Article 6'], ['id' => '7', 'title' => 'My Article 7'], ['id' => '8', 'title' => 'My Article 8'], ['id' => '9', 'title' => 'My Article 9'], ['id' => '10', 'title' => 'My Article 10']], 'article' => ['id' => '1', 'isPublished' => TRUE, 'title' => 'My Article 1', 'body' => 'This is a post', 'author' => ['id' => '123', 'name' => 'John Smith', 'pic' => ['url' => 'cdn://123', 'width' => 640, 'height' => 480], 'recentArticle' => ['id' => '1', 'isPublished' => TRUE, 'title' => 'My Article 1', 'body' => 'This is a post', 'keywords' => ['foo', 'bar', '1', 'true', NULL]]]]]];
        $parser = new Parser();
        $this->assertEquals($expected, Executor::execute($blogSchema, NULL, $parser->parse(new Source($request)), '', []));
    }
Example #6
0
 /**
  * Not exactly the same as the executor's definition of getFieldDef, in this
  * statically evaluated environment we do not always have an Object type,
  * and need to handle Interface and Union types.
  *
  * @param Schema $schema
  * @param Type $parentType
  * @param Field $fieldAST
  *
  * @return FieldDefinition
  */
 protected static function getFieldDefinition(Schema $schema, Type $parentType, Field $fieldAST)
 {
     $name = $fieldAST->get('name')->get('value');
     $schemaMeta = Introspection::schemaMetaFieldDefinition();
     if ($name === $schemaMeta->getName() && $schema->getQueryType() === $parentType) {
         return $schemaMeta;
     }
     $typeMeta = Introspection::typeMetaFieldDefinition();
     if ($name === $typeMeta->getName() && $schema->getQueryType() === $parentType) {
         return $typeMeta;
     }
     $typeNameMeta = Introspection::typeNameMetaFieldDefinition();
     if ($name === $typeNameMeta->getName() && ($parentType instanceof ObjectType || $parentType instanceof InterfaceType || $parentType instanceof UnionType)) {
         return $typeNameMeta;
     }
     if ($parentType instanceof ObjectType || $parentType instanceof InterfaceType) {
         $fields = $parentType->getFields();
         return isset($fields[$name]) ? $fields[$name] : NULL;
     }
     return NULL;
 }
Example #7
0
 /**
  * @dataProvider coercesOutputBooleanProvider
  *
  * @param mixed $input
  * @param float|null $expected
  */
 public function testCoercesOutputBoolean($input, $expected)
 {
     $this->assertSame($expected, Type::booleanType()->coerce($input));
 }
Example #8
0
 public function prohibitsPuttingNonObjcetTypesInUnionsProvider()
 {
     return [[Type::intType()], [new NonNullModifier(Type::intType())], [new ListModifier(Type::intType())], [new InterfaceType('Interface')], [new UnionType('Union')], [new EnumType('Enum')], [new InputObjectType('InputObject')]];
 }
Example #9
0
 public function testRespectsTheIncludeDeprecatedParameterForFields()
 {
     $testType = new ObjectType('TestType', ['nonDeprecated' => ['type' => Type::stringType()], 'deprecated' => ['type' => Type::stringType(), 'deprecationReason' => 'Removed in 1.0']]);
     $schema = new Schema($testType);
     $request = '
         {
             __type(name: "TestType") {
                 name
                 trueFields: fields(includeDeprecated: true) {
                     name
                 }
                 falseFields: fields(includeDeprecated: false) {
                     name
                 }
                 omittedFields: fields {
                     name
                 }
             }
         }
     ';
     $expected = ['data' => ['__type' => ['name' => 'TestType', 'trueFields' => [['name' => 'nonDeprecated'], ['name' => 'deprecated']], 'falseFields' => [['name' => 'nonDeprecated']], 'omittedFields' => [['name' => 'nonDeprecated']]]]];
     $this->assertEquals($expected, GraphQL::execute($schema, $request));
 }
Example #10
0
 protected function getSchema()
 {
     $testInputObject = new InputObjectType('TestInputObject', ['a' => ['type' => Type::stringType()], 'b' => ['type' => new ListModifier(Type::stringType())], 'c' => ['type' => new NonNullModifier(Type::stringType())]]);
     $testType = new ObjectType('TestType', ['fieldWithObjectInput' => ['type' => Type::stringType(), 'args' => ['input' => ['type' => $testInputObject]], 'resolve' => function ($_, $args) {
         return json_encode($args['input']);
     }], 'fieldWithNullableStringInput' => ['type' => Type::stringType(), 'args' => ['input' => ['type' => Type::stringType()]], 'resolve' => function ($_, $args) {
         return json_encode($args['input']);
     }], 'fieldWithNonNullableStringInput' => ['type' => Type::stringType(), 'args' => ['input' => ['type' => new NonNullModifier(Type::stringType())]], 'resolve' => function ($_, $args) {
         return json_encode($args['input']);
     }], 'list' => ['type' => Type::stringType(), 'args' => ['input' => ['type' => new ListModifier(Type::stringType())]], 'resolve' => function ($_, $args) {
         return json_encode($args['input']);
     }], 'nnList' => ['type' => Type::stringType(), 'args' => ['input' => ['type' => new NonNullModifier(new ListModifier(Type::stringType()))]], 'resolve' => function ($_, $args) {
         return json_encode($args['input']);
     }], 'listNN' => ['type' => Type::stringType(), 'args' => ['input' => ['type' => new ListModifier(new NonNullModifier(Type::stringType()))]], 'resolve' => function ($_, $args) {
         return json_encode($args['input']);
     }], 'nnListNN' => ['type' => Type::stringType(), 'args' => ['input' => ['type' => new NonNullModifier(new ListModifier(new NonNullModifier(Type::stringType())))]], 'resolve' => function ($_, $args) {
         return json_encode($args['input']);
     }]]);
     $schema = new Schema($testType);
     return $schema;
 }
Example #11
0
 protected function executeTestQuery($document)
 {
     $data = ['a' => function () {
         return 'a';
     }, 'b' => function () {
         return 'b';
     }];
     $schema = new Schema(new ObjectType('TestType', ['a' => ['type' => Type::stringType()], 'b' => ['type' => Type::stringType()]]));
     $parser = new Parser();
     return Executor::execute($schema, $data, $parser->parse(new Source($document)));
 }
Example #12
0
 /**
  * @return \Fubhy\GraphQL\Type\Definition\FieldDefinition
  */
 public static function typeNameMetaFieldDefinition()
 {
     if (!isset(static::$typeNameMetaFieldDefinition)) {
         static::$typeNameMetaFieldDefinition = new FieldDefinition(['name' => '__typename', 'type' => new NonNullModifier(Type::stringType()), 'description' => 'The name of the current Object type at runtime.', 'args' => [], 'resolve' => [__CLASS__, 'resolveTypeNameMetaField']]);
     }
     return static::$typeNameMetaFieldDefinition;
 }
Example #13
0
 /**
  * Constructor.
  *
  * @param string $name
  * @param array $fields
  * @param string|null $description
  */
 public function __construct($name, array $fields = [], $description = NULL)
 {
     parent::__construct($name, $description);
     $this->fields = $fields;
 }
Example #14
0
 protected function getSchema()
 {
     $dataType = new ObjectType('DataType', ['list' => ['type' => new ListModifier(Type::intType())], 'listOfNonNull' => ['type' => new ListModifier(new NonNullModifier(Type::intType()))], 'nonNullList' => ['type' => new NonNullModifier(new ListModifier(Type::intType()))], 'nonNullListOfNonNull' => ['type' => new NonNullModifier(new ListModifier(new NonNullModifier(Type::intType())))], 'listContainsNull' => ['type' => new ListModifier(Type::intType())], 'listOfNonNullContainsNull' => ['type' => new ListModifier(new NonNullModifier(Type::intType()))], 'nonNullListContainsNull' => ['type' => new NonNullModifier(new ListModifier(Type::intType()))], 'nonNullListOfNonNullContainsNull' => ['type' => new NonNullModifier(new ListModifier(new NonNullModifier(Type::intType())))], 'listReturnsNull' => ['type' => new ListModifier(Type::intType())], 'listOfNonNullReturnsNull' => ['type' => new ListModifier(new NonNullModifier(Type::intType()))], 'nonNullListReturnsNull' => ['type' => new NonNullModifier(new ListModifier(Type::intType()))], 'nonNullListOfNonNullReturnsNull' => ['type' => new NonNullModifier(new ListModifier(new NonNullModifier(Type::intType())))], 'nest' => ['type' => function () use(&$dataType) {
         return $dataType;
     }]]);
     $schema = new Schema($dataType);
     return $schema;
 }
Example #15
0
 protected function getStarWarsSchema()
 {
     /**
      * The original trilogy consists of three movies.
      *
      * This implements the following type system shorthand:
      *   enum Episode { NEWHOPE, EMPIRE, JEDI }
      */
     $episodeEnum = new EnumType('Episode', ['NEWHOPE' => ['value' => 4, 'description' => 'Released in 1977.'], 'EMPIRE' => ['value' => 5, 'description' => 'Released in 1980.'], 'JEDI' => ['value' => 6, 'description' => 'Released in 1983.']], 'One of the films in the Star Wars Trilogy');
     $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('Character', ['id' => ['type' => new NonNullModifier(Type::stringType()), 'description' => 'The id of the character.'], 'name' => ['type' => Type::stringType(), 'description' => 'The name of the character.'], 'friends' => ['type' => function () use(&$characterInterface) {
         return new ListModifier($characterInterface);
     }, 'description' => 'The friends of the character, or an empty list if they have none.'], 'appearsIn' => ['type' => new ListModifier($episodeEnum), 'description' => 'Which movies they appear in.']], function ($obj) use(&$humanType, &$droidType) {
         $humans = $this->getHumans();
         if (isset($humans[$obj['id']])) {
             return $humanType;
         }
         $droids = $this->getDroids();
         if (isset($droids[$obj['id']])) {
             return $droidType;
         }
         return NULL;
     }, 'A character in the Star Wars Trilogy');
     /**
      * 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('Human', ['id' => ['type' => new NonNullModifier(Type::stringType()), 'description' => 'The id of the human.'], 'name' => ['type' => Type::stringType(), 'description' => 'The name of the human.'], 'friends' => ['type' => new ListModifier($characterInterface), 'description' => 'The friends of the human, or an empty list if they have none.', 'resolve' => function ($human) {
         return $this->getStarWarsFriends($human);
     }], 'appearsIn' => ['type' => new ListModifier($episodeEnum), 'description' => 'Which movies they appear in.'], 'homePlanet' => ['type' => Type::stringType(), 'description' => 'The home planet of the human, or null if unknown.']], [$characterInterface], NULL, 'A humanoid creature in the Star Wars universe.');
     /**
      * 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('Droid', ['id' => ['type' => new NonNullModifier(Type::stringType()), 'description' => 'The id of the droid.'], 'name' => ['type' => Type::stringType(), 'description' => 'The name of the droid.'], 'friends' => ['type' => new ListModifier($characterInterface), 'description' => 'The friends of the droid, or an empty list if they have none.', 'resolve' => function ($droid) {
         return $this->getStarWarsFriends($droid);
     }], 'appearsIn' => ['type' => new ListModifier($episodeEnum), 'description' => 'Which movies they appear in.'], 'primaryFunction' => ['type' => Type::stringType(), 'description' => 'The primary function of the droid.']], [$characterInterface], NULL, 'A mechanical creature in the Star Wars universe.');
     /**
      * 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 {
      *     hero: Character
      *     human(id: String!): Human
      *     droid(id: String!): Droid
      *   }
      *
      */
     $queryType = new ObjectType('Query', ['hero' => ['type' => $characterInterface, '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 () {
         return $this->getArtoo();
     }], 'human' => ['type' => $humanType, 'args' => ['id' => ['name' => 'id', 'description' => 'The id of the human.', 'type' => new NonNullModifier(Type::stringType())]], 'resolve' => function ($root, array $args) {
         $humans = $this->getHumans();
         return isset($humans[$args['id']]) ? $humans[$args['id']] : NULL;
     }], 'droid' => ['type' => $droidType, 'args' => ['id' => ['name' => 'id', 'description' => 'The id of the droid.', 'type' => new NonNullModifier(Type::stringType())]], 'resolve' => function ($root, array $args) {
         $droids = $this->getDroids();
         return isset($droids[$args['id']]) ? $droids[$args['id']] : NULL;
     }]]);
     return new Schema($queryType);
 }
Example #16
0
 /**
  * Constructor.
  *
  * @param string $name
  * @param array $values
  * @param string|null $description
  */
 public function __construct($name, array $values = [], $description = NULL)
 {
     parent::__construct($name, $description);
     $this->values = $values;
 }
Example #17
0
 /**
  * Re-populate static properties when de-serializing.
  */
 public function __wakeup()
 {
     Type::intType();
     Type::booleanType();
     Type::floatType();
     Type::idType();
     Type::stringType();
 }
Example #18
0
 public function testDoesNotIncludeIllegalFieldsInOutput()
 {
     $document = '
         mutation M {
             thisIsIllegalDontIncludeMe
         }
     ';
     $parser = new Parser();
     $ast = $parser->parse(new Source($document));
     $schema = new Schema(new ObjectType('Q', ['a' => ['type' => Type::stringType()]]), new ObjectType('M', ['c' => ['type' => Type::stringType()]]));
     $result = Executor::execute($schema, NULL, $ast);
     $this->assertEquals(['data' => []], $result);
 }