Skip to content

Commit

Permalink
feat(doctrine): added 'exactly' condition to DateFilter
Browse files Browse the repository at this point in the history
fixes: #6114
  • Loading branch information
vjandrea committed Dec 22, 2024
1 parent 9389b4f commit 79d6c45
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 19 deletions.
1 change: 1 addition & 0 deletions src/Doctrine/Common/Filter/DateFilterInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ interface DateFilterInterface
{
public const PARAMETER_BEFORE = 'before';
public const PARAMETER_STRICTLY_BEFORE = 'strictly_before';
public const PARAMETER_EXACTLY = 'exactly';
public const PARAMETER_AFTER = 'after';
public const PARAMETER_STRICTLY_AFTER = 'strictly_after';
public const EXCLUDE_NULL = 'exclude_null';
Expand Down
3 changes: 2 additions & 1 deletion src/Doctrine/Common/Filter/DateFilterTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ public function getDescription(string $resourceClass): array
continue;
}

$description += $this->getFilterDescription($property, self::PARAMETER_BEFORE);
$description += $this->getFilterDescription($property, self::PARAMETER_STRICTLY_BEFORE);
$description += $this->getFilterDescription($property, self::PARAMETER_BEFORE);
$description += $this->getFilterDescription($property, self::PARAMETER_EXACTLY);
$description += $this->getFilterDescription($property, self::PARAMETER_AFTER);
$description += $this->getFilterDescription($property, self::PARAMETER_STRICTLY_AFTER);
}
Expand Down
26 changes: 19 additions & 7 deletions src/Doctrine/Odm/Filter/DateFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
/**
* The date filter allows to filter a collection by date intervals.
*
* Syntax: `?property[<after|before|strictly_after|strictly_before>]=value`.
* Syntax: `?property[<strictly_before|before|exactly|after|strictly_after>]=value`.
*
* The value can take any date format supported by the [`\DateTime` constructor](https://www.php.net/manual/en/datetime.construct.php).
*
Expand Down Expand Up @@ -158,6 +158,16 @@ protected function filterProperty(string $property, $value, Builder $aggregation
$aggregationBuilder->match()->field($matchField)->notEqual(null);
}

if (isset($value[self::PARAMETER_STRICTLY_BEFORE])) {
$this->addMatch(
$aggregationBuilder,
$matchField,
self::PARAMETER_STRICTLY_BEFORE,
$value[self::PARAMETER_STRICTLY_BEFORE],
$nullManagement
);
}

if (isset($value[self::PARAMETER_BEFORE])) {
$this->addMatch(
$aggregationBuilder,
Expand All @@ -168,12 +178,12 @@ protected function filterProperty(string $property, $value, Builder $aggregation
);
}

if (isset($value[self::PARAMETER_STRICTLY_BEFORE])) {
if (isset($value[self::PARAMETER_EXACTLY])) {
$this->addMatch(
$aggregationBuilder,
$matchField,
self::PARAMETER_STRICTLY_BEFORE,
$value[self::PARAMETER_STRICTLY_BEFORE],
self::PARAMETER_EXACTLY,
$value[self::PARAMETER_EXACTLY],
$nullManagement
);
}
Expand Down Expand Up @@ -222,8 +232,9 @@ private function addMatch(Builder $aggregationBuilder, string $field, string $op
}

$operatorValue = [
self::PARAMETER_BEFORE => '$lte',
self::PARAMETER_STRICTLY_BEFORE => '$lt',
self::PARAMETER_BEFORE => '$lte',
self::PARAMETER_EXACTLY => '$eq',
self::PARAMETER_AFTER => '$gte',
self::PARAMETER_STRICTLY_AFTER => '$gt',
];
Expand Down Expand Up @@ -257,10 +268,11 @@ public function getOpenApiParameters(Parameter $parameter): OpenApiParameter|arr
$key = $parameter->getKey();

return [
new OpenApiParameter(name: $key.'[after]', in: $in),
new OpenApiParameter(name: $key.'[strictly_before]', in: $in),
new OpenApiParameter(name: $key.'[before]', in: $in),
new OpenApiParameter(name: $key.'[exactly]', in: $in),
new OpenApiParameter(name: $key.'[after]', in: $in),
new OpenApiParameter(name: $key.'[strictly_after]', in: $in),
new OpenApiParameter(name: $key.'[strictly_before]', in: $in),
];
}
}
7 changes: 6 additions & 1 deletion src/Doctrine/Odm/Tests/Filter/DateFilterTestTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,17 @@ public function testGetDescription(): void
$filter = $this->buildFilter();

$this->assertEquals([
'dummyDate[strictly_before]' => [
'property' => 'dummyDate',
'type' => \DateTimeInterface::class,
'required' => false,
],
'dummyDate[before]' => [
'property' => 'dummyDate',
'type' => \DateTimeInterface::class,
'required' => false,
],
'dummyDate[strictly_before]' => [
'dummyDate[exactly]' => [
'property' => 'dummyDate',
'type' => \DateTimeInterface::class,
'required' => false,
Expand Down
29 changes: 22 additions & 7 deletions src/Doctrine/Orm/Filter/DateFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
/**
* The date filter allows to filter a collection by date intervals.
*
* Syntax: `?property[<after|before|strictly_after|strictly_before>]=value`.
* Syntax: `?property[<strictly_before|before|exactly|after|strictly_after|>]=value`.
*
* The value can take any date format supported by the [`\DateTime` constructor](https://www.php.net/manual/en/datetime.construct.php).
*
Expand Down Expand Up @@ -169,6 +169,19 @@ protected function filterProperty(string $property, $value, QueryBuilder $queryB
$queryBuilder->andWhere($queryBuilder->expr()->isNotNull(\sprintf('%s.%s', $alias, $field)));
}

if (isset($value[self::PARAMETER_STRICTLY_BEFORE])) {
$this->addWhere(
$queryBuilder,
$queryNameGenerator,
$alias,
$field,
self::PARAMETER_STRICTLY_BEFORE,
$value[self::PARAMETER_STRICTLY_BEFORE],
$nullManagement,
$type
);
}

if (isset($value[self::PARAMETER_BEFORE])) {
$this->addWhere(
$queryBuilder,
Expand All @@ -182,14 +195,14 @@ protected function filterProperty(string $property, $value, QueryBuilder $queryB
);
}

if (isset($value[self::PARAMETER_STRICTLY_BEFORE])) {
if (isset($value[self::PARAMETER_EXACTLY])) {
$this->addWhere(
$queryBuilder,
$queryNameGenerator,
$alias,
$field,
self::PARAMETER_STRICTLY_BEFORE,
$value[self::PARAMETER_STRICTLY_BEFORE],
self::PARAMETER_EXACTLY,
$value[self::PARAMETER_EXACTLY],
$nullManagement,
$type
);
Expand Down Expand Up @@ -247,8 +260,9 @@ protected function addWhere(QueryBuilder $queryBuilder, QueryNameGeneratorInterf

$valueParameter = $queryNameGenerator->generateParameterName($field);
$operatorValue = [
self::PARAMETER_BEFORE => '<=',
self::PARAMETER_STRICTLY_BEFORE => '<',
self::PARAMETER_BEFORE => '<=',
self::PARAMETER_EXACTLY => '=',
self::PARAMETER_AFTER => '>=',
self::PARAMETER_STRICTLY_AFTER => '>',
];
Expand Down Expand Up @@ -289,10 +303,11 @@ public function getOpenApiParameters(Parameter $parameter): OpenApiParameter|arr
$key = $parameter->getKey();

return [
new OpenApiParameter(name: $key.'[after]', in: $in),
new OpenApiParameter(name: $key.'[strictly_before]', in: $in),
new OpenApiParameter(name: $key.'[before]', in: $in),
new OpenApiParameter(name: $key.'[exactly]', in: $in),
new OpenApiParameter(name: $key.'[after]', in: $in),
new OpenApiParameter(name: $key.'[strictly_after]', in: $in),
new OpenApiParameter(name: $key.'[strictly_before]', in: $in),
];
}
}
7 changes: 6 additions & 1 deletion src/Doctrine/Orm/Tests/Filter/DateFilterTestTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,17 @@ public function testGetDescription(): void
$filter = $this->buildFilter();

$this->assertEquals([
'dummyDate[strictly_before]' => [
'property' => 'dummyDate',
'type' => \DateTimeInterface::class,
'required' => false,
],
'dummyDate[before]' => [
'property' => 'dummyDate',
'type' => \DateTimeInterface::class,
'required' => false,
],
'dummyDate[strictly_before]' => [
'dummyDate[exactly]' => [
'property' => 'dummyDate',
'type' => \DateTimeInterface::class,
'required' => false,
Expand Down
9 changes: 7 additions & 2 deletions tests/Functional/Parameters/DoctrineTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public function testDoctrineEntitySearchFilter(): void
$this->assertEquals('bar', $a['hydra:member'][1]['foo']);

$this->assertArraySubset(['hydra:search' => [
'hydra:template' => \sprintf('/%s{?foo,fooAlias,order[order[id]],order[order[foo]],searchPartial[foo],searchExact[foo],searchOnTextAndDate[foo],searchOnTextAndDate[createdAt][before],searchOnTextAndDate[createdAt][strictly_before],searchOnTextAndDate[createdAt][after],searchOnTextAndDate[createdAt][strictly_after],q,id,createdAt}', $route),
'hydra:template' => \sprintf('/%s{?foo,fooAlias,order[order[id]],order[order[foo]],searchPartial[foo],searchExact[foo],searchOnTextAndDate[foo],searchOnTextAndDate[createdAt][strictly_before],searchOnTextAndDate[createdAt][before],searchOnTextAndDate[createdAt][exactly],searchOnTextAndDate[createdAt][after],searchOnTextAndDate[createdAt][strictly_after],q,id,createdAt}', $route),
]], $a);

$this->assertArraySubset(['@type' => 'IriTemplateMapping', 'variable' => 'fooAlias', 'property' => 'foo'], $a['hydra:search']['hydra:mapping'][1]);
Expand All @@ -71,6 +71,11 @@ public function testDoctrineEntitySearchFilter(): void
$members = $response->toArray()['hydra:member'];
$this->assertCount(1, $members);
$this->assertArraySubset(['foo' => 'bar', 'createdAt' => '2024-01-21T00:00:00+00:00'], $members[0]);

$response = self::createClient()->request('GET', $route.'?searchOnTextAndDate[createdAt][exactly]=2024-01-22');
$members = $response->toArray()['hydra:member'];
$this->assertCount(1, $members);
$this->assertArraySubset(['foo' => 'bar', 'createdAt' => '2024-01-22T00:00:00+00:00'], $members[0]);
}

public function testGraphQl(): void
Expand Down Expand Up @@ -134,7 +139,7 @@ public function testStateOptions(): void
$manager->flush();
$response = self::createClient()->request('GET', 'filter_with_state_options?date[before]='.$d->format('Y-m-d'));
$a = $response->toArray();
$this->assertEquals('/filter_with_state_options{?date[before],date[strictly_before],date[after],date[strictly_after]}', $a['hydra:search']['hydra:template']);
$this->assertEquals('/filter_with_state_options{?date[strictly_before],date[before],date[exactly],date[after],date[strictly_after]}', $a['hydra:search']['hydra:template']);
$this->assertCount(1, $a['hydra:member']);
$this->assertEquals('current', $a['hydra:member'][0]['name']);
$response = self::createClient()->request('GET', 'filter_with_state_options?date[strictly_after]='.$d->format('Y-m-d'));
Expand Down

0 comments on commit 79d6c45

Please sign in to comment.