From 0235c34d2a7326f0414c1aaf89cc145803c13640 Mon Sep 17 00:00:00 2001 From: Milroy Fraser Date: Sat, 27 Mar 2021 05:16:21 +0100 Subject: [PATCH] PHP 7.4 and defaults to simple pagination --- composer.json | 4 +- src/QueryBuilderAbstract.php | 116 ++++++++------------ tests/Queries/PostListQuery.php | 6 +- tests/Queries/PostListWithPageSizeQuery.php | 2 +- tests/QueryBuilderPaginationTest.php | 32 +++--- 5 files changed, 64 insertions(+), 96 deletions(-) diff --git a/composer.json b/composer.json index 76aa21e..710a4eb 100644 --- a/composer.json +++ b/composer.json @@ -17,8 +17,8 @@ } ], "require": { - "php": "~7.2 || ^8.0", - "apichef/laravel-request-query-helper": "^0.5.0" + "php": "~7.4 || ^8.0", + "apichef/laravel-request-query-helper": "^1.0" }, "require-dev": { "laravel/legacy-factories": "^1.1", diff --git a/src/QueryBuilderAbstract.php b/src/QueryBuilderAbstract.php index d43975a..7ec3941 100644 --- a/src/QueryBuilderAbstract.php +++ b/src/QueryBuilderAbstract.php @@ -11,8 +11,6 @@ use ApiChef\RequestQueryHelper\Sorts; use Illuminate\Contracts\Pagination\LengthAwarePaginator; use Illuminate\Database\Eloquent\Builder as EloquentBuilder; -use Illuminate\Database\Eloquent\Collection; -use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Query\Builder as QueryBuilder; use Illuminate\Http\Request; use Illuminate\Support\Arr; @@ -21,39 +19,22 @@ abstract class QueryBuilderAbstract { - /** @var Request */ - private $request; - - /** @var Fields */ - protected $fields; - - /** @var QueryParamBag */ - protected $includes; - - /** @var QueryParamBag */ - protected $filters; - - /** @var Sorts */ - protected $sorts; - - /** @var PaginationParams */ - protected $paginationParams; - - protected $defaultPageSize = null; + private Request $request; + protected Fields $fields; + protected QueryParamBag $includes; + protected QueryParamBag $filters; + protected Sorts $sorts; + protected PaginationParams $paginationParams; + protected ?int $defaultPageSize = null; + private array $allowedIncludes = []; + private ?array $allPossibleAvailableIncludes = null; + protected array $availableIncludes = []; + protected array $availableFilters = []; + protected array $availableSorts = []; /** @var EloquentBuilder|QueryBuilder */ private $query; - private $allowedIncludes = []; - - private $allPossibleAvailableIncludes = null; - - protected $availableIncludes = []; - - protected $availableFilters = []; - - protected $availableSorts = []; - public function __construct(Request $request) { $this->request = $request; @@ -95,7 +76,7 @@ public function parseAllowedIncludes(array $allowedIncludes): self return $this; } - private function getPossibleRelationshipCombinations(array $relations) + private function getPossibleRelationshipCombinations(array $relations): array { $combinations = []; @@ -112,11 +93,6 @@ private function getPossibleRelationshipCombinations(array $relations) return $combinations; } - /** - * Build and get query. - * - * @return EloquentBuilder|QueryBuilder - */ public function query() { if (! empty($this->allowedIncludes) && $this->includes->filled()) { @@ -134,47 +110,43 @@ public function query() return $this->query; } - /** - * Execute the query. - * - * @param array $columns - * @return Collection|LengthAwarePaginator - */ - public function get($columns = ['*']) + public function get(array $columns = ['*']) { - if ($this->paginationParams->filled()) { - return $this->query()->paginate( - $this->paginationParams->perPage(), - $columns, - $this->paginationParams->pageName(), - $this->paginationParams->page() - ); - } - - if ($this->defaultPageSize !== null) { - return $this->query()->paginate( - $this->defaultPageSize, - $columns, - $this->paginationParams->pageName(), - 1 - ); + if ($this->shouldPaginate()) { + return $this->paginate($columns); } return $this->query()->get($columns); } - /** - * Execute the query and get the first result. - * - * @param array $columns - * @return Model|object|null - */ - public function first($columns = ['*']) + public function paginateWithTotal(array $columns = ['*']): LengthAwarePaginator + { + return $this->paginate($columns, true); + } + + private function paginate(array $columns, bool $withTotalCount = false) + { + $paginate = $withTotalCount ? 'paginate' : 'simplePaginate'; + + return $this->query()->{$paginate}( + $this->paginationParams->perPage($this->defaultPageSize), + $columns, + $this->paginationParams->pageName(), + $this->paginationParams->page(1) + ); + } + + private function shouldPaginate(): bool + { + return $this->defaultPageSize !== null || $this->paginationParams->filled(); + } + + public function first(array $columns = ['*']) { return $this->query()->first($columns); } - private function loadIncludes(QueryParamBag $includes) + private function loadIncludes(QueryParamBag $includes): void { $includes->each(function ($params, $relation) { if ($this->isAllowedToInclude($relation)) { @@ -216,14 +188,14 @@ private function loadRelation($relation, $params): void throw new RuntimeException("Trying to include non existing relationship {$relation}"); } - private function applyFilters(QueryParamBag $filters) + private function applyFilters(QueryParamBag $filters): void { $filters->each(function ($params, $scope) { $this->applyFilter($scope, $params); }); } - private function applyFilter($scope, $params) + private function applyFilter($scope, $params): void { if ($filterAlias = Arr::get($this->filtersMap(), $scope)) { $this->query->{$filterAlias}($params); @@ -248,14 +220,14 @@ private function applyFilter($scope, $params) throw new RuntimeException("Trying to filter by non existing filter {$scope}"); } - private function applySorts(Sorts $sorts) + private function applySorts(Sorts $sorts): void { $sorts->each(function (SortField $sortField) { $this->applySort($sortField->getField(), $sortField->getDirection(), $sortField->getParams()); }); } - private function applySort(string $field, string $direction, string $param = null) + private function applySort(string $field, string $direction, string $param = null): void { if ($sortAlias = Arr::get($this->sortsMap(), $field)) { $this->query->orderBy($sortAlias, $direction); diff --git a/tests/Queries/PostListQuery.php b/tests/Queries/PostListQuery.php index e5595eb..955925f 100644 --- a/tests/Queries/PostListQuery.php +++ b/tests/Queries/PostListQuery.php @@ -19,7 +19,7 @@ protected function init(Request $request) // includes - protected $availableIncludes = [ + protected array $availableIncludes = [ 'comments.user', 'author.posts.tags', ]; @@ -43,7 +43,7 @@ public function includeFeedbackWithSubmittedBy($query) // filters - protected $availableFilters = [ + protected array $availableFilters = [ 'draft', ]; @@ -61,7 +61,7 @@ public function filterByPublishedBefore($query, $params) // sorts - protected $availableSorts = [ + protected array $availableSorts = [ 'published_at', ]; diff --git a/tests/Queries/PostListWithPageSizeQuery.php b/tests/Queries/PostListWithPageSizeQuery.php index 030c31d..06a0c0f 100644 --- a/tests/Queries/PostListWithPageSizeQuery.php +++ b/tests/Queries/PostListWithPageSizeQuery.php @@ -4,5 +4,5 @@ class PostListWithPageSizeQuery extends PostListQuery { - protected $defaultPageSize = 10; + protected ?int $defaultPageSize = 10; } diff --git a/tests/QueryBuilderPaginationTest.php b/tests/QueryBuilderPaginationTest.php index 8d8ffc9..dc1c9e2 100644 --- a/tests/QueryBuilderPaginationTest.php +++ b/tests/QueryBuilderPaginationTest.php @@ -5,35 +5,33 @@ use ApiChef\RequestToEloquent\Dummy\Post; use ApiChef\RequestToEloquent\Queries\PostListQuery; use ApiChef\RequestToEloquent\Queries\PostListWithPageSizeQuery; -use Illuminate\Database\Eloquent\Collection; +use Illuminate\Contracts\Pagination\LengthAwarePaginator; +use Illuminate\Contracts\Pagination\Paginator; use Illuminate\Http\Request; -use Illuminate\Pagination\LengthAwarePaginator; class QueryBuilderPaginationTest extends TestCase { public function test_can_paginate() { - factory(Post::class, 6)->create(); - - $request = Request::create('/posts?page[number]=1&page[size]=4'); + factory(Post::class, 20)->create(); + $request = Request::create('/posts?page[number]=2&page[size]=4'); - /** @var Collection $post */ - $result = (new PostListQuery($request)) - ->get(); + /** @var Paginator $result */ + $result = (new PostListQuery($request))->get(); - $this->assertInstanceOf(LengthAwarePaginator::class, $result); + $this->assertInstanceOf(Paginator::class, $result); + $this->assertEquals(2, $result->currentPage()); + $this->assertEquals(4, $result->perPage()); } - public function test_it_picks_up_number_and_size() + public function test_can_paginate_with_total_count() { factory(Post::class, 20)->create(); - $request = Request::create('/posts?page[number]=2&page[size]=4'); - /** @var LengthAwarePaginator $post */ - $result = (new PostListQuery($request)) - ->get(); + $result = (new PostListQuery($request))->paginateWithTotal(); + $this->assertInstanceOf(LengthAwarePaginator::class, $result); $this->assertEquals(2, $result->currentPage()); $this->assertEquals(5, $result->lastPage()); $this->assertEquals(4, $result->perPage()); @@ -42,12 +40,10 @@ public function test_it_picks_up_number_and_size() public function test_it_uses_default_psge_size() { factory(Post::class, 20)->create(); - $request = Request::create('/posts'); - /** @var LengthAwarePaginator $post */ - $result = (new PostListWithPageSizeQuery($request)) - ->get(); + /** @var Paginator $result */ + $result = (new PostListWithPageSizeQuery($request))->get(); $this->assertCount(10, $result->items()); }