diff --git a/config/classification_store.yaml b/config/classification_store.yaml index 58583ec90..f71bed000 100644 --- a/config/classification_store.yaml +++ b/config/classification_store.yaml @@ -25,6 +25,9 @@ services: Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Service\KeyGroupRelationServiceInterface: class: Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Service\KeyGroupRelationService + Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Service\SearchHelperServiceInterface: + class: Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Service\SearchHelperService + # # Repositories diff --git a/src/ClassificationStore/Controller/GetCollectionsController.php b/src/ClassificationStore/Controller/GetCollectionsController.php index 55fe576c6..c79f66fcd 100644 --- a/src/ClassificationStore/Controller/GetCollectionsController.php +++ b/src/ClassificationStore/Controller/GetCollectionsController.php @@ -93,6 +93,12 @@ public function __construct( required: true, example: 'technicalAttributes' )] + #[TextFieldParameter( + name: 'searchTerm', + description: 'Search Term', + required: false, + example: 'search term' + )] #[DefaultResponses([ HttpResponseCodes::FORBIDDEN, HttpResponseCodes::UNAUTHORIZED, diff --git a/src/ClassificationStore/Controller/GetGroupsController.php b/src/ClassificationStore/Controller/GetGroupsController.php index 9b6b0c2ca..a7e6583ff 100644 --- a/src/ClassificationStore/Controller/GetGroupsController.php +++ b/src/ClassificationStore/Controller/GetGroupsController.php @@ -85,6 +85,12 @@ public function __construct( namePrefix: 'object', required: false )] + #[TextFieldParameter( + name: 'searchTerm', + description: 'Search Term', + required: false, + example: 'search term' + )] #[PageParameter] #[PageSizeParameter] #[TextFieldParameter( diff --git a/src/ClassificationStore/Controller/GetKeyGroupRelationsController.php b/src/ClassificationStore/Controller/GetKeyGroupRelationsController.php index 7947d3b1d..3f22e181f 100644 --- a/src/ClassificationStore/Controller/GetKeyGroupRelationsController.php +++ b/src/ClassificationStore/Controller/GetKeyGroupRelationsController.php @@ -85,6 +85,12 @@ public function __construct( namePrefix: 'object', required: false )] + #[TextFieldParameter( + name: 'searchTerm', + description: 'Search Term', + required: false, + example: 'search term' + )] #[PageParameter] #[PageSizeParameter] #[TextFieldParameter( diff --git a/src/ClassificationStore/MappedParameter/ListClassificationStoreParameter.php b/src/ClassificationStore/MappedParameter/ListClassificationStoreParameter.php index 7889f9eb0..5e3f73846 100644 --- a/src/ClassificationStore/MappedParameter/ListClassificationStoreParameter.php +++ b/src/ClassificationStore/MappedParameter/ListClassificationStoreParameter.php @@ -34,6 +34,7 @@ public function __construct( #[NotBlank(message: 'The page size name must not be empty.')] private int $pageSize, private ?int $objectId = null, + private ?string $searchTerm = null, ) { } @@ -61,4 +62,9 @@ public function getPageSize(): int { return $this->pageSize; } + + public function getSearchTerm(): ?string + { + return $this->searchTerm; + } } diff --git a/src/ClassificationStore/Repository/CollectionConfigRepository.php b/src/ClassificationStore/Repository/CollectionConfigRepository.php index 185081999..3f8a74476 100644 --- a/src/ClassificationStore/Repository/CollectionConfigRepository.php +++ b/src/ClassificationStore/Repository/CollectionConfigRepository.php @@ -16,6 +16,7 @@ namespace Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Repository; +use Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Service\SearchHelperServiceInterface; use Pimcore\Bundle\StudioBackendBundle\MappedParameter\CollectionParametersInterface; use Pimcore\Model\DataObject\Classificationstore\CollectionConfig\Listing; use function count; @@ -25,13 +26,19 @@ */ final class CollectionConfigRepository implements CollectionConfigRepositoryInterface { + public function __construct( + private SearchHelperServiceInterface $searchHelperService + ) { + } + /** * {@inheritDoc} */ public function getPaginatedCollectionsByStore( int $storeId, CollectionParametersInterface $collectionParameters, - ?array $collectionIds = null + ?array $collectionIds = null, + ?string $searchTerm = null ): array { $list = new Listing(); @@ -45,6 +52,10 @@ public function getPaginatedCollectionsByStore( $this->applyCollectionIdsFilter($list, $collectionIds); } + if ($searchTerm !== null) { + $this->searchHelperService->applySearchTermFilter($list, $searchTerm); + } + return $list->load(); } diff --git a/src/ClassificationStore/Repository/CollectionConfigRepositoryInterface.php b/src/ClassificationStore/Repository/CollectionConfigRepositoryInterface.php index ad1d80800..fab542e15 100644 --- a/src/ClassificationStore/Repository/CollectionConfigRepositoryInterface.php +++ b/src/ClassificationStore/Repository/CollectionConfigRepositoryInterface.php @@ -32,7 +32,8 @@ interface CollectionConfigRepositoryInterface public function getPaginatedCollectionsByStore( int $storeId, CollectionParametersInterface $collectionParameters, - ?array $collectionIds = null + ?array $collectionIds = null, + ?string $searchTerm = null ): array; public function getCountByStoreId(int $storeId): int; diff --git a/src/ClassificationStore/Repository/GroupConfigRepository.php b/src/ClassificationStore/Repository/GroupConfigRepository.php index 9f68e9a08..997621343 100644 --- a/src/ClassificationStore/Repository/GroupConfigRepository.php +++ b/src/ClassificationStore/Repository/GroupConfigRepository.php @@ -16,6 +16,7 @@ namespace Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Repository; +use Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Service\SearchHelperServiceInterface; use Pimcore\Bundle\StudioBackendBundle\MappedParameter\CollectionParametersInterface; use Pimcore\Model\DataObject\Classificationstore\GroupConfig\Listing; use function count; @@ -25,13 +26,19 @@ */ final class GroupConfigRepository implements GroupConfigRepositoryInterface { + public function __construct( + private SearchHelperServiceInterface $searchHelperService + ) { + } + /** * {@inheritDoc} */ public function getPaginatedGroupsByStore( int $storeId, CollectionParametersInterface $collectionParameters, - ?array $groupIds = null + ?array $groupIds = null, + ?string $searchTerm = null ): array { $listing = new Listing(); @@ -41,6 +48,10 @@ public function getPaginatedGroupsByStore( $listing->setOrderKey('id'); $listing->setCondition('storeId = ?', $storeId); + if ($searchTerm !== null) { + $this->searchHelperService->applySearchTermFilter($listing, $searchTerm); + } + if ($groupIds !== null) { $this->applyGroupIdsFilter($listing, $groupIds); } diff --git a/src/ClassificationStore/Repository/GroupConfigRepositoryInterface.php b/src/ClassificationStore/Repository/GroupConfigRepositoryInterface.php index e0f4f9651..ee3f009b2 100644 --- a/src/ClassificationStore/Repository/GroupConfigRepositoryInterface.php +++ b/src/ClassificationStore/Repository/GroupConfigRepositoryInterface.php @@ -32,7 +32,8 @@ interface GroupConfigRepositoryInterface public function getPaginatedGroupsByStore( int $storeId, CollectionParametersInterface $collectionParameters, - ?array $groupIds = null + ?array $groupIds = null, + ?string $searchTerm = null ): array; public function getAllGroupsByStore( diff --git a/src/ClassificationStore/Repository/KeyGroupRelationRepository.php b/src/ClassificationStore/Repository/KeyGroupRelationRepository.php index dbfb6e789..05fc1330d 100644 --- a/src/ClassificationStore/Repository/KeyGroupRelationRepository.php +++ b/src/ClassificationStore/Repository/KeyGroupRelationRepository.php @@ -16,17 +16,21 @@ namespace Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Repository; +use Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Service\SearchHelperServiceInterface; 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\Listing; use function count; /** * @internal */ -final class KeyGroupRelationRepository implements KeyGroupRelationRepositoryInterface +final readonly class KeyGroupRelationRepository implements KeyGroupRelationRepositoryInterface { public function __construct( - private GroupConfigRepositoryInterface $groupConfigRepository + private GroupConfigRepositoryInterface $groupConfigRepository, + private SearchHelperServiceInterface $searchHelperService ) { } @@ -36,7 +40,8 @@ public function __construct( public function getPaginatedKeyGroupRelationByStore( int $storeId, CollectionParametersInterface $collectionParameters, - ?array $groupIds = null + ?array $groupIds = null, + ?string $searchTerm = null ): array { $groupIds = array_map( @@ -50,7 +55,11 @@ public function getPaginatedKeyGroupRelationByStore( $listing->setOrderKey('sorter'); $this->applyGroupIdsFilter($listing, $groupIds); - return $listing->load(); + if ($searchTerm !== null) { + $this->applySearchTermFilter($listing, $searchTerm); + } + + return $listing->getList(); } public function getCountByStoreId(int $storeId, ?array $groupIds = null): int @@ -66,6 +75,22 @@ public function getCountByStoreId(int $storeId, ?array $groupIds = null): int return $listing->count(); } + private function applySearchTermFilter(Listing $list, string $searchTerm): void + { + $searchTerms = $this->searchHelperService->getTranslatedSearchFilterTerms($searchTerm); + $searchFilterConditions = []; + + foreach ($searchTerms as $term) { + $searchFilterConditions[] = + KeyConfigDao::TABLE_NAME_KEYS.'.name LIKE '.$list->quote('%'.$term.'%') + .' OR '.GroupConfigDao::TABLE_NAME_GROUPS.'.name LIKE '.$list->quote('%'.$term.'%') + .' OR '.KeyConfigDao::TABLE_NAME_KEYS.'.description LIKE '.$list->quote('%'.$term.'%'); + } + $list->setResolveGroupName(true); + + $list->addConditionParam(implode(' OR ', $searchFilterConditions)); + } + private function applyGroupIdsFilter(Listing $list, array $groupIds): void { $placeholders = implode(',', array_fill(0, count($groupIds), '?')); diff --git a/src/ClassificationStore/Repository/KeyGroupRelationRepositoryInterface.php b/src/ClassificationStore/Repository/KeyGroupRelationRepositoryInterface.php index 75816931d..82aa0fea3 100644 --- a/src/ClassificationStore/Repository/KeyGroupRelationRepositoryInterface.php +++ b/src/ClassificationStore/Repository/KeyGroupRelationRepositoryInterface.php @@ -30,7 +30,8 @@ interface KeyGroupRelationRepositoryInterface public function getPaginatedKeyGroupRelationByStore( int $storeId, CollectionParametersInterface $collectionParameters, - ?array $groupIds = null + ?array $groupIds = null, + ?string $searchTerm = null ): array; public function getCountByStoreId(int $storeId, ?array $groupIds = null): int; diff --git a/src/ClassificationStore/Service/CollectionService.php b/src/ClassificationStore/Service/CollectionService.php index 8b33feb77..2741a925e 100644 --- a/src/ClassificationStore/Service/CollectionService.php +++ b/src/ClassificationStore/Service/CollectionService.php @@ -56,7 +56,8 @@ public function getCollections(ListClassificationStoreParameter $parameter): Col $collections = $this->collectionConfigRepository->getPaginatedCollectionsByStore( $parameter->getStoreId(), $parameter, - $allowedCollectionIds + $allowedCollectionIds, + $parameter->getSearchTerm() ); $hydratedCollections = []; diff --git a/src/ClassificationStore/Service/GroupService.php b/src/ClassificationStore/Service/GroupService.php index d34084aad..ec94a0b10 100644 --- a/src/ClassificationStore/Service/GroupService.php +++ b/src/ClassificationStore/Service/GroupService.php @@ -54,7 +54,8 @@ public function getGroups(ListClassificationStoreParameter $parameter): Collecti $groups = $this->groupConfigRepository->getPaginatedGroupsByStore( $parameter->getStoreId(), $parameter, - $allowedGroupIds + $allowedGroupIds, + $parameter->getSearchTerm() ); $hydratedGroups = []; diff --git a/src/ClassificationStore/Service/KeyGroupRelationService.php b/src/ClassificationStore/Service/KeyGroupRelationService.php index c9bec23d9..8504adf56 100644 --- a/src/ClassificationStore/Service/KeyGroupRelationService.php +++ b/src/ClassificationStore/Service/KeyGroupRelationService.php @@ -54,7 +54,8 @@ public function getKeyGroupRelations(ListClassificationStoreParameter $parameter $keyGroupRelations = $this->keyGroupRelationRepository->getPaginatedKeyGroupRelationByStore( $parameter->getStoreId(), $parameter, - $allowedGroupIds + $allowedGroupIds, + $parameter->getSearchTerm() ); foreach ($keyGroupRelations as $keyGroupRelation) { diff --git a/src/ClassificationStore/Service/SearchHelperService.php b/src/ClassificationStore/Service/SearchHelperService.php new file mode 100644 index 000000000..8cfe92f02 --- /dev/null +++ b/src/ClassificationStore/Service/SearchHelperService.php @@ -0,0 +1,70 @@ +getTranslatedSearchFilterTerms($searchTerm); + + $conditions = []; + $preparedSearchTerms = []; + foreach ($searchTerms as $term) { + $conditions[] = 'name LIKE ? OR description LIKE ?'; + $preparedSearchTerms[] = '%' . $term . '%'; + $preparedSearchTerms[] = '%' . $term . '%'; + } + + $list->addConditionParam('(' . implode(' OR ', $conditions) . ')', $preparedSearchTerms); + } + + public function getTranslatedSearchFilterTerms(string $searchTerm): array + { + try { + $user = $this->securityService->getCurrentUser(); + + $translatedSearchKeys = $this->translationRepository->getTranslationKeysWithTextFilter( + $searchTerm, + $user->getLanguage(), + Translation::DOMAIN_ADMIN + ); + + $searchTerms = array_merge([$searchTerm], $translatedSearchKeys); + } catch (UserNotFoundException) { + $searchTerms = [$searchTerm]; + } + + return $searchTerms; + } +} diff --git a/src/ClassificationStore/Service/SearchHelperServiceInterface.php b/src/ClassificationStore/Service/SearchHelperServiceInterface.php new file mode 100644 index 000000000..0259f8227 --- /dev/null +++ b/src/ClassificationStore/Service/SearchHelperServiceInterface.php @@ -0,0 +1,30 @@ +save(); } - private function getTranslationList(): Listing + private function getTranslationList(string $domain = TranslatorServiceInterface::DOMAIN): Listing { $list = new Translation\Listing(); - $list->setDomain(TranslatorServiceInterface::DOMAIN); + $list->setDomain($domain); $list->setOrder('asc'); - $list->setOrderKey('translations_' . TranslatorServiceInterface::DOMAIN . '.key', false); + $list->setOrderKey('translations_' . $domain . '.key', false); return $list; } @@ -133,6 +133,23 @@ private function setNewValues(Translation $translation, array $languages): void } } + public function getTranslationKeysWithTextFilter( + string $filterTerm, + string $language, + string $domain = TranslatorServiceInterface::DOMAIN, + ): array { + $list = $this->getTranslationList($domain); + $list->addConditionParam('language=? AND text LIKE ?', [$language, '%'.$filterTerm.'%']); + + $keys = []; + + foreach ($list->getTranslations() as $translation) { + $keys[] = $translation->getKey(); + } + + return $keys; + } + private function getTranslationByKey(string $key): ?Translation { $list = $this->getTranslationList(); diff --git a/src/Translation/Repository/TranslationRepositoryInterface.php b/src/Translation/Repository/TranslationRepositoryInterface.php index 2c9b40d98..f9b7f1f5b 100644 --- a/src/Translation/Repository/TranslationRepositoryInterface.php +++ b/src/Translation/Repository/TranslationRepositoryInterface.php @@ -19,6 +19,7 @@ use Pimcore\Bundle\StudioBackendBundle\Exception\Api\ElementExistsException; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\InvalidLocaleException; use Pimcore\Bundle\StudioBackendBundle\Translation\Schema\TranslationData; +use Pimcore\Bundle\StudioBackendBundle\Translation\Service\TranslatorServiceInterface; use Pimcore\Model\Translation; /** @@ -46,4 +47,13 @@ public function createTranslations(array $translationData): void; public function updateTranslations(array $translationData, string $locale): void; public function deleteTranslation(string $key): void; + + /** + * @return array + */ + public function getTranslationKeysWithTextFilter( + string $filterTerm, + string $language, + string $domain = TranslatorServiceInterface::DOMAIN + ): array; }