From fabc9e4814527990d6c1774f58dee7e3d493ff69 Mon Sep 17 00:00:00 2001 From: henzeb Date: Mon, 14 Mar 2022 11:52:14 +0100 Subject: [PATCH] added filterArray for allowing JSON-api --- CHANGELOG.md | 4 ++ doc/LARAVEL.md | 12 ++++-- src/Illuminate/Mixins/FormRequestMixin.php | 27 +++++++++++- .../FormRequestMxin/FormRequestMixinTest.php | 42 +++++++++++++++++++ 4 files changed, 81 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6df4d15..7d8d5ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to `Query Filter Builder` will be documented in this file +## 1.1.3 - 2022-03-14 + +- added filterArray to easily handle comma separated strings as per recommendation in the JSON:API specification + ## 1.1.2 - 2022-03-02 - a few bugfixes diff --git a/doc/LARAVEL.md b/doc/LARAVEL.md index e74ca87..d477ced 100644 --- a/doc/LARAVEL.md +++ b/doc/LARAVEL.md @@ -63,18 +63,24 @@ protected array $allowSorting = [ `defaultSort` works the same way, except it is allowed to be a string. -### Add your own filters +### Add your filters To add your own filters, simply add the following method in your FormRequest. -You can use `filter` and `hasFilter` methods as shortcut to the filter +You can use `filter`, `filterArray` and `hasFilter` methods as shortcut to the filter query parameter family as specified in [JSON:API specification: Filtering](https://jsonapi.org/format/1.1/#fetching-filtering) - +The `filterArray` method makes sure the result is always returned as an array, so you can pass a comma separated +string in your `filter['animals]` as per recommendation or an array. ```php private function filters(Query $query): void { if($this->hasFilter('animal')) { $query->is('animal_field', $this->filter('animal')); } + + if($this->hasFilter('animals')) { + $query->in('animal_field', $this->filterArray('animals')); + } + } ``` Note: You need to add your own validations in your rules method. diff --git a/src/Illuminate/Mixins/FormRequestMixin.php b/src/Illuminate/Mixins/FormRequestMixin.php index 3f8269e..0aba2e8 100644 --- a/src/Illuminate/Mixins/FormRequestMixin.php +++ b/src/Illuminate/Mixins/FormRequestMixin.php @@ -87,11 +87,36 @@ public function filter(): Closure return Arr::get( $this->query->all(), - $key, $default + $key, + $default ); }; } + public function filterArray(): Closure + { + return function (string $key, mixed $default = null): array { + /** + * @var $this FormRequest + */ + $result = $this->filter($key, $default); + + if (is_string($result) && str_contains($result, ',')) { + return array_filter( + array_map('trim', + explode(',', $result) + ) + ); + } + + if(is_array($result)) { + return $result; + } + + return array_filter([$result]); + }; + } + public function hasFilter(): Closure { return function (string $key): bool { diff --git a/tests/Unit/Illuminate/Mixins/FormRequestMxin/FormRequestMixinTest.php b/tests/Unit/Illuminate/Mixins/FormRequestMxin/FormRequestMixinTest.php index ff9881f..9b2dbab 100644 --- a/tests/Unit/Illuminate/Mixins/FormRequestMxin/FormRequestMixinTest.php +++ b/tests/Unit/Illuminate/Mixins/FormRequestMxin/FormRequestMixinTest.php @@ -34,6 +34,24 @@ public function providesTestCasesForFilter(): array 'basic' => [['filter' => ['animal' => 'dog']], 'animal', 'dog'], 'boolean' => [['filter' => ['alive' => true]], 'alive', true], 'integer' => [['filter' => ['age' => 100]], 'age', 100], + 'comma-separated-string' => [['filter' => ['animal' => 'dog,cat']], 'animal', 'dog,cat'], + 'nested-array' => [['filter' => ['animal' => ['type' => 'mammal']]], 'animal.type', 'mammal'], + 'default' => [['filter' => []], 'animal', 'cat', 'cat'], + ]; + } + + + public function providesTestCasesForFilterArray(): array + { + return [ + 'basic' => [['filter' => ['animal' => 'dog']], 'animal', 'dog'], + 'boolean' => [['filter' => ['alive' => true]], 'alive', true], + 'integer' => [['filter' => ['age' => 100]], 'age', 100], + 'array' => [['filter' => ['animal' => ['dog','cat'] ]], 'animal', ['dog','cat']], + 'comma-separated-string' => [['filter' => ['animal' => 'dog,cat']], 'animal', ['dog','cat']], + 'comma-separated-string-with-spaces' => [['filter' => ['animal' => 'dog, cat']], 'animal', ['dog','cat']], + 'random-comma' => [['filter' => ['animal' => ',']], 'animal', []], + 'just-some-commas' => [['filter' => ['animal' => ', , ,']], 'animal', []], 'nested-array' => [['filter' => ['animal' => ['type' => 'mammal']]], 'animal.type', 'mammal'], 'default' => [['filter' => []], 'animal', 'cat', 'cat'], ]; @@ -69,6 +87,30 @@ public function testFilterShouldReturnValue(array $input, string $filter, mixed ); } + /** + * @param array $input + * @param string $filter + * @param mixed $expected + * @param mixed|null $default + * @return void + * + * @dataProvider providesTestCasesForFilterArray + */ + public function testFilterArrayShouldReturnValueAsArray(array $input, string $filter, mixed $expected, mixed $default = null) + { + $mock = $this->getFormRequest(); + $mock->query = new InputBag($input); + + if(!is_array($expected)) { + $expected = [$expected]; + } + + $this->assertEquals( + $expected, + $mock->filterArray($filter, $default) + ); + } + /** * @param array $input * @param string $filter