From ef713c879887a87f3345cd0c2f0bc8cd3f16d29e Mon Sep 17 00:00:00 2001 From: Joe Lambert Date: Tue, 25 Aug 2020 12:52:40 +0100 Subject: [PATCH 1/2] Remove redundant properties --- src/QueryBuilder.php | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/QueryBuilder.php b/src/QueryBuilder.php index 501b1ed..e5fd11a 100644 --- a/src/QueryBuilder.php +++ b/src/QueryBuilder.php @@ -15,24 +15,6 @@ class QueryBuilder implements QueryBuilderContract protected $postClass = Post::class; - private $postType; - - private $limit; - private $offset; - - private $orderby; - private $order; - - private $metaOrderBy; - private $metaOrder; - private $metaOrderNumeric; - - private $whereIn; - private $whereNotIn; - - private $metaRelationship; - private $metaQueries = []; - private $params = []; // Order Directions From ae4064dc5e68491f51a1bb3d1b7c8e0eaf18f5d5 Mon Sep 17 00:00:00 2001 From: Joe Lambert Date: Tue, 25 Aug 2020 12:54:15 +0100 Subject: [PATCH 2/2] Implement `paginate()` function --- src/Contracts/QueryBuilder.php | 29 +++++++----- src/QueryBuilder.php | 49 +++++++++++++------ tests/Unit/QueryBuilderTest.php | 84 +++++++++++++++++++++++++++++++-- 3 files changed, 129 insertions(+), 33 deletions(-) diff --git a/src/Contracts/QueryBuilder.php b/src/Contracts/QueryBuilder.php index 2220ffc..d2f1312 100644 --- a/src/Contracts/QueryBuilder.php +++ b/src/Contracts/QueryBuilder.php @@ -2,33 +2,36 @@ namespace Rareloop\Lumberjack\Contracts; +use Timber\PostQuery; use Tightenco\Collect\Support\Collection; interface QueryBuilder { - public function getParameters() : array; + public function getParameters(): array; - public function wherePostType($postType) : QueryBuilder; + public function wherePostType($postType): QueryBuilder; - public function limit($limit) : QueryBuilder; + public function limit($limit): QueryBuilder; - public function offset($offset) : QueryBuilder; + public function offset($offset): QueryBuilder; - public function orderBy($orderBy, string $order = QueryBuilder::ASC) : QueryBuilder; + public function orderBy($orderBy, string $order = QueryBuilder::ASC): QueryBuilder; - public function orderByMeta($metaKey, string $order = QueryBuilder::ASC, string $type = null) : QueryBuilder; + public function orderByMeta($metaKey, string $order = QueryBuilder::ASC, string $type = null): QueryBuilder; - public function whereIdIn(array $ids) : QueryBuilder; + public function whereIdIn(array $ids): QueryBuilder; - public function whereIdNotIn(array $ids) : QueryBuilder; + public function whereIdNotIn(array $ids): QueryBuilder; - public function whereStatus() : QueryBuilder; + public function whereStatus(): QueryBuilder; - public function whereMeta($key, $value, $compare = '=', $type = null) : QueryBuilder; + public function whereMeta($key, $value, $compare = '=', $type = null): QueryBuilder; - public function whereMetaRelationshipIs(string $relation) : QueryBuilder; + public function whereMetaRelationshipIs(string $relation): QueryBuilder; - public function get() : Collection; + public function get(): Collection; - public function clone() : QueryBuilder; + public function paginate($perPage = 10, $page = 1): PostQuery; + + public function clone(): QueryBuilder; } diff --git a/src/QueryBuilder.php b/src/QueryBuilder.php index e5fd11a..fa9b052 100644 --- a/src/QueryBuilder.php +++ b/src/QueryBuilder.php @@ -7,6 +7,7 @@ use Rareloop\Lumberjack\Post; use Spatie\Macroable\Macroable; use Tightenco\Collect\Support\Collection; +use Timber\PostQuery; use Timber\Timber; class QueryBuilder implements QueryBuilderContract @@ -28,33 +29,33 @@ class QueryBuilder implements QueryBuilderContract const OR = 'OR'; const AND = 'AND'; - public function getParameters() : array + public function getParameters(): array { return $this->params; } - public function wherePostType($postType) : QueryBuilderContract + public function wherePostType($postType): QueryBuilderContract { $this->params['post_type'] = $postType; return $this; } - public function limit($limit) : QueryBuilderContract + public function limit($limit): QueryBuilderContract { $this->params['posts_per_page'] = $limit; return $this; } - public function offset($offset) : QueryBuilderContract + public function offset($offset): QueryBuilderContract { $this->params['offset'] = $offset; return $this; } - public function orderBy($orderBy, string $order = QueryBuilder::ASC) : QueryBuilderContract + public function orderBy($orderBy, string $order = QueryBuilder::ASC): QueryBuilderContract { $order = strtoupper($order); @@ -64,7 +65,7 @@ public function orderBy($orderBy, string $order = QueryBuilder::ASC) : QueryBuil return $this; } - public function orderByMeta($metaKey, string $order = QueryBuilder::ASC, string $type = null) : QueryBuilderContract + public function orderByMeta($metaKey, string $order = QueryBuilder::ASC, string $type = null): QueryBuilderContract { $order = strtoupper($order); @@ -75,21 +76,21 @@ public function orderByMeta($metaKey, string $order = QueryBuilder::ASC, string return $this; } - public function whereIdIn(array $ids) : QueryBuilderContract + public function whereIdIn(array $ids): QueryBuilderContract { $this->params['post__in'] = $ids; return $this; } - public function whereIdNotIn(array $ids) : QueryBuilderContract + public function whereIdNotIn(array $ids): QueryBuilderContract { $this->params['post__not_in'] = $ids; return $this; } - public function whereStatus() : QueryBuilderContract + public function whereStatus(): QueryBuilderContract { $args = func_get_args(); @@ -107,7 +108,7 @@ protected function initialiseMetaQuery() $this->params['meta_query'] = $this->params['meta_query'] ?? []; } - public function whereMeta($key, $value, $compare = '=', $type = null) : QueryBuilderContract + public function whereMeta($key, $value, $compare = '=', $type = null): QueryBuilderContract { $meta = [ 'key' => $key, @@ -125,7 +126,7 @@ public function whereMeta($key, $value, $compare = '=', $type = null) : QueryBui return $this; } - public function whereMetaRelationshipIs(string $relation) : QueryBuilderContract + public function whereMetaRelationshipIs(string $relation): QueryBuilderContract { $relation = strtoupper($relation); @@ -141,14 +142,14 @@ public function whereMetaRelationshipIs(string $relation) : QueryBuilderContract return $this; } - public function as($postClass) : QueryBuilderContract + public function as($postClass): QueryBuilderContract { $this->postClass = $postClass; return $this; } - public function get() : Collection + public function get(): Collection { $posts = Timber::get_posts($this->getParameters(), $this->postClass); @@ -159,12 +160,30 @@ public function get() : Collection return collect($posts); } + public function paginate($perPage = 10, $page = 1): PostQuery + { + global $paged; + + if (isset($page)) { + $paged = $page; + } + + if (!isset($paged) || !$paged) { + $paged = 1; + } + + $this->limit($perPage); + $this->params['paged'] = $paged; + + return new PostQuery($this->getParameters(), $this->postClass); + } + /** * Get the first Post that matches the current query. If no Post matches then return `null`. * * @return \Rareloop\Lumberjack\Post|null */ - public function first() : ?Post + public function first(): ?Post { $params = array_merge($this->getParameters(), [ 'limit' => 1, @@ -179,7 +198,7 @@ public function first() : ?Post return collect($posts)->first(); } - public function clone() : QueryBuilderContract + public function clone(): QueryBuilderContract { $clone = clone $this; diff --git a/tests/Unit/QueryBuilderTest.php b/tests/Unit/QueryBuilderTest.php index 606032a..d30ef7d 100644 --- a/tests/Unit/QueryBuilderTest.php +++ b/tests/Unit/QueryBuilderTest.php @@ -2,16 +2,21 @@ namespace Rareloop\Lumberjack\Test; -use Illuminate\Support\Collection; use Mockery; -use PHPUnit\Framework\TestCase; +use Timber\Timber; +use Timber\PostQuery; +use Timber\PostGetter; +use Timber\PostCollection; +use Brain\Monkey\Functions; use Rareloop\Lumberjack\Post; +use PHPUnit\Framework\TestCase; +use Illuminate\Support\Collection; use Rareloop\Lumberjack\QueryBuilder; -use Timber\Timber; +use Rareloop\Lumberjack\Test\Unit\BrainMonkeyPHPUnitIntegration; class QueryBuilderTest extends TestCase { - use \Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration; + use BrainMonkeyPHPUnitIntegration; /** @test */ public function correct_post_type_is_set() @@ -400,6 +405,75 @@ public function get_retrieves_empty_collection_when_timber_returns_null() $this->assertSame(0, $returnedPosts->count()); } + /** + * @test + * @runInSeparateProcess + * @preserveGlobalState disabled + */ + public function paginate_retrieves_PostQuery_object_with_correct_defaults() + { + $this->assertPostQueryParameters([ + 'post_status' => 'publish', + 'posts_per_page' => 10, + 'paged' => 1, + ]); + + $builder = new QueryBuilder(); + $returnedPostQuery = $builder->whereStatus('publish')->paginate(); + + $this->assertInstanceOf(PostQuery::class, $returnedPostQuery); + } + + /** + * @test + * @runInSeparateProcess + * @preserveGlobalState disabled + */ + public function paginate_retrieves_PostQuery_object_with_provided_arguments() + { + $this->assertPostQueryParameters([ + 'post_status' => 'publish', + 'posts_per_page' => 20, + 'paged' => 2, + ]); + + $builder = new QueryBuilder(); + $returnedPostQuery = $builder->whereStatus('publish')->paginate(20, 2); + + $this->assertInstanceOf(PostQuery::class, $returnedPostQuery); + } + + /** + * We have to mock quite a bit more than is ideal for this but there is no other way to hook + * into this bit of Timber that I've found. It does leave us a little open to failing tests + * if Timber change their implementation but not much we can do about that. + * + * @param array $params The parameters to assert are passed in construction + * @return void + */ + protected function assertPostQueryParameters(array $params) + { + Functions\expect('get_post_type') + ->andReturn('post'); + + $posts = [new Post(1, true), new Post(2, true)]; + + $postGetter = Mockery::mock('alias:' . PostGetter::class); + + $postGetter + ->shouldReceive('get_post_class') + ->andReturn(Post::class); + + $postGetter + ->shouldReceive('query_posts') + ->withArgs([ + Mockery::subset($params), + Post::class, + ]) + ->once() + ->andReturn(new PostCollection($posts, Post::class)); + } + /** * @test * @runInSeparateProcess @@ -593,7 +667,7 @@ class QueryBuilderMixin { function testFunctionAddedByMixin() { - return function() { + return function () { $this->params['foo'] = 'bar'; return $this;