diff --git a/CHANGELOG.md b/CHANGELOG.md index 5dcc1df..6df4d15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ All notable changes to `Query Filter Builder` will be documented in this file +## 1.1.2 - 2022-03-02 + +- a few bugfixes +- added default sorting option + +# 1.1.1 - 2022-02-28 + +- fixed bug where joins weren't allowed when using custom filters with Laravel. + ## 1.1.0 - 2022-02-24 - added FormRequest functionality to ease development in Laravel diff --git a/doc/LARAVEL.md b/doc/LARAVEL.md index feaf48e..e74ca87 100644 --- a/doc/LARAVEL.md +++ b/doc/LARAVEL.md @@ -42,13 +42,14 @@ class YourFormRequest extends FormRequest { protected bool $enablePagination = false; /** disable or enable pagination */ protected bool $enableSorting = false; /** disable or enable sorting */ - protected array $allowSorting = []; /** fields that are allowed for sorting */ + protected array $allowedSorting = []; /** fields that are allowed for sorting */ + protected array|string $defaultSort = []; /** default sort, can be a string or an array */ protected int $defaultLimit = 10; /** The default limit */ protected int $maxLimit = 50; /** The maximum allowed limit */ } ``` By default, the package does not allow any fields for sorting. -You have to add the fields you want to allow into the `$allowSorting` property. +You have to add the fields you want to allow into the `$allowedSorting` property. The format is the same as specified in the [JSON:API specification: Sorting](https://jsonapi.org/format/1.1/#fetching-sorting), except it's listed as an array: @@ -59,6 +60,9 @@ protected array $allowSorting = [ '-animal' /** descending */ ]; ``` + +`defaultSort` works the same way, except it is allowed to be a string. + ### Add your own 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 diff --git a/src/Illuminate/Builders/Builder.php b/src/Illuminate/Builders/Builder.php index 51334c0..ddc006a 100644 --- a/src/Illuminate/Builders/Builder.php +++ b/src/Illuminate/Builders/Builder.php @@ -262,7 +262,7 @@ private function globalFilters(Filter $filter) { $query = DB::query(); $this->filterProxy($filter)->build($query); - + if ($query->joins) { $this->getBuilder()->joins = array_merge( diff --git a/src/Illuminate/Factories/FilterFactory.php b/src/Illuminate/Factories/FilterFactory.php index 2a7e5de..121d111 100644 --- a/src/Illuminate/Factories/FilterFactory.php +++ b/src/Illuminate/Factories/FilterFactory.php @@ -14,21 +14,22 @@ private function __construct(private Query $query, private array $parameters) public static function get( InputBag $inputBag, - bool $enableSorting, - bool $enablePagination, - int $defaultLimit = null + ?bool $enableSorting, + array|string|null $defaultSorting, + ?bool $enablePagination, + ?int $defaultLimit, ): Query { $query = new Query; $filterFactory = new self($query, $inputBag->all()); - if ($enablePagination || config('filter.pagination.auto')) { + if ((null === $enablePagination && config('filter.pagination.auto')) || $enablePagination) { $filterFactory->parsePagination($defaultLimit); } - if ($enableSorting || config('filter.sorting.auto')) { - $filterFactory->parseSorting(); + if ((null === $enableSorting && config('filter.sorting.auto')) || $enableSorting) { + $filterFactory->parseSorting($defaultSorting); } return $query; @@ -57,14 +58,19 @@ private function createConfigKey(array $paths): string return join('.', array_filter($paths)); } - private function parseSorting(): void + private function parseSorting(array|string|null $defaultSorting): void { $key = config('filter.sorting.key', 'sort'); + $sorting = $this->stringToArray($defaultSorting); + if (Arr::has($this->parameters, $key)) { - $sorts = explode(',', $this->parameters[$key]); + $sorting = $this->stringToArray($this->parameters[$key]); + } + + if ($sorting) { - foreach ($sorts as $sort) { + foreach ($sorting as $sort) { if (str_starts_with($sort, '-')) { $this->query->desc(ltrim($sort, '-')); @@ -76,4 +82,17 @@ private function parseSorting(): void } } + private function stringToArray(string|array|null $value): ?array + { + if(is_array($value)) { + return $value; + } + + if(null===$value) { + return null; + } + + return explode(',', $value); + } + } diff --git a/src/Illuminate/Mixins/FormRequestMixin.php b/src/Illuminate/Mixins/FormRequestMixin.php index 6f102ba..3f8269e 100644 --- a/src/Illuminate/Mixins/FormRequestMixin.php +++ b/src/Illuminate/Mixins/FormRequestMixin.php @@ -55,9 +55,10 @@ public function getFilter(): Closure $filters = FilterFactory::get( $this->query, - $this->enableSorting ?? false, - $this->enablePagination ?? false, - $this->defaultLimit ?? null + $this->enableSorting ?? null, + $this->defaultSort ?? null, + $this->enablePagination ?? null, + $this->defaultLimit ?? null, ); if (method_exists($this, 'filters')) { diff --git a/tests/Unit/Illuminate/Mixins/FormRequestMxin/PaginationTest.php b/tests/Unit/Illuminate/Mixins/FormRequestMxin/PaginationTest.php index 817b76f..c9e4f19 100644 --- a/tests/Unit/Illuminate/Mixins/FormRequestMxin/PaginationTest.php +++ b/tests/Unit/Illuminate/Mixins/FormRequestMxin/PaginationTest.php @@ -232,7 +232,7 @@ public function providesEnablePaginationTestcases() { return [ 'config-disabled-fq-enabled' => [false, true,(new Query())->limit(12)], - 'config-enabled-fq-disabled' => [true, false, (new Query())->limit(12)], + 'config-enabled-fq-disabled' => [true, false, (new Query())], 'both-disabled' => [false, false, (new Query())], ]; } diff --git a/tests/Unit/Illuminate/Mixins/FormRequestMxin/SortingTest.php b/tests/Unit/Illuminate/Mixins/FormRequestMxin/SortingTest.php index ec4bc05..7783e8f 100644 --- a/tests/Unit/Illuminate/Mixins/FormRequestMxin/SortingTest.php +++ b/tests/Unit/Illuminate/Mixins/FormRequestMxin/SortingTest.php @@ -109,7 +109,7 @@ public function providesEnablePaginationTestcases() 'config-disabled-fq-enabled' => [false, true, (new Query())->limit(50)->asc('animal')], 'config-enabled-fq-disabled' => - [true, false, (new Query())->limit(50)->asc('animal')], + [true, false, (new Query())->limit(50)], 'both-enabled' => [true, true, (new Query())->limit(50)->asc('animal')], 'both-disabled' => @@ -150,4 +150,46 @@ public function testShouldThrowValidationExceptionForNotAllowedFields() $formRequest->getFilter(); } + + public function testShouldAllowDefaultSortingInFormRequest() + { + $formRequest = $this->getFormRequest(); + $formRequest->enablePagination = false; + $formRequest->defaultSort = 'id'; + + + $this->assertEquals( + (new Query())->asc('id'), + $formRequest->getFilter() + ); + } + + public function testShouldAllowDefaultSortingAsArrayInFormRequest() + { + $formRequest = $this->getFormRequest(); + $formRequest->enablePagination = false; + $formRequest->defaultSort = ['-id']; + + + $this->assertEquals( + (new Query())->desc('id'), + $formRequest->getFilter() + ); + } + + public function testShouldNotUseDefaultWhenSortIsGiven() + { + $formRequest = $this->getFormRequest(); + + $formRequest->enablePagination = false; + $formRequest->allowedSorting = ['animal']; + $formRequest->defaultSort = ['-id']; + + $formRequest->query = new InputBag(['sort' => 'animal']); + + $this->assertEquals( + (new Query())->asc('animal'), + $formRequest->getFilter() + ); + } }