Skip to content

Commit

Permalink
Add support for query scopes (#30)
Browse files Browse the repository at this point in the history
* add support for query scopes

* support dynamic query scopes

* formatting

* pass all arguments to query scope method
  • Loading branch information
aaemnnosttv committed Feb 24, 2018
1 parent 12f5fe9 commit dfe4f0d
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 0 deletions.
17 changes: 17 additions & 0 deletions src/Query/Builder.php
Expand Up @@ -82,4 +82,21 @@ public function getModel()
{
return $this->model;
}

/**
* Handle dynamic method calls on the builder.
*
* @param string $name Method name
* @param array $arguments
*
* @return mixed
*/
public function __call($name, $arguments)
{
if (method_exists($this->model, 'scope' . ucfirst($name))) {
return $this->model->{'scope' . ucfirst($name)}($this, ...$arguments);
}

throw new \BadMethodCallException("No '$name' method exists on " . static::class);
}
}
94 changes: 94 additions & 0 deletions tests/unit/Post/PostQueryBuilderTest.php
Expand Up @@ -108,9 +108,103 @@ function it_can_set_arbitrary_query_vars()

$this->assertSame('donut', $query->get('foo'));
}

/** @test */
function it_delegates_query_scopes_to_the_model()
{
$model = new ModelTestScope();
$this->factory()->post->create_many(3, [
'post_type' => $model->post_type,
'post_status' => 'publish',
]);
$this->factory()->post->create_many(4, [
'post_type' => $model->post_type,
'post_status' => 'draft',
]);
$this->factory()->post->create_many(5, [
'post_type' => $model->post_type,
'post_status' => 'inherit',
]);

$builder = new QueryBuilder(new WP_Query);
$builder->setModel($model);

$this->assertCount(3, $builder->published()->results());
$this->assertCount(4, $builder->draft()->results());
$this->assertCount(5, $builder->revision()->results());
}

/** @test */
function undefined_scopes_throw_method_not_found_exception()
{
$model = new ModelTestScope();
$this->factory()->post->create_many(3, [
'post_type' => $model->post_type,
'post_status' => 'publish',
]);

$builder = new QueryBuilder(new WP_Query);
$builder->setModel($model);

$this->assertFalse(method_exists($model, 'scopeNonExistentScope'));

try {
$builder->nonExistentScope();
} catch (\BadMethodCallException $e) {
return;
}

$this->fail('Expected a BadMethodCallException due to missing query scope');
}

/** @test */
function scopes_can_pass_parameters_to_the_model_methods()
{
$model = new ModelTestScope();
$parent_id = $this->factory()->post->create([
'post_type' => $model->post_type,
]);

$children = $this->factory()->post->create_many(3, [
'post_type' => $model->post_type,
'post_parent' => $parent_id,
]);

$builder = new QueryBuilder(new WP_Query);
$builder->setModel($model);

$this->assertCount(3, $builder->childOf($parent_id)->results());
$this->assertEqualSets($children, $builder->childOf($parent_id)->results()->pluck('id')->all());
}

}

class CustomCPT extends Model
{
const POST_TYPE = 'custom';
}

class ModelTestScope extends Model
{
const POST_TYPE = 'custom';

public function scopeDraft(QueryBuilder $builder)
{
return $builder->whereStatus('draft');
}

public function scopePublished(QueryBuilder $builder)
{
return $builder->whereStatus('publish');
}

public function scopeRevision(QueryBuilder $builder)
{
return $builder->whereStatus('inherit');
}

public function scopeChildOf(QueryBuilder $builder, $parent)
{
return $builder->set('post_parent', $parent);
}
}

0 comments on commit dfe4f0d

Please sign in to comment.