From a9ebec03ae73a22cf2af30ae2678cd99b6b5fd4c Mon Sep 17 00:00:00 2001 From: Eduard Lupacescu Date: Tue, 2 Jul 2024 10:55:15 +0300 Subject: [PATCH] feat: add support for POST advanced filters --- src/Bootstrap/RoutesDefinition.php | 5 +++ src/Events/AdvancedFiltersApplied.php | 2 +- src/Filters/AdvancedFiltersCollection.php | 11 +++---- .../RepositoryApplyFiltersController.php | 13 ++++++++ .../RepositoryApplyFiltersRequest.php | 5 +++ src/Http/Requests/RestifyRequest.php | 7 ++++ .../Search/RepositorySearchService.php | 2 +- tests/Feature/Filters/AdvancedFilterTest.php | 32 +++++++++++++++++-- 8 files changed, 66 insertions(+), 11 deletions(-) create mode 100644 src/Http/Controllers/RepositoryApplyFiltersController.php create mode 100644 src/Http/Requests/RepositoryApplyFiltersRequest.php diff --git a/src/Bootstrap/RoutesDefinition.php b/src/Bootstrap/RoutesDefinition.php index a9c0cbe1..895eed1e 100644 --- a/src/Bootstrap/RoutesDefinition.php +++ b/src/Bootstrap/RoutesDefinition.php @@ -22,6 +22,11 @@ public function __invoke(?string $uriKey = null) \Binaryk\LaravelRestify\Http\Controllers\RepositoryFilterController::class )->name('filters.index'); + Route::post( + $prefix.'/apply-restify-advanced-filters', + \Binaryk\LaravelRestify\Http\Controllers\RepositoryApplyFiltersController::class + )->name('filters.apply'); + // Actions Route::get( $prefix.'/actions', diff --git a/src/Events/AdvancedFiltersApplied.php b/src/Events/AdvancedFiltersApplied.php index bb1fd041..e2167af8 100644 --- a/src/Events/AdvancedFiltersApplied.php +++ b/src/Events/AdvancedFiltersApplied.php @@ -10,6 +10,6 @@ class AdvancedFiltersApplied public function __construct( public Repository $repository, public AdvancedFiltersCollection $advancedFiltersCollection, - public ?string $rawFilters = null, + public array $rawFilters = [], ) {} } diff --git a/src/Filters/AdvancedFiltersCollection.php b/src/Filters/AdvancedFiltersCollection.php index bd276142..cd0f06a8 100644 --- a/src/Filters/AdvancedFiltersCollection.php +++ b/src/Filters/AdvancedFiltersCollection.php @@ -2,6 +2,7 @@ namespace Binaryk\LaravelRestify\Filters; +use Binaryk\LaravelRestify\Http\Requests\RepositoryApplyFiltersRequest; use Binaryk\LaravelRestify\Http\Requests\RestifyRequest; use Binaryk\LaravelRestify\Repositories\Repository; use Illuminate\Support\Collection; @@ -16,28 +17,26 @@ class AdvancedFiltersCollection extends Collection { public function authorized(RestifyRequest $request): self { - return $this->filter(fn (Filter $filter) => $filter->authorizedToSee($request))->values(); + return $this->filter(fn(Filter $filter) => $filter->authorizedToSee($request))->values(); } public function apply(RestifyRequest $request, $query): self { - return $this->each(fn (AdvancedFilter $filter) => $filter->filter($request, $query, $filter->dataObject->value)); + return $this->each(fn(AdvancedFilter $filter) => $filter->filter($request, $query, $filter->dataObject->value)); } public static function collectQueryFilters(RestifyRequest $request, Repository $repository): self { - if (! $request->input('filters')) { + if (! $filters = $request->filters()) { return static::make([]); } - $filters = json_decode(base64_decode($request->input('filters')), true); - $allowedFilters = $repository->collectAdvancedFilters($request); return static::make($filters) ->map(function (array $queryFilter) use ($allowedFilters, $request) { /** * @var AdvancedFilter $advancedFilter */ - $advancedFilter = $allowedFilters->first(fn ( + $advancedFilter = $allowedFilters->first(fn( AdvancedFilter $filter ) => $filter::uriKey() === data_get($queryFilter, 'key')); diff --git a/src/Http/Controllers/RepositoryApplyFiltersController.php b/src/Http/Controllers/RepositoryApplyFiltersController.php new file mode 100644 index 00000000..47207885 --- /dev/null +++ b/src/Http/Controllers/RepositoryApplyFiltersController.php @@ -0,0 +1,13 @@ +repository()->index($request); + } +} diff --git a/src/Http/Requests/RepositoryApplyFiltersRequest.php b/src/Http/Requests/RepositoryApplyFiltersRequest.php new file mode 100644 index 00000000..efce871a --- /dev/null +++ b/src/Http/Requests/RepositoryApplyFiltersRequest.php @@ -0,0 +1,5 @@ +input('filters', []) + : json_decode(base64_decode($this->input('filters', [])), true); + } } diff --git a/src/Services/Search/RepositorySearchService.php b/src/Services/Search/RepositorySearchService.php index afea043e..aecee850 100644 --- a/src/Services/Search/RepositorySearchService.php +++ b/src/Services/Search/RepositorySearchService.php @@ -210,7 +210,7 @@ protected function applyFilters(RestifyRequest $request, Repository $repository, $repository, AdvancedFiltersCollection::collectQueryFilters($request, $repository) ->apply($request, $query), - $request->input('filters'), + $request->filters(), ) ); diff --git a/tests/Feature/Filters/AdvancedFilterTest.php b/tests/Feature/Filters/AdvancedFilterTest.php index bb46986b..f6d57160 100644 --- a/tests/Feature/Filters/AdvancedFilterTest.php +++ b/tests/Feature/Filters/AdvancedFilterTest.php @@ -38,7 +38,7 @@ public function test_filters_can_have_definition(): void $this->getJson(PostRepository::route('filters', query: [ 'only' => 'matches,searchables,sortables', ]))->assertJson( - fn (AssertableJson $json) => $json + fn(AssertableJson $json) => $json ->where('data.1.repository.key', 'users') ->where('data.1.repository.label', 'Users') ->where('data.1.repository.display_key', 'id') @@ -73,7 +73,7 @@ public function test_value_filter_doesnt_require_value(): void 'filters' => $filters, ])) ->assertJson( - fn (AssertableJson $json) => $json + fn(AssertableJson $json) => $json ->where('data.0.attributes.title', $expectedTitle) ->etc() ) @@ -197,7 +197,7 @@ public function test_the_timestamp_filter_is_applied(): void ])) ->assertOk() ->assertJson( - fn (AssertableJson $json) => $json + fn(AssertableJson $json) => $json ->where('data.0.attributes.title', 'Valid post') ->count('data', 1) ->etc() @@ -242,4 +242,30 @@ public function test_filter_can_send_meta(): void 'filters' => $filters, ]))->assertJsonCount(0, 'data'); } + + public function test_filter_can_be_sent_in_post_requests(): void + { + Post::factory()->create([ + 'title' => 'Valid post', + 'description' => 'Zoo bar post', + ]); + + Post::factory()->create([ + 'title' => 'Active post', + 'description' => 'Foo bar post', + ]); + + $filters = [ + [ + 'key' => ValueFilter::uriKey(), + 'value' => 'Valid%', + 'operator' => 'like', + 'column' => 'title', + ], + ]; + + $this->post(PostRepository::route('apply-restify-advanced-filters'), [ + 'filters' => $filters, + ])->assertJsonCount(1, 'data'); + } }