Skip to content

Commit 1377d1f

Browse files
authored
Merge branch 'master' into mo-olsavmic-patch-1
2 parents 68b83fa + b95cb10 commit 1377d1f

File tree

10 files changed

+113
-24
lines changed

10 files changed

+113
-24
lines changed

UPGRADE-0.13.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ The new `default_field_resolver` config entry accepts callable service id.
2323
Stop using internally `symfony/property-access` package
2424
since it was a bottleneck to performance for large schema.
2525

26-
Array access and camelize getter are supported but isser, hasser,
26+
Array access and camelize getter/isser are supported but hasser,
2727
jQuery style (e.g. `last()`) and "can" property accessors
2828
are no more supported out-of-the-box,
2929
please implement a custom resolver if these accessors are needed.

docs/annotations/annotations-reference.md

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ The class exposing the mutation(s) must be declared as a [service](https://symfo
386386

387387
Optional attributes:
388388

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. see [Default Schema](../definitions/schema.md#default-schema)).
389+
- **targetType** : The GraphQL type(s) to attach the field to. It must be a mutation. (by default, it'll be the root Mutation type of the default schema. see [Default Schema](../definitions/schema.md#default-schema)). You can specify one or multiple target types.
390390

391391
Example:
392392

@@ -422,7 +422,7 @@ class MutationProvider {
422422

423423
This annotation applies on classes to indicate that it contains methods tagged with `@Query` or `@Mutation`.
424424
Without it, the `@Query` and `@Mutation` are ignored. When used, **remember to have a corresponding service with the fully qualified name of the class as service id**.
425-
You can use `@Access` and/or `@IsPublic` on a provider class to add default access or visibility on defined query or mutation.
425+
You can use `@Access` and/or `@IsPublic` on a provider class to add default access or visibility on defined query or mutation.
426426

427427
Optional attributes:
428428

@@ -436,7 +436,7 @@ The class exposing the query(ies) must be declared as a [service](https://symfon
436436

437437
Optional attributes:
438438

439-
- **targetType** : The GraphQL type to attach the field to (by default, it'll be the root Query type of the default schema. see [Default Schema](../definitions/schema.md#default-schema)).
439+
- **targetType** : The GraphQL type(s) to attach the field to (by default, it'll be the root Query type of the default schema. see [Default Schema](../definitions/schema.md#default-schema)). You can specify one or multiple target types.
440440

441441
Example:
442442

@@ -589,19 +589,18 @@ class Pet {
589589
}
590590
```
591591

592-
593592
## @Relay\Connection
594593

595-
This annotation extends the `@Type` annotation so it uses the same attributes.
594+
This annotation extends the `@Type` annotation so it uses the same attributes.
596595
It prepends the `RelayConnectionFieldsBuilder` to the list of fields builders.
597596

598597
The extra attributes are :
599598

600599
- **edge** : The GraphQL type of the connection's edges
601-
- **node** : The GraphQL type of the node of the connection's edges'
600+
- **node** : The GraphQL type of the node of the connection's edges'
602601

603602
You must define one and only one of this attributes.
604-
If the `edge` attribute is used, the declaration is the same as adding a `RelayConnectionFieldsBuilder`
603+
If the `edge` attribute is used, the declaration is the same as adding a `RelayConnectionFieldsBuilder`
605604

606605
```php
607606
<?php

src/Annotation/Mutation.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
final class Mutation extends Field
1414
{
1515
/**
16-
* The target type to attach this mutation to (usefull when multiple schemas are allowed).
16+
* The target types to attach this mutation to (useful when multiple schemas are allowed).
1717
*
18-
* @var string
18+
* @var array<string>
1919
*/
2020
public $targetType;
2121
}

src/Annotation/Query.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
final class Query extends Field
1414
{
1515
/**
16-
* The target type to attach this query to.
16+
* The target types to attach this query to.
1717
*
18-
* @var string
18+
* @var array<string>
1919
*/
2020
public $targetType;
2121
}

src/Config/Parser/AnnotationParser.php

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -511,8 +511,8 @@ private static function getTypeFieldConfigurationFromReflector(GraphClass $graph
511511
if (!empty($fieldAnnotation->args)) {
512512
foreach ($fieldAnnotation->args as $arg) {
513513
$args[$arg->name] = ['type' => $arg->type]
514-
+ ($arg->description ? ['description' => $arg->description] : [])
515-
+ ($arg->default ? ['defaultValue' => $arg->default] : []);
514+
+ (null !== $arg->description ? ['description' => $arg->description] : [])
515+
+ (null !== $arg->default ? ['defaultValue' => $arg->default] : []);
516516
}
517517
} elseif ($reflector instanceof ReflectionMethod) {
518518
$args = self::guessArgs($reflector);
@@ -555,7 +555,7 @@ private static function getTypeFieldConfigurationFromReflector(GraphClass $graph
555555
$fieldConfiguration['builder'] = $builder;
556556
$fieldConfiguration['builderConfig'] = $builderConfig ?: [];
557557
} else {
558-
throw new InvalidArgumentException(sprintf('The attribute "argsBuilder" on GraphQL annotation "@%s" defined on "%s" must be a string or an array where first index is the builder name and the second is the config.', $fieldAnnotationName, $reflector->getName()));
558+
throw new InvalidArgumentException(sprintf('The attribute "fieldBuilder" on GraphQL annotation "@%s" defined on "%s" must be a string or an array where first index is the builder name and the second is the config.', $fieldAnnotationName, $reflector->getName()));
559559
}
560560
} else {
561561
if (!$fieldType) {
@@ -674,19 +674,28 @@ private static function getGraphQLFieldsFromProviders(GraphClass $graphClass, st
674674
continue;
675675
}
676676

677-
$annotationTarget = $annotation->targetType;
678-
if (!$annotationTarget && $isDefaultTarget) {
679-
$annotationTarget = $targetType;
680-
if (!($annotation instanceof $expectedAnnotation)) {
677+
$annotationTargets = $annotation->targetType;
678+
679+
if (null === $annotationTargets) {
680+
if ($isDefaultTarget) {
681+
$annotationTargets = [$targetType];
682+
if (!$annotation instanceof $expectedAnnotation) {
683+
continue;
684+
}
685+
} else {
681686
continue;
682687
}
683688
}
684689

685-
if ($annotationTarget !== $targetType) {
690+
if (is_string($annotationTargets)) {
691+
$annotationTargets = [$annotationTargets];
692+
}
693+
694+
if (!in_array($targetType, $annotationTargets)) {
686695
continue;
687696
}
688697

689-
if (!($annotation instanceof $expectedAnnotation)) {
698+
if (!$annotation instanceof $expectedAnnotation) {
690699
if (GQL\Mutation::class == $expectedAnnotation) {
691700
$message = sprintf('The provider "%s" try to add a query field on type "%s" (through @Query on method "%s") but "%s" is a mutation.', $providerMetadata->getName(), $targetType, $method->getName(), $targetType);
692701
} else {

src/Resolver/FieldResolver.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ public static function valueFromObjectOrArray($objectOrArray, string $fieldName)
4242
} elseif (is_object($objectOrArray)) {
4343
if (null !== $getter = self::guessObjectMethod($objectOrArray, $fieldName, 'get')) {
4444
$value = $objectOrArray->$getter();
45+
} elseif (null !== $getter = self::guessObjectMethod($objectOrArray, $fieldName, 'is')) {
46+
$value = $objectOrArray->$getter();
4547
} elseif (null !== $getter = self::guessObjectMethod($objectOrArray, $fieldName, '')) {
4648
$value = $objectOrArray->$getter();
4749
} elseif (isset($objectOrArray->$fieldName)) {

tests/Config/Parser/AnnotationParserTest.php

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,12 @@ public function testTypes(): void
111111
'access' => '@=override_access',
112112
'public' => '@=default_public',
113113
],
114+
'planet_armorResistance' => [
115+
'type' => 'Int!',
116+
'resolve' => '@=call(service(\'Overblog\\\\GraphQLBundle\\\\Tests\\\\Config\\\\Parser\\\\fixtures\\\\annotations\\\\Repository\\\\PlanetRepository\').getArmorResistance, arguments({}, args))',
117+
'access' => '@=default_access',
118+
'public' => '@=default_public',
119+
],
114120
],
115121
]);
116122

@@ -129,7 +135,7 @@ public function testTypes(): void
129135
'currentMaster' => ['type' => 'Sith', 'resolve' => "@=service('master_resolver').getMaster(value)"],
130136
'victims' => [
131137
'type' => '[Character]',
132-
'args' => ['jediOnly' => ['type' => 'Boolean', 'description' => 'Only Jedi victims']],
138+
'args' => ['jediOnly' => ['type' => 'Boolean', 'description' => 'Only Jedi victims', 'defaultValue' => false]],
133139
'resolve' => '@=call(value.getVictims, arguments({jediOnly: "Boolean"}, args))',
134140
],
135141
],
@@ -228,6 +234,12 @@ public function testInterfaceAutoguessed(): void
228234
'fields' => [
229235
'name' => ['type' => 'String!', 'description' => 'The name of the character'],
230236
'friends' => ['type' => '[Character]', 'description' => 'The friends of the character', 'resolve' => "@=resolver('App\\\\MyResolver::getFriends')"],
237+
'planet_armorResistance' => [
238+
'type' => 'Int!',
239+
'resolve' => '@=call(service(\'Overblog\\\\GraphQLBundle\\\\Tests\\\\Config\\\\Parser\\\\fixtures\\\\annotations\\\\Repository\\\\PlanetRepository\').getArmorResistance, arguments({}, args))',
240+
'access' => '@=default_access',
241+
'public' => '@=default_public',
242+
],
231243
],
232244
]);
233245
}
@@ -253,6 +265,13 @@ public function testProviders(): void
253265
'access' => '@=default_access',
254266
'public' => '@=default_public',
255267
],
268+
'planet_isPlanetDestroyed' => [
269+
'type' => 'Boolean!',
270+
'args' => ['planetId' => ['type' => 'Int!']],
271+
'resolve' => "@=call(service('Overblog\\\\GraphQLBundle\\\\Tests\\\\Config\\\\Parser\\\\fixtures\\\\annotations\\\\Repository\\\\PlanetRepository').isPlanetDestroyed, arguments({planetId: \"Int!\"}, args))",
272+
'access' => '@=default_access',
273+
'public' => '@=default_public',
274+
],
256275
],
257276
]);
258277

@@ -265,6 +284,13 @@ public function testProviders(): void
265284
'access' => '@=default_access',
266285
'public' => '@=override_public',
267286
],
287+
'planet_destroyPlanet' => [
288+
'type' => 'Boolean!',
289+
'args' => ['planetId' => ['type' => 'Int!']],
290+
'resolve' => "@=call(service('Overblog\\\\GraphQLBundle\\\\Tests\\\\Config\\\\Parser\\\\fixtures\\\\annotations\\\\Repository\\\\PlanetRepository').destroyPlanet, arguments({planetId: \"Int!\"}, args))",
291+
'access' => '@=default_access',
292+
'public' => '@=default_public',
293+
],
268294
],
269295
]);
270296
}
@@ -279,6 +305,13 @@ public function testProvidersMultischema(): void
279305
'access' => '@=default_access',
280306
'public' => '@=default_public',
281307
],
308+
'planet_isPlanetDestroyed' => [
309+
'type' => 'Boolean!',
310+
'args' => ['planetId' => ['type' => 'Int!']],
311+
'resolve' => "@=call(service('Overblog\\\\GraphQLBundle\\\\Tests\\\\Config\\\\Parser\\\\fixtures\\\\annotations\\\\Repository\\\\PlanetRepository').isPlanetDestroyed, arguments({planetId: \"Int!\"}, args))",
312+
'access' => '@=default_access',
313+
'public' => '@=default_public',
314+
],
282315
],
283316
]);
284317

@@ -291,6 +324,13 @@ public function testProvidersMultischema(): void
291324
'access' => '@=default_access',
292325
'public' => '@=override_public',
293326
],
327+
'planet_destroyPlanet' => [
328+
'type' => 'Boolean!',
329+
'args' => ['planetId' => ['type' => 'Int!']],
330+
'resolve' => "@=call(service('Overblog\\\\GraphQLBundle\\\\Tests\\\\Config\\\\Parser\\\\fixtures\\\\annotations\\\\Repository\\\\PlanetRepository').destroyPlanet, arguments({planetId: \"Int!\"}, args))",
331+
'access' => '@=default_access',
332+
'public' => '@=default_public',
333+
],
294334
],
295335
]);
296336
}

tests/Config/Parser/fixtures/annotations/Repository/PlanetRepository.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,28 @@ public function createPlanetSchema2(array $planetInput): array
6262
{
6363
return [];
6464
}
65+
66+
/**
67+
* @GQL\Mutation(targetType={"RootMutation", "RootMutation2"})
68+
*/
69+
public function destroyPlanet(int $planetId): bool
70+
{
71+
return true;
72+
}
73+
74+
/**
75+
* @GQL\Query(targetType={"RootQuery", "RootQuery2"})
76+
*/
77+
public function isPlanetDestroyed(int $planetId): bool
78+
{
79+
return true;
80+
}
81+
82+
/**
83+
* @GQL\Query(targetType={"Droid", "Mandalorian"}, name="armorResistance")
84+
*/
85+
public function getArmorResistance(): int
86+
{
87+
return 10;
88+
}
6589
}

tests/Resolver/ResolverFieldTest.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ class ResolverFieldTest extends TestCase
1313
/**
1414
* @dataProvider resolverProvider
1515
*
16-
* @param mixed $source
16+
* @param mixed $source
17+
* @param bool|string|null $expected
1718
*/
18-
public function testDefaultFieldResolveFn(string $fieldName, $source, ?string $expected): void
19+
public function testDefaultFieldResolveFn(string $fieldName, $source, $expected): void
1920
{
2021
$info = $this->getMockBuilder(ResolveInfo::class)->disableOriginalConstructor()->getMock();
2122
$info->fieldName = $fieldName;
@@ -36,6 +37,8 @@ public function resolverProvider(): array
3637
['private_property_with_getter2', $object, Toto::PRIVATE_PROPERTY_WITH_GETTER2_VALUE],
3738
['not_object_or_array', 'String', null],
3839
['name', $object, $object->name],
40+
['enabled', $object, $object->isEnabled()],
41+
['isDisabled', $object, $object->isDisabled()],
3942
];
4043
}
4144
}

tests/Resolver/Toto.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ class Toto
1717
private string $privatePropertyWithGetter = self::PRIVATE_PROPERTY_WITH_GETTER_VALUE;
1818
private string $private_property_with_getter2 = self::PRIVATE_PROPERTY_WITH_GETTER2_VALUE;
1919
public string $name = 'public';
20+
private bool $enabled = true;
21+
private bool $isDisabled = false;
2022

2123
public function getPrivatePropertyWithGetter(): string
2224
{
@@ -39,4 +41,14 @@ public function resolve(): array
3941
{
4042
return func_get_args();
4143
}
44+
45+
public function isEnabled(): bool
46+
{
47+
return $this->enabled;
48+
}
49+
50+
public function isDisabled(): bool
51+
{
52+
return $this->isDisabled;
53+
}
4254
}

0 commit comments

Comments
 (0)