diff --git a/config/data_index_filters.yaml b/config/data_index_filters.yaml index ba82da464..53fdfc0b7 100644 --- a/config/data_index_filters.yaml +++ b/config/data_index_filters.yaml @@ -32,6 +32,9 @@ services: Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\PathFilter: tags: [ 'pimcore.studio_backend.open_search.filter' ] + Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\TagFilter: + tags: [ 'pimcore.studio_backend.open_search.filter' ] + # DataObject Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\DataObject\ClassNameFilter: tags: [ 'pimcore.studio_backend.open_search.data_object.filter' ] diff --git a/doc/03_Grid.md b/doc/03_Grid.md index fafdf9582..d5621523d 100644 --- a/doc/03_Grid.md +++ b/doc/03_Grid.md @@ -40,6 +40,7 @@ Available filters are: | metadata.asset | integer | ID fo the asset | | system.string | string | Wildcard search can be used | | system.datetime | integer | `from`, `to`, or `on` | +| system.tag | object | `considerChildTags`, `tags` | @@ -73,3 +74,18 @@ Filter by a date column: ] ... ``` + +Filter by Tags: +```json +... +"columnFilters" [ + { + "type": "system.tag", + "filterValue": { + "considerChildTags": true, + "tags": [1,2,3] + } + } +] +... +``` \ No newline at end of file diff --git a/src/DataIndex/Filter/TagFilter.php b/src/DataIndex/Filter/TagFilter.php new file mode 100644 index 000000000..b514798bb --- /dev/null +++ b/src/DataIndex/Filter/TagFilter.php @@ -0,0 +1,41 @@ +getTagFilter(); + + if (!$filter) { + return $query; + } + + return $query->filterTags($filter->getTags(), $filter->considerChildTags()); + } +} diff --git a/src/DataIndex/Query/AssetQuery.php b/src/DataIndex/Query/AssetQuery.php index c132f13db..e2964166e 100644 --- a/src/DataIndex/Query/AssetQuery.php +++ b/src/DataIndex/Query/AssetQuery.php @@ -24,6 +24,7 @@ use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Filter\FieldType\DateFilter; use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Filter\Tree\ParentIdFilter; use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Filter\Tree\PathFilter; +use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Filter\Tree\TagFilter; use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\FullTextSearch\ElementKeySearch; use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\FullTextSearch\WildcardSearch; use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Sort\OrderByField; @@ -145,4 +146,14 @@ public function filterDatetime( return $this; } + + /** + * @param array $tags + */ + public function filterTags(array $tags, bool $considerChildTags): QueryInterface + { + $this->search->addModifier(new TagFilter($tags, $considerChildTags)); + + return $this; + } } diff --git a/src/DataIndex/Query/DataObjectQuery.php b/src/DataIndex/Query/DataObjectQuery.php index 778e9e709..877c8e3cc 100644 --- a/src/DataIndex/Query/DataObjectQuery.php +++ b/src/DataIndex/Query/DataObjectQuery.php @@ -23,6 +23,7 @@ use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Filter\Basic\IdsFilter; use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Filter\Tree\ParentIdFilter; use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Filter\Tree\PathFilter; +use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Filter\Tree\TagFilter; use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\FullTextSearch\ElementKeySearch; use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Sort\Tree\OrderByFullPath; use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Sort\Tree\OrderByIndexField; @@ -124,4 +125,14 @@ public function orderByIndex(): self return $this; } + + /** + * @param array $tags + */ + public function filterTags(array $tags, bool $considerChildTags): QueryInterface + { + $this->search->addModifier(new TagFilter($tags, $considerChildTags)); + + return $this; + } } diff --git a/src/DataIndex/Query/QueryInterface.php b/src/DataIndex/Query/QueryInterface.php index 8dec22655..6f9d5ad6b 100644 --- a/src/DataIndex/Query/QueryInterface.php +++ b/src/DataIndex/Query/QueryInterface.php @@ -37,4 +37,9 @@ public function getSearch(): SearchInterface; public function orderByPath(string $direction): self; public function searchByIds(array $ids): self; + + /** + * @param array $tags + */ + public function filterTags(array $tags, bool $considerChildTags): self; } diff --git a/src/Filter/MappedParameter/FilterParameter.php b/src/Filter/MappedParameter/FilterParameter.php index ae724c377..f6ee69171 100644 --- a/src/Filter/MappedParameter/FilterParameter.php +++ b/src/Filter/MappedParameter/FilterParameter.php @@ -17,6 +17,7 @@ namespace Pimcore\Bundle\StudioBackendBundle\Filter\MappedParameter; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\InvalidArgumentException; +use Pimcore\Bundle\StudioBackendBundle\Grid\Column\ColumnType; use Pimcore\Bundle\StudioBackendBundle\MappedParameter\CollectionParametersInterface; use Pimcore\Bundle\StudioBackendBundle\MappedParameter\Filter\ColumnFilter; use Pimcore\Bundle\StudioBackendBundle\MappedParameter\Filter\ColumnFiltersParameterInterface; @@ -24,6 +25,9 @@ use Pimcore\Bundle\StudioBackendBundle\MappedParameter\Filter\PathParameterInterface; use Pimcore\Bundle\StudioBackendBundle\MappedParameter\Filter\SortFilter; use Pimcore\Bundle\StudioBackendBundle\MappedParameter\Filter\SortFilterParameterInterface; +use Pimcore\Bundle\StudioBackendBundle\MappedParameter\Filter\TagFilterParameter; +use Pimcore\Bundle\StudioBackendBundle\MappedParameter\Filter\TagFilterParameterInterface; +use function count; /** * @internal @@ -33,7 +37,8 @@ final class FilterParameter implements ExcludeFolderParameterInterface, PathParameterInterface, ColumnFiltersParameterInterface, - SortFilterParameterInterface + SortFilterParameterInterface, + TagFilterParameterInterface { private ?string $path = null; @@ -101,6 +106,29 @@ public function getColumnFilterByType(string $type): iterable } } + public function getTagFilter(): ?TagFilterParameter + { + $columns = array_filter( + $this->columnFilters, + static fn ($columnFilter) => $columnFilter['type'] === ColumnType::SYSTEM_TAG->value + ); + + if (count($columns) > 1) { + throw new InvalidArgumentException('More than one tag filter is not allowed'); + } + + if (isset($columns[0]['filterValue'])) { + $filterValue = $columns[0]['filterValue']; + if (!isset($filterValue['tags'], $filterValue['considerChildTags'])) { + throw new InvalidArgumentException('Invalid tag filter'); + } + + return new TagFilterParameter($filterValue['tags'], $filterValue['considerChildTags']); + } + + return null; + } + public function getFirstColumnFilterByType(string $type): ?ColumnFilter { $columns = iterator_to_array($this->getColumnFilterByType($type)); diff --git a/src/Grid/Column/ColumnType.php b/src/Grid/Column/ColumnType.php index 4ea8a8b1c..c38d59be0 100644 --- a/src/Grid/Column/ColumnType.php +++ b/src/Grid/Column/ColumnType.php @@ -25,6 +25,7 @@ enum ColumnType: string case SYSTEM_FILE_SIZE = 'system.fileSize'; case SYSTEM_INTEGER = 'system.integer'; case SYSTEM_DATETIME = 'system.datetime'; + case SYSTEM_TAG = 'system.tag'; case METADATA_SELECT = 'metadata.select'; case METADATA_INPUT = 'metadata.input'; case METADATA_DATE = 'metadata.date'; diff --git a/src/MappedParameter/Filter/TagFilterParameter.php b/src/MappedParameter/Filter/TagFilterParameter.php new file mode 100644 index 000000000..bd3686f85 --- /dev/null +++ b/src/MappedParameter/Filter/TagFilterParameter.php @@ -0,0 +1,42 @@ + + */ + public function getTags(): array + { + return $this->tags; + } + + public function considerChildTags(): bool + { + return $this->considerChildTags; + } +} diff --git a/src/MappedParameter/Filter/TagFilterParameterInterface.php b/src/MappedParameter/Filter/TagFilterParameterInterface.php new file mode 100644 index 000000000..d65be8577 --- /dev/null +++ b/src/MappedParameter/Filter/TagFilterParameterInterface.php @@ -0,0 +1,25 @@ +