Skip to content

Commit

Permalink
feat: add WhereAll and WhereAny filters
Browse files Browse the repository at this point in the history
  • Loading branch information
Gregory Haddow authored and lindyhopchris committed Oct 13, 2024
1 parent 0401362 commit 3702578
Show file tree
Hide file tree
Showing 6 changed files with 354 additions and 0 deletions.
81 changes: 81 additions & 0 deletions src/Filters/Concerns/HasColumns.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?php
/*
* Copyright 2024 Cloud Creativity Limited
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/

declare(strict_types=1);

namespace LaravelJsonApi\Eloquent\Filters\Concerns;

trait HasColumns
{

/**
* @var string|null
*/
private ?string $table = null;


/**
* @var array<string>
*/
private array $columns = [];

/**
* @return array<string>
*/
public function columns(): array
{
return $this->columns;
}

public function withColumn(string $column): self
{
$this->columns[] = $column;

return $this;
}

/**
* Force the table name when qualifying the columns.
*
* This allows the developer to force the table that the columns are qualified with.
*
* @param string $table
* @return $this
*/
public function qualifyAs(string $table): self
{
$this->table = $table;

return $this;
}

/**
* Determine if developer has forced a table to qualify columns as
*
* @return bool
*/
public function isQualified(): bool
{
return $this->table === null;
}

/**
* Get qualified columns.
*
* @return array<string>
*/
protected function qualifiedColumns(): array
{
if ($this->table) {
return array_map(fn($column) => $this->table . '.' . $column, $this->columns);
}

return $this->columns;
}
}
79 changes: 79 additions & 0 deletions src/Filters/WhereAll.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php
/*
* Copyright 2024 Cloud Creativity Limited
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/

declare(strict_types=1);

namespace LaravelJsonApi\Eloquent\Filters;

use Illuminate\Support\Traits\Conditionable;
use LaravelJsonApi\Eloquent\Contracts\Filter;

class WhereAll implements Filter
{

use Concerns\DeserializesValue;
use Concerns\HasColumns;
use Concerns\HasOperator;
use Concerns\IsSingular;
use Conditionable;

/**
* @var string
*/
private string $name;

/**
* Create a new filter.
*
* @param string $name
* @param array<string> $columns
* @return static
*/
public static function make(string $name, array $columns = null): self
{
return new static($name, $columns);
}

/**
* WhereAny constructor.
*
* @param string $name
* @param array<string> $columns
*/
public function __construct(string $name, array $columns = null)
{
$this->name = $name;
$this->columns = $columns ?? [];
$this->operator = '=';
}

/**
* @inheritDoc
*/
public function key(): string
{
return $this->name;
}

/**
* @inheritDoc
*/
public function apply($query, $value)
{
if (!$this->isQualified()){
$this->qualifyAs($query->getModel()->getTable());
}

return $query->whereAll(
$this->qualifiedColumns(),
$this->operator(),
$this->deserialize($value)
);
}
}
79 changes: 79 additions & 0 deletions src/Filters/WhereAny.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php
/*
* Copyright 2024 Cloud Creativity Limited
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/

declare(strict_types=1);

namespace LaravelJsonApi\Eloquent\Filters;

use Illuminate\Support\Traits\Conditionable;
use LaravelJsonApi\Eloquent\Contracts\Filter;

class WhereAny implements Filter
{

use Concerns\DeserializesValue;
use Concerns\HasColumns;
use Concerns\HasOperator;
use Concerns\IsSingular;
use Conditionable;

/**
* @var string
*/
private string $name;

/**
* Create a new filter.
*
* @param string $name
* @param array<string> $columns
* @return static
*/
public static function make(string $name, array $columns = null): self
{
return new static($name, $columns);
}

/**
* WhereAny constructor.
*
* @param string $name
* @param array<string> $columns
*/
public function __construct(string $name, array $columns = null)
{
$this->name = $name;
$this->columns = $columns ?? [];
$this->operator = '=';
}

/**
* @inheritDoc
*/
public function key(): string
{
return $this->name;
}

/**
* @inheritDoc
*/
public function apply($query, $value)
{
if (!$this->isQualified()){
$this->qualifyAs($query->getModel()->getTable());
}

return $query->whereAny(
$this->qualifiedColumns(),
$this->operator(),
$this->deserialize($value)
);
}
}
4 changes: 4 additions & 0 deletions tests/app/Schemas/PostSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
use LaravelJsonApi\Eloquent\Fields\Str;
use LaravelJsonApi\Eloquent\Filters\OnlyTrashed;
use LaravelJsonApi\Eloquent\Filters\Where;
use LaravelJsonApi\Eloquent\Filters\WhereAll;
use LaravelJsonApi\Eloquent\Filters\WhereAny;
use LaravelJsonApi\Eloquent\Filters\WhereDoesntHave;
use LaravelJsonApi\Eloquent\Filters\WhereHas;
use LaravelJsonApi\Eloquent\Filters\WhereIdIn;
Expand Down Expand Up @@ -94,6 +96,8 @@ public function filters(): iterable
Where::make('slug')->singular(),
WhereIn::make('slugs')->delimiter(','),
WithTrashed::make('withTrashed'),
WhereAll::make('all', ['title','content'])->withColumn('slug')->using('like'),
WhereAny::make('any', ['title','content'])->withColumn('slug')->using('like'),
];
}

Expand Down
56 changes: 56 additions & 0 deletions tests/lib/Acceptance/Filters/WhereAllTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php
/*
* Copyright 2024 Cloud Creativity Limited
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/

declare(strict_types=1);

namespace LaravelJsonApi\Eloquent\Tests\Acceptance\Filters;

use App\Models\Post;
use App\Schemas\PostSchema;

class WhereAllTest extends TestCase
{
/**
* @var PostSchema
*/
private PostSchema $schema;

/**
* @return void
*/
protected function setUp(): void
{
parent::setUp();

$this->schema = $this->schemas()->schemaFor('posts');
}

/**
* @return void
*/
public function testWhereAll(): void
{
Post::factory()->count(5)->create();

$all = Post::factory()->create(['title' => "foobar boofar", 'content' => "boofar foobar", 'slug' => "totally_foobar_1"]);
Post::factory()->create(['title' => "foobar boofar"]);
Post::factory()->create(['content' => "boofar foobar"]);
Post::factory()->create(['slug' => "totally_foobar"]);

$expected = [$all];

$actual = $this->schema
->repository()
->queryAll()
->filter(['all' => '%foobar%'])
->get();

$this->assertFilteredModels($expected, $actual);
}
}
55 changes: 55 additions & 0 deletions tests/lib/Acceptance/Filters/WhereAnyTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php
/*
* Copyright 2024 Cloud Creativity Limited
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/

declare(strict_types=1);

namespace LaravelJsonApi\Eloquent\Tests\Acceptance\Filters;

use App\Models\Post;
use App\Schemas\PostSchema;

class WhereAnyTest extends TestCase
{
/**
* @var PostSchema
*/
private PostSchema $schema;

/**
* @return void
*/
protected function setUp(): void
{
parent::setUp();

$this->schema = $this->schemas()->schemaFor('posts');
}

/**
* @return void
*/
public function testWhereAny(): void
{
Post::factory()->count(5)->create();

$title = Post::factory()->create(['title' => "foobar boofar"]);
$content = Post::factory()->create(['content' => "boofar foobar"]);
$slug = Post::factory()->create(['slug' => "totally_foobar"]);

$expected = [$title,$content, $slug];

$actual = $this->schema
->repository()
->queryAll()
->filter(['any' => '%foobar%'])
->get();

$this->assertFilteredModels($expected, $actual);
}
}

0 comments on commit 3702578

Please sign in to comment.