From 2f1ad0e220d46bc0777a38a8190b01f62bb6e6ef Mon Sep 17 00:00:00 2001 From: Martin Eiber Date: Thu, 27 Nov 2025 11:31:56 +0100 Subject: [PATCH 1/4] Add Time Filter --- docker-compose.yml | 1 - src/Model/DefaultSearch/Query/TimeFilter.php | 93 ++++++++++++++ .../FieldType/ClassificationStoreFilter.php | 4 +- .../Modifier/Filter/FieldType/TimeFilter.php | 53 ++++++++ .../Modifier/Filter/FieldTypeFilters.php | 35 ++++++ .../Modifier/Filter/NestedTypeFilters.php | 4 + .../DefaultSearch/Query/TimeFilterTest.php | 113 ++++++++++++++++++ 7 files changed, 300 insertions(+), 3 deletions(-) create mode 100644 src/Model/DefaultSearch/Query/TimeFilter.php create mode 100644 src/Model/Search/Modifier/Filter/FieldType/TimeFilter.php create mode 100644 tests/Unit/Model/DefaultSearch/Query/TimeFilterTest.php diff --git a/docker-compose.yml b/docker-compose.yml index 87cad8c8..81828fde 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,3 @@ -version: '3.0' services: php-generic-data-index-bundle: image: pimcore/pimcore:php8.3-latest diff --git a/src/Model/DefaultSearch/Query/TimeFilter.php b/src/Model/DefaultSearch/Query/TimeFilter.php new file mode 100644 index 00000000..e1029bcd --- /dev/null +++ b/src/Model/DefaultSearch/Query/TimeFilter.php @@ -0,0 +1,93 @@ +getParams()); + } + + public function getParams(): array + { + $params = []; + + if ($this->onTime) { + $params['gte'] = $this->onTime; + $params['lte'] = $this->onTime; + + return [$this->field => $params]; + } + + $params = $this->addStartParams($params); + $params = $this->addEndParams($params); + + return [$this->field => $params]; + } + + public function toArray(bool $withType = false): array + { + if ($withType) { + return [$this->getType() => $this->getParams()]; + } + + return $this->getParams(); + } + + public function getField(): string + { + return $this->field; + } + + private function addStartParams(array $params): array + { + if (!$this->startTime) { + return $params; + } + + $params['gte'] = $this->startTime; + + return $params; + } + + private function addEndParams(array $params): array + { + if (!$this->endTime) { + return $params; + } + + $params['lte'] = $this->endTime; + + return $params; + } +} diff --git a/src/Model/Search/Modifier/Filter/FieldType/ClassificationStoreFilter.php b/src/Model/Search/Modifier/Filter/FieldType/ClassificationStoreFilter.php index 7a1f054a..36f69157 100644 --- a/src/Model/Search/Modifier/Filter/FieldType/ClassificationStoreFilter.php +++ b/src/Model/Search/Modifier/Filter/FieldType/ClassificationStoreFilter.php @@ -27,7 +27,7 @@ public function __construct( private string $fieldName, private string $group, private BooleanFilter|DateFilter|FullTextSearch|IntegerFilter|MultiSelectFilter|BooleanMultiSelectFilter| - NumberFilter|NumberRangeFilter|WildcardSearch $subModifier, + NumberFilter|NumberRangeFilter|WildcardSearch|TimeFilter $subModifier, private string $locale = MappingProperty::NOT_LOCALIZED_KEY, ) { } @@ -43,7 +43,7 @@ public function getGroup(): string } public function getSubModifier(): BooleanFilter|DateFilter|FullTextSearch|IntegerFilter| - MultiSelectFilter|BooleanMultiSelectFilter|NumberFilter|NumberRangeFilter|WildcardSearch + MultiSelectFilter|BooleanMultiSelectFilter|NumberFilter|NumberRangeFilter|WildcardSearch|TimeFilter { return $this->subModifier; } diff --git a/src/Model/Search/Modifier/Filter/FieldType/TimeFilter.php b/src/Model/Search/Modifier/Filter/FieldType/TimeFilter.php new file mode 100644 index 00000000..06236096 --- /dev/null +++ b/src/Model/Search/Modifier/Filter/FieldType/TimeFilter.php @@ -0,0 +1,53 @@ +startTime; + } + + public function getEndTime(): ?string + { + return $this->endTime; + } + + public function getOnTime(): ?string + { + return $this->onTime; + } + + public function getField(): string + { + return $this->field; + } + + public function isPqlFieldNameResolutionEnabled(): bool + { + return $this->enablePqlFieldNameResolution; + } +} diff --git a/src/SearchIndexAdapter/DefaultSearch/Search/Modifier/Filter/FieldTypeFilters.php b/src/SearchIndexAdapter/DefaultSearch/Search/Modifier/Filter/FieldTypeFilters.php index 60885069..83588fb4 100644 --- a/src/SearchIndexAdapter/DefaultSearch/Search/Modifier/Filter/FieldTypeFilters.php +++ b/src/SearchIndexAdapter/DefaultSearch/Search/Modifier/Filter/FieldTypeFilters.php @@ -17,6 +17,7 @@ use Pimcore\Bundle\GenericDataIndexBundle\Model\DefaultSearch\Modifier\SearchModifierContextInterface; use Pimcore\Bundle\GenericDataIndexBundle\Model\DefaultSearch\Query\BoolExistsQuery; use Pimcore\Bundle\GenericDataIndexBundle\Model\DefaultSearch\Query\DateFilter as DateFilterQuery; +use Pimcore\Bundle\GenericDataIndexBundle\Model\DefaultSearch\Query\TimeFilter as TimeFilterQuery; use Pimcore\Bundle\GenericDataIndexBundle\Model\DefaultSearch\Query\MultiBoolQuery; use Pimcore\Bundle\GenericDataIndexBundle\Model\DefaultSearch\Query\Query as QueryFilter; use Pimcore\Bundle\GenericDataIndexBundle\Model\DefaultSearch\Query\TermsFilter as TermsFilterQuery; @@ -25,6 +26,7 @@ use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Filter\FieldType\DateFilter; use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Filter\FieldType\MultiSelectFilter; use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Filter\FieldType\NumberRangeFilter; +use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Filter\FieldType\TimeFilter; use Pimcore\Bundle\GenericDataIndexBundle\Service\Search\SearchService\SearchPqlFieldNameTransformationServiceInterface; /** @@ -71,6 +73,39 @@ public function getDateFilterQuery( ); } + #[AsSearchModifierHandler] + public function handleTimeFilter( + TimeFilter $timeFilter, + SearchModifierContextInterface $context + ): void { + $context->getSearch()->addQuery($this->getTimeFilterQuery( + $timeFilter, + null, + $context->getOriginalSearch()) + ); + } + + public function getTimeFilterQuery( + TimeFilter $timeFilter, + ?string $prefix = null, + ?SearchInterface $search = null + ): TimeFilterQuery { + $fieldName = $timeFilter->getField(); + if ($prefix) { + $fieldName = $prefix . '.' . $fieldName; + } + if ($search && $timeFilter->isPqlFieldNameResolutionEnabled()) { + $fieldName = $this->fieldNameTransformationService->transformFieldnameForSearch($search, $fieldName); + } + + return new TimeFilterQuery( + $fieldName, + $timeFilter->getStartTime(), + $timeFilter->getEndTime(), + $timeFilter->getOnTime(), + ); + } + #[AsSearchModifierHandler] public function handleMultiSelectFilter( MultiSelectFilter $multiSelectFilter, diff --git a/src/SearchIndexAdapter/DefaultSearch/Search/Modifier/Filter/NestedTypeFilters.php b/src/SearchIndexAdapter/DefaultSearch/Search/Modifier/Filter/NestedTypeFilters.php index 032c3e31..8e1abf4d 100644 --- a/src/SearchIndexAdapter/DefaultSearch/Search/Modifier/Filter/NestedTypeFilters.php +++ b/src/SearchIndexAdapter/DefaultSearch/Search/Modifier/Filter/NestedTypeFilters.php @@ -28,6 +28,7 @@ use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Filter\FieldType\MultiSelectFilter; use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Filter\FieldType\NestedFilter as NestedFilterParam; use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Filter\FieldType\NumberRangeFilter; +use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Filter\FieldType\TimeFilter; use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\FullTextSearch\FullTextSearch; use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\FullTextSearch\WildcardSearch; use Pimcore\Bundle\GenericDataIndexBundle\SearchIndexAdapter\DefaultSearch\Search\Modifier\FullTextSearch\FullTextSearchHandlers; @@ -92,6 +93,9 @@ private function getSubQuery(ClassificationStoreFilter|NestedFilterParam $filter $modifier instanceof DateFilter => $this->fieldTypeFilters->getDateFilterQuery($modifier, $fieldName, $search)->toArray(true), + $modifier instanceof TimeFilter => + $this->fieldTypeFilters->getTimeFilterQuery($modifier, $fieldName, $search)->toArray(true), + $modifier instanceof MultiSelectFilter => $this->fieldTypeFilters->getMultiSelectQuery($modifier, $fieldName, $search)->toArrayAsSubQuery(), diff --git a/tests/Unit/Model/DefaultSearch/Query/TimeFilterTest.php b/tests/Unit/Model/DefaultSearch/Query/TimeFilterTest.php new file mode 100644 index 00000000..e0cb68a9 --- /dev/null +++ b/tests/Unit/Model/DefaultSearch/Query/TimeFilterTest.php @@ -0,0 +1,113 @@ + [ + 'datefield' => [ + 'gte' => '12:15', + 'lte' => '13:15', + ], + ], + ], $timeFilter->toArray(true)); + + $timeFilter = new TimeFilter('datefield', "12:45"); + + self::assertSame([ + 'range' => [ + 'datefield' => [ + 'gte' => '12:45', + ], + ], + ], $timeFilter->toArray(true)); + + $timeFilter = new TimeFilter('datefield', null, "13:00"); + + self::assertSame([ + 'range' => [ + 'datefield' => [ + 'lte' => '13:00', + ], + ], + ], $timeFilter->toArray(true)); + + $timeFilter = new TimeFilter('datefield', null, null, "12:30"); + + self::assertSame([ + 'range' => [ + 'datefield' => [ + 'gte' => '12:30', + 'lte' => '12:30', + ], + ], + ], $timeFilter->toArray(true)); + } + + public function testGetType(): void + { + $dateFilter = new TimeFilter('datefield', "12:30", "12:45"); + + self::assertSame('range', $dateFilter->getType()); + } + + public function testGetParams(): void + { + $timeFilter = new TimeFilter('datefield', '12:15', "13:15"); + + self::assertSame([ + 'datefield' => [ + 'gte' => '12:15', + 'lte' => '12:15', + ], + ], $timeFilter->getParams()); + + $timeFilter = new TimeFilter('datefield', "12:45"); + + self::assertSame([ + 'datefield' => [ + 'gte' => '"12:45', + ], + ], $timeFilter->getParams()); + + $timeFilter = new TimeFilter('datefield', null, "13:00"); + + self::assertSame([ + 'datefield' => [ + 'lte' => '13:00', + ], + ], $timeFilter->getParams()); + + $timeFilter = new TimeFilter('datefield', null, null, "12:30"); + + self::assertSame([ + 'datefield' => [ + 'gte' => '12:30', + 'lte' => '12:30', + ], + ], $timeFilter->getParams()); + } +} From 55c76dc6081e0e592e3e3db5b95076d023fa2f3d Mon Sep 17 00:00:00 2001 From: Martin Eiber Date: Thu, 27 Nov 2025 11:38:23 +0100 Subject: [PATCH 2/4] Fix Test --- tests/Unit/Model/DefaultSearch/Query/TimeFilterTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Model/DefaultSearch/Query/TimeFilterTest.php b/tests/Unit/Model/DefaultSearch/Query/TimeFilterTest.php index e0cb68a9..a401f8ef 100644 --- a/tests/Unit/Model/DefaultSearch/Query/TimeFilterTest.php +++ b/tests/Unit/Model/DefaultSearch/Query/TimeFilterTest.php @@ -81,7 +81,7 @@ public function testGetParams(): void self::assertSame([ 'datefield' => [ 'gte' => '12:15', - 'lte' => '12:15', + 'lte' => '13:15', ], ], $timeFilter->getParams()); From 87967aa11d83a2618d390ca3e51c2d671833b773 Mon Sep 17 00:00:00 2001 From: Martin Eiber Date: Thu, 27 Nov 2025 11:44:46 +0100 Subject: [PATCH 3/4] Fix Test --- .../Model/DefaultSearch/Query/TimeFilterTest.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/Unit/Model/DefaultSearch/Query/TimeFilterTest.php b/tests/Unit/Model/DefaultSearch/Query/TimeFilterTest.php index a401f8ef..432eb6d6 100644 --- a/tests/Unit/Model/DefaultSearch/Query/TimeFilterTest.php +++ b/tests/Unit/Model/DefaultSearch/Query/TimeFilterTest.php @@ -24,7 +24,7 @@ final class TimeFilterTest extends Unit public function testToArray(): void { - $timeFilter = new TimeFilter('datefield', '12:15', "13:15"); + $timeFilter = new TimeFilter('datefield', '12:15', '13:15'); self::assertSame([ 'range' => [ @@ -35,7 +35,7 @@ public function testToArray(): void ], ], $timeFilter->toArray(true)); - $timeFilter = new TimeFilter('datefield', "12:45"); + $timeFilter = new TimeFilter('datefield', '12:45'); self::assertSame([ 'range' => [ @@ -45,7 +45,7 @@ public function testToArray(): void ], ], $timeFilter->toArray(true)); - $timeFilter = new TimeFilter('datefield', null, "13:00"); + $timeFilter = new TimeFilter('datefield', null, '13:00'); self::assertSame([ 'range' => [ @@ -55,7 +55,7 @@ public function testToArray(): void ], ], $timeFilter->toArray(true)); - $timeFilter = new TimeFilter('datefield', null, null, "12:30"); + $timeFilter = new TimeFilter('datefield', null, null, '12:30'); self::assertSame([ 'range' => [ @@ -76,7 +76,7 @@ public function testGetType(): void public function testGetParams(): void { - $timeFilter = new TimeFilter('datefield', '12:15', "13:15"); + $timeFilter = new TimeFilter('datefield', '12:15', '13:15'); self::assertSame([ 'datefield' => [ @@ -85,7 +85,7 @@ public function testGetParams(): void ], ], $timeFilter->getParams()); - $timeFilter = new TimeFilter('datefield', "12:45"); + $timeFilter = new TimeFilter('datefield', '12:45'); self::assertSame([ 'datefield' => [ @@ -93,7 +93,7 @@ public function testGetParams(): void ], ], $timeFilter->getParams()); - $timeFilter = new TimeFilter('datefield', null, "13:00"); + $timeFilter = new TimeFilter('datefield', null, '13:00'); self::assertSame([ 'datefield' => [ @@ -101,7 +101,7 @@ public function testGetParams(): void ], ], $timeFilter->getParams()); - $timeFilter = new TimeFilter('datefield', null, null, "12:30"); + $timeFilter = new TimeFilter('datefield', null, null, '12:30'); self::assertSame([ 'datefield' => [ From 3a86ec1a586c251a279c37e3b4978d602ab6ca6f Mon Sep 17 00:00:00 2001 From: Martin Eiber Date: Thu, 27 Nov 2025 11:50:41 +0100 Subject: [PATCH 4/4] Fix Test --- tests/Unit/Model/DefaultSearch/Query/TimeFilterTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Model/DefaultSearch/Query/TimeFilterTest.php b/tests/Unit/Model/DefaultSearch/Query/TimeFilterTest.php index 432eb6d6..112685b0 100644 --- a/tests/Unit/Model/DefaultSearch/Query/TimeFilterTest.php +++ b/tests/Unit/Model/DefaultSearch/Query/TimeFilterTest.php @@ -89,7 +89,7 @@ public function testGetParams(): void self::assertSame([ 'datefield' => [ - 'gte' => '"12:45', + 'gte' => '12:45', ], ], $timeFilter->getParams());