Skip to content

Commit 4156974

Browse files
committed
fix: ensure root-level filters are not applied on includes/aggregates
1 parent 787acb8 commit 4156974

File tree

4 files changed

+98
-19
lines changed

4 files changed

+98
-19
lines changed

src/Drivers/Standard/QueryBuilder.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,9 @@ public function applyScopesToQuery($query, Request $request): void
119119
*/
120120
public function applyFiltersToQuery($query, Request $request, array $filterDescriptors = []): void
121121
{
122-
if (!$filterDescriptors) {
122+
if (!$filterDescriptors && !$this->intermediateMode) {
123123
$this->paramsValidator->validateFilters($request);
124+
124125
$filterDescriptors = $request->get('filters', []);
125126
}
126127

@@ -610,7 +611,7 @@ public function applyIncludesToQuery($query, Request $request, array $includeDes
610611
public function clone(string $resourceModelClass): self
611612
{
612613
return new static(
613-
$resourceModelClass, $this->paramsValidator, $this->relationsResolver, $this->searchBuilder
614+
$resourceModelClass, $this->paramsValidator, $this->relationsResolver, $this->searchBuilder, true
614615
);
615616
}
616617

tests/Feature/StandardAggregateOperationsTest.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,45 @@ public function getting_a_list_of_resources_with_min_aggregate_operation_with_fi
144144
);
145145
}
146146

147+
/** @test */
148+
public function ensuring_root_level_filters_are_not_applied_on_aggregates(): void
149+
{
150+
if ((float) app()->version() < 8.0) {
151+
$this->markTestSkipped('Unsupported framework version');
152+
}
153+
154+
$user = User::query()->first();
155+
$user->name = 'John Doe';
156+
$user->save();
157+
158+
factory(Post::class)->create(['stars' => 2.8, 'user_id' => $user->id])->fresh();
159+
factory(Post::class)->create(['stars' => 4.2, 'user_id' => $user->id])->fresh();
160+
factory(Post::class)->create(['stars' => 5])->fresh();
161+
162+
Gate::policy(User::class, GreenPolicy::class);
163+
164+
$response = $this->post(
165+
'/api/users/search',
166+
[
167+
'filters' => [
168+
['field' => 'name', 'operator' => '=', 'value' => 'John Doe'],
169+
],
170+
'aggregates' => [
171+
[
172+
'relation' => 'posts',
173+
'field' => 'stars',
174+
'type' => 'min',
175+
]
176+
]
177+
]
178+
);
179+
180+
$this->assertResourcesPaginated(
181+
$response,
182+
$this->makePaginator([$user->loadMin(['posts'], 'stars')->toArray()], 'users/search')
183+
);
184+
}
185+
147186
/** @test */
148187
public function getting_a_list_of_resources_with_max_aggregate_operation(): void
149188
{

tests/Feature/StandardIncludeOperationsTest.php

Lines changed: 55 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,8 @@
22

33
namespace Orion\Tests\Feature;
44

5-
use Carbon\Carbon;
65
use Illuminate\Support\Facades\Gate;
7-
use Orion\Tests\Fixtures\App\Models\Company;
86
use Orion\Tests\Fixtures\App\Models\Post;
9-
use Orion\Tests\Fixtures\App\Models\Team;
107
use Orion\Tests\Fixtures\App\Models\User;
118
use Orion\Tests\Fixtures\App\Policies\GreenPolicy;
129

@@ -27,8 +24,8 @@ public function getting_a_list_of_resources_with_include_operation(): void
2724
'/api/users/search',
2825
[
2926
'includes' => [
30-
['relation' => 'posts']
31-
]
27+
['relation' => 'posts'],
28+
],
3229
]
3330
);
3431

@@ -58,16 +55,58 @@ public function getting_a_list_of_resources_with_include_operation_with_filters(
5855
[
5956
'relation' => 'posts',
6057
'filters' => [
61-
['field' => 'posts.stars', 'operator' => '>', 'value' => 3]
62-
]
63-
]
64-
]
58+
['field' => 'posts.stars', 'operator' => '>', 'value' => 3],
59+
],
60+
],
61+
],
6562
]
6663
);
6764

6865
$this->assertResourcesPaginated(
6966
$response,
70-
$this->makePaginator([$user->load(['posts' => function($query) {$query->where('stars', '>', 3);}])->toArray()], 'users/search'),
67+
$this->makePaginator([
68+
$user->load([
69+
'posts' => function ($query) {
70+
$query->where('stars', '>', 3);
71+
},
72+
])->toArray(),
73+
], 'users/search'),
74+
[],
75+
false
76+
);
77+
}
78+
79+
/** @test */
80+
public function ensuring_root_level_filters_are_not_applied_on_includes(): void
81+
{
82+
/** @var User $user */
83+
$user = User::query()->first();
84+
$user->name = 'John Doe';
85+
$user->save();
86+
87+
factory(Post::class)->create(['stars' => 3, 'user_id' => $user->id])->fresh();
88+
factory(Post::class)->create(['stars' => 4, 'user_id' => $user->id])->fresh();
89+
factory(Post::class)->create(['stars' => 5])->fresh();
90+
91+
Gate::policy(User::class, GreenPolicy::class);
92+
93+
$response = $this->post(
94+
'/api/users/search',
95+
[
96+
'filters' => [
97+
['field' => 'name', 'operator' => '=', 'value' => 'John Doe'],
98+
],
99+
'includes' => [
100+
[
101+
'relation' => 'posts',
102+
],
103+
],
104+
]
105+
);
106+
107+
$this->assertResourcesPaginated(
108+
$response,
109+
$this->makePaginator([$user->load(['posts'])->toArray(),], 'users/search'),
71110
[],
72111
false
73112
);
@@ -89,8 +128,8 @@ public function getting_a_list_of_resources_with_unauthorized_include(): void
89128
'/api/users/search',
90129
[
91130
'includes' => [
92-
['relation' => 'unauthorized']
93-
]
131+
['relation' => 'unauthorized'],
132+
],
94133
]
95134
);
96135

@@ -116,10 +155,10 @@ public function getting_a_list_of_resources_with_unauthorized_include_filter():
116155
[
117156
'relation' => 'posts',
118157
'filters' => [
119-
['field' => 'unauthorized', 'operator' => '>', 'value' => 3]
120-
]
121-
]
122-
]
158+
['field' => 'unauthorized', 'operator' => '>', 'value' => 3],
159+
],
160+
],
161+
],
123162
]
124163
);
125164

tests/Fixtures/app/Http/Controllers/UsersController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@ public function includes(): array
2323

2424
public function filterableBy(): array
2525
{
26-
return ['posts.stars'];
26+
return ['name','posts.stars'];
2727
}
2828
}

0 commit comments

Comments
 (0)