1212use TheCodingMachine \GraphQLite \PrefetchBuffer ;
1313use TheCodingMachine \GraphQLite \QueryField ;
1414
15+ use function array_key_exists ;
1516use function assert ;
1617
1718/**
@@ -27,6 +28,7 @@ public function __construct(
2728 private readonly string $ fieldName ,
2829 private readonly mixed $ resolver ,
2930 public readonly array $ parameters ,
31+ public readonly bool $ returnRequested = false ,
3032 )
3133 {
3234 }
@@ -52,24 +54,40 @@ public function resolve(object|null $source, array $args, mixed $context, Resolv
5254 // So we record all of these ->resolve() calls, collect them together and when a value is actually
5355 // needed, GraphQL calls the callback of Deferred below. That's when we call the prefetch method,
5456 // already knowing all the requested fields (source-arguments combinations).
55- return new Deferred (function () use ($ info , $ context , $ args , $ prefetchBuffer ) {
56- if (! $ prefetchBuffer ->hasResult ($ args , $ info )) {
57- $ prefetchResult = $ this ->computePrefetch ($ args , $ context , $ info , $ prefetchBuffer );
58-
59- $ prefetchBuffer ->storeResult ($ prefetchResult , $ args , $ info );
57+ return new Deferred (function () use ($ source , $ info , $ context , $ args , $ prefetchBuffer ) {
58+ if (! $ prefetchBuffer ->hasResult ($ source )) {
59+ $ this ->computePrefetch ($ args , $ context , $ info , $ prefetchBuffer );
6060 }
6161
62- return $ prefetchResult ?? $ prefetchBuffer ->getResult ($ args , $ info );
62+ return $ prefetchBuffer ->getResult ($ source );
6363 });
6464 }
6565
6666 /** @param array<string, mixed> $args */
67- private function computePrefetch (array $ args , mixed $ context , ResolveInfo $ info , PrefetchBuffer $ prefetchBuffer ): mixed
67+ private function computePrefetch (array $ args , mixed $ context , ResolveInfo $ info , PrefetchBuffer $ prefetchBuffer ): void
6868 {
6969 $ sources = $ prefetchBuffer ->getObjectsByArguments ($ args , $ info );
70+ $ prefetchBuffer ->purge ($ args , $ info );
7071 $ toPassPrefetchArgs = QueryField::paramsToArguments ($ this ->fieldName , $ this ->parameters , null , $ args , $ context , $ info , $ this ->resolver );
7172
72- return ($ this ->resolver )($ sources , ...$ toPassPrefetchArgs );
73+ $ resolvedValues = ($ this ->resolver )($ sources , ...$ toPassPrefetchArgs );
74+ if ($ this ->returnRequested ) {
75+ foreach ($ resolvedValues as $ key => $ resolvedValue ) {
76+ if (! array_key_exists ($ key , $ sources )) {
77+ throw new GraphQLRuntimeException (
78+ 'Called by Prefetch function should accept ' .
79+ 'Array<key> and return Array<value>, but the function did ' .
80+ 'not return an Array of the same length as the Array of keys. ' ,
81+ );
82+ }
83+ $ prefetchBuffer ->storeResult ($ sources [$ key ], $ resolvedValue );
84+ }
85+ } else {
86+ foreach ($ sources as $ source ) {
87+ // map results to each source to support old prefetch behavior
88+ $ prefetchBuffer ->storeResult ($ source , $ resolvedValues );
89+ }
90+ }
7391 }
7492
7593 /** @inheritDoc */
0 commit comments