Skip to content

Commit 794c135

Browse files
committed
fix: calculating max depth for nested filters
1 parent 6cc031f commit 794c135

File tree

2 files changed

+71
-27
lines changed

2 files changed

+71
-27
lines changed

src/Drivers/Standard/ParamsValidator.php

+18-9
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
use Illuminate\Support\Facades\Validator;
66
use Orion\Exceptions\MaxNestedDepthExceededException;
7-
use Orion\Helpers\ArrayHelper;
87
use Orion\Http\Requests\Request;
98
use Orion\Http\Rules\WhitelistedField;
109
use Orion\Http\Rules\WhitelistedQueryFields;
@@ -107,7 +106,7 @@ public function validateSearch(Request $request): void
107106

108107
public function validateAggregators(Request $request): void
109108
{
110-
$depth = $this->nestedFiltersDepth($request->input('aggregates', []), -1);
109+
$depth = $this->nestedFiltersDepth($request->input('aggregates', []));
111110

112111
Validator::make(
113112
$request->all(),
@@ -192,7 +191,7 @@ public function validateAggregators(Request $request): void
192191

193192
public function validateIncludes(Request $request): void
194193
{
195-
$depth = $this->nestedFiltersDepth($request->input('includes', []), -1);
194+
$depth = $this->nestedFiltersDepth($request->input('includes', []));
196195

197196
Validator::make(
198197
$request->all(),
@@ -221,15 +220,25 @@ public function validateIncludes(Request $request): void
221220
/**
222221
* @throws MaxNestedDepthExceededException
223222
*/
224-
protected function nestedFiltersDepth($array, $modifier = 0)
223+
protected function nestedFiltersDepth($array): int
225224
{
226-
$depth = ArrayHelper::depth($array);
227-
$configMaxNestedDepth = config('orion.search.max_nested_depth', 1);
225+
$depth = 0;
226+
227+
foreach ($array as $filterDescriptor) {
228+
if (!isset($filterDescriptor['nested'])) {
229+
continue;
230+
}
231+
232+
$currentFilterDescriptorDepth = 1 + $this->nestedFiltersDepth($filterDescriptor['nested']);
228233

229-
// Here we calculate the real nested filters depth
230-
$depth = floor($depth / 2);
234+
if ($depth < $currentFilterDescriptorDepth) {
235+
$depth = $currentFilterDescriptorDepth;
236+
}
237+
}
238+
239+
$configMaxNestedDepth = config('orion.search.max_nested_depth', 1);
231240

232-
if ($depth + $modifier > $configMaxNestedDepth) {
241+
if ($depth > $configMaxNestedDepth) {
233242
throw new MaxNestedDepthExceededException(
234243
422,
235244
__('Max nested depth :depth is exceeded', ['depth' => $configMaxNestedDepth])

tests/Feature/StandardIndexNestedFilteringOperationsTest.php

+53-18
Original file line numberDiff line numberDiff line change
@@ -2,12 +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;
10-
use Orion\Tests\Fixtures\App\Models\User;
117
use Orion\Tests\Fixtures\App\Policies\GreenPolicy;
128

139
class StandardIndexNestedFilteringOperationsTest extends TestCase
@@ -24,11 +20,13 @@ public function getting_a_list_of_resources_nested_filtered_by_model_field_using
2420
'/api/posts/search',
2521
[
2622
'filters' => [
27-
['field' => 'title', 'operator' => 'in' ,'value' => ['match', 'not_match']],
28-
['nested' => [
29-
['field' => 'title', 'value' => 'match'],
30-
['field' => 'title', 'operator' => '!=', 'value' => 'not match']
31-
]],
23+
['field' => 'title', 'operator' => 'in', 'value' => ['match', 'not_match']],
24+
[
25+
'nested' => [
26+
['field' => 'title', 'value' => 'match'],
27+
['field' => 'title', 'operator' => '!=', 'value' => 'not match'],
28+
],
29+
],
3230
],
3331
]
3432
);
@@ -53,9 +51,12 @@ public function getting_a_list_of_resources_nested_filtered_by_model_field_using
5351
[
5452
'filters' => [
5553
['field' => 'title', 'operator' => '=', 'value' => 'match'],
56-
['type' => 'or', 'nested' => [
57-
['field' => 'position', 'operator' => '=', 'value' => 3],
58-
]],
54+
[
55+
'type' => 'or',
56+
'nested' => [
57+
['field' => 'position', 'operator' => '=', 'value' => 3],
58+
],
59+
],
5960
],
6061
]
6162
);
@@ -66,6 +67,36 @@ public function getting_a_list_of_resources_nested_filtered_by_model_field_using
6667
);
6768
}
6869

70+
/** @test */
71+
public function getting_a_list_of_resources_nested_filtered_by_model_field_using_in_operator(): void
72+
{
73+
$matchingPost = factory(Post::class)->create(['title' => 'match'])->fresh();
74+
factory(Post::class)->create(['title' => 'not match'])->fresh();
75+
76+
Gate::policy(Post::class, GreenPolicy::class);
77+
78+
$response = $this->post(
79+
'/api/posts/search',
80+
[
81+
'filters' => [
82+
83+
['field' => 'title', 'operator' => '!=', 'value' => 'not match'],
84+
[
85+
'nested' => [
86+
['field' => 'title', 'operator' => 'in', 'value' => ['match']],
87+
['field' => 'title', 'operator' => '!=', 'value' => 'not match'],
88+
],
89+
],
90+
],
91+
]
92+
);
93+
94+
$this->assertResourcesPaginated(
95+
$response,
96+
$this->makePaginator([$matchingPost], 'posts/search')
97+
);
98+
}
99+
69100
/** @test */
70101
public function getting_a_list_of_resources_nested_filtered_by_model_field_using_not_equal_operator(): void
71102
{
@@ -78,9 +109,11 @@ public function getting_a_list_of_resources_nested_filtered_by_model_field_using
78109
'/api/posts/search',
79110
[
80111
'filters' => [
81-
['nested' => [
82-
['field' => 'position', 'operator' => '!=', 'value' => 5]
83-
]],
112+
[
113+
'nested' => [
114+
['field' => 'position', 'operator' => '!=', 'value' => 5],
115+
],
116+
],
84117
],
85118
]
86119
);
@@ -103,9 +136,11 @@ public function getting_a_list_of_resources_nested_filtered_by_not_whitelisted_f
103136
'/api/posts/search',
104137
[
105138
'filters' => [
106-
['nested' => [
107-
['field' => 'body', 'operator' => '=', 'value' => 'match']
108-
]],
139+
[
140+
'nested' => [
141+
['field' => 'body', 'operator' => '=', 'value' => 'match'],
142+
],
143+
],
109144
],
110145
]
111146
);

0 commit comments

Comments
 (0)