Skip to content

Commit 046ed72

Browse files
committed
Allow nullable return for deferred type loaders
When a field/query is configured with a deferred type loader for return, while the field is nullable itself, it should not call the type loader. Instead it should just return null.
1 parent 894de59 commit 046ed72

File tree

6 files changed

+48
-4
lines changed

6 files changed

+48
-4
lines changed

phpstan-baseline.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,12 @@
367367
'count' => 1,
368368
'path' => __DIR__ . '/tests/Doubles/FullFeatured/Query/DeprecatedQuery.php',
369369
];
370+
$ignoreErrors[] = [
371+
'message' => '#^Method Jerowork\\\\GraphqlAttributeSchema\\\\Test\\\\Doubles\\\\FullFeatured\\\\Query\\\\WithNullableReturnDeferredTypeLoader\\:\\:__invoke\\(\\) never returns string so it can be removed from the return type\\.$#',
372+
'identifier' => 'return.unusedType',
373+
'count' => 1,
374+
'path' => __DIR__ . '/tests/Doubles/FullFeatured/Query/WithNullableReturnDeferredTypeLoader.php',
375+
];
370376
$ignoreErrors[] = [
371377
'message' => '#^Method Jerowork\\\\GraphqlAttributeSchema\\\\Test\\\\Doubles\\\\FullFeatured\\\\Query\\\\WithUnionOutputQuery\\:\\:getUnionQuery\\(\\) never returns Jerowork\\\\GraphqlAttributeSchema\\\\Test\\\\Doubles\\\\FullFeatured\\\\Type\\\\AgentType so it can be removed from the return type\\.$#',
372378
'identifier' => 'return.unusedType',

src/Resolver/Type/Field/FieldResolver.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,12 +136,12 @@ public function resolveField(FieldNode $node, TypeResolverSelector $typeResolver
136136
{
137137
if ($node->fieldType === FieldNodeType::Property) {
138138
return function (object $object) use ($node, $typeResolverSelector): mixed {
139-
/** @var list<int|string|Stringable>|int|string|Stringable $result */
139+
/** @var null|list<int|string|Stringable>|int|string|Stringable $result */
140140
$result = $typeResolverSelector
141141
->getResolver($node->reference)
142142
->resolve($node->reference, fn() => $object->{$node->propertyName});
143143

144-
if ($node->deferredTypeLoader !== null) {
144+
if ($node->deferredTypeLoader !== null && $result !== null) {
145145
return $this->deferredTypeResolver->resolve($node->deferredTypeLoader, $result);
146146
}
147147

@@ -158,12 +158,12 @@ public function resolveField(FieldNode $node, TypeResolverSelector $typeResolver
158158
$arguments[] = $this->argumentNodeResolver->resolve($argumentNode, $args, $typeResolverSelector);
159159
}
160160

161-
/** @var list<int|string|Stringable>|int|string|Stringable $result */
161+
/** @var null|list<int|string|Stringable>|int|string|Stringable $result */
162162
$result = $typeResolverSelector
163163
->getResolver($node->reference)
164164
->resolve($node->reference, fn() => $object->{$node->methodName}(...$arguments));
165165

166-
if ($node->deferredTypeLoader !== null) {
166+
if ($node->deferredTypeLoader !== null && $result !== null) {
167167
return $this->deferredTypeResolver->resolve($node->deferredTypeLoader, $result);
168168
}
169169

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Jerowork\GraphqlAttributeSchema\Test\Doubles\FullFeatured\Query;
6+
7+
use Jerowork\GraphqlAttributeSchema\Attribute\Query;
8+
use Jerowork\GraphqlAttributeSchema\Test\Doubles\Type\Loader\TestTypeLoader;
9+
10+
final readonly class WithNullableReturnDeferredTypeLoader
11+
{
12+
#[Query(name: 'withNullableReturnDeferredTypeLoader', description: 'A description', deferredTypeLoader: TestTypeLoader::class)]
13+
public function __invoke(): ?string
14+
{
15+
return null;
16+
}
17+
}

tests/ParserTest.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
use Jerowork\GraphqlAttributeSchema\Test\Doubles\FullFeatured\Query\WithInputObjectQuery;
3434
use Jerowork\GraphqlAttributeSchema\Test\Doubles\FullFeatured\Query\WithInterfaceOutputQuery;
3535
use Jerowork\GraphqlAttributeSchema\Test\Doubles\FullFeatured\Query\WithListOutputQuery;
36+
use Jerowork\GraphqlAttributeSchema\Test\Doubles\FullFeatured\Query\WithNullableReturnDeferredTypeLoader;
3637
use Jerowork\GraphqlAttributeSchema\Test\Doubles\FullFeatured\Query\WithOverwrittenTypeQuery;
3738
use Jerowork\GraphqlAttributeSchema\Test\Doubles\FullFeatured\Query\WithUnionOutputQuery;
3839
use Jerowork\GraphqlAttributeSchema\Test\Doubles\FullFeatured\Type\AbstractAdminType;
@@ -233,6 +234,16 @@ public function itShouldParseDirectory(): void
233234
null,
234235
null,
235236
),
237+
new QueryNode(
238+
WithNullableReturnDeferredTypeLoader::class,
239+
'withNullableReturnDeferredTypeLoader',
240+
'A description',
241+
[],
242+
ScalarTypeReference::create('string')->setNullableValue(),
243+
'__invoke',
244+
null,
245+
TestTypeLoader::class,
246+
),
236247
new QueryNode(
237248
WithOverwrittenTypeQuery::class,
238249
'withOverwrittenType',

tests/SchemaBuilderTest.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use Jerowork\GraphqlAttributeSchema\Test\Doubles\FullFeatured\Query\WithInputObjectQuery;
2323
use Jerowork\GraphqlAttributeSchema\Test\Doubles\FullFeatured\Query\WithInterfaceOutputQuery;
2424
use Jerowork\GraphqlAttributeSchema\Test\Doubles\FullFeatured\Query\WithListOutputQuery;
25+
use Jerowork\GraphqlAttributeSchema\Test\Doubles\FullFeatured\Query\WithNullableReturnDeferredTypeLoader;
2526
use Jerowork\GraphqlAttributeSchema\Test\Doubles\FullFeatured\Query\WithOverwrittenTypeQuery;
2627
use Jerowork\GraphqlAttributeSchema\Test\Doubles\FullFeatured\Query\WithUnionOutputQuery;
2728
use Jerowork\GraphqlAttributeSchema\Test\Doubles\Query\TestQuery;
@@ -91,6 +92,7 @@ public function itShouldBuildSchema(): void
9192
$this->container->set(WithOverwrittenTypeQuery::class, new WithOverwrittenTypeQuery());
9293
$this->container->set(WithUnionOutputQuery::class, new WithUnionOutputQuery());
9394
$this->container->set(WithDeferredTypeLoader::class, new WithDeferredTypeLoader());
95+
$this->container->set(WithNullableReturnDeferredTypeLoader::class, new WithNullableReturnDeferredTypeLoader());
9496

9597
$ast = $this->parser->parse(__DIR__ . '/Doubles/FullFeatured');
9698
$schema = $this->schemaBuilder->build($ast);
@@ -223,6 +225,13 @@ public function itShouldBuildSchema(): void
223225
'deprecationReason' => null,
224226
'args' => [],
225227
],
228+
[
229+
'name' => 'withNullableReturnDeferredTypeLoader',
230+
'type' => 'String',
231+
'description' => 'A description',
232+
'deprecationReason' => null,
233+
'args' => [],
234+
],
226235
[
227236
'name' => 'withOverwrittenType',
228237
'type' => 'Boolean',

tests/Util/Finder/Native/NativeFinderTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public function itShouldRetrieveFilesFromFolder(): void
4545
'Doubles/FullFeatured/Query/WithInputObjectQuery.php',
4646
'Doubles/FullFeatured/Query/WithInterfaceOutputQuery.php',
4747
'Doubles/FullFeatured/Query/WithListOutputQuery.php',
48+
'Doubles/FullFeatured/Query/WithNullableReturnDeferredTypeLoader.php',
4849
'Doubles/FullFeatured/Query/WithOverwrittenTypeQuery.php',
4950
'Doubles/FullFeatured/Query/WithUnionOutputQuery.php',
5051
'Doubles/FullFeatured/Type/AbstractAdminType.php',

0 commit comments

Comments
 (0)