Skip to content

Commit

Permalink
Implement paginate() function
Browse files Browse the repository at this point in the history
  • Loading branch information
joelambert committed Oct 1, 2021
1 parent ef713c8 commit ae4064d
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 33 deletions.
29 changes: 16 additions & 13 deletions src/Contracts/QueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
49 changes: 34 additions & 15 deletions src/QueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);

Expand All @@ -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);

Expand All @@ -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();

Expand All @@ -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,
Expand All @@ -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);

Expand All @@ -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);

Expand All @@ -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,
Expand All @@ -179,7 +198,7 @@ public function first() : ?Post
return collect($posts)->first();
}

public function clone() : QueryBuilderContract
public function clone(): QueryBuilderContract
{
$clone = clone $this;

Expand Down
84 changes: 79 additions & 5 deletions tests/Unit/QueryBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -593,7 +667,7 @@ class QueryBuilderMixin
{
function testFunctionAddedByMixin()
{
return function() {
return function () {
$this->params['foo'] = 'bar';

return $this;
Expand Down

0 comments on commit ae4064d

Please sign in to comment.