├── .gitignore
├── .scrutinizer.yml
├── .travis.yml
├── CHANGELOG.md
├── LICENSE
├── README.md
├── composer.json
├── examples
├── 01_sandbox
│ └── index.php
├── 02_blog
│ ├── Schema
│ │ ├── BannerType.php
│ │ ├── BlogSchema.php
│ │ ├── ContentBlockInterface.php
│ │ ├── ContentBlockUnion.php
│ │ ├── DataProvider.php
│ │ ├── LatestPostField.php
│ │ ├── LikePostField.php
│ │ ├── PostInputType.php
│ │ ├── PostStatus.php
│ │ └── PostType.php
│ ├── index.php
│ ├── router.php
│ ├── schema-bootstrap.php
│ └── server.sh
├── 02_blog_inline
│ ├── index.php
│ └── inline-schema.php
├── 03_relay_star_wars
│ ├── Schema
│ │ ├── FactionType.php
│ │ ├── ShipType.php
│ │ ├── StarWarsRelaySchema.php
│ │ └── TestDataProvider.php
│ ├── index.php
│ ├── router.php
│ ├── schema-bootstrap.php
│ └── server.sh
├── 04_bookstore
│ ├── DataProvider.php
│ ├── Schema
│ │ ├── BookStoreSchema.php
│ │ ├── Field
│ │ │ ├── Book
│ │ │ │ └── RecentBooksField.php
│ │ │ └── CategoriesField.php
│ │ └── Type
│ │ │ ├── AuthorType.php
│ │ │ ├── BookType.php
│ │ │ └── CategoryType.php
│ ├── index.php
│ ├── schema-bootstrap.php
│ └── server.sh
├── GraphiQL
│ ├── cookiejar.js
│ ├── fetch.js
│ ├── fetch.min.js
│ ├── graphiql.css
│ ├── graphiql.js
│ ├── graphiql.min.js
│ ├── index-js.html
│ ├── index.html
│ ├── react-dom.min.js
│ ├── react.min.js
│ └── screenshot.png
├── js-relay
│ ├── .babelrc
│ ├── .gitignore
│ ├── README.md
│ ├── build
│ │ └── babelRelayPlugin.js
│ ├── data
│ │ ├── database.js
│ │ ├── schema.js
│ │ └── schema.json
│ ├── js
│ │ ├── app.js
│ │ ├── components
│ │ │ ├── StarWarsApp.js
│ │ │ └── StarWarsShip.js
│ │ ├── mutation
│ │ │ └── AddShipMutation.js
│ │ └── routes
│ │ │ └── StarWarsAppHomeRoute.js
│ ├── package.json
│ ├── public
│ │ └── index.html
│ ├── scripts
│ │ └── updateSchema.js
│ └── server.js
├── js
│ ├── .babelrc
│ ├── index.js
│ └── package.json
├── structure.sketch
└── structure.xd
├── phpstan.neon
├── phpunit.xml.dist
├── src
├── Config
│ ├── AbstractConfig.php
│ ├── Directive
│ │ └── DirectiveConfig.php
│ ├── Field
│ │ ├── FieldConfig.php
│ │ └── InputFieldConfig.php
│ ├── Object
│ │ ├── EnumTypeConfig.php
│ │ ├── InputObjectTypeConfig.php
│ │ ├── InterfaceTypeConfig.php
│ │ ├── ListTypeConfig.php
│ │ ├── ObjectTypeConfig.php
│ │ └── UnionTypeConfig.php
│ ├── Schema
│ │ └── SchemaConfig.php
│ ├── Traits
│ │ ├── ArgumentsAwareConfigTrait.php
│ │ ├── ConfigAwareTrait.php
│ │ ├── DirectivesAwareConfigTrait.php
│ │ ├── FieldsAwareConfigTrait.php
│ │ └── ResolvableObjectTrait.php
│ └── TypeConfigInterface.php
├── Directive
│ ├── Directive.php
│ ├── DirectiveInterface.php
│ └── DirectiveLocation.php
├── Exception
│ ├── ConfigurationException.php
│ ├── Interfaces
│ │ ├── ExtendedExceptionInterface.php
│ │ └── LocationableExceptionInterface.php
│ ├── Parser
│ │ ├── AbstractParserError.php
│ │ ├── InvalidRequestException.php
│ │ └── SyntaxErrorException.php
│ ├── ResolveException.php
│ └── ValidationException.php
├── Execution
│ ├── Container
│ │ ├── Container.php
│ │ └── ContainerInterface.php
│ ├── Context
│ │ ├── ExecutionContext.php
│ │ └── ExecutionContextInterface.php
│ ├── DeferredResolver.php
│ ├── DeferredResolverInterface.php
│ ├── DeferredResult.php
│ ├── Processor.php
│ ├── Reducer.php
│ ├── Request.php
│ ├── ResolveInfo.php
│ └── Visitor
│ │ ├── AbstractQueryVisitor.php
│ │ └── MaxComplexityQueryVisitor.php
├── Field
│ ├── AbstractField.php
│ ├── AbstractInputField.php
│ ├── Field.php
│ ├── FieldInterface.php
│ ├── InputField.php
│ └── InputFieldInterface.php
├── Introspection
│ ├── DirectiveLocationType.php
│ ├── DirectiveType.php
│ ├── EnumValueType.php
│ ├── Field
│ │ ├── SchemaField.php
│ │ ├── TypeDefinitionField.php
│ │ └── TypesField.php
│ ├── FieldType.php
│ ├── InputValueType.php
│ ├── QueryType.php
│ ├── SchemaType.php
│ └── Traits
│ │ └── TypeCollectorTrait.php
├── Parser
│ ├── Ast
│ │ ├── AbstractAst.php
│ │ ├── Argument.php
│ │ ├── ArgumentValue
│ │ │ ├── InputList.php
│ │ │ ├── InputObject.php
│ │ │ ├── Literal.php
│ │ │ ├── Variable.php
│ │ │ └── VariableReference.php
│ │ ├── AstArgumentsTrait.php
│ │ ├── AstDirectivesTrait.php
│ │ ├── Directive.php
│ │ ├── Field.php
│ │ ├── Fragment.php
│ │ ├── FragmentReference.php
│ │ ├── Interfaces
│ │ │ ├── FieldInterface.php
│ │ │ ├── FragmentInterface.php
│ │ │ ├── LocatableInterface.php
│ │ │ └── ValueInterface.php
│ │ ├── Mutation.php
│ │ ├── Query.php
│ │ └── TypedFragmentReference.php
│ ├── Location.php
│ ├── Parser.php
│ ├── Token.php
│ └── Tokenizer.php
├── Relay
│ ├── Connection
│ │ ├── ArrayConnection.php
│ │ └── Connection.php
│ ├── Fetcher
│ │ ├── CallableFetcher.php
│ │ └── FetcherInterface.php
│ ├── Field
│ │ ├── GlobalIdField.php
│ │ └── NodeField.php
│ ├── Node.php
│ ├── NodeInterfaceType.php
│ ├── RelayMutation.php
│ └── Type
│ │ └── PageInfoType.php
├── Schema
│ ├── AbstractSchema.php
│ ├── InternalSchemaMutationObject.php
│ ├── InternalSchemaQueryObject.php
│ └── Schema.php
├── Type
│ ├── AbstractInterfaceTypeInterface.php
│ ├── AbstractType.php
│ ├── CompositeTypeInterface.php
│ ├── Enum
│ │ ├── AbstractEnumType.php
│ │ └── EnumType.php
│ ├── InputObject
│ │ ├── AbstractInputObjectType.php
│ │ └── InputObjectType.php
│ ├── InputTypeInterface.php
│ ├── InterfaceType
│ │ ├── AbstractInterfaceType.php
│ │ └── InterfaceType.php
│ ├── ListType
│ │ ├── AbstractListType.php
│ │ └── ListType.php
│ ├── NonNullType.php
│ ├── Object
│ │ ├── AbstractMutationObjectType.php
│ │ ├── AbstractObjectType.php
│ │ └── ObjectType.php
│ ├── Scalar
│ │ ├── AbstractScalarType.php
│ │ ├── BooleanType.php
│ │ ├── DateTimeType.php
│ │ ├── DateTimeTzType.php
│ │ ├── DateType.php
│ │ ├── FloatType.php
│ │ ├── IdType.php
│ │ ├── IntType.php
│ │ ├── StringType.php
│ │ └── TimestampType.php
│ ├── SchemaDirectivesList.php
│ ├── SchemaTypesList.php
│ ├── Traits
│ │ ├── ArgumentsAwareObjectTrait.php
│ │ ├── AutoNameTrait.php
│ │ ├── FieldsArgumentsAwareObjectTrait.php
│ │ └── FieldsAwareObjectTrait.php
│ ├── TypeFactory.php
│ ├── TypeInterface.php
│ ├── TypeMap.php
│ ├── TypeService.php
│ └── Union
│ │ ├── AbstractUnionType.php
│ │ └── UnionType.php
└── Validator
│ ├── ConfigValidator
│ ├── ConfigValidator.php
│ ├── ConfigValidatorInterface.php
│ └── Rules
│ │ ├── TypeValidationRule.php
│ │ └── ValidationRuleInterface.php
│ ├── ErrorContainer
│ ├── ErrorContainerInterface.php
│ └── ErrorContainerTrait.php
│ ├── RequestValidator
│ ├── RequestValidator.php
│ └── RequestValidatorInterface.php
│ ├── ResolveValidator
│ ├── ResolveValidator.php
│ └── ResolveValidatorInterface.php
│ └── SchemaValidator
│ └── SchemaValidator.php
└── tests
├── DataProvider
├── TestConfig.php
├── TestConfigExtraFields.php
├── TestConfigInvalidRule.php
├── TestEmptySchema.php
├── TestEnumType.php
├── TestExtendedType.php
├── TestField.php
├── TestInputField.php
├── TestInputObjectType.php
├── TestInterfaceType.php
├── TestListType.php
├── TestMutationObjectType.php
├── TestObjectType.php
├── TestResolveInfo.php
├── TestScalarDataProvider.php
├── TestSchema.php
├── TestTimeType.php
└── TestUnionType.php
├── Issues
├── Issue109
│ ├── Issue109Schema.php
│ └── Issue109Test.php
├── Issue116
│ └── Issue116Test.php
├── Issue131
│ └── Issue131Test.php
├── Issue149
│ └── Issue149Test.php
├── Issue151
│ └── Issue151Test.php
├── Issue171
│ ├── Issue171Schema.php
│ └── Issue171Test.php
├── Issue193
│ └── Issue193Test.php
├── Issue194
│ └── ProcessorTest.php
├── Issue201
│ └── Issue201Test.php
├── Issue210
│ └── TypeServiceTest.php
├── Issue220
│ └── ResolvableObjectTraitTest.php
├── Issue90
│ ├── Issue90Schema.php
│ └── Issue90Test.php
├── Issue98
│ └── TypeServiceTest.php
└── Issue99
│ ├── Issue99Schema.php
│ └── Issue99Test.php
├── Library
├── Config
│ ├── ConfigTest.php
│ ├── FieldConfigTest.php
│ ├── InterfaceTypeConfigTest.php
│ └── ObjectTypeConfigTest.php
├── Field
│ ├── ArgumentsAwareConfigTraitTest.php
│ ├── FieldAwareConfigTraitTest.php
│ ├── FieldTest.php
│ └── InputFieldTest.php
├── Relay
│ ├── ArrayConnectionTest.php
│ ├── CallableFetcherTest.php
│ ├── ConnectionTest.php
│ ├── GlobalIdFieldTest.php
│ ├── MutationTest.php
│ ├── NodeFieldTest.php
│ ├── NodeInterfaceTypeTest.php
│ └── NodeTest.php
├── Type
│ ├── EnumTypeTest.php
│ ├── InputObjectTypeTest.php
│ ├── InterfaceTypeTest.php
│ ├── ListTypeTest.php
│ ├── NonNullTypeTest.php
│ ├── ObjectTypeTest.php
│ ├── ScalarExtendTypeTest.php
│ ├── ScalarTypeTest.php
│ ├── SchemaDirectivesListTest.php
│ └── UnionTypeTest.php
├── Utilities
│ ├── ErrorContainerTraitTest.php
│ └── TypeUtilitiesTest.php
└── Validator
│ ├── RequestValidatorTest.php
│ ├── SchemaValidatorTest.php
│ └── TypeValidationRuleTest.php
├── Parser
├── AstTest.php
├── ParserTest.php
├── RequestTest.php
└── VariableTest.php
├── Performance
├── LoadTest.php
└── NPlusOneTest.php
├── Schema
├── DeferredTest.php
├── FragmentsTest.php
├── InputObjectDefaultValuesTest.php
├── InputParseTest.php
├── IntrospectionTest.php
├── NonNullableTest.php
├── ProcessorTest.php
├── ResolveInfoTest.php
├── SchemaTest.php
└── VariablesTest.php
└── StarWars
├── Schema
├── CharacterInterface.php
├── DroidType.php
├── EpisodeEnum.php
├── HumanType.php
├── StarWarsData.php
├── StarWarsQueryType.php
└── StarWarsSchema.php
└── StarWarsTest.php
/.gitignore:
--------------------------------------------------------------------------------
1 | composer.phar
2 | phpunit.xml
3 | vendor/
4 | data/schema.graphql
5 | composer.lock
6 | .idea
7 |
--------------------------------------------------------------------------------
/.scrutinizer.yml:
--------------------------------------------------------------------------------
1 | imports:
2 | - php
3 |
4 | tools:
5 | external_code_coverage:
6 | timeout: 600
7 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | matrix:
4 | include:
5 | - php: 5.5
6 | dist: trusty
7 | - php: 5.6
8 | - php: 7.0
9 | - php: 7.1
10 | - php: 7.2
11 | - php: 7.3
12 | env: STATIC_ANALYSIS=true
13 |
14 | install: composer install --prefer-dist --no-interaction
15 |
16 | script:
17 | - ./vendor/bin/phpunit --coverage-clover=coverage.clover
18 | - |
19 | if [[ $STATIC_ANALYSIS == true ]]; then
20 | composer require --ignore-platform-reqs --dev phpstan/phpstan
21 | vendor/bin/phpstan analyze src -c phpstan.neon -l 1
22 | fi
23 |
24 | after_script:
25 | - wget https://scrutinizer-ci.com/ocular.phar && php ocular.phar code-coverage:upload --format=php-clover coverage.clover
26 |
27 | notifications:
28 | email:
29 | recipients:
30 | - portey@gmail.com
31 | - a@viniychuk.com
32 | on_success: change
33 | on_failure: always
34 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | Please update this file right before tagging a new release
4 |
5 | ## v1.7.1
6 |
7 | * relaxed symfony/property-accessor version constraints so the package can be installed in Symfony 4.x projects
8 |
9 | ## v1.7.0
10 |
11 | * fix some README badges
12 | * add a more robust implementation for `TypeService::getPropertyValue()`
13 | * fix PhpStorm inspection performance complaints
14 | * fix a bug that prevented using `null` as a default value
15 | * add support for error extensions
16 | * throw `ConfigurationException` when trying to add two types with the same name to the schema
17 | * add a `getImplementations()` method to `AbstractInterfaceType`, can be used to properly discover all possible types during introspection
18 | * run Travis CI on PHP 7.2 and 7.3 too
19 | * run phpstan static analysis (level 1 only) during Travis CI builds
20 | * rename the `Tests` directory to `tests` for consistency with other projects
21 | * remove some obsolete documentation
22 |
23 | ## v1.6.0
24 |
25 | * fix the Travis CI build for PHP 5.5
26 | * improve examples somewhat
27 | * make `Node` stricter when validating input
28 | * return null not just when the field is scalar but whenever it's non-null
29 |
30 | ## v1.5.5
31 |
32 | * add missing directive locations
33 | * add a `totalCount` field to connections
34 | * fix a regression introduced in #151
35 | * add a type/field lookup cache for improved performance
36 | * add support for nested deferred resolvers
37 | * properly handle null values in `BooleanType`
38 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Youshido
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "youshido/graphql",
3 | "description": "Pure PHP GraphQL",
4 | "license": "MIT",
5 | "authors": [
6 | {
7 | "name": "Alexandr Viniychuk",
8 | "email": "a@viniychuk.com"
9 | },
10 | {
11 | "name": "Portey Vasil",
12 | "email": "portey@gmail.com"
13 | }
14 | ],
15 | "require": {
16 | "php": ">=5.5",
17 | "ext-mbstring": "*",
18 | "symfony/property-access": "^2.8 || ^3.4 || ^4.4"
19 | },
20 | "require-dev": {
21 | "phpunit/phpunit": "^4.8"
22 | },
23 | "autoload": {
24 | "psr-4": {
25 | "Youshido\\GraphQL\\": "src"
26 | }
27 | },
28 | "autoload-dev": {
29 | "psr-4": {
30 | "Youshido\\Tests\\": "tests"
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/examples/01_sandbox/index.php:
--------------------------------------------------------------------------------
1 | new ObjectType([
18 | 'name' => 'RootQueryType',
19 | 'fields' => [
20 | 'currentTime' => [
21 | 'type' => new StringType(),
22 | 'resolve' => function () {
23 | return date('Y-m-d H:ia');
24 | }
25 | ]
26 | ]
27 | ])
28 | ]));
29 |
30 | $processor->processPayload('{ currentTime }');
31 | echo json_encode($processor->getResponseData()) . "\n";
32 |
--------------------------------------------------------------------------------
/examples/02_blog/Schema/BannerType.php:
--------------------------------------------------------------------------------
1 | addField('title', new NonNullType(new StringType()))
18 | ->addField('summary', new StringType())
19 | ->addField('imageLink', new StringType());
20 | }
21 |
22 | public function getInterfaces()
23 | {
24 | return [new ContentBlockInterface()];
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/examples/02_blog/Schema/ContentBlockInterface.php:
--------------------------------------------------------------------------------
1 | addField('title', new NonNullType(new StringType()));
19 | $config->addField('summary', new StringType());
20 | }
21 |
22 | public function resolveType($object)
23 | {
24 | return empty($object['id']) ? null : (strpos($object['id'], 'post') !== false ? new PostType() : new BannerType());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/examples/02_blog/Schema/ContentBlockUnion.php:
--------------------------------------------------------------------------------
1 | "post-" . $id,
14 | "title" => "Post " . $id . " title",
15 | "summary" => "This new GraphQL library for PHP works really well",
16 | "status" => 1,
17 | "likeCount" => 2
18 | ];
19 | }
20 |
21 | public static function getBanner($id)
22 | {
23 | return [
24 | 'id' => "banner-" . $id,
25 | 'title' => "Banner " . $id,
26 | 'imageLink' => "banner" . $id . ".jpg"
27 | ];
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/examples/02_blog/Schema/LatestPostField.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 5/20/16 12:07 AM
7 | */
8 |
9 | namespace Examples\Blog\Schema;
10 |
11 |
12 | use BlogTest\PostType;
13 | use Youshido\GraphQL\Execution\ResolveInfo;
14 | use Youshido\GraphQL\Field\AbstractField;
15 |
16 | class LatestPostField extends AbstractField
17 | {
18 | public function getType()
19 | {
20 | return new PostType();
21 | }
22 |
23 | public function resolve($value, array $args, ResolveInfo $info)
24 | {
25 | return [
26 | "title" => "New approach in API has been revealed",
27 | "summary" => "This post describes a new approach to create and maintain APIs",
28 | ];
29 | }
30 |
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/examples/02_blog/Schema/LikePostField.php:
--------------------------------------------------------------------------------
1 | getReturnType()->getOne($args['id']);
27 | }
28 |
29 | public function getType()
30 | {
31 | return new PostType();
32 | }
33 |
34 | public function build(FieldConfig $config)
35 | {
36 | $config->addArgument('id', new NonNullType(new IntType()));
37 | }
38 |
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/examples/02_blog/Schema/PostInputType.php:
--------------------------------------------------------------------------------
1 | addField('title', new NonNullType(new StringType()))
20 | ->addField('summary', new StringType());
21 | }
22 |
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/examples/02_blog/Schema/PostStatus.php:
--------------------------------------------------------------------------------
1 | 0,
18 | 'name' => 'DRAFT',
19 | ],
20 | [
21 | 'value' => 1,
22 | 'name' => 'PUBLISHED',
23 | ]
24 | ];
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/examples/02_blog/Schema/PostType.php:
--------------------------------------------------------------------------------
1 | addField('oldTitle', [
24 | 'type' => new NonNullType(new StringType()),
25 | 'description' => 'This field contains a post title',
26 | 'isDeprecated' => true,
27 | 'deprecationReason' => 'field title is now deprecated',
28 | 'args' => [
29 | 'truncated' => new BooleanType()
30 | ],
31 | 'resolve' => function ($value, $args) {
32 | return (!empty($args['truncated'])) ? explode(' ', $value)[0] . '...' : $value;
33 | }
34 | ])
35 | ->addField(
36 | 'title', [
37 | 'type' => new NonNullType(new StringType()),
38 | 'args' => [
39 | 'truncated' => new BooleanType()
40 | ],
41 | ])
42 | ->addField('status', new PostStatus())
43 | ->addField('summary', new StringType())
44 | ->addField('likeCount', new IntType());
45 | }
46 |
47 | public function getOne($id)
48 | {
49 | return DataProvider::getPost($id);
50 | }
51 |
52 | public function getInterfaces()
53 | {
54 | return [new ContentBlockInterface()];
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/examples/02_blog/index.php:
--------------------------------------------------------------------------------
1 | processPayload($payload);
21 | echo json_encode($processor->getResponseData()) . "\n";
22 |
--------------------------------------------------------------------------------
/examples/02_blog/router.php:
--------------------------------------------------------------------------------
1 | processPayload($payload, $variables)->getResponseData();
31 |
32 | header('Content-Type: application/json');
33 | echo json_encode($response);
34 |
--------------------------------------------------------------------------------
/examples/02_blog/schema-bootstrap.php:
--------------------------------------------------------------------------------
1 | $rootQueryType
20 | ]));
21 | $payload = '{ latestPost { title(truncated: true), summary } }';
22 |
23 | $processor->processPayload($payload);
24 | echo json_encode($processor->getResponseData()) . "\n";
25 |
--------------------------------------------------------------------------------
/examples/03_relay_star_wars/Schema/ShipType.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 5/10/16 11:17 PM
7 | */
8 |
9 | namespace Examples\StarWars;
10 |
11 |
12 | use Youshido\GraphQL\Relay\Field\GlobalIdField;
13 | use Youshido\GraphQL\Relay\NodeInterfaceType;
14 | use Youshido\GraphQL\Type\Object\AbstractObjectType;
15 | use Youshido\GraphQL\Type\TypeMap;
16 |
17 | class ShipType extends AbstractObjectType
18 | {
19 | const TYPE_KEY = 'ship';
20 |
21 | public function build($config)
22 | {
23 | $config
24 | ->addField(new GlobalIdField(self::TYPE_KEY))
25 | ->addField('name', ['type' => TypeMap::TYPE_STRING, 'description' => 'The name of the ship.']);
26 | }
27 |
28 | public function getOne($id)
29 | {
30 | return TestDataProvider::getShip($id);
31 | }
32 |
33 | public function getDescription()
34 | {
35 | return 'A ship in the Star Wars saga';
36 | }
37 |
38 | public function getInterfaces()
39 | {
40 | return [new NodeInterfaceType()];
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/examples/03_relay_star_wars/index.php:
--------------------------------------------------------------------------------
1 | processPayload($payload, ['names_0' => ['rebels']]);
51 | echo json_encode($processor->getResponseData()) . "\n";
52 |
--------------------------------------------------------------------------------
/examples/03_relay_star_wars/router.php:
--------------------------------------------------------------------------------
1 | processPayload($payload, $variables)->getResponseData();
43 |
44 | header('Content-Type: application/json');
45 | echo json_encode($response);
46 |
--------------------------------------------------------------------------------
/examples/03_relay_star_wars/schema-bootstrap.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 4/23/17 11:10 PM
7 | */
8 |
9 | namespace Examples\BookStore;
10 |
11 |
12 | class DataProvider
13 | {
14 |
15 | static private $authors = [
16 | '1' => [
17 | 'id' => '1',
18 | 'firstName' => 'Mark',
19 | 'lastName' => 'Twain'
20 | ]
21 | ];
22 |
23 | public static function getBooks()
24 | {
25 | return [
26 | [
27 | 'id' => 1,
28 | 'title' => 'The Adventures of Tom Sawyer',
29 | 'year' => 1876,
30 | 'isbn' => '978-0996584838',
31 | 'author' => self::$authors['1']
32 | ],
33 | ];
34 | }
35 |
36 | public static function getAuthors()
37 | {
38 | return self::$authors;
39 | }
40 | }
--------------------------------------------------------------------------------
/examples/04_bookstore/Schema/BookStoreSchema.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 4/23/17 10:43 PM
7 | */
8 |
9 | namespace Examples\BookStore\Schema;
10 |
11 |
12 | use Examples\BookStore\DataProvider;
13 | use Examples\BookStore\Schema\Field\Book\RecentBooksField;
14 | use Examples\BookStore\Schema\Field\CategoriesField;
15 | use Examples\BookStore\Schema\Type\AuthorType;
16 | use Youshido\GraphQL\Config\Schema\SchemaConfig;
17 | use Youshido\GraphQL\Schema\AbstractSchema;
18 | use Youshido\GraphQL\Type\ListType\ListType;
19 |
20 | class BookStoreSchema extends AbstractSchema
21 | {
22 | public function build(SchemaConfig $config)
23 | {
24 | $config->getQuery()->addFields([
25 | 'authors' => [
26 | 'type' => new ListType(new AuthorType()),
27 | 'resolve' => function () {
28 | return DataProvider::getAuthors();
29 | }
30 | ],
31 | new RecentBooksField(),
32 | new CategoriesField(),
33 | ]);
34 | }
35 |
36 | }
--------------------------------------------------------------------------------
/examples/04_bookstore/Schema/Field/Book/RecentBooksField.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 4/23/17 11:09 PM
7 | */
8 |
9 | namespace Examples\BookStore\Schema\Field\Book;
10 |
11 |
12 | use Examples\BookStore\DataProvider;
13 | use Examples\BookStore\Schema\Type\BookType;
14 | use Youshido\GraphQL\Execution\ResolveInfo;
15 | use Youshido\GraphQL\Field\AbstractField;
16 | use Youshido\GraphQL\Type\ListType\ListType;
17 |
18 | class RecentBooksField extends AbstractField
19 | {
20 | public function getType()
21 | {
22 | return new ListType(new BookType());
23 | }
24 |
25 | public function resolve($value, array $args, ResolveInfo $info)
26 | {
27 | return DataProvider::getBooks();
28 | }
29 |
30 |
31 | }
--------------------------------------------------------------------------------
/examples/04_bookstore/Schema/Field/CategoriesField.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 4/24/17 11:42 PM
7 | */
8 |
9 | namespace Examples\BookStore\Schema\Field;
10 |
11 |
12 | use Examples\BookStore\Schema\Type\CategoryType;
13 | use Youshido\GraphQL\Execution\DeferredResolver;
14 | use Youshido\GraphQL\Execution\ResolveInfo;
15 | use Youshido\GraphQL\Field\AbstractField;
16 | use Youshido\GraphQL\Type\ListType\ListType;
17 |
18 | class CategoriesField extends AbstractField
19 | {
20 | public function getType()
21 | {
22 | return new ListType(new CategoryType());
23 | }
24 |
25 | public function resolve($value, array $args, ResolveInfo $info)
26 | {
27 | return new DeferredResolver(function () use ($value) {
28 | $id = empty($value['id']) ? "1" : $value['id'] . ".1";
29 |
30 | return [
31 | 'id' => $id,
32 | 'title' => 'Category ' . $id,
33 | 'authors' => [
34 | [
35 | 'id' => 'author1',
36 | 'firstName' => 'John',
37 | 'lastName' => 'Doe',
38 | ],
39 | ],
40 | 'children' => [],
41 | ];
42 | });
43 | }
44 | }
--------------------------------------------------------------------------------
/examples/04_bookstore/Schema/Type/AuthorType.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 4/23/17 11:05 PM
7 | */
8 |
9 | namespace Examples\BookStore\Schema\Type;
10 |
11 | use Youshido\GraphQL\Type\NonNullType;
12 | use Youshido\GraphQL\Type\Object\AbstractObjectType;
13 | use Youshido\GraphQL\Type\Scalar\IdType;
14 | use Youshido\GraphQL\Type\Scalar\StringType;
15 |
16 | class AuthorType extends AbstractObjectType
17 | {
18 | public function build($config)
19 | {
20 | $config->addFields([
21 | 'id' => new NonNullType(new IdType()),
22 | 'firstName' => new StringType(),
23 | 'lastName' => new StringType(),
24 | ]);
25 | }
26 | }
--------------------------------------------------------------------------------
/examples/04_bookstore/Schema/Type/BookType.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 4/23/17 11:08 PM
7 | */
8 |
9 | namespace Examples\BookStore\Schema\Type;
10 |
11 |
12 | use Youshido\GraphQL\Config\Object\ObjectTypeConfig;
13 | use Youshido\GraphQL\Type\Object\AbstractObjectType;
14 | use Youshido\GraphQL\Type\Scalar\IdType;
15 | use Youshido\GraphQL\Type\Scalar\IntType;
16 | use Youshido\GraphQL\Type\Scalar\StringType;
17 |
18 | class BookType extends AbstractObjectType
19 | {
20 | public function build($config)
21 | {
22 | $config->addFields([
23 | 'id' => new IdType(),
24 | 'title' => new StringType(),
25 | 'year' => new IntType(),
26 | 'isbn' => new StringType(),
27 | 'author' => new AuthorType(),
28 | ]);
29 | }
30 |
31 | }
--------------------------------------------------------------------------------
/examples/04_bookstore/Schema/Type/CategoryType.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 4/24/17 11:40 PM
7 | */
8 |
9 | namespace Examples\BookStore\Schema\Type;
10 |
11 | use Examples\BookStore\Schema\Field\CategoriesField;
12 | use Youshido\GraphQL\Type\ListType\ListType;
13 | use Youshido\GraphQL\Type\Object\AbstractObjectType;
14 | use Youshido\GraphQL\Type\Scalar\IdType;
15 | use Youshido\GraphQL\Type\Scalar\StringType;
16 |
17 | class CategoryType extends AbstractObjectType
18 | {
19 | public function build($config)
20 | {
21 | $config->addFields([
22 | 'id' => new IdType(),
23 | 'title' => new StringType(),
24 | 'authors' => new ListType(new AuthorType()),
25 | new CategoriesField(),
26 | ]);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/examples/04_bookstore/index.php:
--------------------------------------------------------------------------------
1 | processPayload($payload, $variables)->getResponseData();
44 |
45 | header('Content-Type: application/json');
46 | echo json_encode($response);
47 |
--------------------------------------------------------------------------------
/examples/04_bookstore/schema-bootstrap.php:
--------------------------------------------------------------------------------
1 | ,
32 | document.getElementById('root')
33 | );
34 |
--------------------------------------------------------------------------------
/examples/js-relay/js/components/StarWarsShip.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This file provided by Facebook is for non-commercial testing and evaluation
3 | * purposes only. Facebook reserves all rights not expressly granted.
4 | *
5 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
7 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
8 | * FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
9 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
10 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11 | */
12 |
13 | import React from 'react';
14 | import Relay from 'react-relay';
15 |
16 | class StarWarsShip extends React.Component {
17 | render() {
18 | const {ship} = this.props;
19 | return
{ship.name}
;
20 | }
21 | }
22 |
23 | export default Relay.createContainer(StarWarsShip, {
24 | fragments: {
25 | ship: () => Relay.QL`
26 | fragment on Ship {
27 | id,
28 | name
29 | }
30 | `,
31 | },
32 | });
33 |
--------------------------------------------------------------------------------
/examples/js-relay/js/mutation/AddShipMutation.js:
--------------------------------------------------------------------------------
1 | import Relay from 'react-relay';
2 |
3 | export default class AddShipMutation extends Relay.Mutation {
4 |
5 | static fragments = {
6 | faction: () => Relay.QL`
7 | fragment on Faction {
8 | id,
9 | factionId
10 | }
11 | `,
12 | };
13 |
14 | getMutation() {
15 | return Relay.QL`mutation { introduceShip }`;
16 | }
17 |
18 | getVariables() {
19 | return {
20 | shipName: this.props.name,
21 | factionId: this.props.faction.factionId,
22 | };
23 | }
24 |
25 | getFatQuery() {
26 | return Relay.QL`
27 | fragment on IntroduceShipPayload @relay(pattern: true) {
28 | faction {
29 | name
30 | ships {
31 | edges {
32 | node {
33 | name
34 | }
35 | }
36 | }
37 | }
38 | newShipEdge
39 | }
40 | `;
41 | }
42 |
43 | getConfigs() {
44 | return [{
45 | type: 'RANGE_ADD',
46 | parentName: 'faction',
47 | parentID: this.props.faction.id,
48 | connectionName: 'ships',
49 | edgeName: 'newShipEdge',
50 | rangeBehaviors: {
51 | '': 'append',
52 | 'orderby(oldest)': 'prepend',
53 | },
54 | }];
55 | }
56 |
57 | getOptimisticResponse() {
58 | return {
59 | newShipEdge: {
60 | node: {
61 | name: this.props.name,
62 | },
63 | },
64 | faction: {
65 | id: this.props.faction.id,
66 | },
67 | };
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/examples/js-relay/js/routes/StarWarsAppHomeRoute.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This file provided by Facebook is for non-commercial testing and evaluation
3 | * purposes only. Facebook reserves all rights not expressly granted.
4 | *
5 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
7 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
8 | * FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
9 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
10 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11 | */
12 |
13 | import Relay from 'react-relay';
14 |
15 | export default class extends Relay.Route {
16 | static queries = {
17 | factions: () => Relay.QL`query { factions(names: $factionNames) }`,
18 | };
19 | static routeName = 'StarWarsAppHomeRoute';
20 | }
21 |
--------------------------------------------------------------------------------
/examples/js-relay/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "relay-starter-kit",
3 | "private": true,
4 | "description": "A quick way to get up and running with Relay",
5 | "repository": "facebook/relay-starter-kit",
6 | "version": "0.1.0",
7 | "scripts": {
8 | "start": "babel-node ./server.js",
9 | "update-schema": "babel-node ./scripts/updateSchema.js"
10 | },
11 | "dependencies": {
12 | "babel-cli": "^6.7.7",
13 | "babel-core": "^6.7.7",
14 | "babel-loader": "6.2.4",
15 | "babel-polyfill": "6.7.4",
16 | "babel-preset-es2015": "6.6.0",
17 | "babel-preset-react": "6.5.0",
18 | "babel-preset-stage-0": "6.5.0",
19 | "babel-relay-plugin": "0.8.1",
20 | "classnames": "2.2.4",
21 | "express": "4.13.4",
22 | "express-graphql": "0.5.1",
23 | "graphql": "0.5.0",
24 | "graphql-relay": "0.4.1",
25 | "react": "15.0.1",
26 | "react-dom": "15.0.1",
27 | "react-relay": "0.8.1",
28 | "webpack": "1.13.0",
29 | "webpack-dev-server": "1.14.1"
30 | },
31 | "devDependencies": {
32 | "babel-cli": "6.7.7"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/examples/js-relay/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Relay • Star Wars
7 |
8 |
9 |
10 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/examples/js-relay/scripts/updateSchema.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env babel-node --optional es7.asyncFunctions
2 | /**
3 | * This file provided by Facebook is for non-commercial testing and evaluation
4 | * purposes only. Facebook reserves all rights not expressly granted.
5 | *
6 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
7 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
8 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
9 | * FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
10 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
11 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12 | */
13 |
14 | import fs from 'fs';
15 | import path from 'path';
16 | import { schema } from '../data/schema';
17 | import { graphql } from 'graphql';
18 | import { introspectionQuery, printSchema } from 'graphql/utilities';
19 |
20 | // Save JSON of full schema introspection for Babel Relay Plugin to use
21 | (async () => {
22 | const result = await (graphql(schema, introspectionQuery));
23 | if (result.errors) {
24 | console.error(
25 | 'ERROR introspecting schema: ',
26 | JSON.stringify(result.errors, null, 2)
27 | );
28 | } else {
29 | fs.writeFileSync(
30 | path.join(__dirname, '../data/schema.json'),
31 | JSON.stringify(result, null, 2)
32 | );
33 | }
34 | })();
35 |
36 | // Save user readable type system shorthand of schema
37 | fs.writeFileSync(
38 | path.join(__dirname, '../data/schema.graphql'),
39 | printSchema(schema)
40 | );
41 |
--------------------------------------------------------------------------------
/examples/js/.babelrc:
--------------------------------------------------------------------------------
1 | { "presets": ["es2015"] }
2 |
--------------------------------------------------------------------------------
/examples/js/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "graphql-js-example",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "dependencies": {
7 | "babel-preset-es2015": "^6.6.0",
8 | "express": "^4.13.4",
9 | "express-graphql": "^0.5.1",
10 | "graphql": "^0.5.0",
11 | "graphql-relay": "^0.4.1"
12 | },
13 | "devDependencies": {
14 | "babel-cli": "^6.14.0",
15 | "babel-preset-es2015": "^6.14.0",
16 | "graphql-relay": "^0.4.3"
17 | },
18 | "scripts": {
19 | "test": "exit 1"
20 | },
21 | "author": "",
22 | "license": "ISC"
23 | }
24 |
--------------------------------------------------------------------------------
/examples/structure.sketch:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/youshido-php/GraphQL/b080756d8d441d68473b12569bfe621f5be73f7b/examples/structure.sketch
--------------------------------------------------------------------------------
/examples/structure.xd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/youshido-php/GraphQL/b080756d8d441d68473b12569bfe621f5be73f7b/examples/structure.xd
--------------------------------------------------------------------------------
/phpstan.neon:
--------------------------------------------------------------------------------
1 | # nothing here for now
2 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | ./tests
7 |
8 |
9 |
10 |
11 |
12 | ./src/
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/Config/Directive/DirectiveConfig.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Config\Directive;
9 |
10 |
11 | use Youshido\GraphQL\Config\AbstractConfig;
12 | use Youshido\GraphQL\Config\Traits\ArgumentsAwareConfigTrait;
13 | use Youshido\GraphQL\Type\TypeService;
14 |
15 | /**
16 | * Class DirectiveConfig
17 | *
18 | * @package Youshido\GraphQL\Config\Directive
19 | */
20 | class DirectiveConfig extends AbstractConfig
21 | {
22 |
23 | use ArgumentsAwareConfigTrait;
24 |
25 | protected $locations = [];
26 |
27 | public function getRules()
28 | {
29 | return [
30 | 'name' => ['type' => TypeService::TYPE_STRING, 'final' => true],
31 | 'description' => ['type' => TypeService::TYPE_STRING],
32 | 'args' => ['type' => TypeService::TYPE_ARRAY],
33 | 'locations' => ['type' => TypeService::TYPE_ARRAY],
34 | ];
35 | }
36 |
37 | public function getLocations()
38 | {
39 | return $this->locations;
40 | }
41 |
42 | public function build()
43 | {
44 | $this->buildArguments();
45 |
46 | if (!empty($this->data['locations'])) {
47 | foreach ($this->data['locations'] as $location) {
48 | $this->locations[] = $location;
49 | }
50 | }
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/src/Config/Field/FieldConfig.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 11/30/15 1:30 AM
7 | */
8 |
9 | namespace Youshido\GraphQL\Config\Field;
10 |
11 | use Youshido\GraphQL\Config\AbstractConfig;
12 | use Youshido\GraphQL\Config\Traits\ArgumentsAwareConfigTrait;
13 | use Youshido\GraphQL\Type\Object\AbstractObjectType;
14 | use Youshido\GraphQL\Type\TypeInterface;
15 | use Youshido\GraphQL\Type\TypeService;
16 |
17 | /**
18 | * Class FieldConfig
19 | * @package Youshido\GraphQL\Config\Field
20 | * @method $this setDescription(string $description)
21 | * @method $this setCost(int $cost)
22 | */
23 | class FieldConfig extends AbstractConfig
24 | {
25 |
26 | use ArgumentsAwareConfigTrait;
27 |
28 | public function getRules()
29 | {
30 | return [
31 | 'name' => ['type' => TypeService::TYPE_STRING, 'final' => true],
32 | 'type' => ['type' => TypeService::TYPE_GRAPHQL_TYPE, 'final' => true],
33 | 'args' => ['type' => TypeService::TYPE_ARRAY],
34 | 'description' => ['type' => TypeService::TYPE_STRING],
35 | 'resolve' => ['type' => TypeService::TYPE_CALLABLE],
36 | 'isDeprecated' => ['type' => TypeService::TYPE_BOOLEAN],
37 | 'deprecationReason' => ['type' => TypeService::TYPE_STRING],
38 | 'cost' => ['type' => TypeService::TYPE_ANY]
39 | ];
40 | }
41 |
42 | protected function build()
43 | {
44 | $this->buildArguments();
45 | }
46 |
47 | /**
48 | * @return TypeInterface|AbstractObjectType
49 | */
50 | public function getType()
51 | {
52 | return $this->data['type'];
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/src/Config/Field/InputFieldConfig.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 12/1/15 11:28 PM
7 | */
8 |
9 | namespace Youshido\GraphQL\Config\Field;
10 |
11 |
12 | use Youshido\GraphQL\Config\AbstractConfig;
13 | use Youshido\GraphQL\Type\TypeService;
14 |
15 | /**
16 | * Class InputFieldConfig
17 | * @package Youshido\GraphQL\Config\Field
18 | * @method $this setDescription(string $description)
19 | */
20 | class InputFieldConfig extends AbstractConfig
21 | {
22 |
23 | public function getRules()
24 | {
25 | return [
26 | 'name' => ['type' => TypeService::TYPE_STRING, 'final' => true],
27 | 'type' => ['type' => TypeService::TYPE_ANY_INPUT, 'final' => true],
28 | 'defaultValue' => ['type' => TypeService::TYPE_ANY],
29 | 'description' => ['type' => TypeService::TYPE_STRING],
30 | 'isDeprecated' => ['type' => TypeService::TYPE_BOOLEAN],
31 | 'deprecationReason' => ['type' => TypeService::TYPE_STRING],
32 | ];
33 | }
34 |
35 | public function getDefaultValue()
36 | {
37 | return $this->get('defaultValue');
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/src/Config/Object/EnumTypeConfig.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 12/5/15 12:18 AM
7 | */
8 |
9 | namespace Youshido\GraphQL\Config\Object;
10 |
11 |
12 | use Youshido\GraphQL\Config\AbstractConfig;
13 | use Youshido\GraphQL\Config\Traits\ArgumentsAwareConfigTrait;
14 | use Youshido\GraphQL\Config\Traits\FieldsAwareConfigTrait;
15 | use Youshido\GraphQL\Config\TypeConfigInterface;
16 | use Youshido\GraphQL\Type\TypeService;
17 |
18 | class EnumTypeConfig extends AbstractConfig implements TypeConfigInterface
19 | {
20 | use FieldsAwareConfigTrait, ArgumentsAwareConfigTrait;
21 |
22 | public function getRules()
23 | {
24 | return [
25 | 'name' => ['type' => TypeService::TYPE_STRING, 'final' => true],
26 | 'description' => ['type' => TypeService::TYPE_STRING],
27 | 'values' => ['type' => TypeService::TYPE_ENUM_VALUES, 'required' => true],
28 | ];
29 | }
30 |
31 | public function getValues()
32 | {
33 | return $this->get('values', []);
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/Config/Object/InputObjectTypeConfig.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 12/1/15 11:13 PM
7 | */
8 |
9 | namespace Youshido\GraphQL\Config\Object;
10 |
11 |
12 | use Youshido\GraphQL\Type\TypeService;
13 |
14 | class InputObjectTypeConfig extends ObjectTypeConfig
15 | {
16 | public function getRules()
17 | {
18 | return [
19 | 'name' => ['type' => TypeService::TYPE_STRING, 'required' => true],
20 | 'fields' => ['type' => TypeService::TYPE_ARRAY_OF_INPUT_FIELDS, 'final' => true],
21 | 'description' => ['type' => TypeService::TYPE_STRING],
22 | ];
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Config/Object/InterfaceTypeConfig.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 12/5/15 12:18 AM
7 | */
8 |
9 | namespace Youshido\GraphQL\Config\Object;
10 |
11 |
12 | use Youshido\GraphQL\Config\AbstractConfig;
13 | use Youshido\GraphQL\Config\Traits\ArgumentsAwareConfigTrait;
14 | use Youshido\GraphQL\Config\Traits\FieldsAwareConfigTrait;
15 | use Youshido\GraphQL\Config\TypeConfigInterface;
16 | use Youshido\GraphQL\Exception\ConfigurationException;
17 | use Youshido\GraphQL\Type\TypeService;
18 |
19 | /**
20 | * Class InterfaceTypeConfig
21 | * @package Youshido\GraphQL\Config\Object
22 | * @method $this setDescription(string $description)
23 | */
24 | class InterfaceTypeConfig extends AbstractConfig implements TypeConfigInterface
25 | {
26 | use FieldsAwareConfigTrait, ArgumentsAwareConfigTrait;
27 |
28 | public function getRules()
29 | {
30 | return [
31 | 'name' => ['type' => TypeService::TYPE_STRING, 'final' => true],
32 | 'fields' => ['type' => TypeService::TYPE_ARRAY_OF_FIELDS_CONFIG, 'final' => true],
33 | 'description' => ['type' => TypeService::TYPE_STRING],
34 | 'resolveType' => ['type' => TypeService::TYPE_CALLABLE, 'final' => true],
35 | ];
36 | }
37 |
38 | protected function build()
39 | {
40 | $this->buildFields();
41 | }
42 |
43 | public function resolveType($object)
44 | {
45 | $callable = $this->get('resolveType');
46 |
47 | if ($callable && is_callable($callable)) {
48 | return $callable($object);
49 | } elseif (is_callable([$this->contextObject, 'resolveType'])) {
50 | return $this->contextObject->resolveType($object);
51 | }
52 |
53 | throw new ConfigurationException('There is no valid resolveType for ' . $this->getName());
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/Config/Object/ListTypeConfig.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 12/1/15 1:22 AM
7 | */
8 |
9 | namespace Youshido\GraphQL\Config\Object;
10 |
11 |
12 | use Youshido\GraphQL\Type\TypeService;
13 |
14 | class ListTypeConfig extends ObjectTypeConfig
15 | {
16 | public function getRules()
17 | {
18 | return [
19 | 'itemType' => ['type' => TypeService::TYPE_GRAPHQL_TYPE, 'final' => true],
20 | 'resolve' => ['type' => TypeService::TYPE_CALLABLE],
21 | 'args' => ['type' => TypeService::TYPE_ARRAY_OF_INPUT_FIELDS],
22 | ];
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/Config/Object/ObjectTypeConfig.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 11/27/15 2:32 AM
7 | */
8 |
9 | namespace Youshido\GraphQL\Config\Object;
10 |
11 | use Youshido\GraphQL\Config\AbstractConfig;
12 | use Youshido\GraphQL\Config\Traits\FieldsAwareConfigTrait;
13 | use Youshido\GraphQL\Config\TypeConfigInterface;
14 | use Youshido\GraphQL\Type\InterfaceType\AbstractInterfaceType;
15 | use Youshido\GraphQL\Type\TypeService;
16 |
17 | /**
18 | * Class ObjectTypeConfig
19 | * @package Youshido\GraphQL\Config\Object
20 | * @method setDescription(string $description)
21 | * @method string getDescription()
22 | */
23 | class ObjectTypeConfig extends AbstractConfig implements TypeConfigInterface
24 | {
25 |
26 | use FieldsAwareConfigTrait;
27 |
28 | public function getRules()
29 | {
30 | return [
31 | 'name' => ['type' => TypeService::TYPE_STRING, 'required' => true],
32 | 'description' => ['type' => TypeService::TYPE_STRING],
33 | 'fields' => ['type' => TypeService::TYPE_ARRAY_OF_FIELDS_CONFIG, 'final' => true],
34 | 'interfaces' => ['type' => TypeService::TYPE_ARRAY_OF_INTERFACES]
35 | ];
36 | }
37 |
38 | protected function build()
39 | {
40 | $this->buildFields();
41 | }
42 |
43 | /**
44 | * @return AbstractInterfaceType[]
45 | */
46 | public function getInterfaces()
47 | {
48 | return $this->get('interfaces', []);
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/Config/Object/UnionTypeConfig.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 12/5/15 12:18 AM
7 | */
8 |
9 | namespace Youshido\GraphQL\Config\Object;
10 |
11 |
12 | use Youshido\GraphQL\Config\AbstractConfig;
13 | use Youshido\GraphQL\Config\Traits\ArgumentsAwareConfigTrait;
14 | use Youshido\GraphQL\Config\Traits\FieldsAwareConfigTrait;
15 | use Youshido\GraphQL\Config\TypeConfigInterface;
16 | use Youshido\GraphQL\Type\TypeService;
17 |
18 | class UnionTypeConfig extends AbstractConfig implements TypeConfigInterface
19 | {
20 | use FieldsAwareConfigTrait, ArgumentsAwareConfigTrait;
21 |
22 | public function getRules()
23 | {
24 | return [
25 | 'name' => ['type' => TypeService::TYPE_STRING, 'required' => true],
26 | 'types' => ['type' => TypeService::TYPE_ARRAY_OF_OBJECT_TYPES],
27 | 'description' => ['type' => TypeService::TYPE_STRING],
28 | 'resolveType' => ['type' => TypeService::TYPE_CALLABLE, 'final' => true]
29 | ];
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/Config/Traits/ConfigAwareTrait.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 2:02 PM 5/13/16
7 | */
8 |
9 | namespace Youshido\GraphQL\Config\Traits;
10 |
11 |
12 | use Youshido\GraphQL\Config\AbstractConfig;
13 | use Youshido\GraphQL\Config\Field\FieldConfig;
14 | use Youshido\GraphQL\Config\Field\InputFieldConfig;
15 | use Youshido\GraphQL\Config\Object\ObjectTypeConfig;
16 |
17 | trait ConfigAwareTrait
18 | {
19 |
20 | /** @var AbstractConfig|ObjectTypeConfig|FieldConfig|InputFieldConfig */
21 | protected $config;
22 | protected $configCache = [];
23 |
24 | public function getConfig()
25 | {
26 | return $this->config;
27 | }
28 |
29 | protected function getConfigValue($key, $defaultValue = null)
30 | {
31 | if (array_key_exists($key, $this->configCache)) {
32 | return $this->configCache[$key];
33 | }
34 | $this->configCache[$key] = !empty($this->config) ? $this->config->get($key, $defaultValue) : $defaultValue;
35 | return $this->configCache[$key];
36 | }
37 |
38 | public function getDescription()
39 | {
40 | return $this->getConfigValue('description');
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/Config/Traits/ResolvableObjectTrait.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Config\Traits;
9 |
10 | use Youshido\GraphQL\Execution\ResolveInfo;
11 | use Youshido\GraphQL\Type\TypeMap;
12 | use Youshido\GraphQL\Type\TypeService;
13 |
14 | trait ResolvableObjectTrait
15 | {
16 |
17 | public function resolve($value, array $args, ResolveInfo $info)
18 | {
19 | if ($resolveFunction = $this->getConfig()->getResolveFunction()) {
20 | return $resolveFunction($value, $args, $info);
21 | } else {
22 | if (is_array($value) && array_key_exists($this->getName(), $value)) {
23 | return $value[$this->getName()];
24 | } elseif (is_object($value)) {
25 | return TypeService::getPropertyValue($value, $this->getName());
26 | } elseif ($this->getType()->getKind() !== TypeMap::KIND_NON_NULL) {
27 | return null;
28 | } else {
29 | throw new \Exception(sprintf('Property "%s" not found in resolve result', $this->getName()));
30 | }
31 | }
32 | }
33 |
34 |
35 | public function getResolveFunction()
36 | {
37 | return $this->getConfig()->getResolveFunction();
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/Config/TypeConfigInterface.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Config;
9 |
10 |
11 | use Youshido\GraphQL\Field\Field;
12 |
13 | interface TypeConfigInterface
14 | {
15 |
16 | /**
17 | * @param Field|string $field
18 | * @param array $fieldInfo
19 | */
20 | public function addField($field, $fieldInfo = null);
21 |
22 | public function getField($name);
23 |
24 | public function removeField($name);
25 |
26 | public function hasField($name);
27 |
28 | public function getFields();
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/Directive/Directive.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Directive;
9 |
10 | use Youshido\GraphQL\Config\Directive\DirectiveConfig;
11 | use Youshido\GraphQL\Type\Traits\ArgumentsAwareObjectTrait;
12 | use Youshido\GraphQL\Type\Traits\AutoNameTrait;
13 |
14 | class Directive implements DirectiveInterface
15 | {
16 |
17 | use ArgumentsAwareObjectTrait;
18 | use AutoNameTrait;
19 |
20 | protected $isFinal = false;
21 |
22 | public function __construct(array $config = [])
23 | {
24 | if (empty($config['name'])) {
25 | $config['name'] = $this->getName();
26 | }
27 |
28 | $this->config = new DirectiveConfig($config, $this, $this->isFinal);
29 | $this->build($this->config);
30 | }
31 |
32 | public function build(DirectiveConfig $config)
33 | {
34 |
35 | }
36 |
37 | public function addArguments($argumentsList)
38 | {
39 | return $this->getConfig()->addArguments($argumentsList);
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/Directive/DirectiveInterface.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Directive;
9 |
10 |
11 | use Youshido\GraphQL\Type\AbstractType;
12 |
13 | interface DirectiveInterface
14 | {
15 |
16 | public function getName();
17 |
18 | public function addArguments($argumentsList);
19 |
20 | public function removeArgument($argumentName);
21 |
22 | public function addArgument($argument, $ArgumentInfo = null);
23 |
24 | /**
25 | * @return AbstractType[]
26 | */
27 | public function getArguments();
28 |
29 | /**
30 | * @param string $argumentName
31 | *
32 | * @return AbstractType
33 | */
34 | public function getArgument($argumentName);
35 |
36 | /**
37 | * @param string $argumentName
38 | *
39 | * @return bool
40 | */
41 | public function hasArgument($argumentName);
42 |
43 | /**
44 | * @return boolean
45 | */
46 | public function hasArguments();
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/Directive/DirectiveLocation.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Directive;
9 |
10 |
11 | class DirectiveLocation
12 | {
13 |
14 | const QUERY = 'QUERY';
15 | const MUTATION = 'MUTATION';
16 | const FIELD = 'FIELD';
17 | const FIELD_DEFINITION = 'FIELD_DEFINITION';
18 | const FRAGMENT_DEFINITION = 'FRAGMENT_DEFINITION';
19 | const FRAGMENT_SPREAD = 'FRAGMENT_SPREAD';
20 | const INLINE_FRAGMENT = 'INLINE_FRAGMENT';
21 | const ENUM_VALUE = 'ENUM_VALUE';
22 | }
23 |
--------------------------------------------------------------------------------
/src/Exception/ConfigurationException.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 11/27/15 2:28 AM
7 | */
8 |
9 | namespace Youshido\GraphQL\Exception;
10 |
11 |
12 | class ConfigurationException extends \Exception
13 | {
14 |
15 | }
--------------------------------------------------------------------------------
/src/Exception/Interfaces/ExtendedExceptionInterface.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Exception\Interfaces;
9 |
10 |
11 | use Youshido\GraphQL\Parser\Location;
12 |
13 | interface LocationableExceptionInterface
14 | {
15 |
16 | /**
17 | * @return Location
18 | */
19 | public function getLocation();
20 |
21 | }
--------------------------------------------------------------------------------
/src/Exception/Parser/AbstractParserError.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Exception\Parser;
9 |
10 |
11 | use Youshido\GraphQL\Exception\Interfaces\LocationableExceptionInterface;
12 | use Youshido\GraphQL\Parser\Location;
13 |
14 | abstract class AbstractParserError extends \Exception implements LocationableExceptionInterface
15 | {
16 |
17 | /** @var Location */
18 | private $location;
19 |
20 | public function __construct($message, Location $location)
21 | {
22 | parent::__construct($message);
23 |
24 | $this->location = $location;
25 | }
26 |
27 | public function getLocation()
28 | {
29 | return $this->location;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/Exception/Parser/InvalidRequestException.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Exception\Parser;
9 |
10 | class InvalidRequestException extends AbstractParserError
11 | {
12 |
13 | }
--------------------------------------------------------------------------------
/src/Exception/Parser/SyntaxErrorException.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Exception\Parser;
9 |
10 | class SyntaxErrorException extends AbstractParserError
11 | {
12 |
13 | }
--------------------------------------------------------------------------------
/src/Exception/ResolveException.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Exception;
9 |
10 |
11 | use Youshido\GraphQL\Exception\Interfaces\LocationableExceptionInterface;
12 | use Youshido\GraphQL\Parser\Location;
13 |
14 | class ResolveException extends \Exception implements LocationableExceptionInterface
15 | {
16 |
17 | /** @var Location */
18 | private $location;
19 |
20 | public function __construct($message, Location $location = null)
21 | {
22 | parent::__construct($message);
23 |
24 | $this->location = $location;
25 | }
26 |
27 |
28 | /**
29 | * @return Location
30 | */
31 | public function getLocation()
32 | {
33 | return $this->location;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/Exception/ValidationException.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Exception;
9 |
10 |
11 | class ValidationException extends \Exception
12 | {
13 |
14 | }
--------------------------------------------------------------------------------
/src/Execution/Container/Container.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 9/22/16 7:00 PM
7 | */
8 |
9 | namespace Youshido\GraphQL\Execution\Container;
10 |
11 | class Container implements ContainerInterface
12 | {
13 |
14 | private $keyset = [];
15 | private $values = [];
16 | private $services = [];
17 |
18 |
19 | /**
20 | * @param $id
21 | * @return mixed
22 | * @throws \Exception if there was no value set under specified id
23 | */
24 | public function get($id)
25 | {
26 | $this->assertIdentifierSet($id);
27 | if (isset($this->services['id'])) {
28 | return $this->services['id']($this);
29 | }
30 | return $this->values[$id];
31 | }
32 |
33 | public function set($id, $value)
34 | {
35 | $this->values[$id] = $value;
36 | $this->keyset[$id] = true;
37 | return $this;
38 | }
39 |
40 | protected function setAsService($id, $service)
41 | {
42 | if (!is_object($service)) {
43 | throw new \RuntimeException(sprintf('Service %s has to be an object', $id));
44 | }
45 |
46 | $this->services[$id] = $service;
47 | if (isset($this->values[$id])) {
48 | unset($this->values[$id]);
49 | }
50 | $this->keyset[$id] = true;
51 | }
52 |
53 | public function remove($id)
54 | {
55 | $this->assertIdentifierSet($id);
56 | if (array_key_exists($id, $this->values)) {
57 | unset($this->values[$id]);
58 | }
59 | if (array_key_exists($id, $this->services)) {
60 | unset($this->services[$id]);
61 | }
62 | }
63 |
64 | public function has($id)
65 | {
66 | return isset($this->keyset[$id]);
67 | }
68 |
69 | private function assertIdentifierSet($id)
70 | {
71 | if (!$this->has($id)) {
72 | throw new \RuntimeException(sprintf('Container item "%s" was not set', $id));
73 | }
74 | }
75 | }
--------------------------------------------------------------------------------
/src/Execution/Container/ContainerInterface.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Execution\Context;
9 |
10 |
11 | use Youshido\GraphQL\Execution\Container\ContainerInterface;
12 | use Youshido\GraphQL\Execution\Request;
13 | use Youshido\GraphQL\Schema\AbstractSchema;
14 | use Youshido\GraphQL\Validator\ErrorContainer\ErrorContainerInterface;
15 |
16 | interface ExecutionContextInterface extends ErrorContainerInterface
17 | {
18 |
19 | /**
20 | * @return AbstractSchema
21 | */
22 | public function getSchema();
23 |
24 | /**
25 | * @param AbstractSchema $schema
26 | *
27 | * @return $this
28 | */
29 | public function setSchema(AbstractSchema $schema);
30 |
31 | /**
32 | * @return Request
33 | */
34 | public function getRequest();
35 |
36 | /**
37 | * @param Request $request
38 | *
39 | * @return $this
40 | */
41 | public function setRequest(Request $request);
42 |
43 | /**
44 | * @return ContainerInterface
45 | */
46 | public function getContainer();
47 |
48 | /**
49 | * @param ContainerInterface $container
50 | * @return mixed
51 | */
52 | public function setContainer(ContainerInterface $container);
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/src/Execution/DeferredResolver.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 4/24/17 11:50 PM
7 | */
8 |
9 | namespace Youshido\GraphQL\Execution;
10 |
11 |
12 | /**
13 | * Default implementation of DeferredResolverInterface
14 | *
15 | * @package Youshido\GraphQL\Execution
16 | */
17 | class DeferredResolver implements DeferredResolverInterface {
18 |
19 | /** @var callable */
20 | private $resolver;
21 |
22 | public function __construct($resolver)
23 | {
24 | $this->resolver = $resolver;
25 | }
26 |
27 | public function resolve() {
28 | return call_user_func($this->resolver);
29 | }
30 | }
--------------------------------------------------------------------------------
/src/Execution/DeferredResolverInterface.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 7/25/17 12:34 PM
7 | */
8 |
9 | namespace Youshido\GraphQL\Execution;
10 |
11 | /**
12 | * Interface definition for deferred resolvers.
13 | *
14 | * Fields may return a value implementing this interface to use deferred
15 | * resolving to optimize query performance.
16 | */
17 | interface DeferredResolverInterface {
18 |
19 | /**
20 | * @return mixed
21 | * The actual result value.
22 | */
23 | public function resolve();
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/Execution/DeferredResult.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 7/25/17 12:34 PM
7 | */
8 |
9 | namespace Youshido\GraphQL\Execution;
10 |
11 |
12 | /**
13 | * Wrapper class for deferred resolvers during execution process.
14 | * Not part of the public API.
15 | *
16 | * @internal
17 | */
18 | class DeferredResult implements DeferredResolverInterface {
19 |
20 | /** @var \Youshido\GraphQL\Execution\DeferredResolver */
21 | private $resolver;
22 |
23 | /** @var callable */
24 | protected $callback;
25 |
26 | /** @var mixed */
27 | public $result;
28 |
29 | public function __construct(DeferredResolverInterface $resolver, callable $callback)
30 | {
31 | $this->resolver = $resolver;
32 | $this->callback = $callback;
33 | }
34 |
35 | public function resolve() {
36 | $this->result = call_user_func($this->callback, $this->resolver->resolve());
37 | }
38 | }
--------------------------------------------------------------------------------
/src/Execution/Visitor/AbstractQueryVisitor.php:
--------------------------------------------------------------------------------
1 | memo. A reasonable thing to do is raise an
20 | * exception if some limit is reached. (see MaxComplexityQueryVisitor for example concrete implementation)
21 | *
22 | * @author Ben Roberts
23 | * created: 7/11/16 11:03 AM
24 | */
25 |
26 | namespace Youshido\GraphQL\Execution\Visitor;
27 |
28 | use Youshido\GraphQL\Config\Field\FieldConfig;
29 |
30 | abstract class AbstractQueryVisitor
31 | {
32 |
33 | /**
34 | * @var int initial value of $this->memo
35 | */
36 | protected $initialValue = 0;
37 |
38 | /**
39 | * @var mixed the accumulator
40 | */
41 | protected $memo;
42 |
43 | /**
44 | * AbstractQueryVisitor constructor.
45 | */
46 | public function __construct()
47 | {
48 | $this->memo = $this->initialValue;
49 | }
50 |
51 | /**
52 | * @return mixed getter for the memo, in case callers want to inspect it after a process run
53 | */
54 | public function getMemo()
55 | {
56 | return $this->memo;
57 | }
58 |
59 | /**
60 | * Visit a query node. See class docstring.
61 | *
62 | * @param array $args
63 | * @param FieldConfig $fieldConfig
64 | * @param int $childScore
65 | *
66 | * @return int|null
67 | */
68 | abstract public function visit(array $args, FieldConfig $fieldConfig, $childScore = 0);
69 | }
--------------------------------------------------------------------------------
/src/Execution/Visitor/MaxComplexityQueryVisitor.php:
--------------------------------------------------------------------------------
1 |
9 | * created: 7/11/16 11:05 AM
10 | */
11 |
12 | namespace Youshido\GraphQL\Execution\Visitor;
13 |
14 |
15 | use Youshido\GraphQL\Config\Field\FieldConfig;
16 |
17 | class MaxComplexityQueryVisitor extends AbstractQueryVisitor
18 | {
19 |
20 | /**
21 | * @var int max score allowed before throwing an exception (causing processing to stop)
22 | */
23 | public $maxScore;
24 |
25 | /**
26 | * @var int default score for nodes without explicit cost functions
27 | */
28 | protected $defaultScore = 1;
29 |
30 | /**
31 | * MaxComplexityQueryVisitor constructor.
32 | *
33 | * @param int $max max allowed complexity score
34 | */
35 | public function __construct($max)
36 | {
37 | parent::__construct();
38 |
39 | $this->maxScore = $max;
40 | }
41 |
42 | /**
43 | * {@inheritdoc}
44 | */
45 | public function visit(array $args, FieldConfig $fieldConfig, $childScore = 0)
46 | {
47 | $cost = $fieldConfig->get('cost', null);
48 | if (is_callable($cost)) {
49 | $cost = $cost($args, $fieldConfig, $childScore);
50 | }
51 |
52 | $cost = is_null($cost) ? $this->defaultScore : $cost;
53 | $this->memo += $cost;
54 |
55 | if ($this->memo > $this->maxScore) {
56 | throw new \Exception('query exceeded max allowed complexity of ' . $this->maxScore);
57 | }
58 |
59 | return $cost;
60 | }
61 | }
--------------------------------------------------------------------------------
/src/Field/AbstractInputField.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Field;
9 |
10 |
11 | use Youshido\GraphQL\Config\Field\InputFieldConfig;
12 | use Youshido\GraphQL\Type\InputTypeInterface;
13 | use Youshido\GraphQL\Type\Traits\AutoNameTrait;
14 | use Youshido\GraphQL\Type\Traits\FieldsArgumentsAwareObjectTrait;
15 | use Youshido\GraphQL\Type\TypeFactory;
16 | use Youshido\GraphQL\Type\TypeService;
17 |
18 | abstract class AbstractInputField implements InputFieldInterface
19 | {
20 |
21 | use FieldsArgumentsAwareObjectTrait, AutoNameTrait;
22 |
23 | protected $isFinal = false;
24 |
25 | public function __construct(array $config = [])
26 | {
27 | if (empty($config['type'])) {
28 | $config['type'] = $this->getType();
29 | $config['name'] = $this->getName();
30 | }
31 |
32 | if (TypeService::isScalarType($config['type'])) {
33 | $config['type'] = TypeFactory::getScalarType($config['type']);
34 | }
35 |
36 | $this->config = new InputFieldConfig($config, $this, $this->isFinal);
37 | $this->build($this->config);
38 | }
39 |
40 | public function build(InputFieldConfig $config)
41 | {
42 |
43 | }
44 |
45 | /**
46 | * @return InputTypeInterface
47 | */
48 | abstract public function getType();
49 |
50 | public function getDefaultValue()
51 | {
52 | return $this->config->getDefaultValue();
53 | }
54 |
55 | //todo: think about serialize, parseValue methods
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/src/Field/Field.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Field;
9 |
10 | use Youshido\GraphQL\Type\Object\AbstractObjectType;
11 |
12 | /**
13 | * Class Field
14 | * @package Youshido\GraphQL\Type\Field
15 | *
16 | */
17 | final class Field extends AbstractField
18 | {
19 |
20 | protected $isFinal = true;
21 |
22 | protected $_typeCache = null;
23 | protected $_nameCache = null;
24 |
25 | /**
26 | * @return AbstractObjectType
27 | */
28 | public function getType()
29 | {
30 | return $this->_typeCache ? $this->_typeCache : ($this->_typeCache = $this->getConfigValue('type'));
31 | }
32 |
33 | public function getName()
34 | {
35 | return $this->_nameCache ? $this->_nameCache : ($this->_nameCache = $this->getConfigValue('name'));
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/Field/FieldInterface.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Field;
9 |
10 |
11 | use Youshido\GraphQL\Execution\ResolveInfo;
12 |
13 | interface FieldInterface extends InputFieldInterface
14 | {
15 | public function resolve($value, array $args, ResolveInfo $info);
16 |
17 | public function getResolveFunction();
18 | }
19 |
--------------------------------------------------------------------------------
/src/Field/InputField.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 12/1/15 11:26 PM
7 | */
8 |
9 | namespace Youshido\GraphQL\Field;
10 |
11 |
12 | use Youshido\GraphQL\Type\Object\AbstractObjectType;
13 |
14 | final class InputField extends AbstractInputField
15 | {
16 |
17 | protected $isFinal = false;
18 |
19 | /**
20 | * @return AbstractObjectType
21 | */
22 | public function getType()
23 | {
24 | return $this->getConfigValue('type');
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/Field/InputFieldInterface.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 9/29/16 10:32 PM
7 | */
8 |
9 | namespace Youshido\GraphQL\Field;
10 |
11 |
12 | use Youshido\GraphQL\Type\AbstractType;
13 |
14 | interface InputFieldInterface
15 | {
16 | /**
17 | * @return AbstractType
18 | */
19 | public function getType();
20 |
21 | public function getName();
22 |
23 | public function addArguments($argumentsList);
24 |
25 | public function removeArgument($argumentName);
26 |
27 | public function addArgument($argument, $ArgumentInfo = null);
28 |
29 | /**
30 | * @return AbstractType[]
31 | */
32 | public function getArguments();
33 |
34 | /**
35 | * @param string $argumentName
36 | *
37 | * @return AbstractType
38 | */
39 | public function getArgument($argumentName);
40 |
41 | /**
42 | * @param string $argumentName
43 | *
44 | * @return bool
45 | */
46 | public function hasArgument($argumentName);
47 |
48 | /**
49 | * @return boolean
50 | */
51 | public function hasArguments();
52 |
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/src/Introspection/DirectiveLocationType.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Introspection;
9 |
10 | use Youshido\GraphQL\Directive\DirectiveLocation;
11 | use Youshido\GraphQL\Type\Enum\AbstractEnumType;
12 |
13 | class DirectiveLocationType extends AbstractEnumType
14 | {
15 |
16 | const QUERY = DirectiveLocation::QUERY;
17 | const MUTATION = DirectiveLocation::MUTATION;
18 | const FIELD = DirectiveLocation::FIELD;
19 | const FIELD_DEFINITION = DirectiveLocation::FIELD_DEFINITION;
20 | const FRAGMENT_DEFINITION = DirectiveLocation::FRAGMENT_DEFINITION;
21 | const FRAGMENT_SPREAD = DirectiveLocation::FRAGMENT_SPREAD;
22 | const INLINE_FRAGMENT = DirectiveLocation::INLINE_FRAGMENT;
23 | const ENUM_VALUE = DirectiveLocation::ENUM_VALUE;
24 |
25 | public function getName()
26 | {
27 | return '__DirectiveLocation';
28 | }
29 |
30 | public function getValues()
31 | {
32 | return [
33 | ['name' => 'QUERY', 'value' => self::QUERY],
34 | ['name' => 'MUTATION', 'value' => self::MUTATION],
35 | ['name' => 'FIELD', 'value' => self::FIELD],
36 | ['name' => 'FIELD_DEFINITION', 'value' => self::FIELD_DEFINITION],
37 | ['name' => 'FRAGMENT_DEFINITION', 'value' => self::FRAGMENT_DEFINITION],
38 | ['name' => 'FRAGMENT_SPREAD', 'value' => self::FRAGMENT_SPREAD],
39 | ['name' => 'INLINE_FRAGMENT', 'value' => self::INLINE_FRAGMENT],
40 | ['name' => 'ENUM_VALUE', 'value' => self::ENUM_VALUE],
41 | ];
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/Introspection/DirectiveType.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Introspection;
9 |
10 | use Youshido\GraphQL\Config\Directive\DirectiveConfig;
11 | use Youshido\GraphQL\Directive\Directive;
12 | use Youshido\GraphQL\Directive\DirectiveInterface;
13 | use Youshido\GraphQL\Type\ListType\ListType;
14 | use Youshido\GraphQL\Type\NonNullType;
15 | use Youshido\GraphQL\Type\Object\AbstractObjectType;
16 | use Youshido\GraphQL\Type\TypeMap;
17 |
18 | class DirectiveType extends AbstractObjectType
19 | {
20 |
21 | /**
22 | * @return String type name
23 | */
24 | public function getName()
25 | {
26 | return '__Directive';
27 | }
28 |
29 | public function resolveArgs(DirectiveInterface $value)
30 | {
31 | if ($value->hasArguments()) {
32 | return $value->getArguments();
33 | }
34 |
35 | return [];
36 | }
37 |
38 | /**
39 | * @param DirectiveInterface|Directive $value
40 | *
41 | * @return mixed
42 | */
43 | public function resolveLocations(DirectiveInterface $value)
44 | {
45 | /** @var DirectiveConfig $directiveConfig */
46 | $directiveConfig = $value->getConfig();
47 |
48 | $locations = $directiveConfig->getLocations();
49 |
50 | return $locations;
51 | }
52 |
53 | public function build($config)
54 | {
55 | $config
56 | ->addField('name', new NonNullType(TypeMap::TYPE_STRING))
57 | ->addField('description', TypeMap::TYPE_STRING)
58 | ->addField('args', [
59 | 'type' => new NonNullType(new ListType(new NonNullType(new InputValueType()))),
60 | 'resolve' => [$this, 'resolveArgs'],
61 | ])
62 | ->addField('locations',[
63 | 'type' => new NonNullType(new ListType(new NonNullType(new DirectiveLocationType()))),
64 | 'resolve' => [$this, 'resolveLocations'],
65 | ]);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/Introspection/EnumValueType.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Introspection;
9 |
10 |
11 | use Youshido\GraphQL\Type\NonNullType;
12 | use Youshido\GraphQL\Type\Object\AbstractObjectType;
13 | use Youshido\GraphQL\Type\TypeMap;
14 |
15 | class EnumValueType extends AbstractObjectType
16 | {
17 |
18 | public function build($config)
19 | {
20 | $config
21 | ->addField('name', new NonNullType(TypeMap::TYPE_STRING))
22 | ->addField('description', TypeMap::TYPE_STRING)
23 | ->addField('deprecationReason', TypeMap::TYPE_STRING)
24 | ->addField('isDeprecated', new NonNullType(TypeMap::TYPE_BOOLEAN));
25 | }
26 |
27 | /**
28 | * @return String type name
29 | */
30 | public function getName()
31 | {
32 | return '__EnumValue';
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/Introspection/Field/SchemaField.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Introspection\Field;
9 |
10 |
11 | use Youshido\GraphQL\Execution\ResolveInfo;
12 | use Youshido\GraphQL\Field\AbstractField;
13 | use Youshido\GraphQL\Introspection\SchemaType;
14 | use Youshido\GraphQL\Type\Object\AbstractObjectType;
15 |
16 | class SchemaField extends AbstractField
17 | {
18 | /**
19 | * @return AbstractObjectType
20 | */
21 | public function getType()
22 | {
23 | return new SchemaType();
24 | }
25 |
26 | public function getName()
27 | {
28 | return '__schema';
29 | }
30 |
31 | public function resolve($value, array $args, ResolveInfo $info)
32 | {
33 | return $info->getExecutionContext()->getSchema();
34 | }
35 |
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/Introspection/Field/TypeDefinitionField.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Introspection\Field;
9 |
10 | use Youshido\GraphQL\Config\Field\FieldConfig;
11 | use Youshido\GraphQL\Execution\ResolveInfo;
12 | use Youshido\GraphQL\Field\AbstractField;
13 | use Youshido\GraphQL\Field\InputField;
14 | use Youshido\GraphQL\Introspection\QueryType;
15 | use Youshido\GraphQL\Introspection\Traits\TypeCollectorTrait;
16 | use Youshido\GraphQL\Type\NonNullType;
17 | use Youshido\GraphQL\Type\Object\AbstractObjectType;
18 | use Youshido\GraphQL\Type\Scalar\StringType;
19 |
20 | class TypeDefinitionField extends AbstractField
21 | {
22 |
23 | use TypeCollectorTrait;
24 |
25 | public function resolve($value, array $args, ResolveInfo $info)
26 | {
27 | $schema = $info->getExecutionContext()->getSchema();
28 | $this->collectTypes($schema->getQueryType());
29 | $this->collectTypes($schema->getMutationType());
30 |
31 | foreach ($schema->getTypesList()->getTypes() as $type) {
32 | $this->collectTypes($type);
33 | }
34 |
35 | foreach ($this->types as $name => $info) {
36 | if ($name == $args['name']) {
37 | return $info;
38 | }
39 | }
40 |
41 | return null;
42 | }
43 |
44 | public function build(FieldConfig $config)
45 | {
46 | $config->addArgument(new InputField([
47 | 'name' => 'name',
48 | 'type' => new NonNullType(new StringType())
49 | ]));
50 | }
51 |
52 |
53 | /**
54 | * @return String type name
55 | */
56 | public function getName()
57 | {
58 | return '__type';
59 | }
60 |
61 | /**
62 | * @return AbstractObjectType
63 | */
64 | public function getType()
65 | {
66 | return new QueryType();
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/Introspection/Field/TypesField.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Introspection\Field;
9 |
10 |
11 | use Youshido\GraphQL\Execution\ResolveInfo;
12 | use Youshido\GraphQL\Field\AbstractField;
13 | use Youshido\GraphQL\Introspection\QueryType;
14 | use Youshido\GraphQL\Introspection\Traits\TypeCollectorTrait;
15 | use Youshido\GraphQL\Schema\AbstractSchema;
16 | use Youshido\GraphQL\Type\ListType\ListType;
17 | use Youshido\GraphQL\Type\Object\AbstractObjectType;
18 |
19 | class TypesField extends AbstractField
20 | {
21 |
22 | use TypeCollectorTrait;
23 |
24 | /**
25 | * @return AbstractObjectType
26 | */
27 | public function getType()
28 | {
29 | return new ListType(new QueryType());
30 | }
31 |
32 | public function getName()
33 | {
34 | return 'types';
35 | }
36 |
37 | public function resolve($value, array $args, ResolveInfo $info)
38 | {
39 | /** @var $value AbstractSchema $a */
40 | $this->types = [];
41 | $this->collectTypes($value->getQueryType());
42 |
43 | if ($value->getMutationType()->hasFields()) {
44 | $this->collectTypes($value->getMutationType());
45 | }
46 |
47 | foreach ($value->getTypesList()->getTypes() as $type) {
48 | $this->collectTypes($type);
49 | }
50 |
51 | return array_values($this->types);
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/src/Introspection/FieldType.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Introspection;
9 |
10 | use Youshido\GraphQL\Field\FieldInterface;
11 | use Youshido\GraphQL\Type\ListType\ListType;
12 | use Youshido\GraphQL\Type\NonNullType;
13 | use Youshido\GraphQL\Type\Object\AbstractObjectType;
14 | use Youshido\GraphQL\Type\TypeMap;
15 |
16 | class FieldType extends AbstractObjectType
17 | {
18 |
19 | public function resolveType(FieldInterface $value)
20 | {
21 | return $value->getType();
22 | }
23 |
24 | public function resolveArgs(FieldInterface $value)
25 | {
26 | if ($value->hasArguments()) {
27 | return $value->getArguments();
28 | }
29 |
30 | return [];
31 | }
32 |
33 | public function build($config)
34 | {
35 | $config
36 | ->addField('name', new NonNullType(TypeMap::TYPE_STRING))
37 | ->addField('description', TypeMap::TYPE_STRING)
38 | ->addField('isDeprecated', new NonNullType(TypeMap::TYPE_BOOLEAN))
39 | ->addField('deprecationReason', TypeMap::TYPE_STRING)
40 | ->addField('type', [
41 | 'type' => new NonNullType(new QueryType()),
42 | 'resolve' => [$this, 'resolveType'],
43 | ])
44 | ->addField('args', [
45 | 'type' => new NonNullType(new ListType(new NonNullType(new InputValueType()))),
46 | 'resolve' => [$this, 'resolveArgs'],
47 | ]);
48 | }
49 |
50 | public function isValidValue($value)
51 | {
52 | return $value instanceof FieldInterface;
53 | }
54 |
55 | /**
56 | * @return String type name
57 | */
58 | public function getName()
59 | {
60 | return '__Field';
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/Introspection/InputValueType.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Introspection;
9 |
10 | use Youshido\GraphQL\Field\Field;
11 | use Youshido\GraphQL\Schema\AbstractSchema;
12 | use Youshido\GraphQL\Type\NonNullType;
13 | use Youshido\GraphQL\Type\Object\AbstractObjectType;
14 | use Youshido\GraphQL\Type\TypeInterface;
15 | use Youshido\GraphQL\Type\TypeMap;
16 |
17 | class InputValueType extends AbstractObjectType
18 | {
19 | /**
20 | * @param AbstractSchema|Field $value
21 | *
22 | * @return TypeInterface
23 | */
24 | public function resolveType($value)
25 | {
26 | return $value->getConfig()->getType();
27 | }
28 |
29 | /**
30 | * @param AbstractSchema|Field $value
31 | *
32 | * @return string|null
33 | *
34 | * //todo implement value printer
35 | */
36 | public function resolveDefaultValue($value)
37 | {
38 | $resolvedValue = $value->getConfig()->getDefaultValue();
39 | return $resolvedValue === null ? $resolvedValue : str_replace('"', '', json_encode($resolvedValue));
40 | }
41 |
42 | public function build($config)
43 | {
44 | $config
45 | ->addField('name', new NonNullType(TypeMap::TYPE_STRING))
46 | ->addField('description', TypeMap::TYPE_STRING)
47 | ->addField('isDeprecated', new NonNullType(TypeMap::TYPE_BOOLEAN))
48 | ->addField('deprecationReason', TypeMap::TYPE_STRING)
49 | ->addField(new Field([
50 | 'name' => 'type',
51 | 'type' => new NonNullType(new QueryType()),
52 | 'resolve' => [$this, 'resolveType']
53 | ]))
54 | ->addField('defaultValue', [
55 | 'type' => TypeMap::TYPE_STRING,
56 | 'resolve' => [$this, 'resolveDefaultValue']
57 | ]);
58 | }
59 |
60 | /**
61 | * @return string type name
62 | */
63 | public function getName()
64 | {
65 | return '__InputValue';
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/Parser/Ast/AbstractAst.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Parser\Ast;
9 |
10 |
11 | use Youshido\GraphQL\Parser\Ast\Interfaces\LocatableInterface;
12 | use Youshido\GraphQL\Parser\Location;
13 |
14 | abstract class AbstractAst implements LocatableInterface
15 | {
16 |
17 | /** @var Location */
18 | private $location;
19 |
20 | public function __construct(Location $location)
21 | {
22 | $this->location = $location;
23 | }
24 |
25 | public function getLocation()
26 | {
27 | return $this->location;
28 | }
29 |
30 | public function setLocation(Location $location)
31 | {
32 | $this->location = $location;
33 | }
34 | }
--------------------------------------------------------------------------------
/src/Parser/Ast/Argument.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Parser\Ast;
9 |
10 |
11 | use Youshido\GraphQL\Parser\Ast\Interfaces\ValueInterface;
12 | use Youshido\GraphQL\Parser\Location;
13 |
14 | class Argument extends AbstractAst
15 | {
16 |
17 | /** @var string */
18 | private $name;
19 |
20 | /** @var ValueInterface */
21 | private $value;
22 |
23 | /**
24 | * @param string $name
25 | * @param ValueInterface $value
26 | * @param Location $location
27 | */
28 | public function __construct($name, ValueInterface $value, Location $location)
29 | {
30 | parent::__construct($location);
31 |
32 | $this->name = $name;
33 | $this->value = $value;
34 | }
35 |
36 | /**
37 | * @return mixed
38 | */
39 | public function getName()
40 | {
41 | return $this->name;
42 | }
43 |
44 | /**
45 | * @param mixed $name
46 | */
47 | public function setName($name)
48 | {
49 | $this->name = $name;
50 | }
51 |
52 | /**
53 | * @return \Youshido\GraphQL\Parser\Ast\Interfaces\ValueInterface
54 | */
55 | public function getValue()
56 | {
57 | return $this->value;
58 | }
59 |
60 | /**
61 | * @param mixed $value
62 | */
63 | public function setValue($value)
64 | {
65 | $this->value = $value;
66 | }
67 |
68 |
69 | }
--------------------------------------------------------------------------------
/src/Parser/Ast/ArgumentValue/InputList.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Parser\Ast\ArgumentValue;
9 |
10 |
11 | use Youshido\GraphQL\Parser\Ast\AbstractAst;
12 | use Youshido\GraphQL\Parser\Ast\Interfaces\ValueInterface;
13 | use Youshido\GraphQL\Parser\Location;
14 |
15 | class InputList extends AbstractAst implements ValueInterface
16 | {
17 |
18 | protected $list = [];
19 |
20 | /**
21 | * @param array $list
22 | * @param Location $location
23 | */
24 | public function __construct(array $list, Location $location)
25 | {
26 | parent::__construct($location);
27 |
28 | $this->list = $list;
29 | }
30 |
31 | /**
32 | * @return array
33 | */
34 | public function getValue()
35 | {
36 | return $this->list;
37 | }
38 |
39 | /**
40 | * @param array $value
41 | */
42 | public function setValue($value)
43 | {
44 | $this->list = $value;
45 | }
46 | }
--------------------------------------------------------------------------------
/src/Parser/Ast/ArgumentValue/InputObject.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Parser\Ast\ArgumentValue;
9 |
10 |
11 | use Youshido\GraphQL\Parser\Ast\AbstractAst;
12 | use Youshido\GraphQL\Parser\Ast\Interfaces\ValueInterface;
13 | use Youshido\GraphQL\Parser\Location;
14 |
15 | class InputObject extends AbstractAst implements ValueInterface
16 | {
17 |
18 | protected $object = [];
19 |
20 | /**
21 | * @param array $object
22 | * @param Location $location
23 | */
24 | public function __construct(array $object, Location $location)
25 | {
26 | parent::__construct($location);
27 |
28 | $this->object = $object;
29 | }
30 |
31 | /**
32 | * @return array
33 | */
34 | public function getValue()
35 | {
36 | return $this->object;
37 | }
38 |
39 | /**
40 | * @param array $value
41 | */
42 | public function setValue($value)
43 | {
44 | $this->object = $value;
45 | }
46 |
47 | }
--------------------------------------------------------------------------------
/src/Parser/Ast/ArgumentValue/Literal.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Parser\Ast\ArgumentValue;
9 |
10 |
11 | use Youshido\GraphQL\Parser\Ast\AbstractAst;
12 | use Youshido\GraphQL\Parser\Ast\Interfaces\ValueInterface;
13 | use Youshido\GraphQL\Parser\Location;
14 |
15 | class Literal extends AbstractAst implements ValueInterface
16 | {
17 |
18 | private $value;
19 |
20 | /**
21 | * @param mixed $value
22 | * @param Location $location
23 | */
24 | public function __construct($value, Location $location)
25 | {
26 | parent::__construct($location);
27 |
28 | $this->value = $value;
29 | }
30 |
31 | public function getValue()
32 | {
33 | return $this->value;
34 | }
35 |
36 | /**
37 | * @param string $value
38 | */
39 | public function setValue($value)
40 | {
41 | $this->value = $value;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/Parser/Ast/ArgumentValue/VariableReference.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Parser\Ast\ArgumentValue;
9 |
10 |
11 | use Youshido\GraphQL\Parser\Ast\AbstractAst;
12 | use Youshido\GraphQL\Parser\Ast\Interfaces\ValueInterface;
13 | use Youshido\GraphQL\Parser\Location;
14 |
15 | class VariableReference extends AbstractAst implements ValueInterface
16 | {
17 |
18 | /** @var string */
19 | private $name;
20 |
21 | /** @var Variable */
22 | private $variable;
23 |
24 | /** @var mixed */
25 | private $value;
26 |
27 | /**
28 | * @param string $name
29 | * @param Variable|null $variable
30 | * @param Location $location
31 | */
32 | public function __construct($name, Variable $variable = null, Location $location)
33 | {
34 | parent::__construct($location);
35 |
36 | $this->name = $name;
37 | $this->variable = $variable;
38 | }
39 |
40 | public function getVariable()
41 | {
42 | return $this->variable;
43 | }
44 |
45 | public function getValue()
46 | {
47 | return $this->value;
48 | }
49 |
50 | public function setValue($value)
51 | {
52 | $this->value = $value;
53 | }
54 |
55 | /**
56 | * @return string
57 | */
58 | public function getName()
59 | {
60 | return $this->name;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/Parser/Ast/AstDirectivesTrait.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Parser\Ast;
9 |
10 |
11 | trait AstDirectivesTrait
12 | {
13 |
14 | /** @var Directive[] */
15 | protected $directives;
16 |
17 | private $directivesCache = null;
18 |
19 |
20 | public function hasDirectives()
21 | {
22 | return (bool)count($this->directives);
23 | }
24 |
25 | public function hasDirective($name)
26 | {
27 | return array_key_exists($name, $this->directives);
28 | }
29 |
30 | /**
31 | * @param $name
32 | *
33 | * @return null|Directive
34 | */
35 | public function getDirective($name)
36 | {
37 | $directive = null;
38 | if (isset($this->directives[$name])) {
39 | $directive = $this->directives[$name];
40 | }
41 |
42 | return $directive;
43 | }
44 |
45 | /**
46 | * @return Directive[]
47 | */
48 | public function getDirectives()
49 | {
50 | return $this->directives;
51 | }
52 |
53 | /**
54 | * @param $directives Directive[]
55 | */
56 | public function setDirectives(array $directives)
57 | {
58 | $this->directives = [];
59 | $this->directivesCache = null;
60 |
61 | foreach ($directives as $directive) {
62 | $this->addDirective($directive);
63 | }
64 | }
65 |
66 | public function addDirective(Directive $directive)
67 | {
68 | $this->directives[$directive->getName()] = $directive;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/Parser/Ast/Directive.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Parser\Ast;
9 |
10 |
11 | use Youshido\GraphQL\Parser\Location;
12 |
13 | class Directive extends AbstractAst
14 | {
15 | use AstArgumentsTrait;
16 |
17 | /** @var string */
18 | private $name;
19 |
20 |
21 | /**
22 | * @param string $name
23 | * @param array $arguments
24 | * @param Location $location
25 | */
26 | public function __construct($name, array $arguments, Location $location)
27 | {
28 | parent::__construct($location);
29 |
30 | $this->name = $name;
31 | $this->setArguments($arguments);
32 | }
33 |
34 | /**
35 | * @return mixed
36 | */
37 | public function getName()
38 | {
39 | return $this->name;
40 | }
41 |
42 | /**
43 | * @param mixed $name
44 | */
45 | public function setName($name)
46 | {
47 | $this->name = $name;
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/src/Parser/Ast/Field.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Parser\Ast;
9 |
10 |
11 | use Youshido\GraphQL\Parser\Ast\Interfaces\FieldInterface;
12 | use Youshido\GraphQL\Parser\Location;
13 |
14 | class Field extends AbstractAst implements FieldInterface
15 | {
16 | use AstArgumentsTrait;
17 | use AstDirectivesTrait;
18 |
19 | /** @var string */
20 | private $name;
21 |
22 | /** @var string */
23 | private $alias;
24 |
25 | /**
26 | * @param string $name
27 | * @param string $alias
28 | * @param array $arguments
29 | * @param array $directives
30 | * @param Location $location
31 | */
32 | public function __construct($name, $alias, array $arguments, array $directives, Location $location)
33 | {
34 | parent::__construct($location);
35 |
36 | $this->name = $name;
37 | $this->alias = $alias;
38 | $this->setArguments($arguments);
39 | $this->setDirectives($directives);
40 | }
41 |
42 | /**
43 | * @return string
44 | */
45 | public function getName()
46 | {
47 | return $this->name;
48 | }
49 |
50 | /**
51 | * @param string $name
52 | */
53 | public function setName($name)
54 | {
55 | $this->name = $name;
56 | }
57 |
58 | /**
59 | * @return null|string
60 | */
61 | public function getAlias()
62 | {
63 | return $this->alias;
64 | }
65 |
66 | /**
67 | * @param null|string $alias
68 | */
69 | public function setAlias($alias)
70 | {
71 | $this->alias = $alias;
72 | }
73 |
74 | public function hasFields()
75 | {
76 | return false;
77 | }
78 |
79 | public function getFields()
80 | {
81 | return [];
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/src/Parser/Ast/FragmentReference.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Parser\Ast;
9 |
10 |
11 | use Youshido\GraphQL\Parser\Ast\Interfaces\FragmentInterface;
12 | use Youshido\GraphQL\Parser\Location;
13 |
14 | class FragmentReference extends AbstractAst implements FragmentInterface
15 | {
16 |
17 | /** @var string */
18 | protected $name;
19 |
20 | /**
21 | * @param string $name
22 | * @param Location $location
23 | */
24 | public function __construct($name, Location $location)
25 | {
26 | parent::__construct($location);
27 |
28 | $this->name = $name;
29 | }
30 |
31 | /**
32 | * @return string
33 | */
34 | public function getName()
35 | {
36 | return $this->name;
37 | }
38 |
39 | /**
40 | * @param string $name
41 | */
42 | public function setName($name)
43 | {
44 | $this->name = $name;
45 | }
46 |
47 |
48 | }
--------------------------------------------------------------------------------
/src/Parser/Ast/Interfaces/FieldInterface.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Parser\Ast\Interfaces;
9 |
10 |
11 | use Youshido\GraphQL\Parser\Ast\Argument;
12 |
13 | interface FieldInterface extends LocatableInterface
14 | {
15 |
16 | /**
17 | * @return string
18 | */
19 | public function getName();
20 |
21 | /**
22 | * @return string
23 | */
24 | public function getAlias();
25 |
26 | /**
27 | * @return Argument[]
28 | */
29 | public function getArguments();
30 |
31 | /**
32 | * @param string $name
33 | *
34 | * @return Argument
35 | */
36 | public function getArgument($name);
37 |
38 | /**
39 | * @return bool
40 | */
41 | public function hasFields();
42 |
43 | /**
44 | * @return array
45 | */
46 | public function getFields();
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/Parser/Ast/Interfaces/FragmentInterface.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 12:26 PM 5/14/16
7 | */
8 |
9 | namespace Youshido\GraphQL\Parser\Ast\Interfaces;
10 |
11 |
12 | interface FragmentInterface
13 | {
14 |
15 | }
--------------------------------------------------------------------------------
/src/Parser/Ast/Interfaces/LocatableInterface.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Parser\Ast\Interfaces;
9 |
10 |
11 | use Youshido\GraphQL\Parser\Location;
12 |
13 | interface LocatableInterface
14 | {
15 |
16 | /**
17 | * @return Location
18 | */
19 | public function getLocation();
20 |
21 | }
--------------------------------------------------------------------------------
/src/Parser/Ast/Interfaces/ValueInterface.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Parser\Ast\Interfaces;
9 |
10 |
11 | interface ValueInterface
12 | {
13 |
14 | public function getValue();
15 |
16 | public function setValue($value);
17 | }
--------------------------------------------------------------------------------
/src/Parser/Ast/Mutation.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Parser\Ast;
9 |
10 |
11 | class Mutation extends Query
12 | {
13 |
14 | }
--------------------------------------------------------------------------------
/src/Parser/Ast/TypedFragmentReference.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Parser\Ast;
9 |
10 |
11 | use Youshido\GraphQL\Parser\Ast\Interfaces\FragmentInterface;
12 | use Youshido\GraphQL\Parser\Location;
13 |
14 | class TypedFragmentReference extends AbstractAst implements FragmentInterface
15 | {
16 | use AstDirectivesTrait;
17 |
18 | /** @var Field[]|Query[] */
19 | protected $fields;
20 |
21 | /** @var string */
22 | protected $typeName;
23 |
24 | /**
25 | * @param string $typeName
26 | * @param Field[]|Query[] $fields
27 | * @param Directive[] $directives
28 | * @param Location $location
29 | */
30 | public function __construct($typeName, array $fields, array $directives, Location $location)
31 | {
32 | parent::__construct($location);
33 |
34 | $this->typeName = $typeName;
35 | $this->fields = $fields;
36 | $this->setDirectives($directives);
37 | }
38 |
39 | /**
40 | * @return Field[]|Query[]
41 | */
42 | public function getFields()
43 | {
44 | return $this->fields;
45 | }
46 |
47 | /**
48 | * @param Field[]|Query[] $fields
49 | */
50 | public function setFields($fields)
51 | {
52 | $this->fields = $fields;
53 | }
54 |
55 | /**
56 | * @return string
57 | */
58 | public function getTypeName()
59 | {
60 | return $this->typeName;
61 | }
62 |
63 | /**
64 | * @param string $typeName
65 | */
66 | public function setTypeName($typeName)
67 | {
68 | $this->typeName = $typeName;
69 | }
70 |
71 | }
--------------------------------------------------------------------------------
/src/Parser/Location.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Parser;
9 |
10 |
11 | class Location
12 | {
13 |
14 | /** @var integer */
15 | private $line;
16 |
17 | /** @var integer */
18 | private $column;
19 |
20 | public function __construct($line, $column)
21 | {
22 | $this->line = $line;
23 | $this->column = $column;
24 | }
25 |
26 | /**
27 | * @return int
28 | */
29 | public function getLine()
30 | {
31 | return $this->line;
32 | }
33 |
34 | /**
35 | * @return int
36 | */
37 | public function getColumn()
38 | {
39 | return $this->column;
40 | }
41 |
42 |
43 | public function toArray()
44 | {
45 | return [
46 | 'line' => $this->getLine(),
47 | 'column' => $this->getColumn()
48 | ];
49 | }
50 |
51 | }
--------------------------------------------------------------------------------
/src/Relay/Fetcher/CallableFetcher.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Relay\Fetcher;
9 |
10 |
11 | class CallableFetcher implements FetcherInterface
12 | {
13 |
14 | /** @var callable */
15 | protected $resolveNodeCallable;
16 |
17 | /** @var callable */
18 | protected $resolveTypeCallable;
19 |
20 | public function __construct(callable $resolveNode, callable $resolveType)
21 | {
22 | $this->resolveNodeCallable = $resolveNode;
23 | $this->resolveTypeCallable = $resolveType;
24 | }
25 |
26 | /**
27 | * @inheritdoc
28 | */
29 | public function resolveNode($type, $id)
30 | {
31 | $callable = $this->resolveNodeCallable;
32 |
33 | return $callable($type, $id);
34 | }
35 |
36 | /**
37 | * @inheritdoc
38 | */
39 | public function resolveType($object)
40 | {
41 | $callable = $this->resolveTypeCallable;
42 |
43 | return $callable($object);
44 | }
45 | }
--------------------------------------------------------------------------------
/src/Relay/Fetcher/FetcherInterface.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Relay\Fetcher;
9 |
10 |
11 | interface FetcherInterface
12 | {
13 |
14 | /**
15 | * Resolve node
16 | *
17 | * @param $type string
18 | * @param $id string
19 | *
20 | * @return mixed
21 | */
22 | public function resolveNode($type, $id);
23 |
24 | /**
25 | * @param $object
26 | * @return mixed
27 | */
28 | public function resolveType($object);
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/Relay/Field/GlobalIdField.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 5/10/16 11:23 PM
7 | */
8 |
9 | namespace Youshido\GraphQL\Relay\Field;
10 |
11 |
12 | use Youshido\GraphQL\Execution\ResolveInfo;
13 | use Youshido\GraphQL\Field\AbstractField;
14 | use Youshido\GraphQL\Relay\Node;
15 | use Youshido\GraphQL\Type\NonNullType;
16 | use Youshido\GraphQL\Type\Scalar\IdType;
17 |
18 | class GlobalIdField extends AbstractField
19 | {
20 |
21 | /** @var string */
22 | protected $typeName;
23 |
24 | /**
25 | * @param string $typeName
26 | */
27 | public function __construct($typeName)
28 | {
29 | $this->typeName = $typeName;
30 |
31 | $config = [
32 | 'type' => $this->getType(),
33 | 'name' => $this->getName(),
34 | 'resolve' => [$this, 'resolve']
35 | ];
36 |
37 | parent::__construct($config);
38 | }
39 |
40 | public function getName()
41 | {
42 | return 'id';
43 | }
44 |
45 | public function getDescription()
46 | {
47 | return 'The ID of an object';
48 | }
49 |
50 | public function getType()
51 | {
52 | return new NonNullType(new IdType());
53 | }
54 |
55 | /**
56 | * @inheritdoc
57 | */
58 | public function resolve($value, array $args, ResolveInfo $info)
59 | {
60 | return $value ? Node::toGlobalId($this->typeName, $value['id']) : null;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/Relay/Field/NodeField.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 5/10/16 11:46 PM
7 | */
8 |
9 | namespace Youshido\GraphQL\Relay\Field;
10 |
11 |
12 | use Youshido\GraphQL\Config\Field\FieldConfig;
13 | use Youshido\GraphQL\Execution\ResolveInfo;
14 | use Youshido\GraphQL\Field\AbstractField;
15 | use Youshido\GraphQL\Field\InputField;
16 | use Youshido\GraphQL\Relay\Fetcher\FetcherInterface;
17 | use Youshido\GraphQL\Relay\Node;
18 | use Youshido\GraphQL\Relay\NodeInterfaceType;
19 | use Youshido\GraphQL\Type\NonNullType;
20 | use Youshido\GraphQL\Type\Scalar\IdType;
21 |
22 | class NodeField extends AbstractField
23 | {
24 |
25 | /** @var FetcherInterface */
26 | protected $fetcher;
27 |
28 | /** @var NodeInterfaceType */
29 | protected $type;
30 |
31 | public function __construct(FetcherInterface $fetcher)
32 | {
33 | $this->fetcher = $fetcher;
34 | $this->type = (new NodeInterfaceType())->setFetcher($this->fetcher);
35 |
36 | parent::__construct([]);
37 | }
38 |
39 | public function getName()
40 | {
41 | return 'node';
42 | }
43 |
44 | public function getDescription()
45 | {
46 | return 'Fetches an object given its ID';
47 | }
48 |
49 | public function build(FieldConfig $config)
50 | {
51 | $config->addArgument(new InputField([
52 | 'name' => 'id',
53 | 'type' => new NonNullType(new IdType()),
54 | 'description' => 'The ID of an object'
55 | ]));
56 | }
57 |
58 | public function getType()
59 | {
60 | return $this->type;
61 | }
62 |
63 | public function resolve($value, array $args, ResolveInfo $info)
64 | {
65 | list($type, $id) = Node::fromGlobalId($args['id']);
66 |
67 | return $this->fetcher->resolveNode($type, $id);
68 | }
69 |
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/src/Relay/Node.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Relay;
9 |
10 |
11 | class Node
12 | {
13 |
14 | /**
15 | * @param $id
16 | *
17 | * @return array with type and id element
18 | */
19 | public static function fromGlobalId($id)
20 | {
21 | $decoded = base64_decode($id, true);
22 | if (!$decoded) {
23 | throw new \InvalidArgumentException('ID must be a valid base 64 string');
24 | }
25 | $decodedParts = explode(':', $decoded, 2);
26 | if (count($decodedParts) !== 2) {
27 | throw new \InvalidArgumentException('ID was not correctly formed');
28 | }
29 | return $decodedParts;
30 | }
31 |
32 | /**
33 | * @param $typeName string name of type
34 | * @param $id int local id
35 | *
36 | * @return string global id
37 | */
38 | public static function toGlobalId($typeName, $id)
39 | {
40 | return base64_encode(implode(':', [$typeName, $id]));
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/Relay/NodeInterfaceType.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 5/10/16 11:32 PM
7 | */
8 |
9 | namespace Youshido\GraphQL\Relay;
10 |
11 |
12 | use Youshido\GraphQL\Relay\Fetcher\FetcherInterface;
13 | use Youshido\GraphQL\Relay\Field\GlobalIdField;
14 | use Youshido\GraphQL\Type\InterfaceType\AbstractInterfaceType;
15 |
16 | class NodeInterfaceType extends AbstractInterfaceType
17 | {
18 |
19 | /** @var FetcherInterface */ //todo: maybe there are better solution
20 | protected $fetcher;
21 |
22 | public function getName()
23 | {
24 | return 'NodeInterface';
25 | }
26 |
27 | public function build($config)
28 | {
29 | $config->addField(new GlobalIdField('NodeInterface'));
30 | }
31 |
32 | public function resolveType($object)
33 | {
34 | if ($this->fetcher) {
35 | return $this->fetcher->resolveType($object);
36 | }
37 |
38 | return null;
39 | }
40 |
41 | /**
42 | * @return FetcherInterface
43 | */
44 | public function getFetcher()
45 | {
46 | return $this->fetcher;
47 | }
48 |
49 | /**
50 | * @param FetcherInterface $fetcher
51 | *
52 | * @return NodeInterfaceType
53 | */
54 | public function setFetcher($fetcher)
55 | {
56 | $this->fetcher = $fetcher;
57 |
58 | return $this;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/Relay/Type/PageInfoType.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 2/23/17 4:19 PM
7 | */
8 |
9 | namespace Youshido\GraphQL\Relay\Type;
10 |
11 |
12 | use Youshido\GraphQL\Type\NonNullType;
13 | use Youshido\GraphQL\Type\Object\AbstractObjectType;
14 | use Youshido\GraphQL\Type\Scalar\BooleanType;
15 | use Youshido\GraphQL\Type\Scalar\StringType;
16 |
17 | class PageInfoType extends AbstractObjectType
18 | {
19 | public function build($config)
20 | {
21 | $config->addFields([
22 | 'hasNextPage' => [
23 | 'type' => new NonNullType(new BooleanType()),
24 | 'description' => 'When paginating forwards, are there more items?'
25 | ],
26 | 'hasPreviousPage' => [
27 | 'type' => new NonNullType(new BooleanType()),
28 | 'description' => 'When paginating backwards, are there more items?'
29 | ],
30 | 'startCursor' => [
31 | 'type' => new StringType(),
32 | 'description' => 'When paginating backwards, the cursor to continue.'
33 | ],
34 | 'endCursor' => [
35 | 'type' => new StringType(),
36 | 'description' => 'When paginating forwards, the cursor to continue.'
37 | ],
38 | ]);
39 | }
40 |
41 | public function getDescription()
42 | {
43 | return "Information about pagination in a connection.";
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/Schema/InternalSchemaMutationObject.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 5/14/16 9:28 AM
7 | */
8 |
9 | namespace Youshido\GraphQL\Schema;
10 |
11 |
12 | use Youshido\GraphQL\Type\Object\AbstractObjectType;
13 |
14 | class InternalSchemaMutationObject extends AbstractObjectType
15 | {
16 | public function build($config)
17 | {
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/Schema/InternalSchemaQueryObject.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 5/14/16 9:28 AM
7 | */
8 |
9 | namespace Youshido\GraphQL\Schema;
10 |
11 |
12 | use Youshido\GraphQL\Type\Object\AbstractObjectType;
13 |
14 | class InternalSchemaQueryObject extends AbstractObjectType
15 | {
16 | public function build($config)
17 | {
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/Schema/Schema.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 11/28/15 3:40 PM
7 | */
8 |
9 | namespace Youshido\GraphQL\Schema;
10 |
11 | use Youshido\GraphQL\Config\Schema\SchemaConfig;
12 |
13 | final class Schema extends AbstractSchema
14 | {
15 | public function build(SchemaConfig $config)
16 | {
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/Type/AbstractInterfaceTypeInterface.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 5/14/16 11:38 AM
7 | */
8 |
9 | namespace Youshido\GraphQL\Type;
10 |
11 |
12 | interface AbstractInterfaceTypeInterface
13 | {
14 | /**
15 | * @param $object object from resolve function
16 | *
17 | * @return AbstractType
18 | */
19 | public function resolveType($object);
20 | }
21 |
--------------------------------------------------------------------------------
/src/Type/AbstractType.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 11/27/15 2:05 AM
7 | */
8 |
9 | namespace Youshido\GraphQL\Type;
10 |
11 |
12 | use Youshido\GraphQL\Type\Object\AbstractObjectType;
13 |
14 | abstract class AbstractType implements TypeInterface
15 | {
16 |
17 | protected $lastValidationError = null;
18 |
19 | public function isCompositeType()
20 | {
21 | return false;
22 | }
23 |
24 | /**
25 | * @return AbstractType
26 | */
27 | public function getType()
28 | {
29 | return $this;
30 | }
31 |
32 | /**
33 | * @return AbstractType
34 | */
35 | public function getNamedType()
36 | {
37 | return $this->getType();
38 | }
39 |
40 | /**
41 | * @return AbstractType|AbstractObjectType
42 | */
43 | public function getNullableType()
44 | {
45 | return $this;
46 | }
47 |
48 | public function getValidationError($value = null)
49 | {
50 | return $this->lastValidationError;
51 | }
52 |
53 | public function isValidValue($value)
54 | {
55 | return true;
56 | }
57 |
58 | public function parseValue($value)
59 | {
60 | return $value;
61 | }
62 |
63 | public function parseInputValue($value)
64 | {
65 | return $this->parseValue($value);
66 | }
67 |
68 | public function serialize($value)
69 | {
70 | return $value;
71 | }
72 |
73 | public function isInputType()
74 | {
75 | return false;
76 | }
77 |
78 | public function __toString()
79 | {
80 | return $this->getName();
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/Type/CompositeTypeInterface.php:
--------------------------------------------------------------------------------
1 |
8 | * created: 3:48 PM 4/29/16
9 | */
10 | interface CompositeTypeInterface
11 | {
12 |
13 | /**
14 | * @return AbstractType
15 | */
16 | public function getTypeOf();
17 | }
18 |
--------------------------------------------------------------------------------
/src/Type/Enum/EnumType.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Type\Enum;
9 |
10 | use Youshido\GraphQL\Config\Object\EnumTypeConfig;
11 |
12 | final class EnumType extends AbstractEnumType
13 | {
14 |
15 | public function __construct(array $config)
16 | {
17 | $this->config = new EnumTypeConfig($config, $this, true);
18 | }
19 |
20 | public function getValues()
21 | {
22 | return $this->getConfig()->getValues();
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/Type/InputObject/InputObjectType.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 12/1/15 10:25 PM
7 | */
8 |
9 | namespace Youshido\GraphQL\Type\InputObject;
10 |
11 | use Youshido\GraphQL\Config\Object\InputObjectTypeConfig;
12 |
13 | final class InputObjectType extends AbstractInputObjectType
14 | {
15 |
16 | public function __construct($config)
17 | {
18 | $this->config = new InputObjectTypeConfig($config, $this, true);
19 | }
20 |
21 | /**
22 | * @inheritdoc
23 | *
24 | * @codeCoverageIgnore
25 | */
26 | public function build($config)
27 | {
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/Type/InputTypeInterface.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 9/29/16 10:41 PM
7 | */
8 |
9 | namespace Youshido\GraphQL\Type;
10 |
11 |
12 | use Youshido\GraphQL\Config\AbstractConfig;
13 |
14 | interface InputTypeInterface
15 | {
16 | /**
17 | * @return String type name
18 | */
19 | public function getName();
20 |
21 | /**
22 | * @return String predefined type kind
23 | */
24 | public function getKind();
25 |
26 | /**
27 | * @return String type description
28 | */
29 | public function getDescription();
30 |
31 | /**
32 | * Coercing value received as input to current type
33 | *
34 | * @param $value
35 | * @return mixed
36 | */
37 | public function parseValue($value);
38 |
39 | /**
40 | * Coercing result to current type
41 | *
42 | * @param $value
43 | * @return mixed
44 | */
45 | public function serialize($value);
46 |
47 | /**
48 | * @param $value mixed
49 | *
50 | * @return bool
51 | */
52 | public function isValidValue($value);
53 |
54 | /**
55 | * @return AbstractConfig
56 | */
57 | public function getConfig();
58 | }
--------------------------------------------------------------------------------
/src/Type/InterfaceType/InterfaceType.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Type\InterfaceType;
9 |
10 |
11 | use Youshido\GraphQL\Config\Object\InterfaceTypeConfig;
12 |
13 | final class InterfaceType extends AbstractInterfaceType
14 | {
15 |
16 | public function __construct($config = [])
17 | {
18 | $this->config = new InterfaceTypeConfig($config, $this, true);
19 | }
20 |
21 | /**
22 | * @inheritdoc
23 | *
24 | * @codeCoverageIgnore
25 | */
26 | public function build($config)
27 | {
28 | }
29 |
30 | public function resolveType($object)
31 | {
32 | return $this->getConfig()->resolveType($object);
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/Type/ListType/ListType.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 12/1/15 1:22 AM
7 | */
8 |
9 | namespace Youshido\GraphQL\Type\ListType;
10 |
11 |
12 | use Youshido\GraphQL\Config\Object\ListTypeConfig;
13 |
14 | final class ListType extends AbstractListType
15 | {
16 |
17 | public function __construct($itemType)
18 | {
19 | $this->config = new ListTypeConfig(['itemType' => $itemType], $this, true);
20 | }
21 |
22 | public function getItemType()
23 | {
24 | return $this->getConfig()->get('itemType');
25 | }
26 |
27 | public function getName()
28 | {
29 | return null;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/Type/Object/AbstractMutationObjectType.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Type\Object;
9 |
10 | abstract class AbstractMutationObjectType extends AbstractObjectType
11 | {
12 |
13 | public function getType()
14 | {
15 | return $this->getOutputType();
16 | }
17 |
18 | abstract public function getOutputType();
19 | }
20 |
--------------------------------------------------------------------------------
/src/Type/Object/ObjectType.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 11/27/15 1:24 AM
7 | */
8 |
9 | namespace Youshido\GraphQL\Type\Object;
10 |
11 | use Youshido\GraphQL\Config\Object\ObjectTypeConfig;
12 |
13 | final class ObjectType extends AbstractObjectType
14 | {
15 |
16 | public function __construct(array $config)
17 | {
18 | $this->config = new ObjectTypeConfig($config, $this, true);
19 | }
20 |
21 | /**
22 | * @inheritdoc
23 | *
24 | * @codeCoverageIgnore
25 | */
26 | public function build($config) { }
27 |
28 | public function getName()
29 | {
30 | return $this->getConfigValue('name');
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Type/Scalar/AbstractScalarType.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 11/27/15 1:00 AM
7 | */
8 |
9 | namespace Youshido\GraphQL\Type\Scalar;
10 |
11 | use Youshido\GraphQL\Config\Traits\ConfigAwareTrait;
12 | use Youshido\GraphQL\Type\AbstractType;
13 | use Youshido\GraphQL\Type\TypeMap;
14 |
15 | abstract class AbstractScalarType extends AbstractType
16 | {
17 | use ConfigAwareTrait;
18 |
19 | public function getName()
20 | {
21 | $className = get_class($this);
22 |
23 | return substr($className, strrpos($className, '\\') + 1, -4);
24 | }
25 |
26 | final public function getKind()
27 | {
28 | return TypeMap::KIND_SCALAR;
29 | }
30 |
31 | public function parseValue($value)
32 | {
33 | return $this->serialize($value);
34 | }
35 |
36 | public function isInputType()
37 | {
38 | return true;
39 | }
40 |
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/Type/Scalar/BooleanType.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 11/27/15 1:22 AM
7 | */
8 |
9 | namespace Youshido\GraphQL\Type\Scalar;
10 |
11 |
12 | class BooleanType extends AbstractScalarType
13 | {
14 | public function getName()
15 | {
16 | return 'Boolean';
17 | }
18 |
19 | public function serialize($value)
20 | {
21 | if ($value === null) {
22 | return null;
23 | }
24 | if ($value === 'true') {
25 | return true;
26 | }
27 | if ($value === 'false') {
28 | return false;
29 | }
30 |
31 | return (bool)$value;
32 | }
33 |
34 | public function isValidValue($value)
35 | {
36 | return is_null($value) || is_bool($value);
37 | }
38 |
39 | public function getDescription()
40 | {
41 | return 'The `Boolean` scalar type represents `true` or `false`.';
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/Type/Scalar/DateTimeType.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 11/27/15 1:22 AM
7 | */
8 |
9 | namespace Youshido\GraphQL\Type\Scalar;
10 |
11 | class DateTimeType extends AbstractScalarType
12 | {
13 |
14 | private $format;
15 |
16 | public function __construct($format = 'Y-m-d H:i:s')
17 | {
18 | $this->format = $format;
19 | }
20 |
21 | public function getName()
22 | {
23 | return 'DateTime';
24 | }
25 |
26 | public function isValidValue($value)
27 | {
28 | if ((is_object($value) && $value instanceof \DateTimeInterface) || is_null($value)) {
29 | return true;
30 | } else if (is_string($value)) {
31 | $date = $this->createFromFormat($value);
32 | } else {
33 | $date = null;
34 | }
35 |
36 | return $date ? true : false;
37 | }
38 |
39 | public function serialize($value)
40 | {
41 | $date = null;
42 |
43 | if (is_string($value)) {
44 | $date = $this->createFromFormat($value);
45 | } elseif ($value instanceof \DateTimeInterface) {
46 | $date = $value;
47 | }
48 |
49 | return $date ? $date->format($this->format) : null;
50 | }
51 |
52 | public function parseValue($value)
53 | {
54 | if (is_string($value)) {
55 | $date = $this->createFromFormat($value);
56 | } elseif ($value instanceof \DateTimeInterface) {
57 | $date = $value;
58 | } else {
59 | $date = false;
60 | }
61 |
62 | return $date ?: null;
63 | }
64 |
65 | private function createFromFormat($value)
66 | {
67 | return \DateTime::createFromFormat($this->format, $value);
68 | }
69 |
70 | public function getDescription()
71 | {
72 | return sprintf('Representation of date and time in "%s" format', $this->format);
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/src/Type/Scalar/DateTimeTzType.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 11/27/15 1:22 AM
7 | */
8 |
9 | namespace Youshido\GraphQL\Type\Scalar;
10 |
11 | class DateTimeTzType extends AbstractScalarType
12 | {
13 | private $format = 'D, d M Y H:i:s O';
14 |
15 | public function getName()
16 | {
17 | return 'DateTimeTz';
18 | }
19 | public function isValidValue($value)
20 | {
21 | if ((is_object($value) && $value instanceof \DateTimeInterface) || is_null($value)) {
22 | return true;
23 | } else if (is_string($value)) {
24 | $date = $this->createFromFormat($value);
25 | } else {
26 | $date = null;
27 | }
28 |
29 | return $date ? true : false;
30 | }
31 |
32 | public function serialize($value)
33 | {
34 | $date = null;
35 |
36 | if (is_string($value)) {
37 | $date = $this->createFromFormat($value);
38 | } elseif ($value instanceof \DateTimeInterface) {
39 | $date = $value;
40 | }
41 |
42 | return $date ? $date->format($this->format) : null;
43 | }
44 |
45 | public function parseValue($value)
46 | {
47 | if (is_string($value)) {
48 | $date = $this->createFromFormat($value);
49 | } elseif ($value instanceof \DateTimeInterface) {
50 | $date = $value;
51 | } else {
52 | $date = false;
53 | }
54 |
55 | return $date ?: null;
56 | }
57 |
58 | private function createFromFormat($value)
59 | {
60 | return \DateTime::createFromFormat($this->format, $value);
61 | }
62 |
63 | public function getDescription()
64 | {
65 | return 'Representation of date and time in "r" format';
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/src/Type/Scalar/DateType.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 11/27/15 1:22 AM
7 | */
8 |
9 | namespace Youshido\GraphQL\Type\Scalar;
10 |
11 | /**
12 | * @deprecated USE DateTime type instead. To be removed in 1.4.
13 | *
14 | * Class DateType
15 | * @package Youshido\GraphQL\Type\Scalar
16 | */
17 | class DateType extends AbstractScalarType
18 | {
19 |
20 | public function getName()
21 | {
22 | return 'Date';
23 | }
24 |
25 | /**
26 | * @param $value \DateTime
27 | * @return null|string
28 | */
29 | public function serialize($value)
30 | {
31 | if ($value === null) {
32 | return null;
33 | }
34 |
35 | return $value->format('Y-m-d');
36 | }
37 |
38 | public function isValidValue($value)
39 | {
40 | if (is_null($value) || is_object($value)) {
41 | return true;
42 | }
43 |
44 | $d = \DateTime::createFromFormat('Y-m-d', $value);
45 |
46 | return $d && $d->format('Y-m-d') == $value;
47 | }
48 |
49 | public function getDescription()
50 | {
51 | return 'DEPRECATED. Use DateTime instead';
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/src/Type/Scalar/FloatType.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 12/3/15 10:10 PM
7 | */
8 |
9 | namespace Youshido\GraphQL\Type\Scalar;
10 |
11 | class FloatType extends AbstractScalarType
12 | {
13 |
14 | public function getName()
15 | {
16 | return 'Float';
17 | }
18 |
19 | public function serialize($value)
20 | {
21 | if ($value === null) {
22 | return null;
23 | } else {
24 | return floatval($value);
25 | }
26 | }
27 |
28 | public function isValidValue($value)
29 | {
30 | return is_null($value) || is_float($value) || is_int($value);
31 | }
32 |
33 | public function getDescription()
34 | {
35 | return 'The `Float` scalar type represents signed double-precision fractional ' .
36 | 'values as specified by ' .
37 | '[IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point).';
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/src/Type/Scalar/IdType.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 12/4/15 12:41 AM
7 | */
8 |
9 | namespace Youshido\GraphQL\Type\Scalar;
10 |
11 |
12 | class IdType extends AbstractScalarType
13 | {
14 |
15 | public function getName()
16 | {
17 | return 'ID';
18 | }
19 |
20 | public function serialize($value)
21 | {
22 | if (null === $value) {
23 | return null;
24 | }
25 |
26 | return (string)$value;
27 | }
28 |
29 | public function getDescription()
30 | {
31 | return 'The `ID` scalar type represents a unique identifier, often used to ' .
32 | 'refetch an object or as key for a cache. The ID type appears in a JSON ' .
33 | 'response as a String; however, it is not intended to be human-readable. ' .
34 | 'When expected as an input type, any string (such as `"4"`) or integer ' .
35 | '(such as `4`) input value will be accepted as an ID.';
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/Type/Scalar/IntType.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 11/27/15 1:22 AM
7 | */
8 |
9 | namespace Youshido\GraphQL\Type\Scalar;
10 |
11 |
12 | class IntType extends AbstractScalarType
13 | {
14 |
15 | public function getName()
16 | {
17 | return 'Int';
18 | }
19 |
20 | public function serialize($value)
21 | {
22 | if ($value === null) {
23 | return null;
24 | } else {
25 | if (is_int($value)) {
26 | return $value;
27 | } else {
28 | $value = (int)$value;
29 |
30 | return $value != 0 ? $value : null;
31 | }
32 | }
33 | }
34 |
35 | public function isValidValue($value)
36 | {
37 | return is_null($value) || is_int($value);
38 | }
39 |
40 | public function getDescription()
41 | {
42 | return 'The `Int` scalar type represents non-fractional signed whole numeric ' .
43 | 'values. Int can represent values between -(2^53 - 1) and 2^53 - 1 since ' .
44 | 'represented in JSON as double-precision floating point numbers specified' .
45 | 'by [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point).';
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/Type/Scalar/StringType.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 11/27/15 1:05 AM
7 | */
8 |
9 | namespace Youshido\GraphQL\Type\Scalar;
10 |
11 |
12 | class StringType extends AbstractScalarType
13 | {
14 |
15 | public function getName()
16 | {
17 | return 'String';
18 | }
19 |
20 | public function serialize($value)
21 | {
22 | if ($value === true) {
23 | return 'true';
24 | } elseif ($value === false) {
25 | return 'false';
26 | } elseif ($value === null) {
27 | return null;
28 | }
29 |
30 | if(is_array($value)) {
31 | return '';
32 | }
33 |
34 | return (string) $value;
35 | }
36 |
37 | public function isValidValue($value)
38 | {
39 | return is_null($value) || is_scalar($value) || ((is_object($value) && method_exists($value, '__toString')));
40 | }
41 |
42 | public function getDescription()
43 | {
44 | return 'The `String` scalar type represents textual data, represented as UTF-8 ' .
45 | 'character sequences. The String type is most often used by GraphQL to ' .
46 | 'represent free-form human-readable text.';
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/src/Type/Scalar/TimestampType.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 11/27/15 1:22 AM
7 | */
8 |
9 | namespace Youshido\GraphQL\Type\Scalar;
10 |
11 |
12 | /**
13 | * Class TimestampType
14 | * @package Youshido\GraphQL\Type\Scalar
15 | * @deprecated Should not be used, to be removed in 1.5
16 | */
17 | class TimestampType extends AbstractScalarType
18 | {
19 |
20 | public function getName()
21 | {
22 | return 'Timestamp';
23 | }
24 |
25 | /**
26 | * @param $value \DateTime
27 | * @return null|string
28 | */
29 | public function serialize($value)
30 | {
31 | if ($value === null || !is_object($value)) {
32 | return null;
33 | }
34 |
35 | return $value->getTimestamp();
36 | }
37 |
38 | public function isValidValue($value)
39 | {
40 | if (is_null($value) || is_object($value)) {
41 | return true;
42 | }
43 |
44 | return is_int($value);
45 | }
46 |
47 | public function getDescription()
48 | {
49 | return 'DEPRECATED. Will be converted to a real timestamp';
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/src/Type/SchemaDirectivesList.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Type;
9 |
10 | use Youshido\GraphQL\Directive\DirectiveInterface;
11 |
12 |
13 | class SchemaDirectivesList
14 | {
15 |
16 | private $directivesList = [];
17 |
18 | /**
19 | * @param array $directives
20 | *
21 | * @throws
22 | * @return $this
23 | */
24 | public function addDirectives($directives)
25 | {
26 | if (!is_array($directives)) {
27 | throw new \Exception('addDirectives accept only array of directives');
28 | }
29 | foreach ($directives as $directive) {
30 | $this->addDirective($directive);
31 | }
32 |
33 | return $this;
34 | }
35 |
36 | /**
37 | * @param DirectiveInterface $directive
38 | *
39 | * @return $this
40 | */
41 | public function addDirective(DirectiveInterface $directive)
42 | {
43 | $directiveName = $this->getDirectiveName($directive);
44 | if ($this->isDirectiveNameRegistered($directiveName)) return $this;
45 |
46 | $this->directivesList[$directiveName] = $directive;
47 |
48 | return $this;
49 | }
50 |
51 | private function getDirectiveName($directive)
52 | {
53 | if (is_string($directive)) return $directive;
54 | if (is_object($directive) && $directive instanceof DirectiveInterface) {
55 | return $directive->getName();
56 | }
57 | throw new \Exception('Invalid directive passed to Schema');
58 | }
59 |
60 | public function isDirectiveNameRegistered($directiveName)
61 | {
62 | return (isset($this->directivesList[$directiveName]));
63 | }
64 |
65 | public function getDirectives()
66 | {
67 | return $this->directivesList;
68 | }
69 |
70 | }
--------------------------------------------------------------------------------
/src/Type/SchemaTypesList.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 10/7/16 3:36 PM
7 | */
8 |
9 | namespace Youshido\GraphQL\Type;
10 |
11 |
12 | class SchemaTypesList
13 | {
14 |
15 | private $typesList = [];
16 |
17 | /**
18 | * @param array $types
19 | * @throws
20 | * @return $this
21 | */
22 | public function addTypes($types)
23 | {
24 | if (!is_array($types)) {
25 | throw new \Exception('addTypes accept only array of types');
26 | }
27 | foreach($types as $type) {
28 | $this->addType($type);
29 | }
30 | return $this;
31 | }
32 |
33 | public function getTypes()
34 | {
35 | return $this->typesList;
36 | }
37 |
38 | /**
39 | * @param TypeInterface $type
40 | * @return $this
41 | */
42 | public function addType(TypeInterface $type)
43 | {
44 | $typeName = $this->getTypeName($type);
45 | if ($this->isTypeNameRegistered($typeName)) return $this;
46 |
47 | $this->typesList[$typeName] = $type;
48 | return $this;
49 | }
50 |
51 | public function isTypeNameRegistered($typeName)
52 | {
53 | return (isset($this->typesList[$typeName]));
54 | }
55 |
56 | private function getTypeName($type) {
57 | if (is_string($type)) return $type;
58 | if (is_object($type) && $type instanceof AbstractType) {
59 | return $type->getName();
60 | }
61 | throw new \Exception('Invalid type passed to Schema');
62 | }
63 |
64 | }
--------------------------------------------------------------------------------
/src/Type/Traits/ArgumentsAwareObjectTrait.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 5:07 PM 5/14/16
7 | */
8 |
9 | namespace Youshido\GraphQL\Type\Traits;
10 |
11 |
12 | use Youshido\GraphQL\Config\Traits\ConfigAwareTrait;
13 |
14 | /**
15 | * Class ArgumentsAwareObjectTrait
16 | * @package Youshido\GraphQL\Type\Traits
17 | * @codeCoverageIgnore
18 | *
19 | * @deprecated To be removed during the release optimization
20 | */
21 | trait ArgumentsAwareObjectTrait
22 | {
23 | use ConfigAwareTrait;
24 |
25 | public function addArgument($argument, $argumentInfo = null)
26 | {
27 | return $this->getConfig()->addArgument($argument, $argumentInfo);
28 | }
29 |
30 | public function removeArgument($argumentName)
31 | {
32 | return $this->getConfig()->removeArgument($argumentName);
33 | }
34 |
35 | public function getArguments()
36 | {
37 | return $this->getConfig()->getArguments();
38 | }
39 |
40 | public function getArgument($argumentName)
41 | {
42 | return $this->getConfig()->getArgument($argumentName);
43 | }
44 |
45 | public function hasArgument($argumentName)
46 | {
47 | return $this->getConfig()->hasArgument($argumentName);
48 | }
49 |
50 | public function hasArguments()
51 | {
52 | return $this->getConfig()->hasArguments();
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/src/Type/Traits/AutoNameTrait.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 5/4/16 9:18 PM
7 | */
8 |
9 | namespace Youshido\GraphQL\Type\Traits;
10 | use Youshido\GraphQL\Field\FieldInterface;
11 |
12 | /**
13 | * Class AutoNameTrait
14 | * @package Youshido\GraphQL\Type\Traits
15 | */
16 | trait AutoNameTrait
17 | {
18 |
19 | public function getName()
20 | {
21 | if (!empty($this->config)) {
22 | return $this->config->getName();
23 | }
24 |
25 | $className = get_called_class();
26 |
27 | if ($prevPos = strrpos($className, '\\')) {
28 | $className = substr($className, $prevPos + 1);
29 | }
30 | if (substr($className, -5) == 'Field') {
31 | $className = lcfirst(substr($className, 0, -5));
32 | } elseif (substr($className, -4) == 'Type') {
33 | $className = substr($className, 0, -4);
34 | }
35 |
36 | if ($this instanceof FieldInterface) {
37 | $className = lcfirst($className);
38 | }
39 |
40 |
41 | return $className;
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/Type/Traits/FieldsArgumentsAwareObjectTrait.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 5:12 PM 5/14/16
7 | */
8 |
9 | namespace Youshido\GraphQL\Type\Traits;
10 |
11 |
12 | trait FieldsArgumentsAwareObjectTrait
13 | {
14 | use FieldsAwareObjectTrait;
15 |
16 | protected $hasArgumentCache = null;
17 |
18 | public function addArguments($argumentsList)
19 | {
20 | return $this->getConfig()->addArguments($argumentsList);
21 | }
22 |
23 | public function removeArgument($argumentName)
24 | {
25 | return $this->getConfig()->removeArgument($argumentName);
26 | }
27 |
28 | public function addArgument($argument, $ArgumentInfo = null)
29 | {
30 | return $this->getConfig()->addArgument($argument, $ArgumentInfo);
31 | }
32 |
33 | public function getArguments()
34 | {
35 | return $this->getConfig()->getArguments();
36 | }
37 |
38 | public function getArgument($argumentName)
39 | {
40 | return $this->getConfig()->getArgument($argumentName);
41 | }
42 |
43 | public function hasArgument($argumentName)
44 | {
45 | return $this->getConfig()->hasArgument($argumentName);
46 | }
47 |
48 | public function hasArguments()
49 | {
50 | return $this->hasArgumentCache === null ? ($this->hasArgumentCache = $this->getConfig()->hasArguments()) : $this->hasArgumentCache;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/Type/Traits/FieldsAwareObjectTrait.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 5:07 PM 5/14/16
7 | */
8 |
9 | namespace Youshido\GraphQL\Type\Traits;
10 |
11 |
12 | use Youshido\GraphQL\Config\Traits\ConfigAwareTrait;
13 |
14 | trait FieldsAwareObjectTrait
15 | {
16 | use ConfigAwareTrait;
17 |
18 | public function addFields($fieldsList)
19 | {
20 | $this->getConfig()->addFields($fieldsList);
21 |
22 | return $this;
23 | }
24 |
25 | public function addField($field, $fieldInfo = null)
26 | {
27 | $this->getConfig()->addField($field, $fieldInfo);
28 |
29 | return $this;
30 | }
31 |
32 | public function getFields()
33 | {
34 | return $this->getConfig()->getFields();
35 | }
36 |
37 | public function getField($fieldName)
38 | {
39 | return $this->getConfig()->getField($fieldName);
40 | }
41 |
42 | public function hasField($fieldName)
43 | {
44 | return $this->getConfig()->hasField($fieldName);
45 | }
46 |
47 | public function hasFields()
48 | {
49 | return $this->getConfig()->hasFields();
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/src/Type/TypeFactory.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 5/11/16 9:19 PM
7 | */
8 |
9 | namespace Youshido\GraphQL\Type;
10 |
11 |
12 | use Youshido\GraphQL\Exception\ConfigurationException;
13 | use Youshido\GraphQL\Type\Scalar\AbstractScalarType;
14 |
15 | class TypeFactory
16 | {
17 | private static $objectsHash = [];
18 |
19 | /**
20 | * @param string $type
21 | *
22 | * @throws ConfigurationException
23 | * @return AbstractScalarType
24 | */
25 | public static function getScalarType($type)
26 | {
27 | if (TypeService::isScalarType($type)) {
28 | if (is_object($type)) {
29 | return $type;
30 | }
31 | if (empty(self::$objectsHash[$type])) {
32 | $name = ucfirst($type);
33 |
34 | $name = $name == 'Datetime' ? 'DateTime' : $name;
35 | $name = $name == 'Datetimetz' ? 'DateTimeTz' : $name;
36 |
37 | $className = 'Youshido\GraphQL\Type\Scalar\\' . $name . 'Type';
38 | self::$objectsHash[$type] = new $className();
39 | }
40 |
41 | return self::$objectsHash[$type];
42 | } else {
43 | throw new ConfigurationException('Configuration problem with type ' . $type);
44 | }
45 | }
46 |
47 | /**
48 | * @return string[]
49 | */
50 | public static function getScalarTypesNames()
51 | {
52 | return [
53 | TypeMap::TYPE_INT,
54 | TypeMap::TYPE_FLOAT,
55 | TypeMap::TYPE_STRING,
56 | TypeMap::TYPE_BOOLEAN,
57 | TypeMap::TYPE_ID,
58 | TypeMap::TYPE_DATETIME,
59 | TypeMap::TYPE_DATE,
60 | TypeMap::TYPE_TIMESTAMP,
61 | TypeMap::TYPE_DATETIMETZ,
62 | ];
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/Type/TypeInterface.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 11/27/15 12:51 AM
7 | */
8 |
9 | namespace Youshido\GraphQL\Type;
10 |
11 | Interface TypeInterface extends InputTypeInterface
12 | {
13 |
14 | }
--------------------------------------------------------------------------------
/src/Type/TypeMap.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 11/30/15 12:36 AM
7 | */
8 |
9 | namespace Youshido\GraphQL\Type;
10 |
11 | class TypeMap
12 | {
13 |
14 | const KIND_SCALAR = 'SCALAR';
15 | const KIND_OBJECT = 'OBJECT';
16 | const KIND_INTERFACE = 'INTERFACE';
17 | const KIND_UNION = 'UNION';
18 | const KIND_ENUM = 'ENUM';
19 | const KIND_INPUT_OBJECT = 'INPUT_OBJECT';
20 | const KIND_LIST = 'LIST';
21 | const KIND_NON_NULL = 'NON_NULL';
22 |
23 | const TYPE_INT = 'int';
24 | const TYPE_FLOAT = 'float';
25 | const TYPE_STRING = 'string';
26 | const TYPE_BOOLEAN = 'boolean';
27 | const TYPE_ID = 'id';
28 | const TYPE_DATETIME = 'datetime';
29 | const TYPE_DATETIMETZ = 'datetimetz';
30 | const TYPE_DATE = 'date';
31 | const TYPE_TIMESTAMP = 'timestamp';
32 |
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/Type/Union/AbstractUnionType.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 12/5/15 12:12 AM
7 | */
8 |
9 | namespace Youshido\GraphQL\Type\Union;
10 |
11 |
12 | use Youshido\GraphQL\Config\Object\UnionTypeConfig;
13 | use Youshido\GraphQL\Config\Traits\ConfigAwareTrait;
14 | use Youshido\GraphQL\Type\AbstractInterfaceTypeInterface;
15 | use Youshido\GraphQL\Type\AbstractType;
16 | use Youshido\GraphQL\Type\Object\AbstractObjectType;
17 | use Youshido\GraphQL\Type\Scalar\AbstractScalarType;
18 | use Youshido\GraphQL\Type\Traits\AutoNameTrait;
19 | use Youshido\GraphQL\Type\TypeMap;
20 |
21 | abstract class AbstractUnionType extends AbstractType implements AbstractInterfaceTypeInterface
22 | {
23 |
24 | use ConfigAwareTrait, AutoNameTrait;
25 |
26 | protected $isFinal = false;
27 |
28 | /**
29 | * ObjectType constructor.
30 | * @param $config
31 | */
32 | public function __construct($config = [])
33 | {
34 | if (empty($config)) {
35 | $config['name'] = $this->getName();
36 | $config['types'] = $this->getTypes();
37 | }
38 |
39 | $this->config = new UnionTypeConfig($config, $this, $this->isFinal);
40 | }
41 |
42 | /**
43 | * @return AbstractObjectType[]|AbstractScalarType[]
44 | */
45 | abstract public function getTypes();
46 |
47 | public function getKind()
48 | {
49 | return TypeMap::KIND_UNION;
50 | }
51 |
52 | public function getNamedType()
53 | {
54 | return $this;
55 | }
56 |
57 | public function isValidValue($value)
58 | {
59 | return true;
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/src/Type/Union/UnionType.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 11:54 AM 5/5/16
7 | */
8 |
9 | namespace Youshido\GraphQL\Type\Union;
10 |
11 | final class UnionType extends AbstractUnionType
12 | {
13 |
14 | protected $isFinal = true;
15 |
16 | public function resolveType($object)
17 | {
18 | $callable = $this->getConfigValue('resolveType');
19 |
20 | return $callable($object);
21 | }
22 |
23 | public function getTypes()
24 | {
25 | return $this->getConfig()->get('types', []);
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/Validator/ConfigValidator/ConfigValidatorInterface.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Validator\ConfigValidator;
9 |
10 |
11 | interface ConfigValidatorInterface
12 | {
13 |
14 | public function validate($data, $rules = [], $allowExtraFields = null);
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/Validator/ConfigValidator/Rules/ValidationRuleInterface.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 11/28/15 6:11 PM
7 | */
8 |
9 | namespace Youshido\GraphQL\Validator\ConfigValidator\Rules;
10 |
11 |
12 | interface ValidationRuleInterface
13 | {
14 | public function validate($data, $ruleInfo);
15 | }
--------------------------------------------------------------------------------
/src/Validator/ErrorContainer/ErrorContainerInterface.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Validator\ErrorContainer;
9 |
10 |
11 | interface ErrorContainerInterface
12 | {
13 |
14 | public function addError(\Exception $exception);
15 |
16 | public function mergeErrors(ErrorContainerInterface $errorContainer);
17 |
18 | public function hasErrors();
19 |
20 | public function getErrors();
21 |
22 | public function getErrorsArray();
23 |
24 | public function clearErrors();
25 |
26 | }
--------------------------------------------------------------------------------
/src/Validator/RequestValidator/RequestValidatorInterface.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Validator\RequestValidator;
9 |
10 |
11 | use Youshido\GraphQL\Execution\Request;
12 |
13 | interface RequestValidatorInterface
14 | {
15 |
16 | public function validate(Request $request);
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/Validator/ResolveValidator/ResolveValidatorInterface.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\GraphQL\Validator\ResolveValidator;
9 |
10 |
11 | use Youshido\GraphQL\Execution\Request;
12 | use Youshido\GraphQL\Field\FieldInterface;
13 | use Youshido\GraphQL\Parser\Ast\Interfaces\FieldInterface as AstFieldInterface;
14 | use Youshido\GraphQL\Type\AbstractType;
15 | use Youshido\GraphQL\Type\InterfaceType\AbstractInterfaceType;
16 | use Youshido\GraphQL\Type\Union\AbstractUnionType;
17 |
18 | interface ResolveValidatorInterface
19 | {
20 |
21 | public function assetTypeHasField(AbstractType $objectType, AstFieldInterface $ast);
22 |
23 | public function assertValidArguments(FieldInterface $field, AstFieldInterface $query, Request $request);
24 |
25 | public function assertValidResolvedValueForField(FieldInterface $field, $resolvedValue);
26 |
27 | public function assertTypeImplementsInterface(AbstractType $type, AbstractInterfaceType $interface);
28 |
29 | public function assertTypeInUnionTypes(AbstractType $type, AbstractUnionType $unionType);
30 | }
31 |
--------------------------------------------------------------------------------
/tests/DataProvider/TestConfig.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 5/11/16 10:45 PM
7 | */
8 |
9 | namespace Youshido\Tests\DataProvider;
10 |
11 |
12 | use Youshido\GraphQL\Config\AbstractConfig;
13 | use Youshido\GraphQL\Type\TypeService;
14 |
15 | class TestConfig extends AbstractConfig
16 | {
17 | public function getRules()
18 | {
19 | return [
20 | 'name' => ['type' => TypeService::TYPE_ANY, 'required' => true],
21 | 'resolve' => ['type' => TypeService::TYPE_CALLABLE, 'final' => true],
22 | ];
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/tests/DataProvider/TestConfigExtraFields.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 5/12/16 9:27 PM
7 | */
8 |
9 | namespace Youshido\Tests\DataProvider;
10 |
11 |
12 | use Youshido\GraphQL\Config\AbstractConfig;
13 | use Youshido\GraphQL\Type\TypeService;
14 |
15 | class TestConfigExtraFields extends AbstractConfig
16 | {
17 |
18 | protected $extraFieldsAllowed = true;
19 |
20 | public function getRules()
21 | {
22 | return [
23 | 'name' => ['type' => TypeService::TYPE_ANY, 'required' => true]
24 | ];
25 | }
26 |
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/tests/DataProvider/TestConfigInvalidRule.php:
--------------------------------------------------------------------------------
1 | ['type' => TypeService::TYPE_ANY, 'required' => true],
15 | 'invalidRuleField' => ['type' => TypeService::TYPE_ANY, 'invalid rule' => true]
16 | ];
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/tests/DataProvider/TestEmptySchema.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 12/3/15 11:28 PM
7 | */
8 |
9 | namespace Youshido\Tests\DataProvider;
10 |
11 | use Youshido\GraphQL\Config\Schema\SchemaConfig;
12 | use Youshido\GraphQL\Schema\AbstractSchema;
13 |
14 |
15 | class TestEmptySchema extends AbstractSchema
16 | {
17 | public function build(SchemaConfig $config)
18 | {
19 | }
20 |
21 |
22 | public function getName($config)
23 | {
24 | return 'TestSchema';
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/tests/DataProvider/TestEnumType.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 5/12/16 6:42 PM
7 | */
8 |
9 | namespace Youshido\Tests\DataProvider;
10 |
11 |
12 | use Youshido\GraphQL\Type\Enum\AbstractEnumType;
13 |
14 | class TestEnumType extends AbstractEnumType
15 | {
16 | public function getValues()
17 | {
18 | return [
19 | [
20 | 'name' => 'FINISHED',
21 | 'value' => 1,
22 | ],
23 | [
24 | 'name' => 'NEW',
25 | 'value' => 0,
26 | ]
27 | ];
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/tests/DataProvider/TestExtendedType.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 8/14/16 1:19 PM
7 | */
8 |
9 | namespace Youshido\Tests\DataProvider;
10 |
11 |
12 | use Youshido\GraphQL\Config\Object\ObjectTypeConfig;
13 | use Youshido\GraphQL\Type\Object\AbstractObjectType;
14 | use Youshido\GraphQL\Type\Scalar\StringType;
15 |
16 | class TestExtendedType extends AbstractObjectType
17 | {
18 | public function build($config)
19 | {
20 | $config->applyInterface(new TestInterfaceType())
21 | ->addField('ownField', new StringType());
22 | }
23 |
24 |
25 | }
--------------------------------------------------------------------------------
/tests/DataProvider/TestField.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\Tests\DataProvider;
9 |
10 | use Youshido\GraphQL\Execution\ResolveInfo;
11 | use Youshido\GraphQL\Field\AbstractField;
12 | use Youshido\GraphQL\Type\Object\AbstractObjectType;
13 | use Youshido\GraphQL\Type\Scalar\IntType;
14 |
15 | class TestField extends AbstractField
16 | {
17 |
18 | /**
19 | * @return AbstractObjectType
20 | */
21 | public function getType()
22 | {
23 | return new IntType();
24 | }
25 |
26 | public function resolve($value, array $args, ResolveInfo $info)
27 | {
28 | return $value;
29 | }
30 |
31 | public function getDescription()
32 | {
33 | return 'description';
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/tests/DataProvider/TestInputField.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\Tests\DataProvider;
9 |
10 |
11 | use Youshido\GraphQL\Field\AbstractInputField;
12 | use Youshido\GraphQL\Type\InputTypeInterface;
13 | use Youshido\GraphQL\Type\Scalar\IntType;
14 |
15 | class TestInputField extends AbstractInputField
16 | {
17 |
18 | /**
19 | * @return InputTypeInterface
20 | */
21 | public function getType()
22 | {
23 | return new IntType();
24 | }
25 |
26 | public function getDescription()
27 | {
28 | return 'description';
29 | }
30 |
31 | public function getDefaultValue()
32 | {
33 | return 'default';
34 | }
35 | }
--------------------------------------------------------------------------------
/tests/DataProvider/TestInputObjectType.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 4:16 PM 5/13/16
7 | */
8 |
9 | namespace Youshido\Tests\DataProvider;
10 |
11 |
12 | use Youshido\GraphQL\Type\InputObject\AbstractInputObjectType;
13 | use Youshido\GraphQL\Type\NonNullType;
14 | use Youshido\GraphQL\Type\Scalar\StringType;
15 |
16 | class TestInputObjectType extends AbstractInputObjectType
17 | {
18 | public function build($config)
19 | {
20 | $config->addField('name', new NonNullType(new StringType()));
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/tests/DataProvider/TestInterfaceType.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 5/12/16 4:24 PM
7 | */
8 |
9 | namespace Youshido\Tests\DataProvider;
10 |
11 |
12 | use Youshido\GraphQL\Type\InterfaceType\AbstractInterfaceType;
13 | use Youshido\GraphQL\Type\Scalar\StringType;
14 |
15 | class TestInterfaceType extends AbstractInterfaceType
16 | {
17 |
18 | public function resolveType($object)
19 | {
20 | return is_object($object) ? $object : new TestObjectType();
21 | }
22 |
23 | public function build($config)
24 | {
25 | $config->addField('name', new StringType());
26 | }
27 |
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/tests/DataProvider/TestListType.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 5/15/16 3:19 PM
7 | */
8 |
9 | namespace Youshido\Tests\DataProvider;
10 |
11 |
12 | use Youshido\GraphQL\Type\ListType\AbstractListType;
13 | use Youshido\GraphQL\Type\Scalar\StringType;
14 |
15 | class TestListType extends AbstractListType
16 | {
17 | public function getItemType()
18 | {
19 | return new StringType();
20 | }
21 |
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/tests/DataProvider/TestMutationObjectType.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 2:00 PM 5/15/16
7 | */
8 |
9 | namespace Youshido\Tests\DataProvider;
10 |
11 |
12 | use Youshido\GraphQL\Type\Object\AbstractMutationObjectType;
13 | use Youshido\GraphQL\Type\Scalar\IntType;
14 | use Youshido\GraphQL\Type\Scalar\StringType;
15 |
16 | class TestMutationObjectType extends AbstractMutationObjectType
17 | {
18 | public function getOutputType()
19 | {
20 | return new StringType();
21 | }
22 |
23 | public function build($config)
24 | {
25 | $this->addArgument('increment', new IntType());
26 | }
27 |
28 |
29 | }
--------------------------------------------------------------------------------
/tests/DataProvider/TestResolveInfo.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 5/20/16 12:41 AM
7 | */
8 |
9 | namespace Youshido\Tests\DataProvider;
10 |
11 |
12 | use Youshido\GraphQL\Execution\Context\ExecutionContext;
13 | use Youshido\GraphQL\Execution\ResolveInfo;
14 |
15 | class TestResolveInfo
16 | {
17 | public static function createTestResolveInfo($field = null)
18 | {
19 | if (empty($field)) {
20 | $field = new TestField();
21 | }
22 |
23 | return new ResolveInfo($field, [], new ExecutionContext(new TestSchema()));
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/tests/DataProvider/TestSchema.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 10:48 PM 5/14/16
7 | */
8 |
9 | namespace Youshido\Tests\DataProvider;
10 |
11 |
12 | use Youshido\GraphQL\Config\Schema\SchemaConfig;
13 | use Youshido\GraphQL\Execution\ResolveInfo;
14 | use Youshido\GraphQL\Schema\AbstractSchema;
15 | use Youshido\GraphQL\Type\ListType\ListType;
16 | use Youshido\GraphQL\Type\Scalar\IntType;
17 |
18 | class TestSchema extends AbstractSchema
19 | {
20 | private $testStatusValue = 0;
21 |
22 | public function build(SchemaConfig $config)
23 | {
24 | $config->getQuery()->addFields([
25 | 'me' => [
26 | 'type' => new TestObjectType(),
27 | 'resolve' => function ($value, $args, ResolveInfo $info) {
28 | return $info->getReturnType()->getData();
29 | }
30 | ],
31 | 'status' => [
32 | 'type' => new TestEnumType(),
33 | 'resolve' => function () {
34 | return $this->testStatusValue;
35 | }
36 | ],
37 | ]);
38 | $config->getMutation()->addFields([
39 | 'updateStatus' => [
40 | 'type' => new TestEnumType(),
41 | 'resolve' => function () {
42 | return $this->testStatusValue;
43 | },
44 | 'args' => [
45 | 'newStatus' => new TestEnumType(),
46 | 'list' => new ListType(new IntType())
47 | ]
48 | ]
49 | ]);
50 | }
51 |
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/tests/DataProvider/TestTimeType.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 8/14/16 12:26 PM
7 | */
8 |
9 | namespace Youshido\Tests\DataProvider;
10 |
11 |
12 | use Youshido\GraphQL\Type\Scalar\AbstractScalarType;
13 |
14 | class TestTimeType extends AbstractScalarType
15 | {
16 |
17 | public function getName()
18 | {
19 | return 'TestTime';
20 | }
21 |
22 | /**
23 | * @param $value \DateTime
24 | * @return null|string
25 | */
26 | public function serialize($value)
27 | {
28 | if ($value === null) {
29 | return null;
30 | }
31 |
32 | return $value instanceof \DateTime ? $value->format('H:i:s') : $value;
33 | }
34 |
35 | public function isValidValue($value)
36 | {
37 | if (is_object($value)) {
38 | return true;
39 | }
40 |
41 | $d = \DateTime::createFromFormat('H:i:s', $value);
42 |
43 | return $d && $d->format('H:i:s') == $value;
44 | }
45 |
46 | public function getDescription()
47 | {
48 | return 'Representation time in "H:i:s" format';
49 | }
50 |
51 | }
--------------------------------------------------------------------------------
/tests/DataProvider/TestUnionType.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\Tests\DataProvider;
9 |
10 |
11 | use Youshido\GraphQL\Type\Union\AbstractUnionType;
12 |
13 | class TestUnionType extends AbstractUnionType
14 | {
15 |
16 | public function getTypes()
17 | {
18 | return [
19 | new TestObjectType()
20 | ];
21 | }
22 |
23 | public function resolveType($object)
24 | {
25 | return $object;
26 | }
27 |
28 | public function getDescription()
29 | {
30 | return 'Union collect cars types';
31 | }
32 |
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/tests/Issues/Issue109/Issue109Test.php:
--------------------------------------------------------------------------------
1 | processPayload('
15 | query ($postId: Int, $commentId: Int) {
16 | latestPost(id: $postId) {
17 | id(comment_id: $commentId),
18 | comments(comment_id: $commentId) {
19 | comment_id
20 | }
21 | }
22 | }',
23 | [
24 | 'postId' => 1,
25 | 'commentId' => 100
26 | ])->getResponseData();
27 | $this->assertEquals(['data' => ['latestPost' => [
28 | 'id' => 1,
29 | 'comments' => [
30 | ['comment_id' => 100]
31 | ]
32 | ]]], $response);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/tests/Issues/Issue171/Issue171Schema.php:
--------------------------------------------------------------------------------
1 | getQuery()->addField(
14 | 'plan',
15 | [
16 | 'type' => new PlanType(),
17 | ]
18 | );
19 | }
20 | }
21 |
22 | class PlanType extends AbstractObjectType
23 | {
24 | public function build($config)
25 | {
26 | $config->addField('kpi_status', [
27 | 'type' => new KpiStatusType(),
28 | ]);
29 | }
30 | }
31 |
32 | class KpiStatusType extends AbstractEnumType
33 | {
34 | public function getValues()
35 | {
36 | return [
37 | [
38 | 'name' => 'BAD',
39 | 'value' => 'Bad',
40 | ],
41 | [
42 | 'name' => 'GOOD',
43 | 'value' => 'Good',
44 | ],
45 | [
46 | 'name' => 'WARNING',
47 | 'value' => 'Warning',
48 | ]
49 | ];
50 | }
51 | }
--------------------------------------------------------------------------------
/tests/Issues/Issue201/Issue201Test.php:
--------------------------------------------------------------------------------
1 | new ObjectType([
23 | 'name' => 'RootQuery',
24 | 'fields' => [
25 | 'user' => [
26 | 'type' => new StringType(),
27 | ],
28 | ],
29 | ]),
30 | ]);
31 |
32 | $schema->getQueryType()->addFields([
33 | 'user' => new StringType(),
34 | ]);
35 |
36 | $schemaValidator = new SchemaValidator();
37 | $schemaValidator->validate($schema);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/tests/Issues/Issue210/TypeServiceTest.php:
--------------------------------------------------------------------------------
1 | assertEquals('Foo', TypeService::getPropertyValue($object, 'issuer'));
16 | $this->assertEquals('something', TypeService::getPropertyValue($object, 'something'));
17 | $this->assertEquals('Bar', TypeService::getPropertyValue($object, 'issuerName'));
18 | }
19 | }
20 |
21 | class DummyObjectWithTrickyGetters
22 | {
23 | public function getIssuer()
24 | {
25 | return 'Foo';
26 | }
27 |
28 | public function something()
29 | {
30 | return 'something';
31 | }
32 |
33 | public function issuerName()
34 | {
35 | return 'Bar';
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/tests/Issues/Issue220/ResolvableObjectTraitTest.php:
--------------------------------------------------------------------------------
1 | 'scalarField',
18 | 'type' => new StringType(),
19 | ]);
20 |
21 | $resolveInfo = TestResolveInfo::createTestResolveInfo($fieldWithResolve);
22 |
23 | $this->assertEquals(null, $fieldWithResolve->resolve([], [], $resolveInfo));
24 | }
25 |
26 | public function testValueNotFoundInResolveObjectType()
27 | {
28 | $fieldWithResolve = new Field([
29 | 'name' => 'scalarField',
30 | 'type' => new ArticleType(),
31 | ]);
32 |
33 | $resolveInfo = TestResolveInfo::createTestResolveInfo($fieldWithResolve);
34 |
35 | $this->assertEquals(null, $fieldWithResolve->resolve([], [], $resolveInfo));
36 | }
37 |
38 | public function testValueFoundInResolve()
39 | {
40 | $fieldWithResolve = new Field([
41 | 'name' => 'scalarField',
42 | 'type' => new StringType(),
43 | ]);
44 |
45 | $resolveInfo = TestResolveInfo::createTestResolveInfo($fieldWithResolve);
46 |
47 | $this->assertEquals('foo', $fieldWithResolve->resolve(['scalarField' => 'foo'], [], $resolveInfo));
48 | }
49 | }
50 |
51 | class ArticleType extends AbstractObjectType
52 | {
53 | public function build($config)
54 | {
55 | $config->addFields([
56 | 'title' => new StringType(),
57 | ]);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/tests/Issues/Issue90/Issue90Schema.php:
--------------------------------------------------------------------------------
1 | setQuery(
15 | new ObjectType([
16 | 'name' => 'QueryType',
17 | 'fields' => [
18 | 'echo' => [
19 | 'type' => new DateTimeType('Y-m-d H:ia'),
20 | 'args' => [
21 | 'date' => new DateTimeType('Y-m-d H:ia')
22 | ],
23 | 'resolve' => function ($value, $args, $info) {
24 |
25 | if (isset($args['date'])) {
26 | return $args['date'];
27 | }
28 |
29 | return null;
30 | }
31 | ]
32 | ]
33 | ])
34 | );
35 |
36 | $config->setMutation(
37 | new ObjectType([
38 | 'name' => 'MutationType',
39 | 'fields' => [
40 | 'echo' => [
41 | 'type' => new DateTimeType('Y-m-d H:ia'),
42 | 'args' => [
43 | 'date' => new DateTimeType('Y-m-d H:ia')
44 | ],
45 | 'resolve' => function ($value, $args, $info) {
46 |
47 | if (isset($args['date'])) {
48 | return $args['date'];
49 | }
50 |
51 | return null;
52 | }
53 | ]
54 | ]
55 | ])
56 | );
57 | }
58 |
59 | }
--------------------------------------------------------------------------------
/tests/Issues/Issue98/TypeServiceTest.php:
--------------------------------------------------------------------------------
1 | assertEquals('getfoo', TypeService::getPropertyValue($object, 'foo'));
15 | $this->assertEquals('getbar', TypeService::getPropertyValue($object, 'anything'));
16 | }
17 |
18 | public function testPropertyGetValueWithMagicCall()
19 | {
20 | $object = new DummyObjectWithMagicCall();
21 |
22 | // __call() should not be considered by default
23 | $this->assertNull(TypeService::getPropertyValue($object, 'foo'));
24 | $this->assertNull(TypeService::getPropertyValue($object, 'anything'));
25 |
26 | //$this->assertEquals('callfoo', TypeService::getPropertyValue($object, 'foo'));
27 | //$this->assertEquals('callbar', TypeService::getPropertyValue($object, 'anything'));
28 | }
29 | }
30 |
31 | class DummyObjectWithMagicGet
32 | {
33 | public function __get($name)
34 | {
35 | if ($name === 'foo') {
36 | return 'getfoo';
37 | }
38 |
39 | return 'getbar';
40 | }
41 |
42 | }
43 |
44 | class DummyObjectWithMagicCall
45 | {
46 | public function __call($name, $arguments)
47 | {
48 | if ($name === 'foo') {
49 | return 'callfoo';
50 | }
51 |
52 | return 'callbar';
53 | }
54 | }
55 |
56 |
--------------------------------------------------------------------------------
/tests/Issues/Issue99/Issue99Test.php:
--------------------------------------------------------------------------------
1 | processPayload(sprintf("{ items{id, custom(argX: {x: \"%s\"}){ value } } }", self::BUG_NOT_EXISTS_VALUE));
21 | $res = $processor->getResponseData();
22 |
23 | self::assertTrue(isset($res['data']['items']));
24 |
25 | foreach($res['data']['items'] as $item) {
26 | self::assertTrue(isset($item['custom']['value']));
27 | self::assertEquals(self::BUG_NOT_EXISTS_VALUE, $item['custom']['value']);
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/tests/Library/Config/FieldConfigTest.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 5/12/16 7:08 PM
7 | */
8 |
9 | namespace Youshido\Tests\Library\Config;
10 |
11 |
12 | use Youshido\GraphQL\Config\Field\FieldConfig;
13 | use Youshido\GraphQL\Type\Scalar\StringType;
14 |
15 | class FieldConfigTest extends \PHPUnit_Framework_TestCase
16 | {
17 |
18 | public function testInvalidParams()
19 | {
20 | $fieldConfig = new FieldConfig([
21 | 'name' => 'FirstName',
22 | 'type' => new StringType(),
23 | 'resolve' => function ($value, $args = [], $type = null) {
24 | return 'John';
25 | }
26 | ]);
27 |
28 | $this->assertEquals('FirstName', $fieldConfig->getName());
29 | $this->assertEquals(new StringType(), $fieldConfig->getType());
30 |
31 | $resolveFunction = $fieldConfig->getResolveFunction();
32 | $this->assertEquals('John', $resolveFunction([]));
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/tests/Library/Config/ObjectTypeConfigTest.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 5/12/16 4:17 PM
7 | */
8 |
9 | namespace Youshido\Tests\Library\Config;
10 |
11 |
12 | use Youshido\GraphQL\Config\Object\ObjectTypeConfig;
13 | use Youshido\GraphQL\Validator\ConfigValidator\ConfigValidator;
14 | use Youshido\Tests\DataProvider\TestInterfaceType;
15 |
16 | class ObjectTypeConfigTest extends \PHPUnit_Framework_TestCase
17 | {
18 |
19 | public function testCreation()
20 | {
21 | $config = new ObjectTypeConfig(['name' => 'Test'], null, false);
22 | $this->assertEquals($config->getName(), 'Test', 'Normal creation');
23 | }
24 |
25 | /**
26 | * @expectedException Youshido\GraphQL\Exception\ConfigurationException
27 | */
28 | public function testInvalidConfigNoFields()
29 | {
30 | ConfigValidator::getInstance()->assertValidConfig(
31 | new ObjectTypeConfig(['name' => 'Test'], null, true)
32 | );
33 | }
34 |
35 | /**
36 | * @expectedException Youshido\GraphQL\Exception\ConfigurationException
37 | */
38 | public function testInvalidConfigInvalidInterface()
39 | {
40 | ConfigValidator::getInstance()->assertValidConfig(
41 | new ObjectTypeConfig(['name' => 'Test', 'interfaces' => ['Invalid interface']], null, false)
42 | );
43 | }
44 |
45 | public function testInterfaces()
46 | {
47 | $testInterfaceType = new TestInterfaceType();
48 | $config = new ObjectTypeConfig(['name' => 'Test', 'interfaces' => [$testInterfaceType]], null, false);
49 | $this->assertEquals($config->getInterfaces(), [$testInterfaceType]);
50 | }
51 |
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/tests/Library/Relay/CallableFetcherTest.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 5/17/16 11:56 AM
7 | */
8 |
9 | namespace Youshido\Tests\Library\Relay;
10 |
11 |
12 | use Youshido\GraphQL\Relay\Fetcher\CallableFetcher;
13 | use Youshido\Tests\DataProvider\TestObjectType;
14 |
15 | class CallableFetcherTest extends \PHPUnit_Framework_TestCase
16 | {
17 | public function testMethods()
18 | {
19 | $fetcher = new CallableFetcher(function ($type, $id) { return ['name' => $type . ' Name', 'id' => $id]; }, function ($object) { return $object; });
20 | $this->assertEquals([
21 | 'name' => 'User Name',
22 | 'id' => 12
23 | ], $fetcher->resolveNode('User', 12));
24 |
25 | $object = new TestObjectType();
26 | $this->assertEquals($object, $fetcher->resolveType($object));
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/tests/Library/Relay/GlobalIdFieldTest.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 10:51 PM 5/18/16
7 | */
8 |
9 | namespace Youshido\Tests\Library\Relay;
10 |
11 |
12 | use Youshido\GraphQL\Relay\Field\GlobalIdField;
13 | use Youshido\GraphQL\Type\NonNullType;
14 | use Youshido\GraphQL\Type\Scalar\IdType;
15 |
16 | class GlobalIdFieldTest extends \PHPUnit_Framework_TestCase
17 | {
18 |
19 | public function testSimpleMethods()
20 | {
21 | $typeName = 'user';
22 | $field = new GlobalIdField($typeName);
23 | $this->assertEquals('id', $field->getName());
24 | $this->assertEquals('The ID of an object', $field->getDescription());
25 | $this->assertEquals(new NonNullType(new IdType()), $field->getType());
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/tests/Library/Relay/MutationTest.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 2:11 PM 5/19/16
7 | */
8 |
9 | namespace Youshido\Tests\Library\Relay;
10 |
11 |
12 | use Youshido\GraphQL\Relay\RelayMutation;
13 | use Youshido\GraphQL\Type\Scalar\IdType;
14 | use Youshido\GraphQL\Type\Scalar\IntType;
15 | use Youshido\GraphQL\Type\Scalar\StringType;
16 |
17 | class MutationTest extends \PHPUnit_Framework_TestCase
18 | {
19 |
20 | public function testCreation()
21 | {
22 | $mutation = RelayMutation::buildMutation('ship', [
23 | 'name' => new StringType()
24 | ],[
25 | 'id' => new IdType(),
26 | 'name' => new StringType()
27 | ], function($source, $args, $info) {
28 |
29 | });
30 | $this->assertEquals('ship', $mutation->getName());
31 | }
32 |
33 | /**
34 | * @expectedException \Exception
35 | */
36 | public function testInvalidType()
37 | {
38 | RelayMutation::buildMutation('ship', [
39 | 'name' => new StringType()
40 | ], new IntType(), function($source, $args, $info) {});
41 |
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/tests/Library/Relay/NodeFieldTest.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 5/17/16 10:29 PM
7 | */
8 |
9 | namespace Youshido\Tests\Library\Relay;
10 |
11 |
12 | use Youshido\GraphQL\Relay\Fetcher\CallableFetcher;
13 | use Youshido\GraphQL\Relay\Field\NodeField;
14 |
15 | class NodeFieldTest extends \PHPUnit_Framework_TestCase
16 | {
17 |
18 | public function testMethods()
19 | {
20 | $fetcher = new CallableFetcher(function () { }, function () { });
21 | $field = new NodeField($fetcher);
22 |
23 | $this->assertEquals('Fetches an object given its ID', $field->getDescription());
24 | $this->assertEquals('node', $field->getName());
25 | $this->assertEquals($fetcher, $field->getType()->getFetcher());
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/tests/Library/Relay/NodeInterfaceTypeTest.php:
--------------------------------------------------------------------------------
1 |
8 | * created: 5/17/16 11:49 AM
9 | */
10 |
11 | use Youshido\GraphQL\Relay\Fetcher\CallableFetcher;
12 | use Youshido\GraphQL\Relay\NodeInterfaceType;
13 | use Youshido\Tests\DataProvider\TestObjectType;
14 |
15 | class NodeInterfaceTypeTest extends \PHPUnit_Framework_TestCase
16 | {
17 |
18 | public function testMethods()
19 | {
20 | $type = new NodeInterfaceType();
21 | $testObject = new TestObjectType();
22 |
23 |
24 | $this->assertEquals('NodeInterface', $type->getName());
25 | $this->assertNull($type->getFetcher());
26 | $this->assertNull($type->resolveType($testObject));
27 |
28 | $fetcher = new CallableFetcher(function () { }, function () { return new TestObjectType(); });
29 | $type->setFetcher($fetcher);
30 | $this->assertEquals($fetcher, $type->getFetcher());
31 |
32 | $this->assertEquals($testObject, $type->resolveType($testObject));
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/tests/Library/Relay/NodeTest.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 3:59 PM 5/17/16
7 | */
8 |
9 | namespace Youshido\Tests\Library\Relay;
10 |
11 |
12 | use InvalidArgumentException;
13 | use Youshido\GraphQL\Relay\Node;
14 |
15 | class NodeTest extends \PHPUnit_Framework_TestCase
16 | {
17 | public function testMethods()
18 | {
19 | $global = Node::toGlobalId('user', 1);
20 | $fromGlobal = Node::fromGlobalId($global);
21 |
22 | $this->assertEquals('user', $fromGlobal[0]);
23 | $this->assertEquals(1, $fromGlobal[1]);
24 | }
25 |
26 | public function malformedIdProvider()
27 | {
28 | return [
29 | [''],
30 | [base64_encode('I have no colon')],
31 | [null],
32 | ];
33 | }
34 |
35 | /**
36 | * @dataProvider malformedIdProvider
37 | */
38 | public function testFromGlobalIdThrowsExceptionIfGivenMalformedId($idToCheck)
39 | {
40 | $this->setExpectedException(InvalidArgumentException::class);
41 | Node::fromGlobalId($idToCheck);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/tests/Library/Type/ListTypeTest.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 5/15/16 2:46 PM
7 | */
8 |
9 | namespace Youshido\Tests\Library\Type;
10 |
11 |
12 | use Youshido\GraphQL\Type\ListType\ListType;
13 | use Youshido\GraphQL\Type\Scalar\StringType;
14 | use Youshido\Tests\DataProvider\TestListType;
15 |
16 |
17 | class ListTypeTest extends \PHPUnit_Framework_TestCase
18 | {
19 |
20 | public function testInline()
21 | {
22 | $listType = new ListType(new StringType());
23 | $this->assertEquals(new StringType(), $listType->getNamedType());
24 | $this->assertEquals(new StringType(), $listType->getTypeOf());
25 | $this->assertTrue($listType->isCompositeType());
26 | $this->assertTrue($listType->isValidValue(['Test', 'Value']));
27 | $this->assertFalse($listType->isValidValue('invalid value'));
28 | }
29 |
30 | public function testStandaloneClass()
31 | {
32 | $listType = new TestListType();
33 | $this->assertEquals(new StringType(), $listType->getNamedType());
34 | }
35 |
36 | public function testListOfInputsWithArguments()
37 | {
38 |
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/tests/Library/Type/ScalarExtendTypeTest.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 8/14/16 12:16 PM
7 | */
8 |
9 | namespace Youshido\Tests\Library\Type;
10 |
11 |
12 | use Youshido\GraphQL\Execution\Processor;
13 | use Youshido\GraphQL\Schema\Schema;
14 | use Youshido\GraphQL\Type\Object\ObjectType;
15 | use Youshido\GraphQL\Type\Scalar\StringType;
16 | use Youshido\Tests\DataProvider\TestTimeType;
17 |
18 | class ScalarExtendTypeTest extends \PHPUnit_Framework_TestCase
19 | {
20 |
21 | public function testType()
22 | {
23 | $reportType = new ObjectType([
24 | 'name' => 'Report',
25 | 'fields' => [
26 | 'time' => new TestTimeType(),
27 | 'title' => new StringType(),
28 | ]
29 | ]);
30 | $processor = new Processor(new Schema([
31 | 'query' => new ObjectType([
32 | 'name' => 'RootQueryType',
33 | 'fields' => [
34 | 'latestReport' => [
35 | 'type' => $reportType,
36 | 'resolve' => function () {
37 | return [
38 | 'title' => 'Accident #1',
39 | 'time' => '13:30:12',
40 | ];
41 | }
42 | ],
43 | ]
44 | ])
45 | ])
46 | );
47 |
48 | $processor->processPayload('{ latestReport { title, time} }');
49 | $this->assertEquals(['data' => ['latestReport' => ['title' => 'Accident #1', 'time' => '13:30:12']]], $processor->getResponseData());
50 |
51 |
52 | }
53 |
54 | }
--------------------------------------------------------------------------------
/tests/Library/Type/SchemaDirectivesListTest.php:
--------------------------------------------------------------------------------
1 | addDirective(
14 | new Directive([
15 | 'name' => 'testDirective'
16 | ])
17 | );
18 | $this->assertTrue($directiveList->isDirectiveNameRegistered('testDirective'));
19 | }
20 |
21 | public function testCanAddMultipleDirectives()
22 | {
23 | $directiveList = new SchemaDirectivesList();
24 | $directiveList->addDirectives([
25 | new Directive([
26 | 'name' => 'testDirectiveOne'
27 | ]),
28 | new Directive([
29 | 'name' => 'testDirectiveTwo'
30 | ]),
31 | ]);
32 | $this->assertTrue($directiveList->isDirectiveNameRegistered('testDirectiveOne'));
33 | $this->assertTrue($directiveList->isDirectiveNameRegistered('testDirectiveTwo'));
34 | }
35 |
36 | public function testItThrowsExceptionWhenAddingInvalidDirectives()
37 | {
38 | $this->setExpectedException(\Exception::class, "addDirectives accept only array of directives");
39 | $directiveList = new SchemaDirectivesList();
40 | $directiveList->addDirectives("foobar");
41 | }
42 |
43 | }
--------------------------------------------------------------------------------
/tests/Schema/ResolveInfoTest.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 5/19/16 1:28 PM
7 | */
8 |
9 | namespace Youshido\Tests\Schema;
10 |
11 |
12 | use Youshido\GraphQL\Execution\Context\ExecutionContext;
13 | use Youshido\GraphQL\Execution\ResolveInfo;
14 | use Youshido\GraphQL\Field\Field;
15 | use Youshido\GraphQL\Parser\Ast\Field as FieldAST;
16 | use Youshido\GraphQL\Parser\Location;
17 | use Youshido\GraphQL\Type\Scalar\IntType;
18 | use Youshido\Tests\DataProvider\TestSchema;
19 |
20 | class ResolveInfoTest extends \PHPUnit_Framework_TestCase
21 | {
22 | public function testMethods()
23 | {
24 | $fieldAst = new FieldAST('name', null, [], [], new Location(1,1));
25 | $field = new Field(['name' => 'id', 'type' => new IntType()]);
26 | $returnType = new IntType();
27 | $executionContext = new ExecutionContext(new TestSchema());
28 | $info = new ResolveInfo($field, [$fieldAst], $executionContext);
29 |
30 | $this->assertEquals($field, $info->getField());
31 | $this->assertEquals([$fieldAst], $info->getFieldASTList());
32 | $this->assertEquals($returnType, $info->getReturnType());
33 | $this->assertEquals($executionContext, $info->getExecutionContext());
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/tests/StarWars/Schema/CharacterInterface.php:
--------------------------------------------------------------------------------
1 |
6 | * created: 12/6/15 11:15 PM
7 | */
8 |
9 | namespace Youshido\Tests\StarWars\Schema;
10 |
11 | use Youshido\GraphQL\Type\InterfaceType\AbstractInterfaceType;
12 | use Youshido\GraphQL\Type\ListType\ListType;
13 | use Youshido\GraphQL\Type\NonNullType;
14 | use Youshido\GraphQL\Type\Scalar\IdType;
15 | use Youshido\GraphQL\Type\Scalar\StringType;
16 |
17 | class CharacterInterface extends AbstractInterfaceType
18 | {
19 | public function build($config)
20 | {
21 | $config
22 | ->addField('id', new NonNullType(new IdType()))
23 | ->addField('name', new NonNullType(new StringType()))
24 | ->addField('friends', [
25 | 'type' => new ListType(new CharacterInterface()),
26 | 'resolve' => function ($value) {
27 | return $value['friends'];
28 | }
29 | ])
30 | ->addField('appearsIn', new ListType(new EpisodeEnum()));
31 | }
32 |
33 | public function getDescription()
34 | {
35 | return 'A character in the Star Wars Trilogy';
36 | }
37 |
38 | public function getName()
39 | {
40 | return 'Character';
41 | }
42 |
43 | public function resolveType($object)
44 | {
45 | $humans = StarWarsData::humans();
46 | $droids = StarWarsData::droids();
47 |
48 | $id = isset($object['id']) ? $object['id'] : $object;
49 |
50 | if (isset($humans[$id])) {
51 | return new HumanType();
52 | }
53 |
54 | if (isset($droids[$id])) {
55 | return new DroidType();
56 | }
57 |
58 | return null;
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/tests/StarWars/Schema/DroidType.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\Tests\StarWars\Schema;
9 |
10 |
11 | use Youshido\GraphQL\Type\TypeMap;
12 |
13 | class DroidType extends HumanType
14 | {
15 |
16 | /**
17 | * @return String type name
18 | */
19 | public function getName()
20 | {
21 | return 'Droid';
22 | }
23 |
24 | public function build($config)
25 | {
26 | parent::build($config);
27 |
28 | $config->getField('friends')->getConfig()->set('resolve', function ($droid) {
29 | return StarWarsData::getFriends($droid);
30 | });
31 |
32 | $config
33 | ->addField('primaryFunction', TypeMap::TYPE_STRING);
34 | }
35 |
36 | public function getInterfaces()
37 | {
38 | return [new CharacterInterface()];
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/tests/StarWars/Schema/EpisodeEnum.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\Tests\StarWars\Schema;
9 |
10 |
11 | use Youshido\GraphQL\Type\Enum\AbstractEnumType;
12 |
13 | class EpisodeEnum extends AbstractEnumType
14 | {
15 |
16 | public function getValues()
17 | {
18 | return [
19 | [
20 | 'value' => 4,
21 | 'name' => 'NEWHOPE',
22 | 'description' => 'Released in 1977.'
23 | ],
24 | [
25 | 'value' => 5,
26 | 'name' => 'EMPIRE',
27 | 'description' => 'Released in 1980.'
28 | ],
29 | [
30 | 'value' => 6,
31 | 'name' => 'JEDI',
32 | 'description' => 'Released in 1983.'
33 | ],
34 | ];
35 | }
36 |
37 | /**
38 | * @return String type name
39 | */
40 | public function getName()
41 | {
42 | return 'Episode';
43 | }
44 | }
--------------------------------------------------------------------------------
/tests/StarWars/Schema/HumanType.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\Tests\StarWars\Schema;
9 |
10 |
11 | use Youshido\GraphQL\Type\ListType\ListType;
12 | use Youshido\GraphQL\Type\NonNullType;
13 | use Youshido\GraphQL\Type\Object\AbstractObjectType;
14 | use Youshido\GraphQL\Type\Scalar\IdType;
15 | use Youshido\GraphQL\Type\Scalar\StringType;
16 | use Youshido\GraphQL\Type\TypeMap;
17 |
18 | class HumanType extends AbstractObjectType
19 | {
20 |
21 | public function build($config)
22 | {
23 | $config
24 | ->addField('id', new NonNullType(new IdType()))
25 | ->addField('name', new NonNullType(new StringType()))
26 | ->addField('friends', [
27 | 'type' => new ListType(new CharacterInterface()),
28 | 'resolve' => function ($droid) {
29 | return StarWarsData::getFriends($droid);
30 | },
31 | ])
32 | ->addField('appearsIn', new ListType(new EpisodeEnum()))
33 | ->addField('homePlanet', TypeMap::TYPE_STRING);
34 | }
35 |
36 | public function getInterfaces()
37 | {
38 | return [new CharacterInterface()];
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/tests/StarWars/Schema/StarWarsQueryType.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\Tests\StarWars\Schema;
9 |
10 |
11 | use Youshido\GraphQL\Field\Field;
12 | use Youshido\GraphQL\Field\FieldFactory;
13 | use Youshido\GraphQL\Type\Object\AbstractObjectType;
14 | use Youshido\GraphQL\Type\Scalar\IdType;
15 |
16 | class StarWarsQueryType extends AbstractObjectType
17 | {
18 |
19 | /**
20 | * @return String type name
21 | */
22 | public function getName()
23 | {
24 | return 'Query';
25 | }
26 |
27 | public function build($config)
28 | {
29 | $config
30 | ->addField('hero', [
31 | 'type' => new CharacterInterface(),
32 | 'args' => [
33 | 'episode' => ['type' => new EpisodeEnum()]
34 | ],
35 | 'resolve' => function ($root, $args) {
36 | return StarWarsData::getHero(isset($args['episode']) ? $args['episode'] : null);
37 | },
38 | ])
39 | ->addField(new Field([
40 | 'name' => 'human',
41 | 'type' => new HumanType(),
42 | 'args' => [
43 | 'id' => new IdType()
44 | ],
45 | 'resolve' => function ($value = null, $args = []) {
46 | $humans = StarWarsData::humans();
47 |
48 | return isset($humans[$args['id']]) ? $humans[$args['id']] : null;
49 | }
50 | ]))
51 | ->addField(new Field([
52 | 'name' => 'droid',
53 | 'type' => new DroidType(),
54 | 'args' => [
55 | 'id' => new IdType()
56 | ],
57 | 'resolve' => function ($value = null, $args = []) {
58 | $droids = StarWarsData::droids();
59 |
60 | return isset($droids[$args['id']]) ? $droids[$args['id']] : null;
61 | }
62 | ]));
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/tests/StarWars/Schema/StarWarsSchema.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Youshido\Tests\StarWars\Schema;
9 |
10 |
11 | use Youshido\GraphQL\Config\Schema\SchemaConfig;
12 | use Youshido\GraphQL\Schema\AbstractSchema;
13 |
14 | class StarWarsSchema extends AbstractSchema
15 | {
16 |
17 | public function build(SchemaConfig $config)
18 | {
19 | $config->setQuery(new StarWarsQueryType());
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------