From e8718f4af285d2fb55c5ea6c3fb011f1b24011b0 Mon Sep 17 00:00:00 2001 From: Martin Eiber Date: Tue, 17 Sep 2024 13:50:59 +0200 Subject: [PATCH 1/3] [Grid] Add Owner and Modification Date (#424) * Initial Commit. * Add owner. --- .../DetailedConfigurationHydrator.php | 6 +++++- src/Grid/Schema/DetailedConfiguration.php | 20 ++++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/Grid/Hydrator/DetailedConfigurationHydrator.php b/src/Grid/Hydrator/DetailedConfigurationHydrator.php index e395af39b..a08b896be 100644 --- a/src/Grid/Hydrator/DetailedConfigurationHydrator.php +++ b/src/Grid/Hydrator/DetailedConfigurationHydrator.php @@ -30,6 +30,7 @@ public function hydrate( array $roles, bool $isFavorite ): DetailedConfiguration { + return new DetailedConfiguration( name: $data->getName(), description: $data->getDescription(), @@ -40,7 +41,10 @@ public function hydrate( sharedRoles: $roles, columns: $data->getColumns(), filter: $data->getFilter() ?? [], - pageSize: $data->getPageSize() + pageSize: $data->getPageSize(), + modificationDate: $data->getModificationDate()->getTimestamp(), + creationDate: $data->getCreationDate()->getTimestamp(), + ownerId: $data->getOwner() ); } } diff --git a/src/Grid/Schema/DetailedConfiguration.php b/src/Grid/Schema/DetailedConfiguration.php index d82df2da3..f2394e7ab 100644 --- a/src/Grid/Schema/DetailedConfiguration.php +++ b/src/Grid/Schema/DetailedConfiguration.php @@ -57,7 +57,10 @@ public function __construct( #[Property(description: 'filter', type: 'array', items: new Items(ref: Filter::class))] private readonly array $filter, #[Property(description: 'Page Size', type: 'integer', example: 42)] - private readonly int $pageSize = 25 + private readonly int $pageSize = 25, + private readonly ?int $modificationDate = null, + private readonly ?int $creationDate = null, + private readonly ?int $ownerId = null, ) { } @@ -122,4 +125,19 @@ public function getPageSize(): int { return $this->pageSize; } + + public function getModificationDate(): ?int + { + return $this->modificationDate; + } + + public function getCreationDate(): ?int + { + return $this->creationDate; + } + + public function getOwnerId(): ?int + { + return $this->ownerId; + } } From 83dc3bd5ac49c79b7e0fa513e21d3b13cc916d48 Mon Sep 17 00:00:00 2001 From: Martin Eiber Date: Thu, 19 Sep 2024 09:48:25 +0200 Subject: [PATCH 2/3] [Grid] Add PQLQuery Filter (#429) * Add PQL Query Filter. * Apply php-cs-fixer changes --------- Co-authored-by: martineiber --- config/data_index_filters.yaml | 3 ++ doc/03_Grid.md | 30 +++++------ src/DataIndex/Adapter/AssetSearchAdapter.php | 6 ++- .../Adapter/AssetSearchAdapterInterface.php | 3 +- src/DataIndex/AssetSearchService.php | 3 +- src/DataIndex/AssetSearchServiceInterface.php | 3 +- src/DataIndex/Filter/PqlFilter.php | 50 +++++++++++++++++++ src/DataIndex/Filter/TagFilter.php | 16 ++++-- src/DataIndex/Grid/GridSearch.php | 3 +- src/DataIndex/Query/AssetQuery.php | 10 +++- src/DataIndex/Query/DataObjectQuery.php | 10 +++- src/DataIndex/Query/QueryInterface.php | 2 + .../MappedParameter/FilterParameter.php | 24 ++++----- src/Grid/Column/ColumnType.php | 1 + src/MappedParameter/Filter/ColumnFilter.php | 13 +---- ...erParameter.php => SimpleColumnFilter.php} | 17 +++---- ...SimpleColumnFiltersParameterInterface.php} | 7 ++- 17 files changed, 139 insertions(+), 62 deletions(-) create mode 100644 src/DataIndex/Filter/PqlFilter.php rename src/MappedParameter/Filter/{TagFilterParameter.php => SimpleColumnFilter.php} (67%) rename src/MappedParameter/Filter/{TagFilterParameterInterface.php => SimpleColumnFiltersParameterInterface.php} (73%) diff --git a/config/data_index_filters.yaml b/config/data_index_filters.yaml index 53fdfc0b7..f056e893a 100644 --- a/config/data_index_filters.yaml +++ b/config/data_index_filters.yaml @@ -35,6 +35,9 @@ services: Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\TagFilter: tags: [ 'pimcore.studio_backend.open_search.filter' ] + Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\PqlFilter: + 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 d5621523d..ca02c8754 100644 --- a/doc/03_Grid.md +++ b/doc/03_Grid.md @@ -24,23 +24,25 @@ Here you can define `page`, `pageSize` and `includeDescendants`. ### ColumnFilter It is also possible to filter the data by a column. This is done by adding a `columnFilter` to the `filter` property. -A `columnFilter` has a reference to the column and the value you want to filter by. +A `columnFilter` has a reference to the column and the value you want to filter by. Some filters do not require a +specific column, like the `system.tag` filter. This filters will be applied to the general search query. Available filters are: -| Type | filterValue | Options | -|:-----------------:|:-------------------:|:---------------------------:| -| metadata.select | string | | -| metadata.date | object of timestamp | `from`, `to`, or `on` | -| metadata.input | string | | -| metadata.checkbox | boolean | | -| metadata.textarea | string | | -| metadata.object | integer | ID of the object | -| metadata.document | integer | ID fo the document | -| 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` | +| Type | filterValue | Options | `key` required | +|:-----------------:|:-------------------:|:---------------------------:|:--------------:| +| metadata.select | string | | true | +| metadata.date | object of timestamp | `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 | integer | `from`, `to`, or `on` | true | +| system.tag | object | `considerChildTags`, `tags` | false | +| system.pql | string | PQL Query | false | diff --git a/src/DataIndex/Adapter/AssetSearchAdapter.php b/src/DataIndex/Adapter/AssetSearchAdapter.php index 0c4f0500f..f1bbb00e0 100644 --- a/src/DataIndex/Adapter/AssetSearchAdapter.php +++ b/src/DataIndex/Adapter/AssetSearchAdapter.php @@ -16,6 +16,7 @@ namespace Pimcore\Bundle\StudioBackendBundle\DataIndex\Adapter; +use Exception; use Pimcore\Bundle\GenericDataIndexBundle\Exception\AssetSearchException; use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Asset\AssetSearch; use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Sort\Tree\OrderByFullPath; @@ -26,6 +27,7 @@ use Pimcore\Bundle\StudioBackendBundle\DataIndex\AssetSearchResult; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Hydrator\HydratorServiceInterface; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\QueryInterface; +use Pimcore\Bundle\StudioBackendBundle\Exception\Api\InvalidArgumentException; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\SearchException; use function sprintf; @@ -41,7 +43,7 @@ public function __construct( } /** - * @throws SearchException + * @throws SearchException|InvalidArgumentException */ public function searchAssets(QueryInterface $assetQuery): AssetSearchResult { @@ -49,6 +51,8 @@ public function searchAssets(QueryInterface $assetQuery): AssetSearchResult $searchResult = $this->searchService->search($assetQuery->getSearch()); } catch (AssetSearchException) { throw new SearchException('assets'); + } catch (Exception $e) { + throw new InvalidArgumentException($e->getMessage()); } $result = []; diff --git a/src/DataIndex/Adapter/AssetSearchAdapterInterface.php b/src/DataIndex/Adapter/AssetSearchAdapterInterface.php index bfb6557d1..2c42cfe17 100644 --- a/src/DataIndex/Adapter/AssetSearchAdapterInterface.php +++ b/src/DataIndex/Adapter/AssetSearchAdapterInterface.php @@ -20,13 +20,14 @@ use Pimcore\Bundle\StudioBackendBundle\Asset\Schema\Asset; use Pimcore\Bundle\StudioBackendBundle\DataIndex\AssetSearchResult; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\QueryInterface; +use Pimcore\Bundle\StudioBackendBundle\Exception\Api\InvalidArgumentException; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\SearchException; interface AssetSearchAdapterInterface { /** - * @throws SearchException + * @throws SearchException|InvalidArgumentException */ public function searchAssets(QueryInterface $assetQuery): AssetSearchResult; diff --git a/src/DataIndex/AssetSearchService.php b/src/DataIndex/AssetSearchService.php index 1e46d9ac7..7f19d1d30 100644 --- a/src/DataIndex/AssetSearchService.php +++ b/src/DataIndex/AssetSearchService.php @@ -29,6 +29,7 @@ use Pimcore\Bundle\StudioBackendBundle\DataIndex\Adapter\AssetSearchAdapterInterface; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Provider\AssetQueryProviderInterface; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\QueryInterface; +use Pimcore\Bundle\StudioBackendBundle\Exception\Api\InvalidArgumentException; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\SearchException; use function count; @@ -42,7 +43,7 @@ public function __construct( } /** - * @throws SearchException + * @throws SearchException|InvalidArgumentException */ public function searchAssets(QueryInterface $assetQuery): AssetSearchResult { diff --git a/src/DataIndex/AssetSearchServiceInterface.php b/src/DataIndex/AssetSearchServiceInterface.php index 8d516e2bc..e26244cb5 100644 --- a/src/DataIndex/AssetSearchServiceInterface.php +++ b/src/DataIndex/AssetSearchServiceInterface.php @@ -27,13 +27,14 @@ use Pimcore\Bundle\StudioBackendBundle\Asset\Schema\Type\Unknown; use Pimcore\Bundle\StudioBackendBundle\Asset\Schema\Type\Video; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\QueryInterface; +use Pimcore\Bundle\StudioBackendBundle\Exception\Api\InvalidArgumentException; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\SearchException; interface AssetSearchServiceInterface { /** - * @throws SearchException + * @throws SearchException|InvalidArgumentException */ public function searchAssets(QueryInterface $assetQuery): AssetSearchResult; diff --git a/src/DataIndex/Filter/PqlFilter.php b/src/DataIndex/Filter/PqlFilter.php new file mode 100644 index 000000000..3432d204e --- /dev/null +++ b/src/DataIndex/Filter/PqlFilter.php @@ -0,0 +1,50 @@ +getSimpleColumnFilterByType(ColumnType::SYSTEM_PQL_QUERY->value); + + if (!$filter) { + return $query; + } + + if (!is_string($filter->getFilterValue())) { + throw new InvalidArgumentException('Invalid PQL filter. Filter value must be a string.'); + } + + $filterValue = $filter->getFilterValue(); + + return $query->filterByPql($filterValue); + } +} diff --git a/src/DataIndex/Filter/TagFilter.php b/src/DataIndex/Filter/TagFilter.php index b514798bb..3e13c9d9c 100644 --- a/src/DataIndex/Filter/TagFilter.php +++ b/src/DataIndex/Filter/TagFilter.php @@ -17,7 +17,9 @@ namespace Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\QueryInterface; -use Pimcore\Bundle\StudioBackendBundle\MappedParameter\Filter\TagFilterParameterInterface; +use Pimcore\Bundle\StudioBackendBundle\Exception\Api\InvalidArgumentException; +use Pimcore\Bundle\StudioBackendBundle\Grid\Column\ColumnType; +use Pimcore\Bundle\StudioBackendBundle\MappedParameter\Filter\SimpleColumnFiltersParameterInterface; /** * @internal @@ -26,16 +28,22 @@ final class TagFilter implements FilterInterface { public function apply(mixed $parameters, QueryInterface $query): QueryInterface { - if (!$parameters instanceof TagFilterParameterInterface) { + if (!$parameters instanceof SimpleColumnFiltersParameterInterface) { return $query; } - $filter = $parameters->getTagFilter(); + $filter = $parameters->getSimpleColumnFilterByType(ColumnType::SYSTEM_TAG->value); if (!$filter) { return $query; } - return $query->filterTags($filter->getTags(), $filter->considerChildTags()); + $filterValue = $filter->getFilterValue(); + + if (!isset($filterValue['tags'], $filterValue['considerChildTags'])) { + throw new InvalidArgumentException('Invalid tag filter'); + } + + return $query->filterTags($filterValue['tags'], $filterValue['considerChildTags']); } } diff --git a/src/DataIndex/Grid/GridSearch.php b/src/DataIndex/Grid/GridSearch.php index 42420043d..e04967c8d 100644 --- a/src/DataIndex/Grid/GridSearch.php +++ b/src/DataIndex/Grid/GridSearch.php @@ -20,6 +20,7 @@ use Pimcore\Bundle\StudioBackendBundle\DataIndex\AssetSearchResult; use Pimcore\Bundle\StudioBackendBundle\DataIndex\AssetSearchServiceInterface; use Pimcore\Bundle\StudioBackendBundle\DataIndex\OpenSearchFilterInterface; +use Pimcore\Bundle\StudioBackendBundle\Exception\Api\InvalidArgumentException; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\SearchException; use Pimcore\Bundle\StudioBackendBundle\Filter\Service\FilterServiceProviderInterface; @@ -39,7 +40,7 @@ public function __construct( } /** - * @throws NotFoundException|SearchException + * @throws NotFoundException|SearchException|InvalidArgumentException */ public function searchAssets(GridParameter $gridParameter): AssetSearchResult { diff --git a/src/DataIndex/Query/AssetQuery.php b/src/DataIndex/Query/AssetQuery.php index e2964166e..df97b3d65 100644 --- a/src/DataIndex/Query/AssetQuery.php +++ b/src/DataIndex/Query/AssetQuery.php @@ -27,6 +27,7 @@ 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\QueryLanguage\PqlFilter; use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Sort\OrderByField; use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Sort\Tree\OrderByFullPath; @@ -150,10 +151,17 @@ public function filterDatetime( /** * @param array $tags */ - public function filterTags(array $tags, bool $considerChildTags): QueryInterface + public function filterTags(array $tags, bool $considerChildTags): self { $this->search->addModifier(new TagFilter($tags, $considerChildTags)); return $this; } + + public function filterByPql(string $pqlQuery): self + { + $this->search->addModifier(new PqlFilter($pqlQuery)); + + return $this; + } } diff --git a/src/DataIndex/Query/DataObjectQuery.php b/src/DataIndex/Query/DataObjectQuery.php index 877c8e3cc..db3b11d9e 100644 --- a/src/DataIndex/Query/DataObjectQuery.php +++ b/src/DataIndex/Query/DataObjectQuery.php @@ -25,6 +25,7 @@ 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\QueryLanguage\PqlFilter; use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Sort\Tree\OrderByFullPath; use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Sort\Tree\OrderByIndexField; use Pimcore\Bundle\StaticResolverBundle\Models\DataObject\ClassDefinitionResolverInterface; @@ -129,10 +130,17 @@ public function orderByIndex(): self /** * @param array $tags */ - public function filterTags(array $tags, bool $considerChildTags): QueryInterface + public function filterTags(array $tags, bool $considerChildTags): self { $this->search->addModifier(new TagFilter($tags, $considerChildTags)); return $this; } + + public function filterByPql(string $pqlQuery): self + { + $this->search->addModifier(new PqlFilter($pqlQuery)); + + return $this; + } } diff --git a/src/DataIndex/Query/QueryInterface.php b/src/DataIndex/Query/QueryInterface.php index 6f9d5ad6b..17e791058 100644 --- a/src/DataIndex/Query/QueryInterface.php +++ b/src/DataIndex/Query/QueryInterface.php @@ -42,4 +42,6 @@ public function searchByIds(array $ids): self; * @param array $tags */ public function filterTags(array $tags, bool $considerChildTags): self; + + public function filterByPql(string $pqlQuery): self; } diff --git a/src/Filter/MappedParameter/FilterParameter.php b/src/Filter/MappedParameter/FilterParameter.php index f6ee69171..c7f934823 100644 --- a/src/Filter/MappedParameter/FilterParameter.php +++ b/src/Filter/MappedParameter/FilterParameter.php @@ -17,16 +17,15 @@ 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; use Pimcore\Bundle\StudioBackendBundle\MappedParameter\Filter\ExcludeFolderParameterInterface; use Pimcore\Bundle\StudioBackendBundle\MappedParameter\Filter\PathParameterInterface; +use Pimcore\Bundle\StudioBackendBundle\MappedParameter\Filter\SimpleColumnFilter; +use Pimcore\Bundle\StudioBackendBundle\MappedParameter\Filter\SimpleColumnFiltersParameterInterface; 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; /** @@ -37,8 +36,8 @@ final class FilterParameter implements ExcludeFolderParameterInterface, PathParameterInterface, ColumnFiltersParameterInterface, - SortFilterParameterInterface, - TagFilterParameterInterface + SimpleColumnFiltersParameterInterface, + SortFilterParameterInterface { private ?string $path = null; @@ -106,24 +105,21 @@ public function getColumnFilterByType(string $type): iterable } } - public function getTagFilter(): ?TagFilterParameter + public function getSimpleColumnFilterByType(string $type): ?SimpleColumnFilter { $columns = array_filter( $this->columnFilters, - static fn ($columnFilter) => $columnFilter['type'] === ColumnType::SYSTEM_TAG->value + static fn ($columnFilter) => $columnFilter['type'] === $type ); if (count($columns) > 1) { - throw new InvalidArgumentException('More than one tag filter is not allowed'); + throw new InvalidArgumentException('More than one filter of same type is not allowed'); } - if (isset($columns[0]['filterValue'])) { - $filterValue = $columns[0]['filterValue']; - if (!isset($filterValue['tags'], $filterValue['considerChildTags'])) { - throw new InvalidArgumentException('Invalid tag filter'); - } + $column = reset($columns); - return new TagFilterParameter($filterValue['tags'], $filterValue['considerChildTags']); + if (isset($column['filterValue'])) { + return new SimpleColumnFilter($type, $column['filterValue']); } return null; diff --git a/src/Grid/Column/ColumnType.php b/src/Grid/Column/ColumnType.php index c38d59be0..78bbd53ec 100644 --- a/src/Grid/Column/ColumnType.php +++ b/src/Grid/Column/ColumnType.php @@ -26,6 +26,7 @@ enum ColumnType: string case SYSTEM_INTEGER = 'system.integer'; case SYSTEM_DATETIME = 'system.datetime'; case SYSTEM_TAG = 'system.tag'; + case SYSTEM_PQL_QUERY = 'system.pql'; case METADATA_SELECT = 'metadata.select'; case METADATA_INPUT = 'metadata.input'; case METADATA_DATE = 'metadata.date'; diff --git a/src/MappedParameter/Filter/ColumnFilter.php b/src/MappedParameter/Filter/ColumnFilter.php index ecd9ef2f9..c7f37f913 100644 --- a/src/MappedParameter/Filter/ColumnFilter.php +++ b/src/MappedParameter/Filter/ColumnFilter.php @@ -19,27 +19,18 @@ /** * @internal */ -final readonly class ColumnFilter +final readonly class ColumnFilter extends SimpleColumnFilter { public function __construct( private string $key, private string $type, private mixed $filterValue, ) { + parent::__construct($this->type, $this->filterValue); } public function getKey(): string { return $this->key; } - - public function getType(): string - { - return $this->type; - } - - public function getFilterValue(): mixed - { - return $this->filterValue; - } } diff --git a/src/MappedParameter/Filter/TagFilterParameter.php b/src/MappedParameter/Filter/SimpleColumnFilter.php similarity index 67% rename from src/MappedParameter/Filter/TagFilterParameter.php rename to src/MappedParameter/Filter/SimpleColumnFilter.php index bd3686f85..05ceea10c 100644 --- a/src/MappedParameter/Filter/TagFilterParameter.php +++ b/src/MappedParameter/Filter/SimpleColumnFilter.php @@ -19,24 +19,21 @@ /** * @internal */ -final readonly class TagFilterParameter +readonly class SimpleColumnFilter { public function __construct( - private array $tags, - private bool $considerChildTags + private string $type, + private mixed $filterValue, ) { } - /** - * @return array - */ - public function getTags(): array + public function getType(): string { - return $this->tags; + return $this->type; } - public function considerChildTags(): bool + public function getFilterValue(): mixed { - return $this->considerChildTags; + return $this->filterValue; } } diff --git a/src/MappedParameter/Filter/TagFilterParameterInterface.php b/src/MappedParameter/Filter/SimpleColumnFiltersParameterInterface.php similarity index 73% rename from src/MappedParameter/Filter/TagFilterParameterInterface.php rename to src/MappedParameter/Filter/SimpleColumnFiltersParameterInterface.php index d65be8577..16500fb3d 100644 --- a/src/MappedParameter/Filter/TagFilterParameterInterface.php +++ b/src/MappedParameter/Filter/SimpleColumnFiltersParameterInterface.php @@ -19,7 +19,10 @@ /** * @internal */ -interface TagFilterParameterInterface +interface SimpleColumnFiltersParameterInterface { - public function getTagFilter(): ?TagFilterParameter; + /** + * A column filter that does not require a key + */ + public function getSimpleColumnFilterByType(string $type): ?SimpleColumnFilter; } From 85febaa9160533f7612398adbef4b8f021d2731b Mon Sep 17 00:00:00 2001 From: Martin Eiber Date: Mon, 23 Sep 2024 08:20:45 +0200 Subject: [PATCH 3/3] Introduce two new interfaces for DataIndex Query (#430) * Refactor QueryInterface * Apply php-cs-fixer changes * Add some unit tests for Asset Filter. * Apply php-cs-fixer changes --------- Co-authored-by: martineiber --- docker-compose.yml | 3 +- .../Filter/Asset/IsAssetFilterTrait.php | 6 +- .../Filter/Asset/Metadata/AssetFilter.php | 4 +- .../Filter/Asset/Metadata/CheckboxFilter.php | 4 +- .../Filter/Asset/Metadata/DateFilter.php | 4 +- .../Filter/Asset/Metadata/DocumentFilter.php | 4 +- .../Filter/Asset/Metadata/InputFilter.php | 4 +- .../Filter/Asset/Metadata/ObjectFilter.php | 4 +- .../Filter/Asset/Metadata/SelectFilter.php | 4 +- .../Filter/Asset/Metadata/TextAreaFilter.php | 4 +- src/DataIndex/Filter/Asset/SortFilter.php | 4 +- .../Filter/Asset/System/DatetimeFilter.php | 6 +- .../Filter/Asset/System/StringFilter.php | 4 +- .../Filter/DataObject/ClassNameFilter.php | 4 +- src/DataIndex/Query/AssetQuery.php | 2 +- src/DataIndex/Query/AssetQueryInterface.php | 44 +++++++ src/DataIndex/Query/DataObjectQuery.php | 2 +- .../Query/DataObjectQueryInterface.php | 30 +++++ .../Filter/Asset/IsAssetFilterTraitTest.php | 72 ++++++++++++ .../Filter/Asset/Metadata/AssetFilterTest.php | 65 ++++++++++ .../Asset/Metadata/CheckboxFilterTest.php | 65 ++++++++++ .../Asset/Metadata/ColumnFilterMockTrait.php | 37 ++++++ .../Filter/Asset/Metadata/DateFilterTest.php | 105 +++++++++++++++++ .../Asset/Metadata/DocumentFilterTest.php | 65 ++++++++++ .../Filter/Asset/Metadata/InputFilterTest.php | 65 ++++++++++ .../Asset/Metadata/ObjectFilterTest.php | 65 ++++++++++ .../Asset/Metadata/SelectFilterTest.php | 65 ++++++++++ .../Asset/Metadata/TextAreaFilterTest.php | 65 ++++++++++ .../DataIndex/Filter/Asset/SortFilterTest.php | 83 +++++++++++++ .../Asset/System/DatetimeFilterTest.php | 111 ++++++++++++++++++ .../Filter/Asset/System/StringFilterTest.php | 75 ++++++++++++ 31 files changed, 1044 insertions(+), 31 deletions(-) create mode 100644 src/DataIndex/Query/AssetQueryInterface.php create mode 100644 src/DataIndex/Query/DataObjectQueryInterface.php create mode 100644 tests/Unit/DataIndex/Filter/Asset/IsAssetFilterTraitTest.php create mode 100644 tests/Unit/DataIndex/Filter/Asset/Metadata/AssetFilterTest.php create mode 100644 tests/Unit/DataIndex/Filter/Asset/Metadata/CheckboxFilterTest.php create mode 100644 tests/Unit/DataIndex/Filter/Asset/Metadata/ColumnFilterMockTrait.php create mode 100644 tests/Unit/DataIndex/Filter/Asset/Metadata/DateFilterTest.php create mode 100644 tests/Unit/DataIndex/Filter/Asset/Metadata/DocumentFilterTest.php create mode 100644 tests/Unit/DataIndex/Filter/Asset/Metadata/InputFilterTest.php create mode 100644 tests/Unit/DataIndex/Filter/Asset/Metadata/ObjectFilterTest.php create mode 100644 tests/Unit/DataIndex/Filter/Asset/Metadata/SelectFilterTest.php create mode 100644 tests/Unit/DataIndex/Filter/Asset/Metadata/TextAreaFilterTest.php create mode 100644 tests/Unit/DataIndex/Filter/Asset/SortFilterTest.php create mode 100644 tests/Unit/DataIndex/Filter/Asset/System/DatetimeFilterTest.php create mode 100644 tests/Unit/DataIndex/Filter/Asset/System/StringFilterTest.php diff --git a/docker-compose.yml b/docker-compose.yml index 210020e65..f5099324b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,4 +5,5 @@ services: environment: PHP_IDE_CONFIG: serverName=localhost volumes: - - .:/var/cli/ \ No newline at end of file + - .:/var/cli/ + - ./.docker/30-xdebug.ini:/usr/local/etc/php/conf.d/30-xdebug.ini \ No newline at end of file diff --git a/src/DataIndex/Filter/Asset/IsAssetFilterTrait.php b/src/DataIndex/Filter/Asset/IsAssetFilterTrait.php index c51b36979..53ad45b8e 100644 --- a/src/DataIndex/Filter/Asset/IsAssetFilterTrait.php +++ b/src/DataIndex/Filter/Asset/IsAssetFilterTrait.php @@ -16,7 +16,7 @@ namespace Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\Asset; -use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\AssetQuery; +use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\AssetQueryInterface; use Pimcore\Bundle\StudioBackendBundle\MappedParameter\Filter\ColumnFiltersParameterInterface; /** @@ -33,9 +33,9 @@ public function validateParameterType(mixed $parameters): ?ColumnFiltersParamete return null; } - public function validateQueryType(mixed $query): ?AssetQuery + public function validateQueryType(mixed $query): ?AssetQueryInterface { - if ($query instanceof AssetQuery) { + if ($query instanceof AssetQueryInterface) { return $query; } diff --git a/src/DataIndex/Filter/Asset/Metadata/AssetFilter.php b/src/DataIndex/Filter/Asset/Metadata/AssetFilter.php index 38cda1d23..64bfe0797 100644 --- a/src/DataIndex/Filter/Asset/Metadata/AssetFilter.php +++ b/src/DataIndex/Filter/Asset/Metadata/AssetFilter.php @@ -18,7 +18,7 @@ use Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\Asset\IsAssetFilterTrait; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\FilterInterface; -use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\AssetQuery; +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; @@ -48,7 +48,7 @@ public function apply(mixed $parameters, QueryInterface $query): QueryInterface return $assetQuery; } - private function applyAssetFilter(ColumnFilter $column, AssetQuery $query): AssetQuery + private function applyAssetFilter(ColumnFilter $column, AssetQueryInterface $query): AssetQueryInterface { if (!is_int($column->getFilterValue())) { throw new InvalidArgumentException('Filter value for asset must be a integer (ID of the asset)'); diff --git a/src/DataIndex/Filter/Asset/Metadata/CheckboxFilter.php b/src/DataIndex/Filter/Asset/Metadata/CheckboxFilter.php index bd8032b02..48704fc95 100644 --- a/src/DataIndex/Filter/Asset/Metadata/CheckboxFilter.php +++ b/src/DataIndex/Filter/Asset/Metadata/CheckboxFilter.php @@ -18,7 +18,7 @@ use Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\Asset\IsAssetFilterTrait; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\FilterInterface; -use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\AssetQuery; +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; @@ -48,7 +48,7 @@ public function apply(mixed $parameters, QueryInterface $query): QueryInterface return $assetQuery; } - private function applyCheckboxFilter(ColumnFilter $column, AssetQuery $query): AssetQuery + private function applyCheckboxFilter(ColumnFilter $column, AssetQueryInterface $query): AssetQueryInterface { if (!is_bool($column->getFilterValue())) { throw new InvalidArgumentException('Filter value for checkbox must be a boolean'); diff --git a/src/DataIndex/Filter/Asset/Metadata/DateFilter.php b/src/DataIndex/Filter/Asset/Metadata/DateFilter.php index 3fb713823..3992d8c16 100644 --- a/src/DataIndex/Filter/Asset/Metadata/DateFilter.php +++ b/src/DataIndex/Filter/Asset/Metadata/DateFilter.php @@ -19,7 +19,7 @@ use Pimcore\Bundle\GenericDataIndexBundle\Model\OpenSearch\Query\DateFilter as GenericDateFilter; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\Asset\IsAssetFilterTrait; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\FilterInterface; -use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\AssetQuery; +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; @@ -49,7 +49,7 @@ public function apply(mixed $parameters, QueryInterface $query): QueryInterface return $assetQuery; } - private function applyDateFilter(ColumnFilter $column, AssetQuery $query): AssetQuery + private function applyDateFilter(ColumnFilter $column, AssetQueryInterface $query): AssetQueryInterface { if (!is_array($column->getFilterValue())) { throw new InvalidArgumentException('Filter value for date must be an array'); diff --git a/src/DataIndex/Filter/Asset/Metadata/DocumentFilter.php b/src/DataIndex/Filter/Asset/Metadata/DocumentFilter.php index b6df25779..b0ed62b73 100644 --- a/src/DataIndex/Filter/Asset/Metadata/DocumentFilter.php +++ b/src/DataIndex/Filter/Asset/Metadata/DocumentFilter.php @@ -18,7 +18,7 @@ use Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\Asset\IsAssetFilterTrait; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\FilterInterface; -use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\AssetQuery; +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; @@ -48,7 +48,7 @@ public function apply(mixed $parameters, QueryInterface $query): QueryInterface return $assetQuery; } - private function applyDocumentFilter(ColumnFilter $column, AssetQuery $query): AssetQuery + private function applyDocumentFilter(ColumnFilter $column, AssetQueryInterface $query): AssetQueryInterface { if (!is_int($column->getFilterValue())) { throw new InvalidArgumentException('Filter value for document must be a integer (ID of the document)'); diff --git a/src/DataIndex/Filter/Asset/Metadata/InputFilter.php b/src/DataIndex/Filter/Asset/Metadata/InputFilter.php index 9c1e3026b..beabecbb1 100644 --- a/src/DataIndex/Filter/Asset/Metadata/InputFilter.php +++ b/src/DataIndex/Filter/Asset/Metadata/InputFilter.php @@ -18,7 +18,7 @@ use Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\Asset\IsAssetFilterTrait; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\FilterInterface; -use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\AssetQuery; +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; @@ -48,7 +48,7 @@ public function apply(mixed $parameters, QueryInterface $query): QueryInterface return $assetQuery; } - private function applyInputFilter(ColumnFilter $column, AssetQuery $query): AssetQuery + private function applyInputFilter(ColumnFilter $column, AssetQueryInterface $query): AssetQueryInterface { if (!is_string($column->getFilterValue())) { throw new InvalidArgumentException('Filter value for input must be a string'); diff --git a/src/DataIndex/Filter/Asset/Metadata/ObjectFilter.php b/src/DataIndex/Filter/Asset/Metadata/ObjectFilter.php index 91d11c313..aad77405d 100644 --- a/src/DataIndex/Filter/Asset/Metadata/ObjectFilter.php +++ b/src/DataIndex/Filter/Asset/Metadata/ObjectFilter.php @@ -18,7 +18,7 @@ use Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\Asset\IsAssetFilterTrait; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\FilterInterface; -use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\AssetQuery; +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; @@ -48,7 +48,7 @@ public function apply(mixed $parameters, QueryInterface $query): QueryInterface return $assetQuery; } - private function applyAssetFilter(ColumnFilter $column, AssetQuery $query): AssetQuery + private function applyAssetFilter(ColumnFilter $column, AssetQueryInterface $query): AssetQueryInterface { if (!is_int($column->getFilterValue())) { throw new InvalidArgumentException('Filter value for object must be a integer (ID of the object)'); diff --git a/src/DataIndex/Filter/Asset/Metadata/SelectFilter.php b/src/DataIndex/Filter/Asset/Metadata/SelectFilter.php index 407c41b32..e08c09807 100644 --- a/src/DataIndex/Filter/Asset/Metadata/SelectFilter.php +++ b/src/DataIndex/Filter/Asset/Metadata/SelectFilter.php @@ -18,7 +18,7 @@ use Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\Asset\IsAssetFilterTrait; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\FilterInterface; -use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\AssetQuery; +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; @@ -48,7 +48,7 @@ public function apply(mixed $parameters, QueryInterface $query): QueryInterface return $assetQuery; } - private function applySelectFilter(ColumnFilter $column, AssetQuery $query): AssetQuery + private function applySelectFilter(ColumnFilter $column, AssetQueryInterface $query): AssetQueryInterface { if (!is_string($column->getFilterValue())) { throw new InvalidArgumentException('Filter value for select must be a string'); diff --git a/src/DataIndex/Filter/Asset/Metadata/TextAreaFilter.php b/src/DataIndex/Filter/Asset/Metadata/TextAreaFilter.php index 3a043d91a..539863406 100644 --- a/src/DataIndex/Filter/Asset/Metadata/TextAreaFilter.php +++ b/src/DataIndex/Filter/Asset/Metadata/TextAreaFilter.php @@ -18,7 +18,7 @@ use Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\Asset\IsAssetFilterTrait; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\FilterInterface; -use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\AssetQuery; +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; @@ -48,7 +48,7 @@ public function apply(mixed $parameters, QueryInterface $query): QueryInterface return $assetQuery; } - private function applyTextAreaFilter(ColumnFilter $column, AssetQuery $query): AssetQuery + private function applyTextAreaFilter(ColumnFilter $column, AssetQueryInterface $query): AssetQueryInterface { if (!is_string($column->getFilterValue())) { throw new InvalidArgumentException('Filter value for textarea must be a string'); diff --git a/src/DataIndex/Filter/Asset/SortFilter.php b/src/DataIndex/Filter/Asset/SortFilter.php index 59b43a1db..8e7c5bbd2 100644 --- a/src/DataIndex/Filter/Asset/SortFilter.php +++ b/src/DataIndex/Filter/Asset/SortFilter.php @@ -18,7 +18,7 @@ use Pimcore\Bundle\GenericDataIndexBundle\Enum\Search\SortDirection; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\FilterInterface; -use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\AssetQuery; +use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\AssetQueryInterface; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\QueryInterface; use Pimcore\Bundle\StudioBackendBundle\MappedParameter\Filter\SortFilterParameterInterface; @@ -29,7 +29,7 @@ final class SortFilter implements FilterInterface { public function apply(mixed $parameters, QueryInterface $query): QueryInterface { - if (!$query instanceof AssetQuery) { + if (!$query instanceof AssetQueryInterface) { return $query; } diff --git a/src/DataIndex/Filter/Asset/System/DatetimeFilter.php b/src/DataIndex/Filter/Asset/System/DatetimeFilter.php index 60096c71f..52e703993 100644 --- a/src/DataIndex/Filter/Asset/System/DatetimeFilter.php +++ b/src/DataIndex/Filter/Asset/System/DatetimeFilter.php @@ -18,7 +18,7 @@ use Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\Asset\IsAssetFilterTrait; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\FilterInterface; -use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\AssetQuery; +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; @@ -48,7 +48,7 @@ public function apply(mixed $parameters, QueryInterface $query): QueryInterface return $assetQuery; } - private function applyDatetimeFilter(ColumnFilter $column, AssetQuery $query): AssetQuery + private function applyDatetimeFilter(ColumnFilter $column, AssetQueryInterface $query): AssetQueryInterface { if (!is_array($column->getFilterValue())) { throw new InvalidArgumentException('Filter value for this filter must be an array'); @@ -57,7 +57,7 @@ private function applyDatetimeFilter(ColumnFilter $column, AssetQuery $query): A $filterValue = $column->getFilterValue(); if (isset($filterValue['on'])) { - $query->filterDatetime($column->getKey(), null, $filterValue['on']); + $query->filterDatetime($column->getKey(), null, null, $filterValue['on']); } if (isset($filterValue['to'])) { diff --git a/src/DataIndex/Filter/Asset/System/StringFilter.php b/src/DataIndex/Filter/Asset/System/StringFilter.php index 3eea4c48a..7d21e6e5e 100644 --- a/src/DataIndex/Filter/Asset/System/StringFilter.php +++ b/src/DataIndex/Filter/Asset/System/StringFilter.php @@ -18,7 +18,7 @@ use Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\Asset\IsAssetFilterTrait; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\FilterInterface; -use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\AssetQuery; +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; @@ -48,7 +48,7 @@ public function apply(mixed $parameters, QueryInterface $query): QueryInterface return $assetQuery; } - private function applyStringFilter(ColumnFilter $column, AssetQuery $query): AssetQuery + private function applyStringFilter(ColumnFilter $column, AssetQueryInterface $query): AssetQueryInterface { if (!is_string($column->getFilterValue())) { throw new InvalidArgumentException('Filter value for this filter must be a string'); diff --git a/src/DataIndex/Filter/DataObject/ClassNameFilter.php b/src/DataIndex/Filter/DataObject/ClassNameFilter.php index bd448855b..e7a09e194 100644 --- a/src/DataIndex/Filter/DataObject/ClassNameFilter.php +++ b/src/DataIndex/Filter/DataObject/ClassNameFilter.php @@ -18,7 +18,7 @@ use Exception; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Filter\FilterInterface; -use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\DataObjectQuery; +use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\DataObjectQueryInterface; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\QueryInterface; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Request\ClassNameParametersInterface; @@ -34,7 +34,7 @@ public function apply(mixed $parameters, QueryInterface $query): QueryInterface { if ( !$parameters instanceof ClassNameParametersInterface || - !$query instanceof DataObjectQuery || + !$query instanceof DataObjectQueryInterface || !$parameters->getClassName() ) { return $query; diff --git a/src/DataIndex/Query/AssetQuery.php b/src/DataIndex/Query/AssetQuery.php index df97b3d65..ac32baddb 100644 --- a/src/DataIndex/Query/AssetQuery.php +++ b/src/DataIndex/Query/AssetQuery.php @@ -31,7 +31,7 @@ use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Sort\OrderByField; use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Modifier\Sort\Tree\OrderByFullPath; -final class AssetQuery implements QueryInterface +final class AssetQuery implements AssetQueryInterface { public const ASSET_QUERY_ID = 'asset_query'; diff --git a/src/DataIndex/Query/AssetQueryInterface.php b/src/DataIndex/Query/AssetQueryInterface.php new file mode 100644 index 000000000..ecf95bf59 --- /dev/null +++ b/src/DataIndex/Query/AssetQueryInterface.php @@ -0,0 +1,44 @@ +assertNull( + $myTestClass->validateParameterType(new DateTime()) + ); + } + + public function testValidateParameterType(): void + { + $myTestClass = new MyTestClass(); + $columnFiltersParameterInterfaceMock = $this->makeEmpty(ColumnFiltersParameterInterface::class); + $this->assertSame( + $columnFiltersParameterInterfaceMock, + $myTestClass->validateParameterType($columnFiltersParameterInterfaceMock) + ); + } + + public function testValidateQueryTypeNullIfWrongInterface(): void + { + $myTestClass = new MyTestClass(); + + $this->assertNull( + $myTestClass->validateQueryType(new DateTime()) + ); + } + + public function testValidateQueryType(): void + { + $myTestClass = new MyTestClass(); + $columnFiltersParameterInterfaceMock = $this->makeEmpty(AssetQueryInterface::class); + $this->assertSame( + $columnFiltersParameterInterfaceMock, + $myTestClass->validateQueryType($columnFiltersParameterInterfaceMock) + ); + } +} + +final class MyTestClass +{ + use IsAssetFilterTrait; +} diff --git a/tests/Unit/DataIndex/Filter/Asset/Metadata/AssetFilterTest.php b/tests/Unit/DataIndex/Filter/Asset/Metadata/AssetFilterTest.php new file mode 100644 index 000000000..2c71be9bc --- /dev/null +++ b/tests/Unit/DataIndex/Filter/Asset/Metadata/AssetFilterTest.php @@ -0,0 +1,65 @@ +makeEmpty(AssetQueryInterface::class, [ + 'filterMetadata' => Expected::never(), + ]); + + $columnFilterMock = $this->getColumnFilterMock('key', 'type', 'not_at'); + + $stringFilter = new AssetFilter(); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Filter value for asset must be a integer (ID of the asset)'); + $stringFilter->apply($columnFilterMock, $queryMock); + } + + public function testApplyAssetFilter(): void + { + $columnFilterMock = $this->getColumnFilterMock('key', 'type', 1); + + $queryMock = $this->makeEmpty(AssetQueryInterface::class, [ + 'filterMetadata' => Expected::once(function ($key, $type, $value) { + $this->assertSame('key', $key); + $this->assertSame(FilterType::ASSET->value, $type); + $this->assertSame(1, $value); + + return $this->makeEmpty(AssetQueryInterface::class); + }), + ]); + + $textAreaFilter = new AssetFilter(); + $textAreaFilter->apply($columnFilterMock, $queryMock); + } +} diff --git a/tests/Unit/DataIndex/Filter/Asset/Metadata/CheckboxFilterTest.php b/tests/Unit/DataIndex/Filter/Asset/Metadata/CheckboxFilterTest.php new file mode 100644 index 000000000..d51aaca59 --- /dev/null +++ b/tests/Unit/DataIndex/Filter/Asset/Metadata/CheckboxFilterTest.php @@ -0,0 +1,65 @@ +makeEmpty(AssetQueryInterface::class, [ + 'filterMetadata' => Expected::never(), + ]); + + $columnFilterMock = $this->getColumnFilterMock('key', 'type', 'not_bool'); + + $stringFilter = new CheckboxFilter(); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Filter value for checkbox must be a boolean'); + $stringFilter->apply($columnFilterMock, $queryMock); + } + + public function testApplyCheckboxFilter(): void + { + $columnFilterMock = $this->getColumnFilterMock('key', 'type', true); + + $queryMock = $this->makeEmpty(AssetQueryInterface::class, [ + 'filterMetadata' => Expected::once(function ($key, $type, $value) { + $this->assertSame('key', $key); + $this->assertSame(FilterType::CHECKBOX->value, $type); + $this->assertSame(true, $value); + + return $this->makeEmpty(AssetQueryInterface::class); + }), + ]); + + $textAreaFilter = new CheckboxFilter(); + $textAreaFilter->apply($columnFilterMock, $queryMock); + } +} diff --git a/tests/Unit/DataIndex/Filter/Asset/Metadata/ColumnFilterMockTrait.php b/tests/Unit/DataIndex/Filter/Asset/Metadata/ColumnFilterMockTrait.php new file mode 100644 index 000000000..b00b1383e --- /dev/null +++ b/tests/Unit/DataIndex/Filter/Asset/Metadata/ColumnFilterMockTrait.php @@ -0,0 +1,37 @@ +makeEmpty(ColumnFiltersParameterInterface::class, [ + 'getColumnFilterByType' => function () use ($key, $type, $value) { + return [ + new ColumnFilter($key, $type, $value), + ]; + }, + ]); + } +} diff --git a/tests/Unit/DataIndex/Filter/Asset/Metadata/DateFilterTest.php b/tests/Unit/DataIndex/Filter/Asset/Metadata/DateFilterTest.php new file mode 100644 index 000000000..f00a24c64 --- /dev/null +++ b/tests/Unit/DataIndex/Filter/Asset/Metadata/DateFilterTest.php @@ -0,0 +1,105 @@ +makeEmpty(AssetQueryInterface::class, [ + 'filterMetadata' => Expected::never(), + ]); + + $columnFilterMock = $this->getColumnFilterMock('key', 'type', 'not_array'); + + $stringFilter = new DateFilter(); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Filter value for date must be an array'); + $stringFilter->apply($columnFilterMock, $queryMock); + } + + public function testApplyDateFilterForOn(): void + { + $time = 1726753660; + $columnFilterMock = $this->getColumnFilterMock('key', 'type', ['on' => $time]); + + $queryMock = $this->makeEmpty(AssetQueryInterface::class, [ + 'filterMetadata' => Expected::once(function ($key, $type, $value) use ($time) { + $this->assertSame('key', $key); + $this->assertSame(FilterType::DATE->value, $type); + $this->assertSame([GenericDateFilter::PARAM_ON => $time], $value); + + return $this->makeEmpty(AssetQueryInterface::class); + }), + ]); + + $textAreaFilter = new DateFilter(); + $textAreaFilter->apply($columnFilterMock, $queryMock); + } + + public function testApplyDateFilterForTo(): void + { + $time = 1726753660; + $columnFilterMock = $this->getColumnFilterMock('key', 'type', ['to' => $time]); + + $queryMock = $this->makeEmpty(AssetQueryInterface::class, [ + 'filterMetadata' => Expected::once(function ($key, $type, $value) use ($time) { + $this->assertSame('key', $key); + $this->assertSame(FilterType::DATE->value, $type); + $this->assertSame([GenericDateFilter::PARAM_END => $time], $value); + + return $this->makeEmpty(AssetQueryInterface::class); + }), + ]); + + $textAreaFilter = new DateFilter(); + $textAreaFilter->apply($columnFilterMock, $queryMock); + } + + public function testApplyDateFilterForFrom(): void + { + $time = 1726753660; + $columnFilterMock = $this->getColumnFilterMock('key', 'type', ['from' => $time]); + + $queryMock = $this->makeEmpty(AssetQueryInterface::class, [ + 'filterMetadata' => Expected::once(function ($key, $type, $value) use ($time) { + $this->assertSame('key', $key); + $this->assertSame(FilterType::DATE->value, $type); + $this->assertSame([GenericDateFilter::PARAM_START => $time], $value); + + return $this->makeEmpty(AssetQueryInterface::class); + }), + ]); + + $textAreaFilter = new DateFilter(); + $textAreaFilter->apply($columnFilterMock, $queryMock); + } +} diff --git a/tests/Unit/DataIndex/Filter/Asset/Metadata/DocumentFilterTest.php b/tests/Unit/DataIndex/Filter/Asset/Metadata/DocumentFilterTest.php new file mode 100644 index 000000000..ddb7c5016 --- /dev/null +++ b/tests/Unit/DataIndex/Filter/Asset/Metadata/DocumentFilterTest.php @@ -0,0 +1,65 @@ +makeEmpty(AssetQueryInterface::class, [ + 'filterMetadata' => Expected::never(), + ]); + + $columnFilterMock = $this->getColumnFilterMock('key', 'type', 'not_int'); + + $stringFilter = new DocumentFilter(); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Filter value for document must be a integer (ID of the document)'); + $stringFilter->apply($columnFilterMock, $queryMock); + } + + public function testApplyDocumentFilter(): void + { + $columnFilterMock = $this->getColumnFilterMock('key', 'type', 1); + + $queryMock = $this->makeEmpty(AssetQueryInterface::class, [ + 'filterMetadata' => Expected::once(function ($key, $type, $value) { + $this->assertSame('key', $key); + $this->assertSame(FilterType::DOCUMENT->value, $type); + $this->assertSame(1, $value); + + return $this->makeEmpty(AssetQueryInterface::class); + }), + ]); + + $textAreaFilter = new DocumentFilter(); + $textAreaFilter->apply($columnFilterMock, $queryMock); + } +} diff --git a/tests/Unit/DataIndex/Filter/Asset/Metadata/InputFilterTest.php b/tests/Unit/DataIndex/Filter/Asset/Metadata/InputFilterTest.php new file mode 100644 index 000000000..59c5b3f00 --- /dev/null +++ b/tests/Unit/DataIndex/Filter/Asset/Metadata/InputFilterTest.php @@ -0,0 +1,65 @@ +makeEmpty(AssetQueryInterface::class, [ + 'filterMetadata' => Expected::never(), + ]); + + $columnFilterMock = $this->getColumnFilterMock('key', 'type', 123); + + $stringFilter = new InputFilter(); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Filter value for input must be a string'); + $stringFilter->apply($columnFilterMock, $queryMock); + } + + public function testApplyInputFilter(): void + { + $columnFilterMock = $this->getColumnFilterMock('key', 'type', 'test_value'); + + $queryMock = $this->makeEmpty(AssetQueryInterface::class, [ + 'filterMetadata' => Expected::once(function ($key, $type, $value) { + $this->assertSame('key', $key); + $this->assertSame(FilterType::INPUT->value, $type); + $this->assertSame('test_value', $value); + + return $this->makeEmpty(AssetQueryInterface::class); + }), + ]); + + $textAreaFilter = new InputFilter(); + $textAreaFilter->apply($columnFilterMock, $queryMock); + } +} diff --git a/tests/Unit/DataIndex/Filter/Asset/Metadata/ObjectFilterTest.php b/tests/Unit/DataIndex/Filter/Asset/Metadata/ObjectFilterTest.php new file mode 100644 index 000000000..b6786ad03 --- /dev/null +++ b/tests/Unit/DataIndex/Filter/Asset/Metadata/ObjectFilterTest.php @@ -0,0 +1,65 @@ +makeEmpty(AssetQueryInterface::class, [ + 'filterMetadata' => Expected::never(), + ]); + + $columnFilterMock = $this->getColumnFilterMock('key', 'type', 'not_int'); + + $stringFilter = new ObjectFilter(); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Filter value for object must be a integer (ID of the object)'); + $stringFilter->apply($columnFilterMock, $queryMock); + } + + public function testApplyObjectFilter(): void + { + $columnFilterMock = $this->getColumnFilterMock('key', 'type', 1); + + $queryMock = $this->makeEmpty(AssetQueryInterface::class, [ + 'filterMetadata' => Expected::once(function ($key, $type, $value) { + $this->assertSame('key', $key); + $this->assertSame(FilterType::OBJECT->value, $type); + $this->assertSame(1, $value); + + return $this->makeEmpty(AssetQueryInterface::class); + }), + ]); + + $textAreaFilter = new ObjectFilter(); + $textAreaFilter->apply($columnFilterMock, $queryMock); + } +} diff --git a/tests/Unit/DataIndex/Filter/Asset/Metadata/SelectFilterTest.php b/tests/Unit/DataIndex/Filter/Asset/Metadata/SelectFilterTest.php new file mode 100644 index 000000000..71cfce2d9 --- /dev/null +++ b/tests/Unit/DataIndex/Filter/Asset/Metadata/SelectFilterTest.php @@ -0,0 +1,65 @@ +makeEmpty(AssetQueryInterface::class, [ + 'filterMetadata' => Expected::never(), + ]); + + $columnFilterMock = $this->getColumnFilterMock('key', 'type', 123); + + $stringFilter = new SelectFilter(); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Filter value for select must be a string'); + $stringFilter->apply($columnFilterMock, $queryMock); + } + + public function testApplySelectFilter(): void + { + $columnFilterMock = $this->getColumnFilterMock('key', 'type', 'value'); + + $queryMock = $this->makeEmpty(AssetQueryInterface::class, [ + 'filterMetadata' => Expected::once(function ($key, $type, $value) { + $this->assertSame('key', $key); + $this->assertSame(FilterType::SELECT->value, $type); + $this->assertSame('value', $value); + + return $this->makeEmpty(AssetQueryInterface::class); + }), + ]); + + $textAreaFilter = new SelectFilter(); + $textAreaFilter->apply($columnFilterMock, $queryMock); + } +} diff --git a/tests/Unit/DataIndex/Filter/Asset/Metadata/TextAreaFilterTest.php b/tests/Unit/DataIndex/Filter/Asset/Metadata/TextAreaFilterTest.php new file mode 100644 index 000000000..461b5d856 --- /dev/null +++ b/tests/Unit/DataIndex/Filter/Asset/Metadata/TextAreaFilterTest.php @@ -0,0 +1,65 @@ +makeEmpty(AssetQueryInterface::class, [ + 'filterMetadata' => Expected::never(), + ]); + + $columnFilterMock = $this->getColumnFilterMock('key', 'type', 123); + + $stringFilter = new TextAreaFilter(); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Filter value for textarea must be a string'); + $stringFilter->apply($columnFilterMock, $queryMock); + } + + public function testApplyTextAreaFilter(): void + { + $columnFilterMock = $this->getColumnFilterMock('key', 'type', 'value'); + + $queryMock = $this->makeEmpty(AssetQueryInterface::class, [ + 'filterMetadata' => Expected::once(function ($key, $type, $value) { + $this->assertSame('key', $key); + $this->assertSame(FilterType::TEXTAREA->value, $type); + $this->assertSame('value', $value); + + return $this->makeEmpty(AssetQueryInterface::class); + }), + ]); + + $textAreaFilter = new TextAreaFilter(); + $textAreaFilter->apply($columnFilterMock, $queryMock); + } +} diff --git a/tests/Unit/DataIndex/Filter/Asset/SortFilterTest.php b/tests/Unit/DataIndex/Filter/Asset/SortFilterTest.php new file mode 100644 index 000000000..91aabeea3 --- /dev/null +++ b/tests/Unit/DataIndex/Filter/Asset/SortFilterTest.php @@ -0,0 +1,83 @@ +makeEmpty(AssetQueryInterface::class, [ + 'orderByField' => Expected::never(), + ]); + + $sortFilter->apply('test', $query); + } + + public function testSortDirectionWithDesc(): void + { + $sortFilter = new SortFilter(); + $parameter = $this->makeEmpty(SortFilterParameterInterface::class, [ + 'getSortFilter' => function () { + return new SortFilterParameter('key', 'desc'); + }, + ]); + + $query = $this->makeEmpty(AssetQueryInterface::class, [ + 'orderByField' => function ($key, $direction) { + $this->assertSame('key', $key); + $this->assertSame(SortDirection::DESC, $direction); + + return $this->makeEmpty(AssetQueryInterface::class); + }, + ]); + + $sortFilter->apply($parameter, $query); + } + + public function testSortDirectionWithDefaultValue(): void + { + $sortFilter = new SortFilter(); + $parameter = $this->makeEmpty(SortFilterParameterInterface::class, [ + 'getSortFilter' => function () { + return new SortFilterParameter(); + }, + ]); + + $query = $this->makeEmpty(AssetQueryInterface::class, [ + 'orderByField' => function ($key, $direction) { + $this->assertSame('id', $key); + $this->assertSame(SortDirection::ASC, $direction); + + return $this->makeEmpty(AssetQueryInterface::class); + }, + ]); + + $sortFilter->apply($parameter, $query); + } +} diff --git a/tests/Unit/DataIndex/Filter/Asset/System/DatetimeFilterTest.php b/tests/Unit/DataIndex/Filter/Asset/System/DatetimeFilterTest.php new file mode 100644 index 000000000..e7cfa6174 --- /dev/null +++ b/tests/Unit/DataIndex/Filter/Asset/System/DatetimeFilterTest.php @@ -0,0 +1,111 @@ +makeEmpty(ColumnFiltersParameterInterface::class, [ + 'getColumnFilterByType' => function () { + return [ + new ColumnFilter('key', 'type', 123), + ]; + }, + ]); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Filter value for this filter must be an array'); + $datetimeFilter->apply($columnParameterMock, $this->makeEmpty(AssetQueryInterface::class)); + } + + public function testDateTimeFilterWithOn(): void + { + $time = 1726753660; + $datetimeFilter = new DatetimeFilter(); + $queryMock = $this->makeEmpty(AssetQueryInterface::class, [ + 'filterDatetime' => Expected::once(function ($key, $start, $end, $on) use ($time) { + $this->assertSame('key', $key); + $this->assertNull($start); + $this->assertNull($end); + $this->assertSame($time, $on); + + return $this->makeEmpty(AssetQueryInterface::class); + }), + ]); + + $columnParameterMock = $this->getColumnFilterMock('key', 'type', ['on' => $time]); + + $datetimeFilter->apply($columnParameterMock, $queryMock); + + } + + public function testDateTimeFilterWithFrom(): void + { + $time = 1726753660; + $datetimeFilter = new DatetimeFilter(); + $queryMock = $this->makeEmpty(AssetQueryInterface::class, [ + 'filterDatetime' => Expected::once(function ($key, $start, $end, $on) use ($time) { + $this->assertSame('key', $key); + $this->assertSame($time, $start); + $this->assertNull($end); + $this->assertNull($on); + + return $this->makeEmpty(AssetQueryInterface::class); + }), + ]); + + $columnParameterMock = $this->getColumnFilterMock('key', 'type', ['from' => $time]); + + $datetimeFilter->apply($columnParameterMock, $queryMock); + } + + public function testDateTimeFilterWithTo(): void + { + $time = 1726753660; + $datetimeFilter = new DatetimeFilter(); + $queryMock = $this->makeEmpty(AssetQueryInterface::class, [ + 'filterDatetime' => Expected::once(function ($key, $start, $end, $on) use ($time) { + $this->assertSame('key', $key); + $this->assertNull($start); + $this->assertSame($time, $end); + $this->assertNull($on); + + return $this->makeEmpty(AssetQueryInterface::class); + }), + ]); + + $columnParameterMock = $this->getColumnFilterMock('key', 'type', ['to' => $time]); + + $datetimeFilter->apply($columnParameterMock, $queryMock); + } +} diff --git a/tests/Unit/DataIndex/Filter/Asset/System/StringFilterTest.php b/tests/Unit/DataIndex/Filter/Asset/System/StringFilterTest.php new file mode 100644 index 000000000..8785cb744 --- /dev/null +++ b/tests/Unit/DataIndex/Filter/Asset/System/StringFilterTest.php @@ -0,0 +1,75 @@ +makeEmpty(AssetQueryInterface::class, [ + 'wildcardSearch' => Expected::never(), + ]); + + $columnFilterMock = $this->makeEmpty(ColumnFiltersParameterInterface::class, [ + 'getColumnFilterByType' => function () { + return [ + new ColumnFilter('key', 'type', 123), + ]; + }, + ]); + + $stringFilter = new StringFilter(); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Filter value for this filter must be a string'); + $stringFilter->apply($columnFilterMock, $queryMock); + } + + public function testApplyStringFilter(): void + { + $queryMock = $this->makeEmpty(AssetQueryInterface::class, [ + 'wildcardSearch' => Expected::once(function ($key, $value) { + $this->assertSame('key', $key); + $this->assertSame('value', $value); + + return $this->makeEmpty(AssetQueryInterface::class); + }), + ]); + + $columnFilterMock = $this->makeEmpty(ColumnFiltersParameterInterface::class, [ + 'getColumnFilterByType' => function () { + return [ + new ColumnFilter('key', 'type', 'value'), + ]; + }, + ]); + + $stringFilter = new StringFilter(); + $stringFilter->apply($columnFilterMock, $queryMock); + } +}