diff --git a/src/Filters/Concerns/HasColumns.php b/src/Filters/Concerns/HasColumns.php new file mode 100644 index 0000000..95ec744 --- /dev/null +++ b/src/Filters/Concerns/HasColumns.php @@ -0,0 +1,81 @@ + + */ + private array $columns = []; + + /** + * @return array + */ + 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 + */ + protected function qualifiedColumns(): array + { + if ($this->table) { + return array_map(fn($column) => $this->table . '.' . $column, $this->columns); + } + + return $this->columns; + } +} diff --git a/src/Filters/WhereAll.php b/src/Filters/WhereAll.php new file mode 100644 index 0000000..c6864fb --- /dev/null +++ b/src/Filters/WhereAll.php @@ -0,0 +1,79 @@ + $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 $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) + ); + } +} diff --git a/src/Filters/WhereAny.php b/src/Filters/WhereAny.php new file mode 100644 index 0000000..43fa0b0 --- /dev/null +++ b/src/Filters/WhereAny.php @@ -0,0 +1,79 @@ + $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 $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) + ); + } +} diff --git a/tests/app/Schemas/PostSchema.php b/tests/app/Schemas/PostSchema.php index 6fbb229..872c686 100644 --- a/tests/app/Schemas/PostSchema.php +++ b/tests/app/Schemas/PostSchema.php @@ -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; @@ -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'), ]; } diff --git a/tests/lib/Acceptance/Filters/WhereAllTest.php b/tests/lib/Acceptance/Filters/WhereAllTest.php new file mode 100644 index 0000000..ee1980c --- /dev/null +++ b/tests/lib/Acceptance/Filters/WhereAllTest.php @@ -0,0 +1,56 @@ +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); + } +} diff --git a/tests/lib/Acceptance/Filters/WhereAnyTest.php b/tests/lib/Acceptance/Filters/WhereAnyTest.php new file mode 100644 index 0000000..3669b28 --- /dev/null +++ b/tests/lib/Acceptance/Filters/WhereAnyTest.php @@ -0,0 +1,55 @@ +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); + } +}