Skip to content

Commit 46a9b81

Browse files
committed
Annotations features
1 parent 6909ee4 commit 46a9b81

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+1856
-1131
lines changed

docs/definitions/annotations-reference.md

+428
Large diffs are not rendered by default.

docs/definitions/expression-language.md

+29-28
Original file line numberDiff line numberDiff line change
@@ -5,38 +5,39 @@ All definition config entries can use expression language but it must be explici
55

66
**Functions description:**
77

8-
Expression | Description | Usage | Alias
9-
---------- | ----------- | ----- | -----
10-
object **service**(string $id) | Get a service from the container | @=service('my_service').customMethod() | serv
11-
mixed **parameter**(string $name) | Get parameter from the container | @=parameter('kernel.debug') | param
12-
boolean **isTypeOf**(string $className) | Verified if `value` is instance of className | @=isTypeOf('AppBundle\\User\\User') |
13-
mixed **resolver**(string $alias, array $args = []) | call the method on the tagged service "overblog_graphql.resolver" with args | @=resolver('blog_by_id', [value['blogID']] | res
14-
mixed **mutation**(string $alias, array $args = []) | call the method on the tagged service "overblog_graphql.mutation" with args | @=mutation('remove_post_from_community', [value]) | mut
15-
string **globalId**(string\|int id, string $typeName = null) | Relay node globalId | @=globalId(15, 'User') |
16-
array **fromGlobalId**(string $globalId) | Relay node fromGlobalId | @=fromGlobalId('QmxvZzox') |
17-
object **newObject**(string $className, array $args = []) | Instantiation $className object with $args | @=newObject('AppBundle\\User\\User', ['John', 15]) |
18-
boolean **hasRole**(string $role) | Checks whether the token has a certain role. | @=hasRole('ROLE_API') |
19-
boolean **hasAnyRole**(string $role1, string $role2, ...string $roleN) | Checks whether the token has any of the given roles. | @=hasAnyRole('ROLE_API', 'ROLE_ADMIN') |
20-
boolean **isAnonymous**() | Checks whether the token is anonymous. | @=isAnonymous() |
21-
boolean **isRememberMe**() | Checks whether the token is remember me. | @=isRememberMe() |
22-
boolean **isFullyAuthenticated**() | Checks whether the token is fully authenticated. | @=isFullyAuthenticated() |
23-
boolean **isAuthenticated**() | Checks whether the token is not anonymous. | @=isAuthenticated() |
24-
boolean **hasPermission**(mixed $var, string $permission) | Checks whether the token has the given permission for the given object (requires the ACL system). | @=hasPermission(object, 'OWNER') |
25-
boolean **hasAnyPermission**(mixed $var, array $permissions) | Checks whether the token has any of the given permissions for the given object | @=hasAnyPermission(object, ['OWNER', 'ADMIN']) |
26-
User **getUser**() | Returns the user which is currently in the security token storage. User can be null. | @=getUser() |
8+
| Expression | Description | Usage | Alias |
9+
| ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------- | ----- |
10+
| object **service**(string $id) | Get a service from the container | @=service('my_service').customMethod() | serv |
11+
| mixed **parameter**(string $name) | Get parameter from the container | @=parameter('kernel.debug') | param |
12+
| boolean **isTypeOf**(string $className) | Verified if `value` is instance of className | @=isTypeOf('AppBundle\\User\\User') |
13+
| mixed **resolver**(string $alias, array $args = []) | call the method on the tagged service "overblog_graphql.resolver" with args | @=resolver('blog_by_id', [value['blogID']] | res |
14+
| mixed **value_resolver**(array $args = [], string $method = null) | call a method on the value itself. If no method name is provided, default to resolving fieldname (info->fieldName) | @=value_resolver([args["gender"]], "getFriends") |
15+
| mixed **mutation**(string $alias, array $args = []) | call the method on the tagged service "overblog_graphql.mutation" with args | @=mutation('remove_post_from_community', [value]) | mut |
16+
| string **globalId**(string\|int id, string $typeName = null) | Relay node globalId | @=globalId(15, 'User') |
17+
| array **fromGlobalId**(string $globalId) | Relay node fromGlobalId | @=fromGlobalId('QmxvZzox') |
18+
| object **newObject**(string $className, array $args = []) | Instantiation $className object with $args | @=newObject('AppBundle\\User\\User', ['John', 15]) |
19+
| boolean **hasRole**(string $role) | Checks whether the token has a certain role. | @=hasRole('ROLE_API') |
20+
| boolean **hasAnyRole**(string $role1, string $role2, ...string $roleN) | Checks whether the token has any of the given roles. | @=hasAnyRole('ROLE_API', 'ROLE_ADMIN') |
21+
| boolean **isAnonymous**() | Checks whether the token is anonymous. | @=isAnonymous() |
22+
| boolean **isRememberMe**() | Checks whether the token is remember me. | @=isRememberMe() |
23+
| boolean **isFullyAuthenticated**() | Checks whether the token is fully authenticated. | @=isFullyAuthenticated() |
24+
| boolean **isAuthenticated**() | Checks whether the token is not anonymous. | @=isAuthenticated() |
25+
| boolean **hasPermission**(mixed $var, string $permission) | Checks whether the token has the given permission for the given object (requires the ACL system). | @=hasPermission(object, 'OWNER') |
26+
| boolean **hasAnyPermission**(mixed $var, array $permissions) | Checks whether the token has any of the given permissions for the given object | @=hasAnyPermission(object, ['OWNER', 'ADMIN']) |
27+
| User **getUser**() | Returns the user which is currently in the security token storage. User can be null. | @=getUser() |
2728

2829

2930
**Variables description:**
3031

31-
Expression | Description | Scope
32-
---------- | ----------- | --------
33-
**typeResolver** | the type resolver | global
34-
**object** | Refers to the value of the field for which access is being requested. For array `object` will be each item of the array. For Relay connection `object` will be the node of each connection edges. | only available for `config.fields.*.access` with query operation or mutation payload type.
35-
**value** | Resolver value | only available in resolve context
36-
**args** | Resolver args array | only available in resolve context
37-
**info** | Resolver GraphQL\Type\Definition\ResolveInfo Object | only available in resolve context
38-
**context** | context is defined by your application on the top level of query execution (useful for storing current user, environment details, etc) | only available in resolve context
39-
**childrenComplexity** | Selection field children complexity | only available in complexity context
32+
| Expression | Description | Scope |
33+
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
34+
| **typeResolver** | the type resolver | global |
35+
| **object** | Refers to the value of the field for which access is being requested. For array `object` will be each item of the array. For Relay connection `object` will be the node of each connection edges. | only available for `config.fields.*.access` with query operation or mutation payload type. |
36+
| **value** | Resolver value | only available in resolve context |
37+
| **args** | Resolver args array | only available in resolve context |
38+
| **info** | Resolver GraphQL\Type\Definition\ResolveInfo Object | only available in resolve context |
39+
| **context** | context is defined by your application on the top level of query execution (useful for storing current user, environment details, etc) | only available in resolve context |
40+
| **childrenComplexity** | Selection field children complexity | only available in complexity context |
4041

4142
[For more details on expression syntax](http://symfony.com/doc/current/components/expression_language/syntax.html)
4243

docs/definitions/index.md

+16-17
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,21 @@
1-
Definitions
2-
===========
1+
# Definitions
32

4-
* [Type System](type-system/index.md)
5-
* [Type Inheritance](type-inheritance.md)
6-
* [GraphQL schema language](graphql-schema-language.md)
7-
* [Schema](schema.md)
3+
- [Type System](type-system/index.md)
4+
- [Type Inheritance](type-inheritance.md)
5+
- [GraphQL schema language](graphql-schema-language.md)
6+
- [Schema](schema.md)
87

9-
Go further
10-
----------
8+
## Go further
119

12-
* [Solving N+1 problem](solving-n-plus-1-problem.md)
13-
* [Resolver](resolver.md)
14-
* [Mutation](mutation.md)
15-
* [Relay](relay/index.md)
16-
* [Builders](builders/index.md)
17-
* [Expression language](expression-language.md)
18-
* [Debug](debug/index.md)
19-
* [GraphiQL](graphiql/index.md)
20-
* [Upload files](upload-files.md)
10+
- [Solving N+1 problem](solving-n-plus-1-problem.md)
11+
- [Resolver](resolver.md)
12+
- [Mutation](mutation.md)
13+
- [Relay](relay/index.md)
14+
- [Builders](builders/index.md)
15+
- [Expression language](expression-language.md)
16+
- [Debug](debug/index.md)
17+
- [GraphiQL](graphiql/index.md)
18+
- [Upload files](upload-files.md)
19+
- [Annotations reference](annotations-reference.md)
2120

2221
Next step [Data fetching](../data-fetching/index.md).

docs/definitions/mutation.md

+4-10
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,6 @@ IntroduceShipInput:
3434
type: "String!"
3535
```
3636
37-
The same example with annotation: @TODO
38-
39-
```php
40-
@TODO
41-
```
42-
4337
To implement the logic behind your mutation, you should create a new class that
4438
implements `MutationInterface` and `AliasedInterface` interfaces.
4539

@@ -54,22 +48,22 @@ use Overblog\GraphQLBundle\Definition\Resolver\MutationInterface;
5448
class ShipMutation implements MutationInterface, AliasedInterface
5549
{
5650
private $factionRepository;
57-
51+
5852
public function __construct(FactionRepository $factionRepository) {
5953
$this->factionRepository = $factionRepository;
6054
}
61-
55+
6256
public function createShip(string $shipName, int $factionId): array
6357
{
6458
// `$shipName` has the value of `args['input']['shipName']`
6559
// `$factionId` has the value of `args['input']['factionId']`
66-
60+
6761
// Do something with `$shipName` and `$factionId` ...
6862
$ship = new Ship($shipName);
6963
$faction = $this->factionRepository->find($factionId);
7064
$faction->addShip($ship);
7165
// ...
72-
66+
7367

7468
// Then returns our payload, it should fits `IntroduceShipPayload` type
7569
return [

docs/definitions/schema.md

+12-52
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Schema
2-
=======
2+
======
33

44
Default files location
55
-------
@@ -63,47 +63,7 @@ Query:
6363
resolve: "@=resolver('character_droid', [args])"
6464
```
6565
66-
Or using annotation:
67-
68-
```php
69-
<?php
70-
71-
use Overblog\GraphQLBundle\Annotation as GQL;
72-
73-
/**
74-
* Class RootQuery
75-
*
76-
* @GQL\GraphQLType(type="object")
77-
* @GQL\GraphQLDescription(description="A humanoid creature in the Star Wars universe.")
78-
*/
79-
class RootQuery
80-
{
81-
/**
82-
* @GQL\GraphQLColumn(type="Character")
83-
* @GQL\GraphQLQuery(
84-
* method="character_hero",
85-
* args={
86-
* "args['episode'].getId()"
87-
* }
88-
* )
89-
*/
90-
public $hero;
91-
92-
/**
93-
* @GQL\GraphQLColumn(type="Human")
94-
* @GQL\GraphQLQuery(method="character_human", args={"args['id']"})
95-
*/
96-
public $human;
97-
98-
/**
99-
* @GQL\GraphQLColumn(type="Droid")
100-
* @GQL\GraphQLQuery(method="character_human", args={"args"})
101-
*/
102-
public $droid;
103-
}
104-
```
105-
106-
66+
10767
```yaml
10868
overblog_graphql:
10969
definitions:
@@ -137,18 +97,18 @@ overblog_graphql:
13797

13898
**foo** schema endpoint can be access:
13999

140-
type | Path
141-
-----| -----
142-
simple request | `/graphql/foo`
143-
batch request | `/graphql/foo/batch`
144-
GraphiQL* | `/graphiql/foo`
100+
| type | Path |
101+
| -------------- | -------------------- |
102+
| simple request | `/graphql/foo` |
103+
| batch request | `/graphql/foo/batch` |
104+
| GraphiQL* | `/graphiql/foo` |
145105

146106
**bar** schema endpoint can be access:
147107

148-
type | Path
149-
-----| -----
150-
simple request | `/graphql/bar`
151-
batch request | `/graphql/bar/batch`
152-
GraphiQL* | `/graphiql/bar`
108+
| type | Path |
109+
| -------------- | -------------------- |
110+
| simple request | `/graphql/bar` |
111+
| batch request | `/graphql/bar/batch` |
112+
| GraphiQL* | `/graphiql/bar` |
153113

154114
\* `/graphiql` depends on [OverblogGraphiQLBundle](https://github.com/overblog/GraphiQLBundle)

docs/definitions/type-system/enum.md

+17-18
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
Enum
2-
====
1+
# Enum
2+
3+
## With YAML
34

45
```yaml
56
# MyBundle/Resources/config/graphql/Episode.types.yml
@@ -25,32 +26,30 @@ Episode:
2526
description: "Released in 2015."
2627
```
2728
28-
Or with annotation:
29+
## With Annotations
30+
31+
Note: At the moment, doctrine annotations on constants are not supported. So if you need to add config like description or deprecationReason, you must add @GQL\EnumValue with the constant name as name attribute on the annotation.
2932
3033
```php
3134
<?php
3235

36+
namespace AppBundle;
37+
38+
use Overblog\GraphQLBundle\Annotation as GQL;
39+
3340
/**
34-
* @\Overblog\GraphQLBundle\Annotation\GraphQLType(type="enum")
35-
* @\Overblog\GraphQLBundle\Annotation\GraphQLDescription(description="One of the films in the Star Wars Trilogy")
41+
* @GQL\Enum(values={
42+
* @GQL\EnumValue(name="NEWHOPE", description="Released in 1977."),
43+
* @GQL\EnumValue(name="EMPIRE", description="Released in 1980."),
44+
* @GQL\EnumValue(name="FORCEAWAKENS", description="Released in 2015."),
45+
* })
46+
* @GQL\Description("One of the films in the Star Wars Trilogy")
3647
*/
3748
class Episode
3849
{
39-
/**
40-
* @\Overblog\GraphQLBundle\Annotation\GraphQLDescription(description="Released in 1977.")
41-
*/
4250
const NEWHOPE = 4;
43-
44-
/**
45-
* @\Overblog\GraphQLBundle\Annotation\GraphQLDescription(description="Released in 1980.")
46-
*/
4751
const EMPIRE = 'constant("App\\StarWars\\Movies::MOVIE_EMPIRE")';
48-
4952
const JEDI = 6;
50-
51-
/**
52-
* @\Overblog\GraphQLBundle\Annotation\GraphQLDescription(description="Released in 2015.")
53-
*/
5453
const FORCEAWAKENS = 'FORCEAWAKENS';
5554
}
56-
```
55+
```
+16-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
Input object
2-
============
1+
# Input object
2+
3+
## With YAML
34

45
```yaml
56
# src/MyBundle/Resources/config/graphql/HumanAndDroid.types.yml
@@ -13,23 +14,29 @@ HeroInput:
1314
config:
1415
fields:
1516
name:
16-
type: "Episode!"
17+
type: "String!"
1718
```
1819
19-
Or with annotation:
20+
## With Annotations
21+
22+
Note: If the attribute `name` is not set on the `@GQL\Input`, the final name will be the class name suffixed by "Input" if it doesn't have already the suffix. (ex: If the class name is `Hero` the input name will be `HeroInput`).
23+
With Input type, the `@Field` annotation on methods are ignored, so is the annotations on properties that need a resolver.
2024

2125
```php
2226
<?php
2327
28+
namespace AppBundle;
29+
30+
use Overblog\GraphQLBundle\Annotation as GQL;
31+
2432
/**
25-
* @\Overblog\GraphQLBundle\Annotation\GraphQLType(type="input-object")
26-
* @\Overblog\GraphQLBundle\Annotation\GraphQLDescription(description="One of the films in the Star Wars Trilogy")
33+
* @GQL\Input
2734
*/
2835
class HeroInput
2936
{
3037
/**
31-
* @\Overblog\GraphQLBundle\Annotation\GraphQLToOne(target="Episode", nullable=false)
38+
* @GQL\Field(type="String!")
3239
*/
33-
public $episode;
40+
public $name;
3441
}
35-
```
42+
```

0 commit comments

Comments
 (0)