Skip to content

Commit 7d433d6

Browse files
authored
Merge pull request overblog#710 from Vincz/master
Annotations refactoring
2 parents 50f85e7 + eae1bbe commit 7d433d6

File tree

19 files changed

+632
-272
lines changed

19 files changed

+632
-272
lines changed

docs/annotations/annotations-reference.md

+9-4
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,10 @@ This annotation applies on methods for classes tagged with the `@Provider` annot
384384
The resulting field is added to the root Mutation type (defined in configuration at key `overblog_graphql.definitions.schema.mutation`).
385385
The class exposing the mutation(s) must be declared as a [service](https://symfony.com/doc/current/service_container.html).
386386

387+
Optional attributes:
388+
389+
- **targetType** : The GraphQL type to attach the field to. It must be a mutation. (by default, it'll be the root Mutation type of the default schema).
390+
387391
Example:
388392

389393
This will add an `updateUserEmail` mutation, with as resolver `@=service('App\Graphql\MutationProvider').updateUserEmail(...)`.
@@ -432,7 +436,7 @@ The class exposing the query(ies) must be declared as a [service](https://symfon
432436

433437
Optional attributes:
434438

435-
- **targetType** : The GraphQL type to attach the field to (by default, it'll be the root Query type).
439+
- **targetType** : The GraphQL type to attach the field to (by default, it'll be the root Query type of the default schema).
436440

437441
Example:
438442

@@ -464,9 +468,10 @@ This annotation is used on _class_ to define a GraphQL Type.
464468
Optional attributes:
465469

466470
- **name** : The GraphQL name of the type (default to the class name without namespace)
467-
- **interfaces** : An array of GraphQL interface this type inherits from
471+
- **interfaces** : An array of GraphQL interface this type inherits from (can be auto-guessed. See interface documentation).
468472
- **isRelay** : Set to true to have a Relay compatible type (ie. A `clientMutationId` will be added).
469-
- **builders**: An array of `@FieldsBuilder` annotations
473+
- **builders** : An array of `@FieldsBuilder` annotations
474+
- **isTypeOf** : Is type of resolver for interface implementation
470475

471476
```php
472477
<?php
@@ -554,7 +559,7 @@ This annotation is used on a _class_ to define an union.
554559

555560
Required attributes:
556561

557-
- **types** : An array of GraphQL Type as string
562+
- **types** : An array of GraphQL Type as string (can be auto-guessed. See union documenation).
558563

559564
Optional attributes:
560565

docs/definitions/type-system/object.md

+2
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ Droid:
7777
7878
## With Annotations
7979
80+
Note: With annotations, you can omit the `interfaces` option. If so, the system will try to guess the interfaces automatically by getting the GraphQL Interface associated with classes that the Class type extends or implements.
81+
8082
```php
8183
<?php
8284

docs/definitions/type-system/union.md

+2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ HumanAndDroid:
1616
1717
## With annotations
1818
19+
Note: With annotations, you can omit the `types` parameter. If so, the system will try to detect GraphQL Type associated with classes that inherit or implement the Union class.
20+
1921
```php
2022
<?php
2123

src/Annotation/Mutation.php

+6
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,10 @@
1212
*/
1313
final class Mutation extends Field
1414
{
15+
/**
16+
* The target type to attach this mutation to (usefull when multiple schemas are allowed).
17+
*
18+
* @var string
19+
*/
20+
public $targetType;
1521
}

src/Annotation/Type.php

+7
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,11 @@ class Type implements Annotation
4646
* @var array<\Overblog\GraphQLBundle\Annotation\FieldsBuilder>
4747
*/
4848
public $builders = [];
49+
50+
/**
51+
* Expression to resolve type for interfaces.
52+
*
53+
* @var string
54+
*/
55+
public $isTypeOf;
4956
}

src/Annotation/Union.php

-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ final class Union implements Annotation
2222
/**
2323
* Union types.
2424
*
25-
* @required
26-
*
2725
* @var array<string>
2826
*/
2927
public $types;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Overblog\GraphQLBundle\Config\Parser\Annotation;
6+
7+
use Doctrine\Common\Annotations\AnnotationException;
8+
use Doctrine\Common\Annotations\AnnotationReader;
9+
use Doctrine\Common\Annotations\AnnotationRegistry;
10+
use ReflectionClass;
11+
use ReflectionMethod;
12+
use ReflectionProperty;
13+
use RuntimeException;
14+
use function class_exists;
15+
16+
class GraphClass extends ReflectionClass
17+
{
18+
private static ?AnnotationReader $annotationReader = null;
19+
20+
protected array $annotations = [];
21+
22+
protected array $propertiesExtended = [];
23+
24+
/**
25+
* @param mixed $className
26+
*/
27+
public function __construct($className)
28+
{
29+
parent::__construct($className);
30+
31+
$annotationReader = self::getAnnotationReader();
32+
$this->annotations = $annotationReader->getClassAnnotations($this);
33+
34+
$reflection = $this;
35+
do {
36+
foreach ($reflection->getProperties() as $property) {
37+
if (isset($this->propertiesExtended[$property->getName()])) {
38+
continue;
39+
}
40+
$this->propertiesExtended[$property->getName()] = $property;
41+
}
42+
} while ($reflection = $reflection->getParentClass());
43+
}
44+
45+
/**
46+
* @return ReflectionProperty[]
47+
*/
48+
public function getPropertiesExtended()
49+
{
50+
return $this->propertiesExtended;
51+
}
52+
53+
/**
54+
* @param ReflectionMethod|ReflectionProperty|null $from
55+
*
56+
* @return array
57+
*/
58+
public function getAnnotations(object $from = null)
59+
{
60+
if (!$from) {
61+
return $this->annotations;
62+
}
63+
64+
if ($from instanceof ReflectionMethod) {
65+
return self::getAnnotationReader()->getMethodAnnotations($from);
66+
}
67+
68+
if ($from instanceof ReflectionProperty) {
69+
return self::getAnnotationReader()->getPropertyAnnotations($from);
70+
}
71+
72+
/** @phpstan-ignore-next-line */
73+
throw new AnnotationException(sprintf('Unable to retrieve annotations from object of class "%s".', get_class($from)));
74+
}
75+
76+
private static function getAnnotationReader(): AnnotationReader
77+
{
78+
if (null === self::$annotationReader) {
79+
if (!class_exists(AnnotationReader::class) ||
80+
!class_exists(AnnotationRegistry::class)) {
81+
throw new RuntimeException('In order to use graphql annotation, you need to require doctrine annotations');
82+
}
83+
84+
AnnotationRegistry::registerLoader('class_exists');
85+
self::$annotationReader = new AnnotationReader();
86+
}
87+
88+
return self::$annotationReader;
89+
}
90+
}

0 commit comments

Comments
 (0)