Skip to content

Commit 5617f37

Browse files
authored
Fix using incorrect root for decorator when paginating (#2671)
1 parent bbc5b7e commit 5617f37

File tree

2 files changed

+76
-3
lines changed

2 files changed

+76
-3
lines changed

src/Schema/Directives/RelationDirectiveHelpers.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ protected function relation(): string
2828
/**
2929
* @param array<string, mixed> $args
3030
*
31-
* @return \Closure(QueryBuilder|\Illuminate\Database\Eloquent\Builder<\Illuminate\Database\Eloquent\Model>|\Illuminate\Database\Eloquent\Relations\Relation<\Illuminate\Database\Eloquent\Model>): void
31+
* @return \Closure(QueryBuilder|\Illuminate\Database\Eloquent\Builder<\Illuminate\Database\Eloquent\Model>|\Illuminate\Database\Eloquent\Relations\Relation<\Illuminate\Database\Eloquent\Model>, ?mixed = null): void
3232
*/
3333
protected function makeBuilderDecorator(mixed $root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): \Closure
3434
{
35-
return function (object $builder) use ($root, $args, $context, $resolveInfo): void {
35+
return function (object $builder, mixed $specificRoot = null) use ($root, $args, $context, $resolveInfo): void {
3636
if ($builder instanceof Relation) {
3737
$builder = $builder->getQuery();
3838
}
@@ -42,7 +42,12 @@ protected function makeBuilderDecorator(mixed $root, array $args, GraphQLContext
4242
$resolveInfo->enhanceBuilder(
4343
$builder,
4444
$this->scopes(),
45-
$root,
45+
/**
46+
* Sometimes overridden to use a different model than the usual root.
47+
* @see \Nuwave\Lighthouse\Execution\ModelsLoader\PaginatedModelsLoader::loadRelatedModels
48+
* @see \Tests\Integration\Schema\Directives\BuilderDirectiveTest::testCallsCustomBuilderMethodOnFieldWithSpecificModel
49+
*/
50+
$specificRoot ?? $root,
4651
$args,
4752
$context,
4853
$resolveInfo,

tests/Integration/Schema/Directives/BuilderDirectiveTest.php

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Nuwave\Lighthouse\Execution\ResolveInfo;
88
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
99
use Tests\DBTestCase;
10+
use Tests\Utils\Models\Task;
1011
use Tests\Utils\Models\User;
1112

1213
final class BuilderDirectiveTest extends DBTestCase
@@ -155,6 +156,60 @@ public function testCallsCustomBuilderMethodOnFieldWithoutValue(): void
155156
')->assertJsonCount(2, 'data.users');
156157
}
157158

159+
public function testCallsCustomBuilderMethodOnFieldWithSpecificModel(): void
160+
{
161+
$this->schema = /** @lang GraphQL */ <<<GRAPHQL
162+
type Query {
163+
users: [User!]! @all
164+
}
165+
166+
type User {
167+
id: ID
168+
tasks: [Task!]! @hasMany(type: SIMPLE) @builder(method: "{$this->qualifyTestResolver('specificModel')}")
169+
}
170+
171+
type Task {
172+
id: ID
173+
}
174+
GRAPHQL;
175+
176+
$users = factory(User::class, 2)->create();
177+
178+
foreach ($users as $user) {
179+
assert($user instanceof User);
180+
181+
$userName = $user->name;
182+
assert(is_string($userName), 'set by UserFactory');
183+
184+
$taskWithSameName = factory(Task::class)->make();
185+
assert($taskWithSameName instanceof Task);
186+
$taskWithSameName->name = $userName;
187+
$taskWithSameName->user()->associate($user);
188+
$taskWithSameName->save();
189+
190+
$taskWithOtherName = factory(Task::class)->make();
191+
assert($taskWithOtherName instanceof Task);
192+
$taskWithOtherName->name = "Different from {$userName}";
193+
$taskWithOtherName->user()->associate($user);
194+
$taskWithOtherName->save();
195+
}
196+
197+
$this->graphQL(/** @lang GraphQL */ '
198+
{
199+
users {
200+
id
201+
tasks(first: 10) {
202+
data {
203+
id
204+
}
205+
}
206+
}
207+
}
208+
')
209+
->assertJsonCount(1, 'data.users.0.tasks.data')
210+
->assertJsonCount(1, 'data.users.1.tasks.data');
211+
}
212+
158213
/**
159214
* @param \Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder<\Tests\Utils\Models\User> $builder
160215
*
@@ -164,4 +219,17 @@ public static function limit(QueryBuilder|EloquentBuilder $builder, ?int $value)
164219
{
165220
return $builder->limit($value ?? 2);
166221
}
222+
223+
/**
224+
* @param \Illuminate\Database\Eloquent\Builder<\Tests\Utils\Models\User> $builder
225+
*
226+
* @return \Illuminate\Database\Eloquent\Builder<\Tests\Utils\Models\User>
227+
*/
228+
public static function specificModel(
229+
EloquentBuilder $builder,
230+
?int $value,
231+
User $user,
232+
): EloquentBuilder {
233+
return $builder->where('name', $user->name);
234+
}
167235
}

0 commit comments

Comments
 (0)