diff --git a/config/data_index_filters.yaml b/config/data_index_filters.yaml index 0d2aba38e..c4ae4f729 100644 --- a/config/data_index_filters.yaml +++ b/config/data_index_filters.yaml @@ -72,6 +72,21 @@ services: Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\DataObject\BooleanFilter: tags: [ 'pimcore.studio_backend.search_index.data_object.filter' ] + Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\DataObject\Classificationstore\StringFilter: + tags: [ 'pimcore.studio_backend.search_index.data_object.filter' ] + + Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\DataObject\Classificationstore\RGBAFilter: + tags: [ 'pimcore.studio_backend.search_index.data_object.filter' ] + + Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\DataObject\Classificationstore\DateFilter: + tags: [ 'pimcore.studio_backend.search_index.data_object.filter' ] + + Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\DataObject\Classificationstore\QuantityValueFilter: + tags: [ 'pimcore.studio_backend.search_index.data_object.filter' ] + + Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\DataObject\Classificationstore\InputQuantityValueFilter: + tags: [ 'pimcore.studio_backend.search_index.data_object.filter' ] + # Asset Metadata Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\Asset\Metadata\SelectFilter: tags: [ 'pimcore.studio_backend.search_index.asset.filter' ] diff --git a/doc/03_Grid.md b/doc/03_Grid.md index 984b207f7..acc1f4dea 100644 --- a/doc/03_Grid.md +++ b/doc/03_Grid.md @@ -29,25 +29,30 @@ specific column, like the `system.tag` filter. This filters will be applied to t Available filters are: -| Type | filterValue | Options | `key` required | -|:-----------------:|:------------------:|:---------------------------:|:--------------:| -| metadata.select | string | | true | -| metadata.date | object of ISO 8601 | `from`, `to`, or `on` | true | -| metadata.input | string | | true | -| metadata.checkbox | boolean | | true | -| metadata.textarea | string | | true | -| metadata.object | integer | ID of the object | true | -| metadata.document | integer | ID fo the document | true | -| metadata.asset | integer | ID fo the asset | true | -| system.string | string | Wildcard search can be used | true | -| system.datetime | object of ISO 8601 | `from`, `to`, or `on` | true | -| system.tag | object | `considerChildTags`, `tags` | false | -| system.pql | string | PQL Query | false | -| system.id | integer | | false | -| system.ids | array of integer | | false | -| system.integer | integer | | true | -| system.fulltext | string | | false | -| system.boolean | boolean or null | | true | +| Type | filterValue | Options | `key` required | +|:----------------------------------------:|:------------------:|:----------------------------------:|:--------------:| +| metadata.select | string | | true | +| metadata.date | object of ISO 8601 | `from`, `to`, or `on` | true | +| metadata.input | string | | true | +| metadata.checkbox | boolean | | true | +| metadata.textarea | string | | true | +| metadata.object | integer | ID of the object | true | +| metadata.document | integer | ID fo the document | true | +| metadata.asset | integer | ID fo the asset | true | +| system.string | string | Wildcard search can be used | true | +| system.datetime | object of ISO 8601 | `from`, `to`, or `on` | true | +| system.tag | object | `considerChildTags`, `tags` | false | +| system.pql | string | PQL Query | false | +| system.id | integer | | false | +| system.ids | array of integer | | false | +| system.integer | integer | | true | +| system.fulltext | string | | false | +| system.boolean | boolean or null | | true | +| classificationstore.string | string | | true | +| classificationstore.rbga | array of integer | `r`,`g`,`b`,`a` | true | +| classificationstore.date | object of ISO 8601 | `from`, `to`, or `on` | true | +| classificationstore.quantity_value | sting, integer | `unitId`(string), `value`(integer) | true | +| classificationstore.input_quantity_value | string | `unitId`(string), `value`(string) | true | @@ -97,6 +102,24 @@ Filter by Tags: ... ``` +Classification Store Basic Filter Value: +The filter value of a Classification Store looks a bit difrent. All Filter need to have a groupId and keyId +```json +... +"columnFilters" [ + { + "key": "technicalAttributes", + "type": "classificationstore.string", + "filterValue": { + "groupId": 6, + "keyId": 12, + "value": "filtervalue" + } + } +] +... +``` + ## Advanced Columns Advanced columns are a special type of column that can be used to display data in a more advanced way. There are a few types of data sources for advanced columns: - `simpleField` - a simple field in the object diff --git a/src/ClassificationStore/Repository/KeyGroupRelationRepository.php b/src/ClassificationStore/Repository/KeyGroupRelationRepository.php index 111f4cf6d..87acc4a5d 100644 --- a/src/ClassificationStore/Repository/KeyGroupRelationRepository.php +++ b/src/ClassificationStore/Repository/KeyGroupRelationRepository.php @@ -14,9 +14,11 @@ namespace Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Repository; use Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Service\SearchHelperServiceInterface; +use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException; use Pimcore\Bundle\StudioBackendBundle\MappedParameter\CollectionParametersInterface; use Pimcore\Model\DataObject\Classificationstore\GroupConfig\Dao as GroupConfigDao; use Pimcore\Model\DataObject\Classificationstore\KeyConfig\Dao as KeyConfigDao; +use Pimcore\Model\DataObject\Classificationstore\KeyGroupRelation; use Pimcore\Model\DataObject\Classificationstore\KeyGroupRelation\Listing; use function count; @@ -111,4 +113,23 @@ private function getOffset(CollectionParametersInterface $collectionParameters): { return ($collectionParameters->getPage() - 1) * $collectionParameters->getPageSize(); } + + /** + * @inheritDoc + */ + public function getByKeyId(int $keyId): KeyGroupRelation + { + + $listing = new Listing(); + $listing->setOrder('ASC'); + $listing->setCondition('id = ?', $keyId); + + $list = $listing->load(); + + if (count($list) != 1) { + throw new NotFoundException('KeyGroupRelation', $keyId); + } + + return $list[0]; + } } diff --git a/src/ClassificationStore/Repository/KeyGroupRelationRepositoryInterface.php b/src/ClassificationStore/Repository/KeyGroupRelationRepositoryInterface.php index 9704cadef..ed13713e9 100644 --- a/src/ClassificationStore/Repository/KeyGroupRelationRepositoryInterface.php +++ b/src/ClassificationStore/Repository/KeyGroupRelationRepositoryInterface.php @@ -13,6 +13,7 @@ namespace Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Repository; +use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException; use Pimcore\Bundle\StudioBackendBundle\MappedParameter\CollectionParametersInterface; use Pimcore\Model\DataObject\Classificationstore\KeyGroupRelation; @@ -37,4 +38,9 @@ public function getCountByStoreId(int $storeId, ?array $groupIds = null): int; * @return KeyGroupRelation[] */ public function getByGroupId(int $groupId): array; + + /** + * @throws NotFoundException + */ + public function getByKeyId(int $keyId): KeyGroupRelation; } diff --git a/src/DataIndex/Filter/Asset/Metadata/DateFilter.php b/src/DataIndex/Filter/Asset/Metadata/DateFilter.php index 65a39911d..6ec4819ce 100644 --- a/src/DataIndex/Filter/Asset/Metadata/DateFilter.php +++ b/src/DataIndex/Filter/Asset/Metadata/DateFilter.php @@ -19,8 +19,10 @@ use Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\FilterInterface; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\AssetQueryInterface; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\QueryInterface; +use Pimcore\Bundle\StudioBackendBundle\Exception\Api\InvalidArgumentException; use Pimcore\Bundle\StudioBackendBundle\Grid\Column\ColumnType; use Pimcore\Bundle\StudioBackendBundle\MappedParameter\Filter\ColumnFilter; +use function is_array; /** * @internal @@ -48,8 +50,11 @@ public function apply(mixed $parameters, QueryInterface $query): QueryInterface private function applyDateFilter(ColumnFilter $column, AssetQueryInterface $query): AssetQueryInterface { + if (!is_array($column->getFilterValue())) { + throw new InvalidArgumentException('Filter value for this filter must be an array'); + } - $this->setFilterValue($column); + $this->setFilterValue($column->getFilterValue()); $filterValue = $column->getFilterValue(); diff --git a/src/DataIndex/Filter/DataObject/Classificationstore/DateFilter.php b/src/DataIndex/Filter/DataObject/Classificationstore/DateFilter.php new file mode 100644 index 000000000..9d12baf4b --- /dev/null +++ b/src/DataIndex/Filter/DataObject/Classificationstore/DateFilter.php @@ -0,0 +1,121 @@ +getColumnFilterByType(ColumnType::CLASSIFICATION_STORE_DATE->value) as $column) { + /** @var DataObjectQueryInterface $query */ + $query = $this->applyDateFilter($column, $query); + } + + return $query; + } + + private function applyDateFilter(ColumnFilter $column, DataObjectQueryInterface $query): QueryInterface + { + $filterValue = $this->getClassificationStoreFilterValue($column->getFilterValue()); + $key = $this->keyGroupRelationRepository->getByKeyId($filterValue->getKeyId()); + $group = $this->groupConfigRepository->getById($filterValue->getGroupId()); + + $this->setFilterValue($filterValue->getValue()); + + if (isset($this->filterValue['from'], $this->filterValue['to'])) { + + $query->classificationStoreFilter( + $column->getKeyWithOutLocale(), + $group->getName(), + $this->buildDateFilterModifier($key->getName(), $this->getFromAsCarbon(), $this->getToAsCarbon()), + $column->getLocale() + ); + + return $query; + } + + if (isset($this->filterValue['on'])) { + $query->classificationStoreFilter( + $column->getKeyWithOutLocale(), + $group->getName(), + $this->buildDateFilterModifier($key->getName(), null, null, $this->getOnAsCarbon()), + $column->getLocale() + ); + } + + if (isset($this->filterValue['to'])) { + $query->classificationStoreFilter( + $column->getKeyWithOutLocale(), + $group->getName(), + $this->buildDateFilterModifier($key->getName(), null, $this->getToAsCarbon()), + $column->getLocale() + ); + } + + if (isset($this->filterValue['from'])) { + $query->classificationStoreFilter( + $column->getKeyWithOutLocale(), + $group->getName(), + $this->buildDateFilterModifier($key->getName(), $this->getFromAsCarbon()), + $column->getLocale() + ); + $query->filterDatetime($column->getKey(), $this->getFromAsCarbon()); + } + + return $query; + } + + private function buildDateFilterModifier( + string $field, + ?Carbon $startDate = null, + ?Carbon $endDate = null, + ?Carbon $onDate = null, + ): GDIDateFilter { + return new GDIDateFilter($field, $startDate, $endDate, $onDate); + } +} diff --git a/src/DataIndex/Filter/DataObject/Classificationstore/InputQuantityValueFilter.php b/src/DataIndex/Filter/DataObject/Classificationstore/InputQuantityValueFilter.php new file mode 100644 index 000000000..2470aa901 --- /dev/null +++ b/src/DataIndex/Filter/DataObject/Classificationstore/InputQuantityValueFilter.php @@ -0,0 +1,82 @@ +getColumnFilterByType(ColumnType::CLASSIFICATION_STORE_INPUT_QUANTITY_VALUE->value) as $column + ) { + + $filterValue = $this->getClassificationStoreFilterValue($column->getFilterValue()); + + $key = $this->keyGroupRelationRepository->getByKeyId($filterValue->getKeyId()); + $group = $this->groupConfigRepository->getById($filterValue->getGroupId()); + $value = $filterValue->getValue(); + + if (!isset($value['value'], $value['unitId'])) { + throw new InvalidArgumentException('Value must contain valu and unitId'); + } + + $query->classificationStoreFilter( + $column->getKeyWithOutLocale(), + $group->getName(), + new WildcardSearch($key->getName(). '.value', $value['value'], true), + null + ); + + $query->classificationStoreFilter( + $column->getKeyWithOutLocale(), + $group->getName(), + new WildcardSearch($key->getName(). '.unitId', $value['unitId'], true), + null + ); + } + + return $query; + } +} diff --git a/src/DataIndex/Filter/DataObject/Classificationstore/QuantityValueFilter.php b/src/DataIndex/Filter/DataObject/Classificationstore/QuantityValueFilter.php new file mode 100644 index 000000000..16fac77a1 --- /dev/null +++ b/src/DataIndex/Filter/DataObject/Classificationstore/QuantityValueFilter.php @@ -0,0 +1,83 @@ +getColumnFilterByType(ColumnType::CLASSIFICATION_STORE_QUANTITY_VALUE->value) as $column + ) { + + $filterValue = $this->getClassificationStoreFilterValue($column->getFilterValue()); + + $key = $this->keyGroupRelationRepository->getByKeyId($filterValue->getKeyId()); + $group = $this->groupConfigRepository->getById($filterValue->getGroupId()); + $value = $filterValue->getValue(); + + if (!isset($value['value'], $value['unitId'])) { + throw new InvalidArgumentException('Value must contain valu and unitId'); + } + + $query->classificationStoreFilter( + $column->getKeyWithOutLocale(), + $group->getName(), + new IntegerFilter($key->getName(). '.value', $value['value'], true), + null + ); + + $query->classificationStoreFilter( + $column->getKeyWithOutLocale(), + $group->getName(), + new WildcardSearch($key->getName(). '.unitId', $value['unitId'], true), + null + ); + } + + return $query; + } +} diff --git a/src/DataIndex/Filter/DataObject/Classificationstore/RGBAFilter.php b/src/DataIndex/Filter/DataObject/Classificationstore/RGBAFilter.php new file mode 100644 index 000000000..b8a3fc94d --- /dev/null +++ b/src/DataIndex/Filter/DataObject/Classificationstore/RGBAFilter.php @@ -0,0 +1,94 @@ +getColumnFilterByType(ColumnType::CLASSIFICATION_STORE_RGBA->value) as $column) { + + $filterValue = $this->getClassificationStoreFilterValue($column->getFilterValue()); + + $key = $this->keyGroupRelationRepository->getByKeyId($filterValue->getKeyId()); + $group = $this->groupConfigRepository->getById($filterValue->getGroupId()); + $value = $filterValue->getValue(); + + if (!isset($value['r'], $value['g'], $value['b'], $value['a'])) { + throw new InvalidArgumentException('Value must contain r,g,b,a'); + } + + $query->classificationStoreFilter( + $column->getKeyWithOutLocale(), + $group->getName(), + new IntegerFilter($key->getName(). '.r', $value['r'], true), + null + ); + + $query->classificationStoreFilter( + $column->getKeyWithOutLocale(), + $group->getName(), + new IntegerFilter($key->getName(). '.g', $value['g'], true), + null + ); + + $query->classificationStoreFilter( + $column->getKeyWithOutLocale(), + $group->getName(), + new IntegerFilter($key->getName(). '.b', $value['b'], true), + null + ); + + $query->classificationStoreFilter( + $column->getKeyWithOutLocale(), + $group->getName(), + new IntegerFilter($key->getName(). '.a', $value['a'], true), + null + ); + } + + return $query; + } +} diff --git a/src/DataIndex/Filter/DataObject/Classificationstore/StringFilter.php b/src/DataIndex/Filter/DataObject/Classificationstore/StringFilter.php new file mode 100644 index 000000000..802b927a9 --- /dev/null +++ b/src/DataIndex/Filter/DataObject/Classificationstore/StringFilter.php @@ -0,0 +1,73 @@ +getColumnFilterByType(ColumnType::CLASSIFICATION_STORE_STRING->value) as $column) { + + $filterValue = $this->getClassificationStoreFilterValue($column->getFilterValue()); + + $key = $this->keyGroupRelationRepository->getByKeyId($filterValue->getKeyId()); + $group = $this->groupConfigRepository->getById($filterValue->getGroupId()); + + if (!is_string($filterValue->getValue())) { + throw new InvalidArgumentException('Filter value for this filter must be a string'); + } + + $query->classificationStoreFilter( + $column->getKeyWithOutLocale(), + $group->getName(), + new WildcardSearch($key->getName(), $filterValue->getValue(), true), + $column->getLocale() + ); + } + + return $query; + } +} diff --git a/src/DataIndex/Filter/DateTimeTrait.php b/src/DataIndex/Filter/DateTimeTrait.php index 73ba0ca6d..5c11c15a3 100644 --- a/src/DataIndex/Filter/DateTimeTrait.php +++ b/src/DataIndex/Filter/DateTimeTrait.php @@ -16,8 +16,6 @@ use Carbon\Carbon; use Carbon\Exceptions\InvalidFormatException; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\InvalidArgumentException; -use Pimcore\Bundle\StudioBackendBundle\MappedParameter\Filter\ColumnFilter; -use function is_array; use function sprintf; /** @@ -27,13 +25,9 @@ trait DateTimeTrait { private array $filterValue = []; - public function setFilterValue(ColumnFilter $column): void + public function setFilterValue(array $value): void { - if (!is_array($column->getFilterValue())) { - throw new InvalidArgumentException('Filter value for this filter must be an array'); - } - - $this->filterValue = $column->getFilterValue(); + $this->filterValue = $value; } public function getOnAsCarbon(): Carbon diff --git a/src/DataIndex/Filter/DatetimeFilter.php b/src/DataIndex/Filter/DatetimeFilter.php index 9d41fe4e9..b2eb7bf1b 100644 --- a/src/DataIndex/Filter/DatetimeFilter.php +++ b/src/DataIndex/Filter/DatetimeFilter.php @@ -15,9 +15,11 @@ use Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\Asset\IsAssetFilterTrait; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\QueryInterface; +use Pimcore\Bundle\StudioBackendBundle\Exception\Api\InvalidArgumentException; use Pimcore\Bundle\StudioBackendBundle\Grid\Column\ColumnType; use Pimcore\Bundle\StudioBackendBundle\MappedParameter\Filter\ColumnFilter; use Pimcore\Bundle\StudioBackendBundle\MappedParameter\Filter\ColumnFiltersParameterInterface; +use function is_array; /** * @internal @@ -42,7 +44,12 @@ public function apply(mixed $parameters, QueryInterface $query): QueryInterface private function applyDatetimeFilter(ColumnFilter $column, QueryInterface $query): QueryInterface { - $this->setFilterValue($column); + + if (!is_array($column->getFilterValue())) { + throw new InvalidArgumentException('Filter value for this filter must be an array'); + } + + $this->setFilterValue($column->getFilterValue()); $filterValue = $column->getFilterValue(); diff --git a/src/DataIndex/Query/DataObjectQuery.php b/src/DataIndex/Query/DataObjectQuery.php index e6c6bf129..f2f672238 100644 --- a/src/DataIndex/Query/DataObjectQuery.php +++ b/src/DataIndex/Query/DataObjectQuery.php @@ -22,7 +22,10 @@ use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Filter\Basic\IdFilter; use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Filter\Basic\IdsFilter; use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Filter\Basic\IntegerFilter; +use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Filter\FieldType\ClassificationStoreFilter; 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\Tree\ClassIdsFilter; use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Filter\Tree\ParentIdFilter; use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Filter\Tree\PathFilter; @@ -231,4 +234,40 @@ public function booleanFilter(string $fieldName, null|bool $value): self return $this; } + + public function classificationStoreFilter( + string $fieldName, + string $group, + BooleanFilter| + DateFilter| + FullTextSearch| + IntegerFilter| + MultiSelectFilter| + NumberRangeFilter| + WildcardSearch $subModifier, + ?string $locale = null + ): self { + if ($locale === null) { + $this->search->addModifier( + new ClassificationStoreFilter( + $fieldName, + $group, + $subModifier, + ) + ); + + return $this; + } + + $this->search->addModifier( + new ClassificationStoreFilter( + $fieldName, + $group, + $subModifier, + $locale + ) + ); + + return $this; + } } diff --git a/src/DataIndex/Query/DataObjectQueryInterface.php b/src/DataIndex/Query/DataObjectQueryInterface.php index a18da97b7..fd3ca8f21 100644 --- a/src/DataIndex/Query/DataObjectQueryInterface.php +++ b/src/DataIndex/Query/DataObjectQueryInterface.php @@ -14,6 +14,13 @@ namespace Pimcore\Bundle\StudioBackendBundle\DataIndex\Query; use Exception; +use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Filter\Basic\BooleanFilter; +use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Filter\Basic\IntegerFilter; +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\FullTextSearch\FullTextSearch; +use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\FullTextSearch\WildcardSearch; /** * @internal @@ -28,4 +35,17 @@ public function setClassDefinitionName(string $classDefinitionId): self; public function setClassDefinitionIds(array $classDefinitionIds): self; public function booleanFilter(string $fieldName, null|bool $value): self; + + public function classificationStoreFilter( + string $fieldName, + string $group, + BooleanFilter| + DateFilter| + FullTextSearch| + IntegerFilter| + MultiSelectFilter| + NumberRangeFilter| + WildcardSearch $subModifier, + ?string $locale + ): self; } diff --git a/src/DataIndex/Utils/ClassificationStoreFilterValue.php b/src/DataIndex/Utils/ClassificationStoreFilterValue.php new file mode 100644 index 000000000..c0e8f5e20 --- /dev/null +++ b/src/DataIndex/Utils/ClassificationStoreFilterValue.php @@ -0,0 +1,43 @@ +groupId; + } + + public function getKeyId(): int + { + return $this->keyId; + } + + public function getValue(): string|array + { + return $this->value; + } +} diff --git a/src/DataIndex/Utils/GetClassificationStoreFilterValueTrait.php b/src/DataIndex/Utils/GetClassificationStoreFilterValueTrait.php new file mode 100644 index 000000000..f9871ed12 --- /dev/null +++ b/src/DataIndex/Utils/GetClassificationStoreFilterValueTrait.php @@ -0,0 +1,45 @@ +key; } + + public function getKeyWithOutLocale(): string + { + return $this->key; + } + + public function getLocale(): ?string + { + return $this->locale; + } }