From 7702f4a0cbc364cf2f7413ac348264c135f2f746 Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Wed, 9 Oct 2024 18:26:49 +0300 Subject: [PATCH 1/2] add select2 support for selects. implements data convertion on search for Date fields. --- composer.json | 1 + docs/Filters.md | 8 ++ src/Filter/AbstractFilter.php | 1 + src/Model/Filter/Criterion/DateCriterion.php | 34 ++++- .../Filter/Criterion/DateTimeCriterion.php | 7 + templates/element/Search/v_templates.php | 41 ++++-- .../Filter/Criterion/DateCriterionTest.php | 22 +-- webroot/js/main.js | 125 ++++++++++++++++-- 8 files changed, 202 insertions(+), 37 deletions(-) diff --git a/composer.json b/composer.json index 3dc6bc8..c3cc2d7 100644 --- a/composer.json +++ b/composer.json @@ -29,6 +29,7 @@ "test": "phpunit --stderr", "coverage-test": "phpunit --stderr --coverage-clover=clover.xml", "stan": "phpstan.phar analyse --memory-limit=-1 src/", + "stan-local": "php vendor/bin/phpstan.phar analyse --memory-limit=-1 src/", "stan-setup": "cp composer.json composer.backup && composer require --dev phpstan/phpstan:0.12.94 psalm/phar:~4.9.2 && mv composer.backup composer.json", "psalm": "psalm.phar --show-info=false", "stan-rebuild-baseline": "phpstan.phar analyse ./src/ --generate-baseline", diff --git a/docs/Filters.md b/docs/Filters.md index fd34990..b1244d9 100644 --- a/docs/Filters.md +++ b/docs/Filters.md @@ -181,6 +181,14 @@ use CakeDC\SearchFilter\Filter\SelectFilter; use CakeDC\SearchFilter\Model\Filter\Criterion\InCriterion; use CakeDC\SearchFilter\Model\Filter\Criterion\StringCriterion; +$selectFilter = (new SelectFilter()) + ->setCriterion($manager->criterion()->numeric('status_id')) + ->setLabel('Status') + ->setOptions($this->Statuses->find('list')->toArray()) + ->setEmpty('All Statuses'); + +// or + $selectFilter = (new SelectFilter()) ->setCriterion(new InCriterion('status', $statusesTable, new StringCriterion('name'))) ->setLabel('Status') diff --git a/src/Filter/AbstractFilter.php b/src/Filter/AbstractFilter.php index 1e17c47..0dac863 100644 --- a/src/Filter/AbstractFilter.php +++ b/src/Filter/AbstractFilter.php @@ -209,6 +209,7 @@ public function setConditions(array|object $conditions): self public function excludeIn(): self { unset($this->conditions[AbstractFilter::COND_IN]); + unset($this->conditions[AbstractFilter::COND_NOT_IN]); return $this; } diff --git a/src/Model/Filter/Criterion/DateCriterion.php b/src/Model/Filter/Criterion/DateCriterion.php index 62bd480..cef5527 100644 --- a/src/Model/Filter/Criterion/DateCriterion.php +++ b/src/Model/Filter/Criterion/DateCriterion.php @@ -33,6 +33,13 @@ class DateCriterion extends BaseCriterion */ protected FunctionsBuilder $func; + /** + * Database type + * + * @var string + */ + protected string $dbType = 'date'; + /** * DateCriterion constructor. * @@ -97,6 +104,10 @@ public function buildFilter(string $condition, array $values, array $criteria, a */ public function buildCondition(string|ExpressionInterface $fieldName, string $condition, array $values, array $options = []): ?callable { + if ($this->dbType === 'date') { + $fieldName = $this->ensureFieldIsDate($fieldName); + } + if ($condition == AbstractFilter::COND_BETWEEN) { $from = $this->getValues('date_from', $condition, $values); $to = $this->getValues('date_to', $condition, $values); @@ -106,15 +117,15 @@ public function buildCondition(string|ExpressionInterface $fieldName, string $co if (!empty($from) && !empty($to)) { return function (QueryExpression $exp) use ($fieldName, $from, $to): QueryExpression { - return $exp->between($fieldName, $from, $to, 'datetime'); + return $exp->between($fieldName, $from, $to, $this->dbType); }; } elseif (!empty($from)) { return function (QueryExpression $exp) use ($fieldName, $from): QueryExpression { - return $exp->gte($fieldName, $from, 'datetime'); + return $exp->gte($fieldName, $from, $this->dbType); }; } elseif (!empty($to)) { return function (QueryExpression $exp) use ($fieldName, $to): QueryExpression { - return $exp->lte($fieldName, $to, 'datetime'); + return $exp->lte($fieldName, $to, $this->dbType); }; } @@ -149,7 +160,7 @@ public function buildCondition(string|ExpressionInterface $fieldName, string $co $value = $this->prepareTime($value); } - return $this->buildQueryByCondition($fieldName, $condition, $value); + return $this->buildQueryByCondition($fieldName, $condition, $value, ['type' => $this->dbType]); } /** @@ -186,4 +197,19 @@ protected function prepareTime(string $dateStr): \DateTimeInterface { return FrozenDate::createFromFormat($this->format, $dateStr); } + + /** + * Ensure the field is converted to a date if it's a datetime + * + * @param string|\Cake\Database\ExpressionInterface $field + * @return \Cake\Database\ExpressionInterface + */ + protected function ensureFieldIsDate(string|ExpressionInterface $field): ExpressionInterface + { + if (is_string($field)) { + $field = new IdentifierExpression($field); + } + + return new FunctionExpression('DATE', [$field], [], 'date'); + } } diff --git a/src/Model/Filter/Criterion/DateTimeCriterion.php b/src/Model/Filter/Criterion/DateTimeCriterion.php index 55f8c6f..8be9ce7 100644 --- a/src/Model/Filter/Criterion/DateTimeCriterion.php +++ b/src/Model/Filter/Criterion/DateTimeCriterion.php @@ -13,6 +13,13 @@ class DateTimeCriterion extends DateCriterion { + /** + * Database type + * + * @var string + */ + protected string $dbType = 'datetime'; + /** * DateCriterion constructor. * diff --git a/templates/element/Search/v_templates.php b/templates/element/Search/v_templates.php index 2f024d1..8e61678 100644 --- a/templates/element/Search/v_templates.php +++ b/templates/element/Search/v_templates.php @@ -175,17 +175,39 @@ class="form-control value" /> + + + @@ -204,7 +226,6 @@ class="form-control value" -