Skip to content

Commit

Permalink
negation filters - wip
Browse files Browse the repository at this point in the history
  • Loading branch information
emargareten committed Mar 18, 2024
1 parent 4614603 commit 03348d6
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 2 deletions.
13 changes: 13 additions & 0 deletions src/Filterable.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public function applyFilter(Builder $query, mixed $filter, ?string $relation = n
$property = $filter['property'];
$operator = $filter['operator'] ?? 'equal';
$value = $filter['value'] ?? null;
$negate = filter_var($filter['negate'] ?? false, FILTER_VALIDATE_BOOLEAN);

$model = $relation ? $this->{$relation}()->getRelated() : $this;

Expand Down Expand Up @@ -77,6 +78,18 @@ public function applyFilter(Builder $query, mixed $filter, ?string $relation = n

if (is_array($operator)) {
// Filter by relation - multiple filters in single relation model

// Filter relationship absence
if ($negate) {
$query->whereDoesntHave(
Str::after($property, '!'),
fn (Builder $query) => $query->filter($operator) // @phpstan-ignore-line
);

return;
}

// Filter relationship existence
$query->whereHas($property, fn (Builder $query) => $query->filter($operator)); // @phpstan-ignore-line

return;
Expand Down
50 changes: 48 additions & 2 deletions tests/Unit/GeneralTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,53 @@
->toBe(1);
});

test('dynamic filter on modal', function () {
test('can apply negative filters on relations using array', function () {
$post = Post::create(['content' => 'Lorem ipsum dolor sit amet.']);
$post->comments()->create([
'body' => 'Lorem ipsum dolor sit amet.',
'created_at' => '2020-01-01 00:00:00',
]);

$post2 = Post::create(['content' => 'Lorem ipsum dolor sit amet.']);
$post2->comments()->create([
'body' => 'Lorem ipsum dolor sit amet.',
'created_at' => '2021-01-01 00:00:00',
]);

$post3 = Post::create(['content' => 'Ipsum dolor sit amet.']);
$post3->comments()->create([
'body' => 'Ipsum dolor sit amet.',
]);

expect(Post::filter([
'property' => 'comments',
'operator' => [
'property' => 'body',
'operator' => 'contains',
'value' => 'Lorem',
],
'negate' => true,
])->count())->toBe(1)
->and(Post::filter([
'property' => 'comments',
'operator' => [
[
'property' => 'body',
'operator' => 'contains',
'value' => 'Lorem',
],
[
'property' => 'created_at',
'operator' => 'date:greater-than-or-equal',
'value' => '2021-01-01',
],
],
'negate' => true,
])->count())
->toBe(2);
});

test('dynamic filter on model', function () {
Post::create(['views' => 10]);
Post::create(['views' => 20]);
Post::create(['views' => 30]);
Expand All @@ -148,7 +194,7 @@
])->count())->toBe(2);
});

test('dynamic filter with value and operator on modal', function () {
test('dynamic filter with value and operator on model', function () {
Post::create(['views' => 10]);
Post::create(['views' => 20]);
Post::create(['views' => 30]);
Expand Down

0 comments on commit 03348d6

Please sign in to comment.