Skip to content

Commit

Permalink
feat: initial work on filter validation
Browse files Browse the repository at this point in the history
  • Loading branch information
lindyhopchris committed Mar 28, 2024
1 parent c91e448 commit e5a6490
Show file tree
Hide file tree
Showing 16 changed files with 121 additions and 50 deletions.
4 changes: 2 additions & 2 deletions src/Contracts/Filter.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@

use Illuminate\Database\Eloquent\Builder;
use LaravelJsonApi\Contracts\Schema\Filter as BaseFilter;
use LaravelJsonApi\Validation\Filters\IsValidated;

interface Filter extends BaseFilter
interface Filter extends BaseFilter, IsValidated
{

/**
* Does the filter return a singular resource?
*
Expand Down
21 changes: 14 additions & 7 deletions src/Filters/Concerns/DeserializesValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,26 @@

trait DeserializesValue
{

/**
* @var Closure|null
*/
private ?Closure $deserializer = null;

/**
* @var bool
*/
private bool $asBool = false;

/**
* Use the supplied callback to deserialize the value.
*
* @param Closure $deserializer
* @return $this
*/
public function deserializeUsing(Closure $deserializer): self
public function deserializeUsing(Closure $deserializer): static
{
$this->deserializer = $deserializer;
$this->asBool = false;

return $this;
}
Expand All @@ -40,11 +45,9 @@ public function deserializeUsing(Closure $deserializer): self
*
* @return $this
*/
public function asBoolean(): self
public function asBoolean(): static
{
$this->deserializeUsing(
static fn($value) => filter_var($value, FILTER_VALIDATE_BOOL)
);
$this->asBool = true;

return $this;
}
Expand All @@ -55,8 +58,12 @@ public function asBoolean(): self
* @param mixed $value
* @return mixed
*/
protected function deserialize($value)
protected function deserialize(mixed $value): mixed
{
if (true === $this->asBool) {
return filter_var($value, FILTER_VALIDATE_BOOL);
}

if ($this->deserializer) {
return ($this->deserializer)($value);
}
Expand Down
13 changes: 5 additions & 8 deletions src/Filters/Concerns/HasDelimiter.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

trait HasDelimiter
{

/**
* @var string|null
*/
Expand All @@ -28,14 +27,12 @@ trait HasDelimiter
/**
* If the filter accepts a string value, the delimiter to use to extract values.
*
* @param string $delimiter
* @param non-empty-string $delimiter
* @return $this
*/
public function delimiter(string $delimiter): self
public function delimiter(string $delimiter): static
{
if (empty($delimiter)) {
throw new InvalidArgumentException('Expecting a non-empty string delimiter.');
}
assert(!empty($delimiter), 'Expecting a non-empty string delimiter.');

$this->delimiter = $delimiter;

Expand All @@ -45,10 +42,10 @@ public function delimiter(string $delimiter): self
/**
* Convert the provided value to an array.
*
* @param string|array|null $value
* @param mixed $value
* @return array
*/
protected function toArray($value): array
protected function toArray(mixed $value): array
{
if ($this->delimiter && is_string($value)) {
return ('' !== $value) ? explode($this->delimiter, $value) : [];
Expand Down
19 changes: 16 additions & 3 deletions src/Filters/Has.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,31 @@

namespace LaravelJsonApi\Eloquent\Filters;

use Illuminate\Http\Request;
use LaravelJsonApi\Core\Query\Input\Query;
use LaravelJsonApi\Eloquent\Contracts\Filter;
use LaravelJsonApi\Eloquent\Filters\Concerns\HasRelation;
use LaravelJsonApi\Eloquent\Filters\Concerns\IsSingular;
use LaravelJsonApi\Eloquent\Schema;
use LaravelJsonApi\Validation\Filters\Validated;
use LaravelJsonApi\Validation\Rules\JsonBoolean;
use function filter_var;

class Has implements Filter
{
use HasRelation;
use IsSingular;
use Validated;

/**
* Create a new filter.
*
* @param Schema $schema
* @param string $fieldName
* @param string|null $key
* @return static
* @return self
*/
public static function make(Schema $schema, string $fieldName, string $key = null)
public static function make(Schema $schema, string $fieldName, string $key = null): self
{
return new static($schema, $fieldName, $key);
}
Expand Down Expand Up @@ -64,13 +69,21 @@ public function apply($query, $value)
return $query->doesntHave($relationName);
}

/**
* @inheritDoc
*/
public function validationRules(?Request $request, Query $query): array
{
return [(new JsonBoolean())->asString()];
}

/**
* Deserialize the value.
*
* @param mixed $value
* @return bool
*/
protected function deserialize($value): bool
protected function deserialize(mixed $value): bool
{
return filter_var($value, FILTER_VALIDATE_BOOL);
}
Expand Down
2 changes: 0 additions & 2 deletions src/Filters/OnlyTrashed.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

class OnlyTrashed extends WithTrashed
{

/**
* @inheritDoc
*/
Expand All @@ -31,5 +30,4 @@ public function apply($query, $value)

throw new LogicException("Filter {$this->key()} expects query builder to have a `withTrashed` method.");
}

}
7 changes: 4 additions & 3 deletions src/Filters/Scope.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@

use LaravelJsonApi\Core\Support\Str;
use LaravelJsonApi\Eloquent\Contracts\Filter;
use LaravelJsonApi\Eloquent\Filters\Concerns\DeserializesValue;
use LaravelJsonApi\Eloquent\Filters\Concerns\IsSingular;

class Scope implements Filter
{

use Concerns\DeserializesValue;
use Concerns\IsSingular;
use DeserializesValue;
use IsSingular;

/**
* @var string
Expand Down
28 changes: 23 additions & 5 deletions src/Filters/Where.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,20 @@

use LaravelJsonApi\Core\Support\Str;
use LaravelJsonApi\Eloquent\Contracts\Filter;
use LaravelJsonApi\Eloquent\Filters\Concerns\DeserializesValue;
use LaravelJsonApi\Eloquent\Filters\Concerns\HasColumn;
use LaravelJsonApi\Eloquent\Filters\Concerns\HasOperator;
use LaravelJsonApi\Eloquent\Filters\Concerns\IsSingular;
use LaravelJsonApi\Validation\Filters\ValidatedWithRules;
use LaravelJsonApi\Validation\Rules\JsonBoolean;

class Where implements Filter
{

use Concerns\DeserializesValue;
use Concerns\HasColumn;
use Concerns\HasOperator;
use Concerns\IsSingular;
use DeserializesValue;
use HasColumn;
use HasOperator;
use IsSingular;
use ValidatedWithRules;

/**
* @var string
Expand Down Expand Up @@ -72,6 +78,18 @@ public function apply($query, $value)
);
}

/**
* @return array<int, mixed>
*/
protected function defaultRules(): array
{
if ($this->asBool) {
return [(new JsonBoolean())->asString()];
}

return [];
}

/**
* @return string
*/
Expand Down
16 changes: 15 additions & 1 deletion src/Filters/WhereHas.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,23 @@
namespace LaravelJsonApi\Eloquent\Filters;

use Closure;
use Illuminate\Http\Request;
use LaravelJsonApi\Core\Query\Input\Query;
use LaravelJsonApi\Eloquent\Contracts\Filter;
use LaravelJsonApi\Eloquent\Filters\Concerns\DeserializesToArray;
use LaravelJsonApi\Eloquent\Filters\Concerns\HasRelation;
use LaravelJsonApi\Eloquent\Filters\Concerns\IsSingular;
use LaravelJsonApi\Eloquent\QueryBuilder\Applicators\FilterApplicator;
use LaravelJsonApi\Eloquent\Schema;
use LaravelJsonApi\Validation\Filters\FilterRuleMap;
use LaravelJsonApi\Validation\Filters\Validated;

class WhereHas implements Filter
{
use DeserializesToArray;
use HasRelation;
use IsSingular;
use Validated;

/**
* Create a new filter.
Expand Down Expand Up @@ -63,13 +68,22 @@ public function apply($query, $value)
);
}

/**
* @inheritDoc
*/
public function validationRules(?Request $request, Query $query): array
{
return FilterRuleMap::make($this->schema->filters())
->rules($request, $query);
}

/**
* Get the relation query callback.
*
* @param mixed $value
* @return Closure
*/
protected function callback($value): Closure
protected function callback(mixed $value): Closure
{
return function($query) use ($value) {
$relation = $this->relation();
Expand Down
4 changes: 2 additions & 2 deletions src/Filters/WhereIdIn.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@
use LaravelJsonApi\Contracts\Schema\Schema;
use LaravelJsonApi\Core\Schema\IdParser;
use LaravelJsonApi\Eloquent\Contracts\Filter;
use LaravelJsonApi\Eloquent\Filters\Concerns\HasDelimiter;
use LaravelJsonApi\Eloquent\Schema as EloquentSchema;

class WhereIdIn implements Filter
{

use Concerns\HasDelimiter;
use HasDelimiter;

/**
* @var ID
Expand Down
1 change: 0 additions & 1 deletion src/Filters/WhereIdNotIn.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

class WhereIdNotIn extends WhereIdIn
{

/**
* @inheritDoc
*/
Expand Down
12 changes: 7 additions & 5 deletions src/Filters/WhereIn.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@

use LaravelJsonApi\Core\Support\Str;
use LaravelJsonApi\Eloquent\Contracts\Filter;
use LaravelJsonApi\Eloquent\Filters\Concerns\DeserializesValue;
use LaravelJsonApi\Eloquent\Filters\Concerns\HasColumn;
use LaravelJsonApi\Eloquent\Filters\Concerns\HasDelimiter;

class WhereIn implements Filter
{

use Concerns\DeserializesValue;
use Concerns\HasColumn;
use Concerns\HasDelimiter;
use DeserializesValue;
use HasColumn;
use HasDelimiter;

/**
* @var string
Expand Down Expand Up @@ -78,7 +80,7 @@ public function apply($query, $value)
}

/**
* Deserialize the fitler value.
* Deserialize the filter value.
*
* @param string|array $value
* @return array
Expand Down
21 changes: 18 additions & 3 deletions src/Filters/WhereNull.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,20 @@

namespace LaravelJsonApi\Eloquent\Filters;

use Illuminate\Http\Request;
use LaravelJsonApi\Core\Query\Input\Query;
use LaravelJsonApi\Core\Support\Str;
use LaravelJsonApi\Eloquent\Contracts\Filter;
use LaravelJsonApi\Eloquent\Filters\Concerns\HasColumn;
use LaravelJsonApi\Eloquent\Filters\Concerns\IsSingular;
use LaravelJsonApi\Validation\Filters\Validated;
use LaravelJsonApi\Validation\Rules\JsonBoolean;

class WhereNull implements Filter
{
use Concerns\HasColumn;
use Concerns\IsSingular;
use HasColumn;
use IsSingular;
use Validated;

/**
* @var string
Expand Down Expand Up @@ -71,6 +78,14 @@ public function apply($query, $value)
return $query->whereNotNull($column);
}

/**
* @inheritDoc
*/
public function validationRules(?Request $request, Query $query): array
{
return [(new JsonBoolean())->asString()];
}

/**
* Should a "where null" query be used?
*
Expand All @@ -88,7 +103,7 @@ protected function isWhereNull(bool $value): bool
* @param mixed $value
* @return bool
*/
private function deserialize($value): bool
private function deserialize(mixed $value): bool
{
return filter_var($value, FILTER_VALIDATE_BOOL);
}
Expand Down
Loading

0 comments on commit e5a6490

Please sign in to comment.