Skip to content

Commit

Permalink
allow is to receive null
Browse files Browse the repository at this point in the history
  • Loading branch information
henzeb committed Mar 14, 2022
1 parent fabc9e4 commit 365c498
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 67 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

All notable changes to `Query Filter Builder` will be documented in this file

## 1.1.4 - 2022-03-14

- when `is` or `not` receives `null`, it should turn into `empty`/`notEmpty`

## 1.1.3 - 2022-03-14

- added filterArray to easily handle comma separated strings as per recommendation in the JSON:API specification
Expand Down
4 changes: 2 additions & 2 deletions src/Filters/Contracts/QueryFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@

interface QueryFilter
{
public function is(string $key, string|float|int|bool $value): self;
public function is(string $key, string|float|int|bool|null $value): self;

public function not(string $key, string|float|int|bool $value): self;
public function not(string $key, string|float|int|bool|null $value): self;

public function empty(string $key): self;

Expand Down
12 changes: 10 additions & 2 deletions src/Filters/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,21 @@ private function shouldApplyAnd(string $action): bool
return true;
}

public function is(string $key, float|bool|int|string $value): QueryFilter
public function is(string $key, float|bool|int|string|null $value): QueryFilter
{
if(null===$value) {
return $this->empty($key);
}

return $this->addFilter(__FUNCTION__, get_defined_vars());
}

public function not(string $key, float|bool|int|string $value): QueryFilter
public function not(string $key, float|bool|int|string|null $value): QueryFilter
{
if(null===$value) {
return $this->notEmpty($key);
}

return $this->addFilter(__FUNCTION__, get_defined_vars());
}

Expand Down
74 changes: 39 additions & 35 deletions tests/Helpers/DataProviders.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,55 +18,57 @@ public function providesOperators(): array
public function providesFilterTestcases(): array
{
return [
'is' => ['method' => 'is', 'parameters' => ['key' => 'animal', 'value' => 'cat']],
'not' => ['method' => 'not', 'parameters' => ['key' => 'animal', 'value' => 'dog']],
'is' => ['method' => 'is', 'parameters' => ['key' => 'animal', 'value' => 'cat'], null],
'is-null' => ['method' => 'is', 'parameters' => ['key' => 'animal', 'value' => null], 'empty'],
'not' => ['method' => 'not', 'parameters' => ['key' => 'animal', 'value' => 'dog'], null],
'not-null' => ['method' => 'not', 'parameters' => ['key' => 'animal', 'value' => null], 'notEmpty'],

'empty' => ['method' => 'empty', 'parameters' => ['key' => 'name']],
'notEmpty' => ['method' => 'notEmpty', 'parameters' => ['key' => 'name']],
'empty' => ['method' => 'empty', 'parameters' => ['key' => 'name'], null],
'notEmpty' => ['method' => 'notEmpty', 'parameters' => ['key' => 'name'], null],

'in' => ['method' => 'in', 'parameters' => ['key' => 'animal', 'in' => ['dog']]],
'in-multi' => ['method' => 'in', 'parameters' => ['key' => 'animal', 'in' => ['dog', 'cat']]],
'in' => ['method' => 'in', 'parameters' => ['key' => 'animal', 'in' => ['dog']], null],
'in-multi' => ['method' => 'in', 'parameters' => ['key' => 'animal', 'in' => ['dog', 'cat']], null],

'notIn' => ['method' => 'notIn', 'parameters' => ['key' => 'animal', 'notIn' => ['dog']]],
'notIn-multi' => ['method' => 'notIn', 'parameters' => ['key' => 'animal', 'notIn' => ['dog', 'cat']]],
'notIn' => ['method' => 'notIn', 'parameters' => ['key' => 'animal', 'notIn' => ['dog']], null],
'notIn-multi' => ['method' => 'notIn', 'parameters' => ['key' => 'animal', 'notIn' => ['dog', 'cat']], null],

'like' => ['method' => 'like', 'parameters' => ['key' => 'animal', 'like' => '%dog%']],
'notLike' => ['method' => 'notLike', 'parameters' => ['key' => 'animal', 'notLike' => '%dog%']],
'like' => ['method' => 'like', 'parameters' => ['key' => 'animal', 'like' => '%dog%'], null],
'notLike' => ['method' => 'notLike', 'parameters' => ['key' => 'animal', 'notLike' => '%dog%'], null],

'less-int' => ['method' => 'less', 'parameters' => ['key' => 'height', 'less' => 10]],
'less-float' => ['method' => 'less', 'parameters' => ['key' => 'height', 'less' => 10.5]],
'less-date' => ['method' => 'less', 'parameters' => ['key' => 'age', 'less' => new DateTime()]],
'less-int' => ['method' => 'less', 'parameters' => ['key' => 'height', 'less' => 10], null],
'less-float' => ['method' => 'less', 'parameters' => ['key' => 'height', 'less' => 10.5], null],
'less-date' => ['method' => 'less', 'parameters' => ['key' => 'age', 'less' => new DateTime()], null],

'greater-int' => ['method' => 'greater', 'parameters' => ['key' => 'height', 'greater' => 10]],
'greater-float' => ['method' => 'greater', 'parameters' => ['key' => 'height', 'greater' => 10.5]],
'greater-date' => ['method' => 'greater', 'parameters' => ['key' => 'age', 'greater' => new DateTime()]],
'greater-int' => ['method' => 'greater', 'parameters' => ['key' => 'height', 'greater' => 10], null],
'greater-float' => ['method' => 'greater', 'parameters' => ['key' => 'height', 'greater' => 10.5], null],
'greater-date' => ['method' => 'greater', 'parameters' => ['key' => 'age', 'greater' => new DateTime()], null],

'lessOrEqual-int' => ['method' => 'lessOrEqual', 'parameters' => ['key' => 'height', 'lessOrEqual' => 10]],
'lessOrEqual-float' => ['method' => 'lessOrEqual', 'parameters' => ['key' => 'height', 'lessOrEqual' => 10.5]],
'lessOrEqual-date' => ['method' => 'lessOrEqual', 'parameters' => ['key' => 'age', 'lessOrEqual' => new DateTime()]],
'lessOrEqual-int' => ['method' => 'lessOrEqual', 'parameters' => ['key' => 'height', 'lessOrEqual' => 10], null],
'lessOrEqual-float' => ['method' => 'lessOrEqual', 'parameters' => ['key' => 'height', 'lessOrEqual' => 10.5], null],
'lessOrEqual-date' => ['method' => 'lessOrEqual', 'parameters' => ['key' => 'age', 'lessOrEqual' => new DateTime()], null],

'greaterOrEqual-int' => ['method' => 'greaterOrEqual', 'parameters' => ['key' => 'height', 'greaterOrEqual' => 10]],
'greaterOrEqual-float' => ['method' => 'greaterOrEqual', 'parameters' => ['key' => 'height', 'greaterOrEqual' => 10.5]],
'greaterOrEqual-date' => ['method' => 'greaterOrEqual', 'parameters' => ['key' => 'age', 'greaterOrEqual' => new DateTime()]],
'greaterOrEqual-int' => ['method' => 'greaterOrEqual', 'parameters' => ['key' => 'height', 'greaterOrEqual' => 10], null],
'greaterOrEqual-float' => ['method' => 'greaterOrEqual', 'parameters' => ['key' => 'height', 'greaterOrEqual' => 10.5], null],
'greaterOrEqual-date' => ['method' => 'greaterOrEqual', 'parameters' => ['key' => 'age', 'greaterOrEqual' => new DateTime()], null],

'between' => ['method' => 'between', 'parameters' => ['key' => 'age', 'low' => 1, 'high' => 1]],
'between-mixed-1' => ['method' => 'between', 'parameters' => ['key' => 'age', 'low' => 1, 'high' => 1.5]],
'between-mixed-2' => ['method' => 'between', 'parameters' => ['key' => 'age', 'low' => 1.1, 'high' => 2]],
'between' => ['method' => 'between', 'parameters' => ['key' => 'age', 'low' => 1, 'high' => 1], null],
'between-mixed-1' => ['method' => 'between', 'parameters' => ['key' => 'age', 'low' => 1, 'high' => 1.5], null],
'between-mixed-2' => ['method' => 'between', 'parameters' => ['key' => 'age', 'low' => 1.1, 'high' => 2], null],

'notBetween' => ['method' => 'notBetween', 'parameters' => ['key' => 'age', 'low' => 1, 'high' => 1]],
'notBetween-mixed-1' => ['method' => 'notBetween', 'parameters' => ['key' => 'age', 'low' => 1, 'high' => 1.5]],
'notBetween-mixed-2' => ['method' => 'notBetween', 'parameters' => ['key' => 'age', 'low' => 1.1, 'high' => 2]],
'notBetween' => ['method' => 'notBetween', 'parameters' => ['key' => 'age', 'low' => 1, 'high' => 1], null],
'notBetween-mixed-1' => ['method' => 'notBetween', 'parameters' => ['key' => 'age', 'low' => 1, 'high' => 1.5], null],
'notBetween-mixed-2' => ['method' => 'notBetween', 'parameters' => ['key' => 'age', 'low' => 1.1, 'high' => 2], null],

'dateBetween' => ['method' => 'dateBetween', 'parameters' => ['key' => 'age', 'low' => new DateTime(), 'high' => new DateTime()]],
'dateNotBetween' => ['method' => 'dateNotBetween', 'parameters' => ['key' => 'age', 'low' => new DateTime(), 'high' => new DateTime()]],
'dateBetween' => ['method' => 'dateBetween', 'parameters' => ['key' => 'age', 'low' => new DateTime(), 'high' => new DateTime()], null],
'dateNotBetween' => ['method' => 'dateNotBetween', 'parameters' => ['key' => 'age', 'low' => new DateTime(), 'high' => new DateTime()], null],

'filter-object' => ['method' => 'filter', 'parameters' => ['filter' => new OwnerFilter()]],
'filter-object' => ['method' => 'filter', 'parameters' => ['filter' => new OwnerFilter()], null],

'limit' => ['method' => 'limit', 'parameters' => ['limit' => 100]],
'offset' => ['method' => 'offset', 'parameters' => ['offset' => 50]],
'limit' => ['method' => 'limit', 'parameters' => ['limit' => 100], null],
'offset' => ['method' => 'offset', 'parameters' => ['offset' => 50], null],

'asc' => ['method' => 'asc', 'parameters' => ['key' => 'animal']],
'desc' => ['method' => 'desc', 'parameters' => ['key' => 'animal']],
'asc' => ['method' => 'asc', 'parameters' => ['key' => 'animal'], null],
'desc' => ['method' => 'desc', 'parameters' => ['key' => 'animal'], null],
];
}

Expand All @@ -76,7 +78,9 @@ public function providesFilterWithQueryTestcases(): array
$this->providesFilterTestcases(),
[
'is' => ['query' => '`animal` = ?'],
'is-null' => ['query' => '`animal` is null'],
'not' => ['query' => '`animal` != ?'],
'not-null' => ['query' => '`animal` is not null'],
'empty' => ['query' => '`name` is null'],
'notEmpty' => ['query' => '`name` is not null'],
'in' => ['query' => '`animal` in (?)'],
Expand Down
13 changes: 7 additions & 6 deletions tests/Unit/Filters/QueryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public function getMock(bool $withGetFilters = true): Query|Mock
*
* @dataProvider providesFilterTestcases
*/
public function testShouldAddFilter(string $method, array $parameters): void
public function testShouldAddFilter(string $method, array $parameters, string $expectedMethod = null): void
{
$queryFilter = $this->getMock();
$expectedParameters = $parameters;
Expand All @@ -51,7 +51,7 @@ public function testShouldAddFilter(string $method, array $parameters): void

$this->assertEquals(
[
['action' => $method, 'parameters' => $expectedParameters]
['action' => $expectedMethod ?? $method, 'parameters' => array_filter($expectedParameters)]
],
$queryFilter->getFilters()
);
Expand Down Expand Up @@ -207,7 +207,7 @@ public function testChainingOfGroupWhenPassing(): void
* @return void
* @dataProvider providesFilterTestcases
*/
public function testShouldBuildSimple(string $method, $parameters)
public function testShouldBuildSimple(string $method, array $parameters, string $expectedMethod = null): void
{
$query = $this->getMock(false);

Expand All @@ -217,7 +217,8 @@ public function testShouldBuildSimple(string $method, $parameters)

$builder = Mockery::mock(QueryBuilder::class.'[empty]');

$builder->expects($method)->withArgs(array_values($parameters));

$builder->expects($expectedMethod ?? $method)->withArgs(array_filter(array_values($parameters)));

$query->build($builder);
}
Expand All @@ -228,7 +229,7 @@ public function testShouldBuildSimple(string $method, $parameters)
* @return void
* @dataProvider providesFilterTestcases
*/
public function testShouldBuildOr(string $method, $parameters): void
public function testShouldBuildOr(string $method, array $parameters, string $expectedMethod = null): void
{
$queryFilter = $this->getMock(false);
$queryFilter->is('is', 'test');
Expand All @@ -238,7 +239,7 @@ public function testShouldBuildOr(string $method, $parameters): void
$builder = Mockery::mock(QueryBuilder::class.'[empty]');
$builder->expects('is')->once();

$orMethod = 'or' . ucfirst($method);
$orMethod = 'or' . ucfirst($expectedMethod ?? $method);
if (method_exists($builder, $orMethod)) {
$method = $orMethod;
}
Expand Down
Loading

0 comments on commit 365c498

Please sign in to comment.