Skip to content

Commit 7542a10

Browse files
committed
Use default resolver like callable service
1 parent 0d54dd1 commit 7542a10

File tree

12 files changed

+57
-40
lines changed

12 files changed

+57
-40
lines changed

UPGRADE-0.13.md

+13-1
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,20 @@ UPGRADE FROM 0.12 to 0.13
33

44
# Table of Contents
55

6+
- [Rename default_field config](#rename-default_field-config)
67
- [Improve default field resolver](#improve-default-field-resolver)
78

9+
### Rename default_field config
10+
11+
```diff
12+
overblog_graphql:
13+
definitions:
14+
- default_resolver: ~
15+
+ default_field_resolver: ~
16+
```
17+
18+
The new `default_field_resolver` config entry accepts callable service id.
19+
820
### Improve default field resolver
921

1022
Stop using internally `symfony/property-access` package
@@ -20,7 +32,7 @@ Globally:
2032
```yaml
2133
overblog_graphql:
2234
definitions:
23-
default_resolver: 'App\GraphQL\CustomResolver::defaultFieldResolver'
35+
default_field_resolver: 'App\GraphQL\CustomResolver'
2436
```
2537
2638
[see default field resolver for more details](https://webonyx.github.io/graphql-php/data-fetching/#default-field-resolver)

docs/definitions/resolver.md

+12
Original file line numberDiff line numberDiff line change
@@ -228,4 +228,16 @@ services:
228228
`addition` mutation can be access by using `App\GraphQL\Mutation\CalcMutation::addition` or
229229
`add` alias.
230230

231+
### Default field resolver
232+
233+
The default field resolver can be define using config:
234+
235+
```yaml
236+
overblog_graphql:
237+
definitions:
238+
default_field_resolver: 'my_default_field_resolver_service'
239+
```
240+
241+
Default field resolver should be a callable service (implementing `__invoker` method)
242+
231243
Next step [solving N+1 problem](solving-n-plus-1-problem.md)

src/DependencyInjection/Configuration.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
use Overblog\GraphQLBundle\EventListener\ErrorLoggerListener;
1414
use Overblog\GraphQLBundle\Executor\Executor;
1515
use Overblog\GraphQLBundle\ExpressionLanguage\ExpressionLanguage;
16-
use Overblog\GraphQLBundle\Resolver\Resolver;
16+
use Overblog\GraphQLBundle\Resolver\FieldResolver;
1717
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
1818
use Symfony\Component\Config\Definition\Builder\EnumNodeDefinition;
1919
use Symfony\Component\Config\Definition\Builder\ScalarNodeDefinition;
@@ -120,7 +120,7 @@ private function definitionsSection()
120120
->children()
121121
->scalarNode('argument_class')->defaultValue(Argument::class)->end()
122122
->scalarNode('use_experimental_executor')->defaultFalse()->end()
123-
->variableNode('default_resolver')->defaultValue([Resolver::class, 'defaultResolveFn'])->end()
123+
->scalarNode('default_field_resolver')->defaultValue(FieldResolver::class)->end()
124124
->scalarNode('class_namespace')->defaultValue('Overblog\\GraphQLBundle\\__DEFINITIONS__')->end()
125125
->scalarNode('cache_dir')->defaultNull()->end()
126126
->scalarNode('cache_dir_permissions')->defaultNull()->end()

src/DependencyInjection/OverblogGraphQLExtension.php

+6-1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public function load(array $configs, ContainerBuilder $container): void
4848
$this->setClassLoaderListener($config, $container);
4949
$this->setCompilerCacheWarmer($config, $container);
5050
$this->registerForAutoconfiguration($container);
51+
$this->setDefaultFieldResolver($config, $container);
5152

5253
$container->setParameter($this->getAlias().'.config', $config);
5354
$container->setParameter($this->getAlias().'.resources_dir', \realpath(__DIR__.'/../Resources'));
@@ -89,6 +90,11 @@ private function registerForAutoconfiguration(ContainerBuilder $container): void
8990
->addTag('overblog_graphql.type');
9091
}
9192

93+
private function setDefaultFieldResolver(array $config, ContainerBuilder $container): void
94+
{
95+
$container->setAlias($this->getAlias().'.default_field_resolver', $config['definitions']['default_field_resolver']);
96+
}
97+
9298
private function setCompilerCacheWarmer(array $config, ContainerBuilder $container): void
9399
{
94100
$container->register(CompileCacheWarmer::class)
@@ -118,7 +124,6 @@ private function setClassLoaderListener(array $config, ContainerBuilder $contain
118124
private function setDefinitionParameters(array $config, ContainerBuilder $container): void
119125
{
120126
// generator and config
121-
$container->setParameter($this->getAlias().'.default_resolver', $config['definitions']['default_resolver']);
122127
$container->setParameter($this->getAlias().'.class_namespace', $config['definitions']['class_namespace']);
123128
$container->setParameter($this->getAlias().'.cache_dir', $config['definitions']['cache_dir']);
124129
$container->setParameter($this->getAlias().'.cache_dir_permissions', $config['definitions']['cache_dir_permissions']);

src/GraphQL/Relay/Mutation/MutationFieldResolver.php

+10-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
use Overblog\GraphQLBundle\Definition\ArgumentFactory;
99
use Overblog\GraphQLBundle\Definition\Resolver\AliasedInterface;
1010
use Overblog\GraphQLBundle\Definition\Resolver\ResolverInterface;
11-
use Overblog\GraphQLBundle\Resolver\Resolver;
1211

1312
final class MutationFieldResolver implements ResolverInterface, AliasedInterface
1413
{
@@ -28,7 +27,7 @@ public function __invoke($args, $context, $info, \Closure $mutateAndGetPayloadCa
2827

2928
return $this->promiseAdapter->createFulfilled($mutateAndGetPayloadCallback($input, $context, $info))
3029
->then(function ($payload) use ($input) {
31-
Resolver::setObjectOrArrayValue($payload, 'clientMutationId', $input['clientMutationId']);
30+
$this->setObjectOrArrayValue($payload, 'clientMutationId', $input['clientMutationId']);
3231

3332
return $payload;
3433
});
@@ -41,4 +40,13 @@ public static function getAliases(): array
4140
{
4241
return ['__invoke' => 'relay_mutation_field'];
4342
}
43+
44+
private function setObjectOrArrayValue(&$objectOrArray, $fieldName, $value): void
45+
{
46+
if (\is_array($objectOrArray)) {
47+
$objectOrArray[$fieldName] = $value;
48+
} elseif (\is_object($objectOrArray)) {
49+
$objectOrArray->$fieldName = $value;
50+
}
51+
}
4452
}

src/GraphQL/Relay/Node/GlobalIdFieldResolver.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@
88
use Overblog\GraphQLBundle\Definition\Resolver\AliasedInterface;
99
use Overblog\GraphQLBundle\Definition\Resolver\ResolverInterface;
1010
use Overblog\GraphQLBundle\Relay\Node\GlobalId;
11-
use Overblog\GraphQLBundle\Resolver\Resolver;
11+
use Overblog\GraphQLBundle\Resolver\FieldResolver;
1212

1313
final class GlobalIdFieldResolver implements ResolverInterface, AliasedInterface
1414
{
1515
public function __invoke($obj, ResolveInfo $info, $idValue, $typeName)
1616
{
1717
return GlobalId::toGlobalId(
1818
!empty($typeName) ? $typeName : $info->parentType->name,
19-
$idValue ? $idValue : Resolver::valueFromObjectOrArray($obj, 'id')
19+
$idValue ? $idValue : FieldResolver::valueFromObjectOrArray($obj, 'id')
2020
);
2121
}
2222

src/Resolver/Resolver.php renamed to src/Resolver/FieldResolver.php

+4-13
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66

77
use GraphQL\Type\Definition\ResolveInfo;
88

9-
class Resolver
9+
class FieldResolver
1010
{
11-
public static function defaultResolveFn($objectOrArray, $args, $context, ResolveInfo $info)
11+
public function __invoke($parentValue, $args, $context, ResolveInfo $info)
1212
{
1313
$fieldName = $info->fieldName;
14-
$value = static::valueFromObjectOrArray($objectOrArray, $fieldName);
14+
$value = self::valueFromObjectOrArray($parentValue, $fieldName);
1515

16-
return $value instanceof \Closure ? $value($objectOrArray, $args, $context, $info) : $value;
16+
return $value instanceof \Closure ? $value($parentValue, $args, $context, $info) : $value;
1717
}
1818

1919
public static function valueFromObjectOrArray($objectOrArray, $fieldName)
@@ -32,15 +32,6 @@ public static function valueFromObjectOrArray($objectOrArray, $fieldName)
3232
return $value;
3333
}
3434

35-
public static function setObjectOrArrayValue(&$objectOrArray, $fieldName, $value): void
36-
{
37-
if (\is_array($objectOrArray)) {
38-
$objectOrArray[$fieldName] = $value;
39-
} elseif (\is_object($objectOrArray)) {
40-
$objectOrArray->$fieldName = $value;
41-
}
42-
}
43-
4435
private static function guessObjectMethod($object, string $fieldName, string $prefix): ?string
4536
{
4637
if (\is_callable([$object, $method = $prefix.\str_replace(' ', '', \ucwords(\str_replace('_', ' ', $fieldName)))])) {

src/Resources/config/definition_config_processors.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ services:
66
Overblog\GraphQLBundle\Definition\ConfigProcessor\AclConfigProcessor:
77
arguments:
88
- '@Overblog\GraphQLBundle\Resolver\AccessResolver'
9-
- "%overblog_graphql.default_resolver%"
9+
- "@overblog_graphql.default_field_resolver"
1010
tags:
1111
- { name: overblog_graphql.definition_config_processor, priority: 512 }
1212

src/Resources/config/services.yaml

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@ services:
88
Overblog\GraphQLBundle\Definition\GlobalVariables: ~
99
GraphQL\Executor\Promise\Adapter\SyncPromiseAdapter: ~
1010
Overblog\GraphQLBundle\Executor\Promise\Adapter\ReactPromiseAdapter: ~
11+
Overblog\GraphQLBundle\Resolver\FieldResolver: ~
1112

1213
Overblog\GraphQLBundle\Request\Executor:
1314
arguments:
1415
- "@overblog_graphql.executor"
1516
- "@overblog_graphql.promise_adapter"
1617
- "@event_dispatcher"
17-
- '%overblog_graphql.default_resolver%'
18+
- '@overblog_graphql.default_field_resolver'
1819
- "%overblog_graphql.use_experimental_executor%"
1920
calls:
2021
- ["setMaxQueryComplexity", ["%overblog_graphql.query_max_complexity%"]]

test.ini

Whitespace-only changes.

tests/Functional/App/Mutation/SimplePromiseMutation.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ public function __construct(PromiseAdapter $promiseAdapter)
1818

1919
public function mutate()
2020
{
21-
return $this->promiseAdapter->createFulfilled(['result' => 1]);
21+
return $this->promiseAdapter->createFulfilled((object) ['result' => 1]);
2222
}
2323
}

tests/Resolver/ResolverTest.php renamed to tests/Resolver/ResolverFieldTest.php

+4-16
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
namespace Overblog\GraphQLBundle\Tests\Resolver;
66

77
use GraphQL\Type\Definition\ResolveInfo;
8-
use Overblog\GraphQLBundle\Resolver\Resolver;
8+
use Overblog\GraphQLBundle\Resolver\FieldResolver;
99
use PHPUnit\Framework\TestCase;
1010

11-
class ResolverTest extends TestCase
11+
class ResolverFieldTest extends TestCase
1212
{
1313
/**
1414
* @param $fieldName
@@ -17,24 +17,12 @@ class ResolverTest extends TestCase
1717
*
1818
* @dataProvider resolverProvider
1919
*/
20-
public function testDefaultResolveFn($fieldName, $source, $expected): void
20+
public function testDefaultFieldResolveFn($fieldName, $source, $expected): void
2121
{
2222
$info = $this->getMockBuilder(ResolveInfo::class)->disableOriginalConstructor()->getMock();
2323
$info->fieldName = $fieldName;
2424

25-
$this->assertSame($expected, Resolver::defaultResolveFn($source, [], [], $info));
26-
}
27-
28-
public function testSetObjectOrArrayValue(): void
29-
{
30-
$object = new \stdClass();
31-
$object->foo = null;
32-
Resolver::setObjectOrArrayValue($object, 'foo', 'bar');
33-
$this->assertSame($object->foo, 'bar');
34-
35-
$data = ['foo' => null];
36-
Resolver::setObjectOrArrayValue($data, 'foo', 'bar');
37-
$this->assertSame($data['foo'], 'bar');
25+
$this->assertSame($expected, (new FieldResolver())($source, [], [], $info));
3826
}
3927

4028
public function resolverProvider()

0 commit comments

Comments
 (0)