diff --git a/config/classification_store.yaml b/config/classification_store.yaml index af4047116..00f9be14a 100644 --- a/config/classification_store.yaml +++ b/config/classification_store.yaml @@ -51,9 +51,6 @@ services: Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Repository\KeyGroupRelationRepositoryInterface: class: Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Repository\KeyGroupRelationRepository - Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Repository\StoreRepositoryInterface: - class: Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Repository\StoreRepository - # # Hydrators @@ -73,3 +70,77 @@ services: Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Hydrator\StoreConfigHydratorInterface: class: Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Hydrator\StoreConfigHydrator + + + # + # Configuration Services + # + + Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Service\Configuration\StoreServiceInterface: + class: Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Service\Configuration\StoreService + + Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Service\Configuration\GroupServiceInterface: + class: Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Service\Configuration\GroupService + + Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Service\Configuration\KeyServiceInterface: + class: Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Service\Configuration\KeyService + + Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Service\Configuration\CollectionServiceInterface: + class: Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Service\Configuration\CollectionService + + + # + # Configuration Repositories + # + + Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Repository\Configuration\StoreRepositoryInterface: + class: Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Repository\Configuration\StoreRepository + + Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Repository\Configuration\GroupRepositoryInterface: + class: Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Repository\Configuration\GroupRepository + + Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Repository\Configuration\KeyRepositoryInterface: + class: Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Repository\Configuration\KeyRepository + + Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Repository\Configuration\CollectionRepositoryInterface: + class: Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Repository\Configuration\CollectionRepository + + Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Repository\Configuration\CollRelationRepositoryInterface: + class: Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Repository\Configuration\CollRelationRepository + + Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Repository\Configuration\KeyGroupRelationRepositoryInterface: + class: Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Repository\Configuration\KeyGroupRelationRepository + + + # + # Configuration Hydrators + # + + Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Hydrator\Configuration\StoreHydratorInterface: + class: Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Hydrator\Configuration\StoreHydrator + + Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Hydrator\Configuration\GroupHydratorInterface: + class: Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Hydrator\Configuration\GroupHydrator + + Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Hydrator\Configuration\KeyHydratorInterface: + class: Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Hydrator\Configuration\KeyHydrator + + Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Hydrator\Configuration\CollectionHydratorInterface: + class: Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Hydrator\Configuration\CollectionHydrator + + Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Hydrator\Configuration\CollectionRelationHydratorInterface: + class: Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Hydrator\Configuration\CollectionRelationHydrator + + Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Hydrator\Configuration\KeyGroupRelationHydratorInterface: + class: Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Hydrator\Configuration\KeyGroupRelationHydrator + + + # + # Configuration Relation Services + # + + Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Service\Configuration\CollectionRelationServiceInterface: + class: Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Service\Configuration\CollectionRelationService + + Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Service\Configuration\KeyGroupRelationServiceInterface: + class: Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Service\Configuration\KeyGroupRelationService diff --git a/doc/05_Additional_Custom_Attributes.md b/doc/05_Additional_Custom_Attributes.md index cf4ce3892..db58a436d 100644 --- a/doc/05_Additional_Custom_Attributes.md +++ b/doc/05_Additional_Custom_Attributes.md @@ -91,6 +91,14 @@ final class AssetEvent extends AbstractPreResponseEvent - `pre_response.class_field_by_type` - `pre_response.classification_store.collection` - `pre_response.classification_store.config_collection` +- `pre_response.classification_store.configuration.collection` +- `pre_response.classification_store.configuration.collection_relation` +- `pre_response.classification_store.configuration.get_page` +- `pre_response.classification_store.configuration.group` +- `pre_response.classification_store.configuration.key` +- `pre_response.classification_store.configuration.key_group_relation` +- `pre_response.classification_store.configuration.store` +- `pre_response.classification_store.configuration.store_tree_node` - `pre_response.classification_store.group` - `pre_response.classification_store.group_layout` - `pre_response.classification_store.key_group_relation` diff --git a/src/ClassificationStore/Controller/Configuration/Collection/CollectionController.php b/src/ClassificationStore/Controller/Configuration/Collection/CollectionController.php new file mode 100644 index 000000000..a14eb6009 --- /dev/null +++ b/src/ClassificationStore/Controller/Configuration/Collection/CollectionController.php @@ -0,0 +1,90 @@ +value)] + #[Post( + path: self::PREFIX . self::ROUTE, + operationId: 'classification_store_configuration_collection_collection', + description: 'classification_store_configuration_collection_collection_description', + summary: 'classification_store_configuration_collection_collection_summary', + tags: [Tags::ClassificationStore->value] + )] + #[IntParameter(name: 'storeId', example: 1, description: 'ID of the store to list collections for')] + #[CollectionRequestBody( + columnFiltersExample: '[{"type":"search","filterValue":"my-collection"}]', + sortFilterExample: '{"key":"name","direction":"ASC"}' + )] + #[SuccessResponse( + description: 'classification_store_configuration_collection_collection_success_response', + content: new CollectionJson(new GenericCollection(CollectionDetail::class)) + )] + #[DefaultResponses([ + HttpResponseCodes::UNAUTHORIZED, + ])] + public function getCollections( + int $storeId, + #[MapRequestPayload] CollectionFilterParameter $parameters, + ): JsonResponse { + $collection = $this->collectionService->listCollections($parameters, $storeId); + + return $this->getPaginatedCollection( + $this->serializer, + $collection->getItems(), + $collection->getTotalItems() + ); + } +} diff --git a/src/ClassificationStore/Controller/Configuration/Collection/CreateController.php b/src/ClassificationStore/Controller/Configuration/Collection/CreateController.php new file mode 100644 index 000000000..863818c6f --- /dev/null +++ b/src/ClassificationStore/Controller/Configuration/Collection/CreateController.php @@ -0,0 +1,82 @@ +value)] + #[Post( + path: self::PREFIX . self::ROUTE, + operationId: 'classification_store_configuration_collection_create', + description: 'classification_store_configuration_collection_create_description', + summary: 'classification_store_configuration_collection_create_summary', + tags: [Tags::ClassificationStore->value] + )] + #[ReferenceRequestBody(CollectionCreate::class)] + #[SuccessResponse( + description: 'classification_store_configuration_collection_create_success_response', + content: new JsonContent(ref: CollectionDetail::class) + )] + #[DefaultResponses([ + HttpResponseCodes::UNAUTHORIZED, + HttpResponseCodes::INTERNAL_SERVER_ERROR, + ])] + public function createCollection( + #[MapRequestPayload] CollectionCreate $parameters + ): JsonResponse { + return $this->jsonResponse($this->collectionService->createCollection($parameters)); + } +} diff --git a/src/ClassificationStore/Controller/Configuration/Collection/DeleteController.php b/src/ClassificationStore/Controller/Configuration/Collection/DeleteController.php new file mode 100644 index 000000000..9120ff9e3 --- /dev/null +++ b/src/ClassificationStore/Controller/Configuration/Collection/DeleteController.php @@ -0,0 +1,71 @@ +value)] + #[Delete( + path: self::PREFIX . self::ROUTE, + operationId: 'classification_store_configuration_collection_delete', + description: 'classification_store_configuration_collection_delete_description', + summary: 'classification_store_configuration_collection_delete_summary', + tags: [Tags::ClassificationStore->value] + )] + #[IdParameter(type: 'collection configuration')] + #[SuccessResponse( + description: 'classification_store_configuration_collection_delete_success_response', + )] + #[DefaultResponses([ + HttpResponseCodes::UNAUTHORIZED, + HttpResponseCodes::NOT_FOUND, + ])] + public function deleteCollection(int $id): Response + { + $this->collectionService->deleteCollection($id); + + return new Response(); + } +} diff --git a/src/ClassificationStore/Controller/Configuration/Collection/UpdateController.php b/src/ClassificationStore/Controller/Configuration/Collection/UpdateController.php new file mode 100644 index 000000000..66b7e1b32 --- /dev/null +++ b/src/ClassificationStore/Controller/Configuration/Collection/UpdateController.php @@ -0,0 +1,80 @@ +value)] + #[Put( + path: self::PREFIX . self::ROUTE, + operationId: 'classification_store_configuration_collection_update', + description: 'classification_store_configuration_collection_update_description', + summary: 'classification_store_configuration_collection_update_summary', + tags: [Tags::ClassificationStore->value] + )] + #[IdParameter(type: 'collection configuration')] + #[ReferenceRequestBody(CollectionUpdate::class)] + #[SuccessResponse( + description: 'classification_store_configuration_collection_update_success_response', + content: new JsonContent(ref: CollectionDetail::class) + )] + #[DefaultResponses([ + HttpResponseCodes::UNAUTHORIZED, + HttpResponseCodes::NOT_FOUND, + ])] + public function updateCollection( + int $id, + #[MapRequestPayload] CollectionUpdate $parameters + ): JsonResponse { + return $this->jsonResponse($this->collectionService->updateCollection($id, $parameters)); + } +} diff --git a/src/ClassificationStore/Controller/Configuration/CollectionRelation/CollectionController.php b/src/ClassificationStore/Controller/Configuration/CollectionRelation/CollectionController.php new file mode 100644 index 000000000..709905df6 --- /dev/null +++ b/src/ClassificationStore/Controller/Configuration/CollectionRelation/CollectionController.php @@ -0,0 +1,89 @@ +value)] + #[Post( + path: self::PREFIX . self::ROUTE, + operationId: 'classification_store_configuration_collection_relation_collection', + description: 'classification_store_configuration_collection_relation_collection_description', + summary: 'classification_store_configuration_collection_relation_collection_summary', + tags: [Tags::ClassificationStore->value] + )] + #[IntParameter(name: 'colId', example: 1, description: 'ID of the collection to list relations for')] + #[CollectionRequestBody( + sortFilterExample: '{"key":"groupId","direction":"ASC"}' + )] + #[SuccessResponse( + description: 'classification_store_configuration_collection_relation_collection_success_response', + content: new CollectionJson(new GenericCollection(CollectionRelationDetail::class)) + )] + #[DefaultResponses([ + HttpResponseCodes::UNAUTHORIZED, + ])] + public function getCollectionRelations( + int $colId, + #[MapRequestPayload] CollectionFilterParameter $parameters, + ): JsonResponse { + $collection = $this->collectionRelationService->listCollectionRelations($parameters, $colId); + + return $this->getPaginatedCollection( + $this->serializer, + $collection->getItems(), + $collection->getTotalItems() + ); + } +} diff --git a/src/ClassificationStore/Controller/Configuration/CollectionRelation/CreateController.php b/src/ClassificationStore/Controller/Configuration/CollectionRelation/CreateController.php new file mode 100644 index 000000000..13f96725d --- /dev/null +++ b/src/ClassificationStore/Controller/Configuration/CollectionRelation/CreateController.php @@ -0,0 +1,82 @@ +value)] + #[Post( + path: self::PREFIX . self::ROUTE, + operationId: 'classification_store_configuration_collection_relation_create', + description: 'classification_store_configuration_collection_relation_create_description', + summary: 'classification_store_configuration_collection_relation_create_summary', + tags: [Tags::ClassificationStore->value] + )] + #[ReferenceRequestBody(CollectionRelationCreate::class)] + #[SuccessResponse( + description: 'classification_store_configuration_collection_relation_create_success_response', + content: new JsonContent(ref: CollectionRelationDetail::class) + )] + #[DefaultResponses([ + HttpResponseCodes::UNAUTHORIZED, + HttpResponseCodes::INTERNAL_SERVER_ERROR, + ])] + public function createCollectionRelation( + #[MapRequestPayload] CollectionRelationCreate $parameters + ): JsonResponse { + return $this->jsonResponse( + $this->collectionRelationService->createOrUpdateCollectionRelation($parameters) + ); + } +} diff --git a/src/ClassificationStore/Controller/Configuration/CollectionRelation/DeleteController.php b/src/ClassificationStore/Controller/Configuration/CollectionRelation/DeleteController.php new file mode 100644 index 000000000..3e5bb287b --- /dev/null +++ b/src/ClassificationStore/Controller/Configuration/CollectionRelation/DeleteController.php @@ -0,0 +1,76 @@ +value)] + #[Delete( + path: self::PREFIX . self::ROUTE, + operationId: 'classification_store_configuration_collection_relation_delete', + description: 'classification_store_configuration_collection_relation_delete_description', + summary: 'classification_store_configuration_collection_relation_delete_summary', + tags: [Tags::ClassificationStore->value] + )] + #[ReferenceRequestBody(CollectionRelationDelete::class)] + #[SuccessResponse( + description: 'classification_store_configuration_collection_relation_delete_success_response', + )] + #[DefaultResponses([ + HttpResponseCodes::UNAUTHORIZED, + ])] + public function deleteCollectionRelation( + #[MapRequestPayload] CollectionRelationDelete $parameters + ): Response { + $this->collectionRelationService->deleteCollectionRelation( + $parameters->getColId(), + $parameters->getGroupId() + ); + + return new Response(); + } +} diff --git a/src/ClassificationStore/Controller/Configuration/Group/CollectionController.php b/src/ClassificationStore/Controller/Configuration/Group/CollectionController.php new file mode 100644 index 000000000..48c972eed --- /dev/null +++ b/src/ClassificationStore/Controller/Configuration/Group/CollectionController.php @@ -0,0 +1,90 @@ +value)] + #[Post( + path: self::PREFIX . self::ROUTE, + operationId: 'classification_store_configuration_group_collection', + description: 'classification_store_configuration_group_collection_description', + summary: 'classification_store_configuration_group_collection_summary', + tags: [Tags::ClassificationStore->value] + )] + #[IntParameter(name: 'storeId', example: 1, description: 'ID of the store to list groups for')] + #[CollectionRequestBody( + columnFiltersExample: '[{"type":"search","filterValue":"my-group"}]', + sortFilterExample: '{"key":"name","direction":"ASC"}' + )] + #[SuccessResponse( + description: 'classification_store_configuration_group_collection_success_response', + content: new CollectionJson(new GenericCollection(GroupDetail::class)) + )] + #[DefaultResponses([ + HttpResponseCodes::UNAUTHORIZED, + ])] + public function getGroups( + int $storeId, + #[MapRequestPayload] CollectionFilterParameter $parameters, + ): JsonResponse { + $collection = $this->groupService->listGroups($parameters, $storeId); + + return $this->getPaginatedCollection( + $this->serializer, + $collection->getItems(), + $collection->getTotalItems() + ); + } +} diff --git a/src/ClassificationStore/Controller/Configuration/Group/CreateController.php b/src/ClassificationStore/Controller/Configuration/Group/CreateController.php new file mode 100644 index 000000000..1b0017cd3 --- /dev/null +++ b/src/ClassificationStore/Controller/Configuration/Group/CreateController.php @@ -0,0 +1,77 @@ +value)] + #[Post( + path: self::PREFIX . self::ROUTE, + operationId: 'classification_store_configuration_group_create', + description: 'classification_store_configuration_group_create_description', + summary: 'classification_store_configuration_group_create_summary', + tags: [Tags::ClassificationStore->value] + )] + #[ReferenceRequestBody(GroupCreate::class)] + #[SuccessResponse( + description: 'classification_store_configuration_group_create_success_response', + content: new JsonContent(ref: GroupDetail::class) + )] + #[DefaultResponses([ + HttpResponseCodes::UNAUTHORIZED, + HttpResponseCodes::INTERNAL_SERVER_ERROR, + ])] + public function createGroup( + #[MapRequestPayload] GroupCreate $parameters + ): JsonResponse { + return $this->jsonResponse($this->groupService->createGroup($parameters)); + } +} diff --git a/src/ClassificationStore/Controller/Configuration/Group/DeleteController.php b/src/ClassificationStore/Controller/Configuration/Group/DeleteController.php new file mode 100644 index 000000000..2b10f43cb --- /dev/null +++ b/src/ClassificationStore/Controller/Configuration/Group/DeleteController.php @@ -0,0 +1,71 @@ +value)] + #[Delete( + path: self::PREFIX . self::ROUTE, + operationId: 'classification_store_configuration_group_delete', + description: 'classification_store_configuration_group_delete_description', + summary: 'classification_store_configuration_group_delete_summary', + tags: [Tags::ClassificationStore->value] + )] + #[IdParameter(type: 'group configuration')] + #[SuccessResponse( + description: 'classification_store_configuration_group_delete_success_response', + )] + #[DefaultResponses([ + HttpResponseCodes::UNAUTHORIZED, + HttpResponseCodes::NOT_FOUND, + ])] + public function deleteGroup(int $id): Response + { + $this->groupService->deleteGroup($id); + + return new Response(); + } +} diff --git a/src/ClassificationStore/Controller/Configuration/Group/UpdateController.php b/src/ClassificationStore/Controller/Configuration/Group/UpdateController.php new file mode 100644 index 000000000..de611f754 --- /dev/null +++ b/src/ClassificationStore/Controller/Configuration/Group/UpdateController.php @@ -0,0 +1,80 @@ +value)] + #[Put( + path: self::PREFIX . self::ROUTE, + operationId: 'classification_store_configuration_group_update', + description: 'classification_store_configuration_group_update_description', + summary: 'classification_store_configuration_group_update_summary', + tags: [Tags::ClassificationStore->value] + )] + #[IdParameter(type: 'group configuration')] + #[ReferenceRequestBody(GroupUpdate::class)] + #[SuccessResponse( + description: 'classification_store_configuration_group_update_success_response', + content: new JsonContent(ref: GroupDetail::class) + )] + #[DefaultResponses([ + HttpResponseCodes::UNAUTHORIZED, + HttpResponseCodes::NOT_FOUND, + ])] + public function updateGroup( + int $id, + #[MapRequestPayload] GroupUpdate $parameters + ): JsonResponse { + return $this->jsonResponse($this->groupService->updateGroup($id, $parameters)); + } +} diff --git a/src/ClassificationStore/Controller/Configuration/Key/CollectionController.php b/src/ClassificationStore/Controller/Configuration/Key/CollectionController.php new file mode 100644 index 000000000..fb2d8cc18 --- /dev/null +++ b/src/ClassificationStore/Controller/Configuration/Key/CollectionController.php @@ -0,0 +1,93 @@ +value)] + #[Post( + path: self::PREFIX . self::ROUTE, + operationId: 'classification_store_configuration_key_collection', + description: 'classification_store_configuration_key_collection_description', + summary: 'classification_store_configuration_key_collection_summary', + tags: [Tags::ClassificationStore->value] + )] + #[IntParameter(name: 'storeId', example: 1, description: 'ID of the store to list keys for')] + #[CollectionRequestBody( + columnFiltersExample: '[' . + '{"type":"search","filterValue":"my-key"},'. + '{"type":"equals","key": "type", "filterValue":"quantityValue"}'. + ']', + sortFilterExample: '{"key":"name","direction":"ASC"}' + )] + #[SuccessResponse( + description: 'classification_store_configuration_key_collection_success_response', + content: new CollectionJson(new GenericCollection(KeyDetail::class)) + )] + #[DefaultResponses([ + HttpResponseCodes::UNAUTHORIZED, + ])] + public function getKeys( + int $storeId, + #[MapRequestPayload] CollectionFilterParameter $parameters, + ): JsonResponse { + $collection = $this->keyService->listKeys($parameters, $storeId); + + return $this->getPaginatedCollection( + $this->serializer, + $collection->getItems(), + $collection->getTotalItems() + ); + } +} diff --git a/src/ClassificationStore/Controller/Configuration/Key/CreateController.php b/src/ClassificationStore/Controller/Configuration/Key/CreateController.php new file mode 100644 index 000000000..29aec2a02 --- /dev/null +++ b/src/ClassificationStore/Controller/Configuration/Key/CreateController.php @@ -0,0 +1,77 @@ +value)] + #[Post( + path: self::PREFIX . self::ROUTE, + operationId: 'classification_store_configuration_key_create', + description: 'classification_store_configuration_key_create_description', + summary: 'classification_store_configuration_key_create_summary', + tags: [Tags::ClassificationStore->value] + )] + #[ReferenceRequestBody(KeyCreate::class)] + #[SuccessResponse( + description: 'classification_store_configuration_key_create_success_response', + content: new JsonContent(ref: KeyDetail::class) + )] + #[DefaultResponses([ + HttpResponseCodes::UNAUTHORIZED, + HttpResponseCodes::INTERNAL_SERVER_ERROR, + ])] + public function createKey( + #[MapRequestPayload] KeyCreate $parameters + ): JsonResponse { + return $this->jsonResponse($this->keyService->createKey($parameters)); + } +} diff --git a/src/ClassificationStore/Controller/Configuration/Key/DeleteController.php b/src/ClassificationStore/Controller/Configuration/Key/DeleteController.php new file mode 100644 index 000000000..79a3dda96 --- /dev/null +++ b/src/ClassificationStore/Controller/Configuration/Key/DeleteController.php @@ -0,0 +1,73 @@ +value)] + #[Delete( + path: self::PREFIX . self::ROUTE, + operationId: 'classification_store_configuration_key_delete', + description: 'classification_store_configuration_key_delete_description', + summary: 'classification_store_configuration_key_delete_summary', + tags: [Tags::ClassificationStore->value] + )] + #[IdParameter(type: 'key configuration')] + #[SuccessResponse( + description: 'classification_store_configuration_key_delete_success_response', + )] + #[DefaultResponses([ + HttpResponseCodes::UNAUTHORIZED, + HttpResponseCodes::NOT_FOUND, + ])] + public function deleteKey(int $id): Response + { + $this->keyService->softDeleteKey($id); + + return new Response(); + } +} diff --git a/src/ClassificationStore/Controller/Configuration/Key/UpdateController.php b/src/ClassificationStore/Controller/Configuration/Key/UpdateController.php new file mode 100644 index 000000000..c36afd283 --- /dev/null +++ b/src/ClassificationStore/Controller/Configuration/Key/UpdateController.php @@ -0,0 +1,80 @@ +value)] + #[Put( + path: self::PREFIX . self::ROUTE, + operationId: 'classification_store_configuration_key_update', + description: 'classification_store_configuration_key_update_description', + summary: 'classification_store_configuration_key_update_summary', + tags: [Tags::ClassificationStore->value] + )] + #[IdParameter(type: 'key configuration')] + #[ReferenceRequestBody(KeyUpdate::class)] + #[SuccessResponse( + description: 'classification_store_configuration_key_update_success_response', + content: new JsonContent(ref: KeyDetail::class) + )] + #[DefaultResponses([ + HttpResponseCodes::UNAUTHORIZED, + HttpResponseCodes::NOT_FOUND, + ])] + public function updateKey( + int $id, + #[MapRequestPayload] KeyUpdate $parameters + ): JsonResponse { + return $this->jsonResponse($this->keyService->updateKey($id, $parameters)); + } +} diff --git a/src/ClassificationStore/Controller/Configuration/KeyGroupRelation/CollectionController.php b/src/ClassificationStore/Controller/Configuration/KeyGroupRelation/CollectionController.php new file mode 100644 index 000000000..504c51e99 --- /dev/null +++ b/src/ClassificationStore/Controller/Configuration/KeyGroupRelation/CollectionController.php @@ -0,0 +1,89 @@ +value)] + #[Post( + path: self::PREFIX . self::ROUTE, + operationId: 'classification_store_configuration_key_group_relation_collection', + description: 'classification_store_configuration_key_group_relation_collection_description', + summary: 'classification_store_configuration_key_group_relation_collection_summary', + tags: [Tags::ClassificationStore->value] + )] + #[IntParameter(name: 'groupId', example: 1, description: 'ID of the group to list key relations for')] + #[CollectionRequestBody( + sortFilterExample: '{"key":"keyId","direction":"ASC"}' + )] + #[SuccessResponse( + description: 'classification_store_configuration_key_group_relation_collection_success_response', + content: new CollectionJson(new GenericCollection(KeyGroupRelationDetail::class)) + )] + #[DefaultResponses([ + HttpResponseCodes::UNAUTHORIZED, + ])] + public function getKeyGroupRelations( + int $groupId, + #[MapRequestPayload] CollectionFilterParameter $parameters, + ): JsonResponse { + $collection = $this->keyGroupRelationService->listKeyGroupRelations($parameters, $groupId); + + return $this->getPaginatedCollection( + $this->serializer, + $collection->getItems(), + $collection->getTotalItems() + ); + } +} diff --git a/src/ClassificationStore/Controller/Configuration/KeyGroupRelation/CreateController.php b/src/ClassificationStore/Controller/Configuration/KeyGroupRelation/CreateController.php new file mode 100644 index 000000000..99672e183 --- /dev/null +++ b/src/ClassificationStore/Controller/Configuration/KeyGroupRelation/CreateController.php @@ -0,0 +1,82 @@ +value)] + #[Post( + path: self::PREFIX . self::ROUTE, + operationId: 'classification_store_configuration_key_group_relation_create', + description: 'classification_store_configuration_key_group_relation_create_description', + summary: 'classification_store_configuration_key_group_relation_create_summary', + tags: [Tags::ClassificationStore->value] + )] + #[ReferenceRequestBody(KeyGroupRelationCreate::class)] + #[SuccessResponse( + description: 'classification_store_configuration_key_group_relation_create_success_response', + content: new JsonContent(ref: KeyGroupRelationDetail::class) + )] + #[DefaultResponses([ + HttpResponseCodes::UNAUTHORIZED, + HttpResponseCodes::INTERNAL_SERVER_ERROR, + ])] + public function createKeyGroupRelation( + #[MapRequestPayload] KeyGroupRelationCreate $parameters + ): JsonResponse { + return $this->jsonResponse( + $this->keyGroupRelationService->createOrUpdateKeyGroupRelation($parameters) + ); + } +} diff --git a/src/ClassificationStore/Controller/Configuration/KeyGroupRelation/DeleteController.php b/src/ClassificationStore/Controller/Configuration/KeyGroupRelation/DeleteController.php new file mode 100644 index 000000000..5e71439a4 --- /dev/null +++ b/src/ClassificationStore/Controller/Configuration/KeyGroupRelation/DeleteController.php @@ -0,0 +1,72 @@ +value)] + #[Delete( + path: self::PREFIX . self::ROUTE, + operationId: 'classification_store_configuration_key_group_relation_delete', + description: 'classification_store_configuration_key_group_relation_delete_description', + summary: 'classification_store_configuration_key_group_relation_delete_summary', + tags: [Tags::ClassificationStore->value] + )] + #[ReferenceRequestBody(KeyGroupRelationDelete::class)] + #[SuccessResponse( + description: 'classification_store_configuration_key_group_relation_delete_success_response', + )] + #[DefaultResponses([ + HttpResponseCodes::UNAUTHORIZED, + ])] + public function deleteKeyGroupRelation( + #[MapRequestPayload] KeyGroupRelationDelete $parameters + ): Response { + $this->keyGroupRelationService->deleteKeyGroupRelation( + $parameters->getKeyId(), + $parameters->getGroupId() + ); + + return new Response(); + } +} diff --git a/src/ClassificationStore/Controller/Configuration/Store/CreateController.php b/src/ClassificationStore/Controller/Configuration/Store/CreateController.php new file mode 100644 index 000000000..ee5adb919 --- /dev/null +++ b/src/ClassificationStore/Controller/Configuration/Store/CreateController.php @@ -0,0 +1,77 @@ +value)] + #[Post( + path: self::PREFIX . self::ROUTE, + operationId: 'classification_store_configuration_store_create', + description: 'classification_store_configuration_store_create_description', + summary: 'classification_store_configuration_store_create_summary', + tags: [Tags::ClassificationStore->value] + )] + #[ReferenceRequestBody(StoreCreate::class)] + #[SuccessResponse( + description: 'classification_store_configuration_store_create_success_response', + content: new JsonContent(ref: StoreDetail::class) + )] + #[DefaultResponses([ + HttpResponseCodes::UNAUTHORIZED, + HttpResponseCodes::INTERNAL_SERVER_ERROR, + ])] + public function createStore( + #[MapRequestPayload] StoreCreate $parameters + ): JsonResponse { + return $this->jsonResponse($this->storeService->createStore($parameters)); + } +} diff --git a/src/ClassificationStore/Controller/Configuration/Store/TreeController.php b/src/ClassificationStore/Controller/Configuration/Store/TreeController.php new file mode 100644 index 000000000..5bca1b2cd --- /dev/null +++ b/src/ClassificationStore/Controller/Configuration/Store/TreeController.php @@ -0,0 +1,71 @@ +value)] + #[Get( + path: self::PREFIX . self::ROUTE, + operationId: 'classification_store_configuration_store_tree', + description: 'classification_store_configuration_store_tree_description', + summary: 'classification_store_configuration_store_tree_summary', + tags: [Tags::ClassificationStore->value] + )] + #[SuccessResponse( + description: 'classification_store_configuration_store_tree_success_response', + content: new JsonContent(type: 'array', items: new Items(ref: StoreTreeNode::class)) + )] + #[DefaultResponses([ + HttpResponseCodes::UNAUTHORIZED, + ])] + public function getStoreTree(): JsonResponse + { + return $this->jsonResponse($this->storeService->getStoreTree()); + } +} diff --git a/src/ClassificationStore/Controller/Configuration/Store/UpdateController.php b/src/ClassificationStore/Controller/Configuration/Store/UpdateController.php new file mode 100644 index 000000000..df9cb4659 --- /dev/null +++ b/src/ClassificationStore/Controller/Configuration/Store/UpdateController.php @@ -0,0 +1,82 @@ +value)] + #[Put( + path: self::PREFIX . self::ROUTE, + operationId: 'classification_store_configuration_store_update', + description: 'classification_store_configuration_store_update_description', + summary: 'classification_store_configuration_store_update_summary', + tags: [Tags::ClassificationStore->value] + )] + #[IdParameter(type: 'store configuration')] + #[ReferenceRequestBody(StoreUpdate::class)] + #[SuccessResponse( + description: 'classification_store_configuration_store_update_success_response', + content: new JsonContent(ref: StoreDetail::class) + )] + #[DefaultResponses([ + HttpResponseCodes::UNAUTHORIZED, + HttpResponseCodes::NOT_FOUND, + ])] + public function updateStore( + int $id, + #[MapRequestPayload] StoreUpdate $parameters + ): JsonResponse { + return $this->jsonResponse($this->storeService->updateStore($id, $parameters)); + } +} diff --git a/src/ClassificationStore/Controller/Configuration/Utility/GetPageController.php b/src/ClassificationStore/Controller/Configuration/Utility/GetPageController.php new file mode 100644 index 000000000..e1dcf5738 --- /dev/null +++ b/src/ClassificationStore/Controller/Configuration/Utility/GetPageController.php @@ -0,0 +1,96 @@ +value)] + #[Get( + path: self::PREFIX . self::ROUTE, + operationId: 'classification_store_configuration_get_page', + description: 'classification_store_configuration_get_page_description', + summary: 'classification_store_configuration_get_page_summary', + tags: [Tags::ClassificationStore->value] + )] + #[TextFieldParameter( + name: 'table', + description: 'Table to search in (keys or groups)', + required: true, + example: 'keys' + )] + #[IntParameter(name: 'id', description: 'ID of the item to find', required: true, example: 1)] + #[IntParameter(name: 'storeId', description: 'ID of the store', required: true, example: 1)] + #[IntParameter(name: 'pageSize', description: 'Number of items per page', required: true, example: 15)] + #[TextFieldParameter(name: 'sortKey', description: 'Column to sort by', required: false, example: 'name')] + #[TextFieldParameter( + name: 'sortDir', + description: 'Sort direction (ASC or DESC)', + required: false, + example: 'ASC' + )] + #[SuccessResponse( + description: 'classification_store_configuration_get_page_success_response', + content: new JsonContent(ref: GetPageResponse::class) + )] + #[DefaultResponses([ + HttpResponseCodes::INTERNAL_SERVER_ERROR, + HttpResponseCodes::UNAUTHORIZED, + HttpResponseCodes::NOT_FOUND, + ])] + public function getPage( + #[MapQueryString] GetPageParameters $parameters = new GetPageParameters() + ): JsonResponse { + return $this->jsonResponse( + $this->keyService->getPage($parameters) + ); + } +} diff --git a/src/ClassificationStore/Controller/GetKeyGroupRelationsController.php b/src/ClassificationStore/Controller/GetKeyGroupRelationsController.php index 49e3695f0..6ed126369 100644 --- a/src/ClassificationStore/Controller/GetKeyGroupRelationsController.php +++ b/src/ClassificationStore/Controller/GetKeyGroupRelationsController.php @@ -78,8 +78,8 @@ public function __construct( namePrefix: 'store', )] #[TextFieldParameter( - description: 'Class ID', name: 'classId', + description: 'Class ID', required: false, example: 'AP' )] diff --git a/src/ClassificationStore/Event/Configuration/CollectionDetailEvent.php b/src/ClassificationStore/Event/Configuration/CollectionDetailEvent.php new file mode 100644 index 000000000..086da0ab8 --- /dev/null +++ b/src/ClassificationStore/Event/Configuration/CollectionDetailEvent.php @@ -0,0 +1,33 @@ +collectionDetail; + } +} diff --git a/src/ClassificationStore/Event/Configuration/CollectionRelationDetailEvent.php b/src/ClassificationStore/Event/Configuration/CollectionRelationDetailEvent.php new file mode 100644 index 000000000..e85d076a9 --- /dev/null +++ b/src/ClassificationStore/Event/Configuration/CollectionRelationDetailEvent.php @@ -0,0 +1,33 @@ +collectionRelationDetail; + } +} diff --git a/src/ClassificationStore/Event/Configuration/GetPageEvent.php b/src/ClassificationStore/Event/Configuration/GetPageEvent.php new file mode 100644 index 000000000..585666e58 --- /dev/null +++ b/src/ClassificationStore/Event/Configuration/GetPageEvent.php @@ -0,0 +1,33 @@ +getPageResponse; + } +} diff --git a/src/ClassificationStore/Event/Configuration/GroupDetailEvent.php b/src/ClassificationStore/Event/Configuration/GroupDetailEvent.php new file mode 100644 index 000000000..5694c1c1b --- /dev/null +++ b/src/ClassificationStore/Event/Configuration/GroupDetailEvent.php @@ -0,0 +1,33 @@ +groupDetail; + } +} diff --git a/src/ClassificationStore/Event/Configuration/KeyDetailEvent.php b/src/ClassificationStore/Event/Configuration/KeyDetailEvent.php new file mode 100644 index 000000000..ee1a00d6f --- /dev/null +++ b/src/ClassificationStore/Event/Configuration/KeyDetailEvent.php @@ -0,0 +1,33 @@ +keyDetail; + } +} diff --git a/src/ClassificationStore/Event/Configuration/KeyGroupRelationDetailEvent.php b/src/ClassificationStore/Event/Configuration/KeyGroupRelationDetailEvent.php new file mode 100644 index 000000000..6daa23740 --- /dev/null +++ b/src/ClassificationStore/Event/Configuration/KeyGroupRelationDetailEvent.php @@ -0,0 +1,33 @@ +keyGroupRelationDetail; + } +} diff --git a/src/ClassificationStore/Event/Configuration/StoreDetailEvent.php b/src/ClassificationStore/Event/Configuration/StoreDetailEvent.php new file mode 100644 index 000000000..da6895a42 --- /dev/null +++ b/src/ClassificationStore/Event/Configuration/StoreDetailEvent.php @@ -0,0 +1,33 @@ +storeDetail; + } +} diff --git a/src/ClassificationStore/Event/Configuration/StoreTreeNodeEvent.php b/src/ClassificationStore/Event/Configuration/StoreTreeNodeEvent.php new file mode 100644 index 000000000..3eae457c8 --- /dev/null +++ b/src/ClassificationStore/Event/Configuration/StoreTreeNodeEvent.php @@ -0,0 +1,33 @@ +storeTreeNode; + } +} diff --git a/src/ClassificationStore/Hydrator/Configuration/CollectionHydrator.php b/src/ClassificationStore/Hydrator/Configuration/CollectionHydrator.php new file mode 100644 index 000000000..2d7ebbe4e --- /dev/null +++ b/src/ClassificationStore/Hydrator/Configuration/CollectionHydrator.php @@ -0,0 +1,35 @@ +getId(), + $collectionConfig->getName(), + $collectionConfig->getStoreId(), + $collectionConfig->getDescription(), + $collectionConfig->getCreationDate(), + $collectionConfig->getModificationDate(), + ); + } +} diff --git a/src/ClassificationStore/Repository/StoreRepositoryInterface.php b/src/ClassificationStore/Hydrator/Configuration/CollectionHydratorInterface.php similarity index 58% rename from src/ClassificationStore/Repository/StoreRepositoryInterface.php rename to src/ClassificationStore/Hydrator/Configuration/CollectionHydratorInterface.php index eb60e739e..11efb07b1 100644 --- a/src/ClassificationStore/Repository/StoreRepositoryInterface.php +++ b/src/ClassificationStore/Hydrator/Configuration/CollectionHydratorInterface.php @@ -11,17 +11,15 @@ * @license Pimcore Open Core License (POCL) */ -namespace Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Repository; +namespace Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Hydrator\Configuration; -use Pimcore\Model\DataObject\Classificationstore\StoreConfig; +use Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Schema\Configuration\CollectionDetail; +use Pimcore\Model\DataObject\Classificationstore\CollectionConfig; /** * @internal */ -interface StoreRepositoryInterface +interface CollectionHydratorInterface { - /** - * @return StoreConfig[] - */ - public function listStores(): array; + public function hydrateCollectionDetail(CollectionConfig $collectionConfig): CollectionDetail; } diff --git a/src/ClassificationStore/Hydrator/Configuration/CollectionRelationHydrator.php b/src/ClassificationStore/Hydrator/Configuration/CollectionRelationHydrator.php new file mode 100644 index 000000000..06b46c0dd --- /dev/null +++ b/src/ClassificationStore/Hydrator/Configuration/CollectionRelationHydrator.php @@ -0,0 +1,39 @@ +getColId(), $relation->getGroupId()), + $relation->getColId(), + $relation->getGroupId(), + $relation->getSorter(), + $groupName, + $groupDescription, + ); + } +} diff --git a/src/ClassificationStore/Hydrator/Configuration/CollectionRelationHydratorInterface.php b/src/ClassificationStore/Hydrator/Configuration/CollectionRelationHydratorInterface.php new file mode 100644 index 000000000..3f3d8ae9c --- /dev/null +++ b/src/ClassificationStore/Hydrator/Configuration/CollectionRelationHydratorInterface.php @@ -0,0 +1,29 @@ +getId(), + $groupConfig->getName(), + $groupConfig->getStoreId(), + $groupConfig->getDescription(), + $groupConfig->getCreationDate(), + $groupConfig->getModificationDate(), + ); + } +} diff --git a/src/ClassificationStore/Repository/StoreRepository.php b/src/ClassificationStore/Hydrator/Configuration/GroupHydratorInterface.php similarity index 61% rename from src/ClassificationStore/Repository/StoreRepository.php rename to src/ClassificationStore/Hydrator/Configuration/GroupHydratorInterface.php index 1c616fb25..b655c5d9d 100644 --- a/src/ClassificationStore/Repository/StoreRepository.php +++ b/src/ClassificationStore/Hydrator/Configuration/GroupHydratorInterface.php @@ -11,20 +11,15 @@ * @license Pimcore Open Core License (POCL) */ -namespace Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Repository; +namespace Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Hydrator\Configuration; -use Pimcore\Model\DataObject\Classificationstore\StoreConfig\Listing; +use Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Schema\Configuration\GroupDetail; +use Pimcore\Model\DataObject\Classificationstore\GroupConfig; /** * @internal */ -final class StoreRepository implements StoreRepositoryInterface +interface GroupHydratorInterface { - /** - * {@inheritdoc} - */ - public function listStores(): array - { - return (new Listing())->load(); - } + public function hydrateGroupDetail(GroupConfig $groupConfig): GroupDetail; } diff --git a/src/ClassificationStore/Hydrator/Configuration/KeyGroupRelationHydrator.php b/src/ClassificationStore/Hydrator/Configuration/KeyGroupRelationHydrator.php new file mode 100644 index 000000000..aefae3bc2 --- /dev/null +++ b/src/ClassificationStore/Hydrator/Configuration/KeyGroupRelationHydrator.php @@ -0,0 +1,44 @@ +getKeyId(), + $relation->getGroupId(), + $relation->getSorter(), + $relation->isMandatory(), + $keyName, + $keyDescription, + $groupName, + ); + } +} diff --git a/src/ClassificationStore/Hydrator/Configuration/KeyGroupRelationHydratorInterface.php b/src/ClassificationStore/Hydrator/Configuration/KeyGroupRelationHydratorInterface.php new file mode 100644 index 000000000..68944576b --- /dev/null +++ b/src/ClassificationStore/Hydrator/Configuration/KeyGroupRelationHydratorInterface.php @@ -0,0 +1,30 @@ +getId(), + $keyConfig->getName(), + $keyConfig->getStoreId(), + $keyConfig->getType(), + $keyConfig->getEnabled(), + $keyConfig->getDescription(), + $this->getKeyDefinition($keyConfig), + $keyConfig->getCreationDate(), + $keyConfig->getModificationDate(), + ); + } + + public function hydrateGetPageResponse(int $page): GetPageResponse + { + return new GetPageResponse($page); + } +} diff --git a/src/ClassificationStore/Hydrator/Configuration/KeyHydratorInterface.php b/src/ClassificationStore/Hydrator/Configuration/KeyHydratorInterface.php new file mode 100644 index 000000000..e702c3892 --- /dev/null +++ b/src/ClassificationStore/Hydrator/Configuration/KeyHydratorInterface.php @@ -0,0 +1,28 @@ +getId(), + $storeConfig->getName(), + $storeConfig->getDescription(), + ); + } + + public function hydrateStoreTreeNode(StoreConfig $storeConfig): StoreTreeNode + { + return new StoreTreeNode( + $storeConfig->getId(), + $storeConfig->getName(), + $storeConfig->getDescription(), + ); + } +} diff --git a/src/ClassificationStore/Hydrator/Configuration/StoreHydratorInterface.php b/src/ClassificationStore/Hydrator/Configuration/StoreHydratorInterface.php new file mode 100644 index 000000000..e79b023bf --- /dev/null +++ b/src/ClassificationStore/Hydrator/Configuration/StoreHydratorInterface.php @@ -0,0 +1,28 @@ +addConditionParam('`colId` = :colId', ['colId' => $colId]); + + $this->listingFilter->applyFilters($parameters, $listing); + + return $listing; + } + + /** + * {@inheritdoc} + */ + public function createOrUpdate(int $colId, int $groupId, int $sorter): CollectionGroupRelation + { + $relation = new CollectionGroupRelation(); + $relation->setColId($colId); + $relation->setGroupId($groupId); + $relation->setSorter($sorter); + + try { + $relation->save(); + } catch (Exception $e) { + throw new ElementSavingFailedException(null, $e->getMessage(), $e); + } + + return $relation; + } + + /** + * {@inheritdoc} + */ + public function delete(int $colId, int $groupId): void + { + $relation = new CollectionGroupRelation(); + $relation->setColId($colId); + $relation->setGroupId($groupId); + $relation->delete(); + } +} diff --git a/src/ClassificationStore/Repository/Configuration/CollRelationRepositoryInterface.php b/src/ClassificationStore/Repository/Configuration/CollRelationRepositoryInterface.php new file mode 100644 index 000000000..29519e669 --- /dev/null +++ b/src/ClassificationStore/Repository/Configuration/CollRelationRepositoryInterface.php @@ -0,0 +1,42 @@ +addConditionParam('`storeId` = :storeId', ['storeId' => $storeId]); + + $this->applySearchCondition($listing, $parameters); + $this->listingFilter->applyFilters($parameters, $listing); + + return $listing; + } + + /** + * {@inheritdoc} + */ + public function getById(int $id): CollectionConfig + { + $config = $this->collectionConfigResolver->getById($id); + + if (!$config) { + throw new NotFoundException('collection configuration', $id); + } + + return $config; + } + + /** + * {@inheritdoc} + */ + public function create(string $name, int $storeId): CollectionConfig + { + $existing = $this->collectionConfigResolver->getByName($name, $storeId); + + if ($existing) { + throw new InvalidArgumentException( + sprintf('Collection with the name "%s" already exists in store %d', $name, $storeId) + ); + } + + $config = new CollectionConfig(); + $config->setName($name); + $config->setStoreId($storeId); + + try { + $config->save(); + } catch (Exception $e) { + throw new ElementSavingFailedException(null, $e->getMessage(), $e); + } + + return $config; + } + + /** + * {@inheritdoc} + */ + public function update(int $id, string $name, ?string $description): CollectionConfig + { + $config = $this->getById($id); + $config->setName($name); + $config->setDescription($description); + + try { + $config->save(); + } catch (Exception $e) { + throw new ElementSavingFailedException($id, $e->getMessage(), $e); + } + + return $config; + } + + /** + * {@inheritdoc} + */ + public function delete(int $id): void + { + $config = $this->getById($id); + + $relations = new CollectionGroupRelation\Listing(); + $relations->setCondition('colId = ?', [$id]); + + foreach ($relations->load() as $relation) { + $relation->delete(); + } + + $config->delete(); + } + + private function applySearchCondition(Listing $listing, FilterParameter $parameters): void + { + $searchFilter = $parameters->getSimpleColumnFilterByType(FilterType::SEARCH->value); + if (!$searchFilter) { + return; + } + + if ($searchFilter->getFilterValue() === '' || $searchFilter->getFilterValue() === null) { + return; + } + + $this->searchHelperService->applySearchTermFilter($listing, $searchFilter->getFilterValue()); + } +} diff --git a/src/ClassificationStore/Repository/Configuration/CollectionRepositoryInterface.php b/src/ClassificationStore/Repository/Configuration/CollectionRepositoryInterface.php new file mode 100644 index 000000000..e95e46643 --- /dev/null +++ b/src/ClassificationStore/Repository/Configuration/CollectionRepositoryInterface.php @@ -0,0 +1,56 @@ +addConditionParam('`storeId` = :storeId', ['storeId' => $storeId]); + + $this->applySearchCondition($listing, $parameters); + $this->listingFilter->applyFilters($parameters, $listing); + + return $listing; + } + + /** + * {@inheritdoc} + */ + public function getById(int $id): GroupConfig + { + $config = $this->groupConfigResolver->getById($id); + + if (!$config) { + throw new NotFoundException('group configuration', $id); + } + + return $config; + } + + /** + * {@inheritdoc} + */ + public function create(string $name, int $storeId): GroupConfig + { + try { + $existing = $this->groupConfigResolver->getByName($name, $storeId); + } catch (Exception $e) { + throw new ElementSavingFailedException(null, $e->getMessage(), $e); + } + + if ($existing) { + throw new InvalidArgumentException( + sprintf('Group with the name "%s" already exists in store %d', $name, $storeId) + ); + } + + $config = new GroupConfig(); + $config->setName($name); + $config->setStoreId($storeId); + + try { + $config->save(); + } catch (Exception $e) { + throw new ElementSavingFailedException(null, $e->getMessage(), $e); + } + + return $config; + } + + /** + * {@inheritdoc} + */ + public function update(int $id, string $name, ?string $description): GroupConfig + { + $config = $this->getById($id); + $config->setName($name); + $config->setDescription($description); + + try { + $config->save(); + } catch (Exception $e) { + throw new ElementSavingFailedException($id, $e->getMessage(), $e); + } + + return $config; + } + + /** + * {@inheritdoc} + */ + public function delete(int $id): void + { + $config = $this->getById($id); + $config->delete(); + } + + private function applySearchCondition(Listing $listing, FilterParameter $parameters): void + { + $searchFilter = $parameters->getSimpleColumnFilterByType(FilterType::SEARCH->value); + if (!$searchFilter) { + return; + } + + if ($searchFilter->getFilterValue() === '' || $searchFilter->getFilterValue() === null) { + return; + } + + $this->searchHelperService->applySearchTermFilter($listing, $searchFilter->getFilterValue()); + } +} diff --git a/src/ClassificationStore/Repository/Configuration/GroupRepositoryInterface.php b/src/ClassificationStore/Repository/Configuration/GroupRepositoryInterface.php new file mode 100644 index 000000000..fe4a93313 --- /dev/null +++ b/src/ClassificationStore/Repository/Configuration/GroupRepositoryInterface.php @@ -0,0 +1,54 @@ +addConditionParam('`groupId` = :groupId', ['groupId' => $groupId]); + + $this->listingFilter->applyFilters($parameters, $listing); + + return $listing; + } + + /** + * {@inheritdoc} + */ + public function createOrUpdate(int $keyId, int $groupId, int $sorter, bool $mandatory): KeyGroupRelation + { + $relation = new KeyGroupRelation(); + $relation->setKeyId($keyId); + $relation->setGroupId($groupId); + $relation->setSorter($sorter); + $relation->setMandatory($mandatory); + + try { + $relation->save(); + } catch (Exception $e) { + throw new ElementSavingFailedException(null, $e->getMessage(), $e); + } + + return $relation; + } + + /** + * {@inheritdoc} + */ + public function delete(int $keyId, int $groupId): void + { + $relation = new KeyGroupRelation(); + $relation->setKeyId($keyId); + $relation->setGroupId($groupId); + $relation->delete(); + } +} diff --git a/src/ClassificationStore/Repository/Configuration/KeyGroupRelationRepositoryInterface.php b/src/ClassificationStore/Repository/Configuration/KeyGroupRelationRepositoryInterface.php new file mode 100644 index 000000000..22edc5090 --- /dev/null +++ b/src/ClassificationStore/Repository/Configuration/KeyGroupRelationRepositoryInterface.php @@ -0,0 +1,42 @@ +addConditionParam('`storeId` = :storeId', ['storeId' => $storeId]); + + $this->applySearchCondition($listing, $parameters); + $this->listingFilter->applyFilters($parameters, $listing); + + return $listing; + } + + /** + * {@inheritdoc} + */ + public function getById(int $id): KeyConfig + { + $config = $this->keyConfigResolver->getById($id); + + if (!$config) { + throw new NotFoundException('key configuration', $id); + } + + return $config; + } + + /** + * {@inheritdoc} + */ + public function create(string $name, int $storeId): KeyConfig + { + $definition = [ + 'fieldtype' => 'input', + 'name' => $name, + 'title' => $name, + 'datatype' => 'data', + ]; + + $config = new KeyConfig(); + $config->setName($name); + $config->setTitle($name); + $config->setType('input'); + $config->setStoreId($storeId); + $config->setEnabled(true); + + try { + $config->setDefinition(json_encode($definition, JSON_THROW_ON_ERROR)); + $config->save(); + } catch (Exception $e) { + throw new ElementSavingFailedException(null, $e->getMessage(), $e); + } + + return $config; + } + + /** + * {@inheritdoc} + */ + public function update( + int $id, + string $name, + ?string $title, + ?string $description, + ?string $type, + ?array $definition, + ): KeyConfig { + $config = $this->getById($id); + $config->setName($name); + $config->setTitle($title ?? $config->getTitle()); + $config->setDescription($description ?? $config->getDescription()); + + if ($type !== null) { + $config->setType($type); + } + + try { + if ($definition !== null) { + $config->setDefinition(json_encode($definition, JSON_THROW_ON_ERROR)); + } + + $config->save(); + } catch (Exception $e) { + throw new ElementSavingFailedException($id, $e->getMessage(), $e); + } + + return $config; + } + + /** + * {@inheritdoc} + */ + public function softDelete(int $id): void + { + $config = $this->getById($id); + $config->setEnabled(false); + + try { + $config->save(); + } catch (Exception $e) { + throw new ElementSavingFailedException($id, $e->getMessage(), $e); + } + } + + /** + * {@inheritdoc} + */ + public function getPageForId( + string $table, + int $id, + int $storeId, + int $pageSize, + string $sortKey, + string $sortDir, + ): int { + $sortKey = in_array($sortKey, self::ALLOWED_SORT_KEYS, true) ? $sortKey : 'name'; + $sortDir = in_array(strtoupper($sortDir), self::ALLOWED_SORT_DIRECTIONS, true) + ? strtoupper($sortDir) + : 'ASC'; + + $tableName = 'classificationstore_' . ($table === 'groups' ? 'groups' : 'keys'); + $enabledCondition = $tableName === 'classificationstore_keys' ? ' AND enabled = 1' : ''; + + $referenceRow = $this->connection->fetchAssociative( + sprintf('SELECT `%s` FROM `%s` WHERE id = ?', $sortKey, $tableName), + [$id] + ); + + if (!$referenceRow) { + throw new NotFoundException($table, $id); + } + + $sortValue = $referenceRow[$sortKey]; + + $comparison = $sortDir === 'DESC' ? '>' : '<'; + + $query = sprintf( + 'SELECT COUNT(*) + 1 as position FROM `%s`' . + ' WHERE storeId = ? AND (`%s` %s ? OR (`%s` = ? AND id %s ?))%s', + $tableName, + $sortKey, + $comparison, + $sortKey, + $comparison, + $enabledCondition, + ); + + try { + $result = $this->connection->fetchAssociative( + $query, + [$storeId, $sortValue, $sortValue, $id] + ); + } catch (DBALException $e) { + throw new DatabaseException('Failed to retrieve position for pagination: ' . $e->getMessage(), $e); + } + + $position = (int) ($result['position'] ?? 1); + + return (int) ceil($position / $pageSize); + } + + private function applySearchCondition(Listing $listing, FilterParameter $parameters): void + { + $searchFilter = $parameters->getSimpleColumnFilterByType(FilterType::SEARCH->value); + if (!$searchFilter) { + return; + } + + if ($searchFilter->getFilterValue() === '' || $searchFilter->getFilterValue() === null) { + return; + } + + $this->searchHelperService->applyKeySearchFilter($listing, $searchFilter->getFilterValue()); + } +} diff --git a/src/ClassificationStore/Repository/Configuration/KeyRepositoryInterface.php b/src/ClassificationStore/Repository/Configuration/KeyRepositoryInterface.php new file mode 100644 index 000000000..6ff31fdc5 --- /dev/null +++ b/src/ClassificationStore/Repository/Configuration/KeyRepositoryInterface.php @@ -0,0 +1,73 @@ +load(); + } + + /** + * {@inheritdoc} + */ + public function getById(int $id): StoreConfig + { + $config = $this->storeConfigResolver->getById($id); + + if (!$config) { + throw new NotFoundException('store configuration', $id); + } + + return $config; + } + + /** + * {@inheritdoc} + */ + public function create(string $name): StoreConfig + { + $existing = $this->storeConfigResolver->getByName($name); + + if ($existing) { + throw new InvalidArgumentException( + sprintf('Store with the name "%s" already exists', $name) + ); + } + + $config = new StoreConfig(); + $config->setName($name); + + try { + $config->save(); + } catch (Exception $e) { + throw new ElementSavingFailedException(null, $e->getMessage(), $e); + } + + return $config; + } + + /** + * {@inheritdoc} + */ + public function update(int $id, string $name, ?string $description): StoreConfig + { + $config = $this->getById($id); + + $existing = $this->storeConfigResolver->getByName($name); + if ($existing && $existing->getId() !== $id) { + throw new InvalidArgumentException( + sprintf('Store with the name "%s" already exists', $name) + ); + } + + $config->setName($name); + $config->setDescription($description); + + try { + $config->save(); + } catch (Exception $e) { + throw new ElementSavingFailedException($id, $e->getMessage(), $e); + } + + return $config; + } +} diff --git a/src/ClassificationStore/Repository/Configuration/StoreRepositoryInterface.php b/src/ClassificationStore/Repository/Configuration/StoreRepositoryInterface.php new file mode 100644 index 000000000..e7b6c1419 --- /dev/null +++ b/src/ClassificationStore/Repository/Configuration/StoreRepositoryInterface.php @@ -0,0 +1,48 @@ +applyGroupIdsFilter($listing, $groupIds); if ($searchTerm !== null && $searchTerm !== '') { - $this->applySearchTermFilter($listing, $searchTerm); + $this->searchHelperService->applyKeyGroupRelationSearchFilter($listing, $searchTerm); } return $listing; } - 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 { if (empty($groupIds)) { diff --git a/src/ClassificationStore/Schema/Collection.php b/src/ClassificationStore/Schema/Collection.php index eff31a713..7c8ae78ec 100644 --- a/src/ClassificationStore/Schema/Collection.php +++ b/src/ClassificationStore/Schema/Collection.php @@ -23,6 +23,8 @@ required: [ 'id', 'name', + 'description', + 'groups', ], type: 'object' )] diff --git a/src/ClassificationStore/Schema/Configuration/CollectionCreate.php b/src/ClassificationStore/Schema/Configuration/CollectionCreate.php new file mode 100644 index 000000000..a863da0d7 --- /dev/null +++ b/src/ClassificationStore/Schema/Configuration/CollectionCreate.php @@ -0,0 +1,54 @@ +name)) { + throw new InvalidArgumentException('Name cannot be empty.'); + } + } + + public function getName(): string + { + return $this->name; + } + + public function getStoreId(): int + { + return $this->storeId; + } +} diff --git a/src/ClassificationStore/Schema/Configuration/CollectionDetail.php b/src/ClassificationStore/Schema/Configuration/CollectionDetail.php new file mode 100644 index 000000000..829e9068f --- /dev/null +++ b/src/ClassificationStore/Schema/Configuration/CollectionDetail.php @@ -0,0 +1,76 @@ +id; + } + + public function getName(): string + { + return $this->name; + } + + public function getStoreId(): int + { + return $this->storeId; + } + + public function getDescription(): ?string + { + return $this->description; + } + + public function getCreationDate(): ?int + { + return $this->creationDate; + } + + public function getModificationDate(): ?int + { + return $this->modificationDate; + } +} diff --git a/src/ClassificationStore/Schema/Configuration/CollectionRelationCreate.php b/src/ClassificationStore/Schema/Configuration/CollectionRelationCreate.php new file mode 100644 index 000000000..987eb34f8 --- /dev/null +++ b/src/ClassificationStore/Schema/Configuration/CollectionRelationCreate.php @@ -0,0 +1,54 @@ +colId; + } + + public function getGroupId(): int + { + return $this->groupId; + } + + public function getSorter(): int + { + return $this->sorter; + } +} diff --git a/src/ClassificationStore/Schema/Configuration/CollectionRelationDelete.php b/src/ClassificationStore/Schema/Configuration/CollectionRelationDelete.php new file mode 100644 index 000000000..613191d25 --- /dev/null +++ b/src/ClassificationStore/Schema/Configuration/CollectionRelationDelete.php @@ -0,0 +1,47 @@ +colId; + } + + public function getGroupId(): int + { + return $this->groupId; + } +} diff --git a/src/ClassificationStore/Schema/Configuration/CollectionRelationDetail.php b/src/ClassificationStore/Schema/Configuration/CollectionRelationDetail.php new file mode 100644 index 000000000..75eb416ce --- /dev/null +++ b/src/ClassificationStore/Schema/Configuration/CollectionRelationDetail.php @@ -0,0 +1,76 @@ +id; + } + + public function getColId(): int + { + return $this->colId; + } + + public function getGroupId(): int + { + return $this->groupId; + } + + public function getSorter(): int + { + return $this->sorter; + } + + public function getGroupName(): ?string + { + return $this->groupName; + } + + public function getGroupDescription(): ?string + { + return $this->groupDescription; + } +} diff --git a/src/ClassificationStore/Schema/Configuration/CollectionUpdate.php b/src/ClassificationStore/Schema/Configuration/CollectionUpdate.php new file mode 100644 index 000000000..2a45eae17 --- /dev/null +++ b/src/ClassificationStore/Schema/Configuration/CollectionUpdate.php @@ -0,0 +1,54 @@ +name)) { + throw new InvalidArgumentException('Name cannot be empty.'); + } + } + + public function getName(): string + { + return $this->name; + } + + public function getDescription(): ?string + { + return $this->description; + } +} diff --git a/src/ClassificationStore/Schema/Configuration/GetPageParameters.php b/src/ClassificationStore/Schema/Configuration/GetPageParameters.php new file mode 100644 index 000000000..22be07b7b --- /dev/null +++ b/src/ClassificationStore/Schema/Configuration/GetPageParameters.php @@ -0,0 +1,60 @@ +table; + } + + public function getId(): int + { + return $this->id; + } + + public function getStoreId(): int + { + return $this->storeId; + } + + public function getPageSize(): int + { + return $this->pageSize; + } + + public function getSortKey(): string + { + return $this->sortKey; + } + + public function getSortDir(): string + { + return $this->sortDir; + } +} diff --git a/src/ClassificationStore/Schema/Configuration/GetPageResponse.php b/src/ClassificationStore/Schema/Configuration/GetPageResponse.php new file mode 100644 index 000000000..63a8528c9 --- /dev/null +++ b/src/ClassificationStore/Schema/Configuration/GetPageResponse.php @@ -0,0 +1,44 @@ +page; + } +} diff --git a/src/ClassificationStore/Schema/Configuration/GroupCreate.php b/src/ClassificationStore/Schema/Configuration/GroupCreate.php new file mode 100644 index 000000000..6fbcaebf9 --- /dev/null +++ b/src/ClassificationStore/Schema/Configuration/GroupCreate.php @@ -0,0 +1,54 @@ +name)) { + throw new InvalidArgumentException('Name cannot be empty.'); + } + } + + public function getName(): string + { + return $this->name; + } + + public function getStoreId(): int + { + return $this->storeId; + } +} diff --git a/src/ClassificationStore/Schema/Configuration/GroupDetail.php b/src/ClassificationStore/Schema/Configuration/GroupDetail.php new file mode 100644 index 000000000..7032b9e53 --- /dev/null +++ b/src/ClassificationStore/Schema/Configuration/GroupDetail.php @@ -0,0 +1,76 @@ +id; + } + + public function getName(): string + { + return $this->name; + } + + public function getStoreId(): int + { + return $this->storeId; + } + + public function getDescription(): ?string + { + return $this->description; + } + + public function getCreationDate(): ?int + { + return $this->creationDate; + } + + public function getModificationDate(): ?int + { + return $this->modificationDate; + } +} diff --git a/src/ClassificationStore/Schema/Configuration/GroupUpdate.php b/src/ClassificationStore/Schema/Configuration/GroupUpdate.php new file mode 100644 index 000000000..79bc69a95 --- /dev/null +++ b/src/ClassificationStore/Schema/Configuration/GroupUpdate.php @@ -0,0 +1,54 @@ +name)) { + throw new InvalidArgumentException('Name cannot be empty.'); + } + } + + public function getName(): string + { + return $this->name; + } + + public function getDescription(): ?string + { + return $this->description; + } +} diff --git a/src/ClassificationStore/Schema/Configuration/KeyCreate.php b/src/ClassificationStore/Schema/Configuration/KeyCreate.php new file mode 100644 index 000000000..0b4234b94 --- /dev/null +++ b/src/ClassificationStore/Schema/Configuration/KeyCreate.php @@ -0,0 +1,54 @@ +name)) { + throw new InvalidArgumentException('Name cannot be empty.'); + } + } + + public function getName(): string + { + return $this->name; + } + + public function getStoreId(): int + { + return $this->storeId; + } +} diff --git a/src/ClassificationStore/Schema/Configuration/KeyDetail.php b/src/ClassificationStore/Schema/Configuration/KeyDetail.php new file mode 100644 index 000000000..6295d133f --- /dev/null +++ b/src/ClassificationStore/Schema/Configuration/KeyDetail.php @@ -0,0 +1,100 @@ +id; + } + + public function getName(): string + { + return $this->name; + } + + public function getStoreId(): int + { + return $this->storeId; + } + + public function getType(): string + { + return $this->type; + } + + public function isEnabled(): bool + { + return $this->enabled; + } + + public function getDescription(): ?string + { + return $this->description; + } + + public function getDefinition(): ?array + { + return $this->definition; + } + + public function getCreationDate(): ?int + { + return $this->creationDate; + } + + public function getModificationDate(): ?int + { + return $this->modificationDate; + } +} diff --git a/src/ClassificationStore/Schema/Configuration/KeyGroupRelationCreate.php b/src/ClassificationStore/Schema/Configuration/KeyGroupRelationCreate.php new file mode 100644 index 000000000..6efac8932 --- /dev/null +++ b/src/ClassificationStore/Schema/Configuration/KeyGroupRelationCreate.php @@ -0,0 +1,61 @@ +keyId; + } + + public function getGroupId(): int + { + return $this->groupId; + } + + public function getSorter(): int + { + return $this->sorter; + } + + public function isMandatory(): bool + { + return $this->mandatory; + } +} diff --git a/src/ClassificationStore/Schema/Configuration/KeyGroupRelationDelete.php b/src/ClassificationStore/Schema/Configuration/KeyGroupRelationDelete.php new file mode 100644 index 000000000..af3150821 --- /dev/null +++ b/src/ClassificationStore/Schema/Configuration/KeyGroupRelationDelete.php @@ -0,0 +1,47 @@ +keyId; + } + + public function getGroupId(): int + { + return $this->groupId; + } +} diff --git a/src/ClassificationStore/Schema/Configuration/KeyGroupRelationDetail.php b/src/ClassificationStore/Schema/Configuration/KeyGroupRelationDetail.php new file mode 100644 index 000000000..e6f40a85d --- /dev/null +++ b/src/ClassificationStore/Schema/Configuration/KeyGroupRelationDetail.php @@ -0,0 +1,83 @@ +keyId; + } + + public function getGroupId(): int + { + return $this->groupId; + } + + public function getSorter(): int + { + return $this->sorter; + } + + public function isMandatory(): bool + { + return $this->mandatory; + } + + public function getKeyName(): ?string + { + return $this->keyName; + } + + public function getKeyDescription(): ?string + { + return $this->keyDescription; + } + + public function getGroupName(): ?string + { + return $this->groupName; + } +} diff --git a/src/ClassificationStore/Schema/Configuration/KeyUpdate.php b/src/ClassificationStore/Schema/Configuration/KeyUpdate.php new file mode 100644 index 000000000..3f092b403 --- /dev/null +++ b/src/ClassificationStore/Schema/Configuration/KeyUpdate.php @@ -0,0 +1,112 @@ + 'weight', + 'datatype' => 'data', + 'fieldtype' => 'quantityValue', + 'title' => 'Weight', + 'tooltip' => '', + 'mandatory' => false, + 'index' => false, + 'noteditable' => false, + 'invisible' => false, + 'visibleGridView' => false, + 'visibleSearch' => false, + 'style' => '', + 'width' => '', + 'unitWidth' => '', + 'defaultValue' => null, + 'defaultUnit' => null, + 'defaultValueGenerator' => '', + 'validUnits' => [ + 'kg', + ], + 'autoConvert' => false, + 'decimalSize' => null, + 'decimalPrecision' => null, + 'integer' => false, + 'unsigned' => false, + 'minValue' => null, + 'maxValue' => null, + 'displayfield-1596-inputEl' => 'The width of this component.', + ] + )] + private ?array $definition = null, + ) { + if (empty($this->name)) { + throw new InvalidArgumentException('Name cannot be empty.'); + } + } + + public function getName(): string + { + return $this->name; + } + + public function getTitle(): ?string + { + return $this->title; + } + + public function getDescription(): ?string + { + return $this->description; + } + + public function getType(): ?string + { + return $this->type; + } + + public function getDefinition(): ?array + { + return $this->definition; + } +} diff --git a/src/ClassificationStore/Schema/Configuration/StoreCreate.php b/src/ClassificationStore/Schema/Configuration/StoreCreate.php new file mode 100644 index 000000000..b50d76a90 --- /dev/null +++ b/src/ClassificationStore/Schema/Configuration/StoreCreate.php @@ -0,0 +1,47 @@ +name)) { + throw new InvalidArgumentException('Name cannot be empty.'); + } + } + + public function getName(): string + { + return $this->name; + } +} diff --git a/src/ClassificationStore/Schema/Configuration/StoreDetail.php b/src/ClassificationStore/Schema/Configuration/StoreDetail.php new file mode 100644 index 000000000..febf46ee5 --- /dev/null +++ b/src/ClassificationStore/Schema/Configuration/StoreDetail.php @@ -0,0 +1,55 @@ +id; + } + + public function getName(): string + { + return $this->name; + } + + public function getDescription(): ?string + { + return $this->description; + } +} diff --git a/src/ClassificationStore/Schema/Configuration/StoreTreeNode.php b/src/ClassificationStore/Schema/Configuration/StoreTreeNode.php new file mode 100644 index 000000000..e37a5fcd0 --- /dev/null +++ b/src/ClassificationStore/Schema/Configuration/StoreTreeNode.php @@ -0,0 +1,55 @@ +id; + } + + public function getName(): string + { + return $this->name; + } + + public function getDescription(): ?string + { + return $this->description; + } +} diff --git a/src/ClassificationStore/Schema/Configuration/StoreUpdate.php b/src/ClassificationStore/Schema/Configuration/StoreUpdate.php new file mode 100644 index 000000000..24cefb91a --- /dev/null +++ b/src/ClassificationStore/Schema/Configuration/StoreUpdate.php @@ -0,0 +1,54 @@ +name)) { + throw new InvalidArgumentException('Name cannot be empty.'); + } + } + + public function getName(): string + { + return $this->name; + } + + public function getDescription(): ?string + { + return $this->description; + } +} diff --git a/src/ClassificationStore/Schema/Group.php b/src/ClassificationStore/Schema/Group.php index 9a9046a70..31c52982d 100644 --- a/src/ClassificationStore/Schema/Group.php +++ b/src/ClassificationStore/Schema/Group.php @@ -23,6 +23,7 @@ required: [ 'id', 'name', + 'description', ], type: 'object' )] diff --git a/src/ClassificationStore/Schema/GroupLayout.php b/src/ClassificationStore/Schema/GroupLayout.php index e9dac2a80..9e5082f3b 100644 --- a/src/ClassificationStore/Schema/GroupLayout.php +++ b/src/ClassificationStore/Schema/GroupLayout.php @@ -24,6 +24,7 @@ required: [ 'id', 'name', + 'description', 'keys', ], type: 'object' diff --git a/src/ClassificationStore/Schema/KeyGroupRelation.php b/src/ClassificationStore/Schema/KeyGroupRelation.php index 3d2da23db..85e98b51e 100644 --- a/src/ClassificationStore/Schema/KeyGroupRelation.php +++ b/src/ClassificationStore/Schema/KeyGroupRelation.php @@ -25,6 +25,8 @@ 'groupId', 'keyName', 'groupName', + 'keyDescription', + 'groupDescription', ], type: 'object' )] diff --git a/src/ClassificationStore/Service/Configuration/CollectionRelationService.php b/src/ClassificationStore/Service/Configuration/CollectionRelationService.php new file mode 100644 index 000000000..e1868020a --- /dev/null +++ b/src/ClassificationStore/Service/Configuration/CollectionRelationService.php @@ -0,0 +1,118 @@ +collectionRelationRepository->getListing( + $this->filterMapper->getFilterParameters($parameters), + $colId + ); + $relations = $listing->load(); + $items = []; + + foreach ($relations as $relation) { + [$groupName, $groupDescription] = $this->resolveGroupInfo( + $relation->getGroupId(), + $this->groupConfigurationRepository + ); + $items[] = $this->getHydratedCollectionRelationDetail($relation, $groupName, $groupDescription); + } + + return new Collection( + $listing->getTotalCount(), + $items + ); + } + + /** + * {@inheritdoc} + */ + public function createOrUpdateCollectionRelation( + CollectionRelationCreate $parameters + ): CollectionRelationDetail { + $relation = $this->collectionRelationRepository->createOrUpdate( + $parameters->getColId(), + $parameters->getGroupId(), + $parameters->getSorter() + ); + + [$groupName, $groupDescription] = $this->resolveGroupInfo( + $relation->getGroupId(), + $this->groupConfigurationRepository + ); + + return $this->getHydratedCollectionRelationDetail($relation, $groupName, $groupDescription); + } + + /** + * {@inheritdoc} + */ + public function deleteCollectionRelation(int $colId, int $groupId): void + { + $this->collectionRelationRepository->delete($colId, $groupId); + } + + private function getHydratedCollectionRelationDetail( + CollectionGroupRelation $relation, + ?string $groupName = null, + ?string $groupDescription = null, + ): CollectionRelationDetail { + $detail = $this->collectionRelationHydrator->hydrateCollectionRelationDetail( + $relation, + $groupName, + $groupDescription, + ); + $this->eventDispatcher->dispatch( + new CollectionRelationDetailEvent($detail), + CollectionRelationDetailEvent::EVENT_NAME + ); + + return $detail; + } +} diff --git a/src/ClassificationStore/Service/Configuration/CollectionRelationServiceInterface.php b/src/ClassificationStore/Service/Configuration/CollectionRelationServiceInterface.php new file mode 100644 index 000000000..306459cab --- /dev/null +++ b/src/ClassificationStore/Service/Configuration/CollectionRelationServiceInterface.php @@ -0,0 +1,48 @@ +collectionConfigurationRepository->getListing( + $this->filterMapper->getFilterParameters($parameters), + $storeId + ); + $configs = $listing->load(); + $items = []; + + foreach ($configs as $config) { + $items[] = $this->getHydratedCollectionDetail($config); + } + + return new Collection( + $listing->getTotalCount(), + $items + ); + } + + /** + * {@inheritdoc} + */ + public function createCollection(CollectionCreate $parameters): CollectionDetail + { + $collectionConfig = $this->collectionConfigurationRepository->create( + $parameters->getName(), + $parameters->getStoreId() + ); + + return $this->getHydratedCollectionDetail($collectionConfig); + } + + /** + * {@inheritdoc} + */ + public function updateCollection(int $id, CollectionUpdate $parameters): CollectionDetail + { + $collectionConfig = $this->collectionConfigurationRepository->update( + $id, + $parameters->getName(), + $parameters->getDescription(), + ); + + return $this->getHydratedCollectionDetail($collectionConfig); + } + + /** + * {@inheritdoc} + */ + public function deleteCollection(int $id): void + { + $this->collectionConfigurationRepository->delete($id); + } + + private function getHydratedCollectionDetail(CollectionConfig $collectionConfig): CollectionDetail + { + $collectionDetail = $this->collectionHydrator->hydrateCollectionDetail($collectionConfig); + $this->eventDispatcher->dispatch( + new CollectionDetailEvent($collectionDetail), + CollectionDetailEvent::EVENT_NAME + ); + + return $collectionDetail; + } +} diff --git a/src/ClassificationStore/Service/Configuration/CollectionServiceInterface.php b/src/ClassificationStore/Service/Configuration/CollectionServiceInterface.php new file mode 100644 index 000000000..16c457958 --- /dev/null +++ b/src/ClassificationStore/Service/Configuration/CollectionServiceInterface.php @@ -0,0 +1,54 @@ +groupConfigurationRepository->getListing( + $this->filterMapper->getFilterParameters($parameters), + $storeId + ); + $configs = $listing->load(); + $items = []; + + foreach ($configs as $config) { + $items[] = $this->getHydratedGroupDetail($config); + } + + return new Collection( + $listing->getTotalCount(), + $items + ); + } + + /** + * {@inheritdoc} + */ + public function createGroup(GroupCreate $parameters): GroupDetail + { + $groupConfig = $this->groupConfigurationRepository->create( + $parameters->getName(), + $parameters->getStoreId() + ); + + return $this->getHydratedGroupDetail($groupConfig); + } + + /** + * {@inheritdoc} + */ + public function updateGroup(int $id, GroupUpdate $parameters): GroupDetail + { + $groupConfig = $this->groupConfigurationRepository->update( + $id, + $parameters->getName(), + $parameters->getDescription(), + ); + + return $this->getHydratedGroupDetail($groupConfig); + } + + /** + * {@inheritdoc} + */ + public function deleteGroup(int $id): void + { + $this->groupConfigurationRepository->delete($id); + } + + private function getHydratedGroupDetail(GroupConfig $groupConfig): GroupDetail + { + $groupDetail = $this->groupHydrator->hydrateGroupDetail($groupConfig); + $this->eventDispatcher->dispatch( + new GroupDetailEvent($groupDetail), + GroupDetailEvent::EVENT_NAME + ); + + return $groupDetail; + } +} diff --git a/src/ClassificationStore/Service/Configuration/GroupServiceInterface.php b/src/ClassificationStore/Service/Configuration/GroupServiceInterface.php new file mode 100644 index 000000000..fcffaf311 --- /dev/null +++ b/src/ClassificationStore/Service/Configuration/GroupServiceInterface.php @@ -0,0 +1,54 @@ +keyGroupRelationRepository->getListingByGroupId( + $this->filterMapper->getFilterParameters($parameters), + $groupId + ); + $relations = $listing->load(); + $items = []; + + foreach ($relations as $relation) { + [$keyName, $keyDescription] = $this->resolveKeyInfo($relation->getKeyId()); + $items[] = $this->getHydratedKeyGroupRelationDetail($relation, $keyName, $keyDescription); + } + + return new Collection( + $listing->getTotalCount(), + $items + ); + } + + /** + * {@inheritdoc} + */ + public function createOrUpdateKeyGroupRelation( + KeyGroupRelationCreate $parameters + ): KeyGroupRelationDetail { + $relation = $this->keyGroupRelationRepository->createOrUpdate( + $parameters->getKeyId(), + $parameters->getGroupId(), + $parameters->getSorter(), + $parameters->isMandatory() + ); + + [$keyName, $keyDescription] = $this->resolveKeyInfo($relation->getKeyId()); + + return $this->getHydratedKeyGroupRelationDetail($relation, $keyName, $keyDescription); + } + + /** + * {@inheritdoc} + */ + public function deleteKeyGroupRelation(int $keyId, int $groupId): void + { + $this->keyGroupRelationRepository->delete($keyId, $groupId); + } + + private function getHydratedKeyGroupRelationDetail( + KeyGroupRelation $relation, + ?string $keyName = null, + ?string $keyDescription = null + ): KeyGroupRelationDetail { + $detail = $this->keyGroupRelationHydrator->hydrateKeyGroupRelationDetail( + $relation, + $keyName, + $keyDescription, + $this->resolveGroupName($relation->getGroupId(), $this->groupConfigurationRepository), + ); + $this->eventDispatcher->dispatch( + new KeyGroupRelationDetailEvent($detail), + KeyGroupRelationDetailEvent::EVENT_NAME + ); + + return $detail; + } + + /** + * @return array{0: ?string, 1: ?string} [keyName, keyDescription] + */ + private function resolveKeyInfo(int $keyId): array + { + try { + $keyConfig = $this->keyConfigurationRepository->getById($keyId); + + return [$keyConfig->getName(), $keyConfig->getDescription()]; + } catch (NotFoundException) { + return [null, null]; + } + } +} diff --git a/src/ClassificationStore/Service/Configuration/KeyGroupRelationServiceInterface.php b/src/ClassificationStore/Service/Configuration/KeyGroupRelationServiceInterface.php new file mode 100644 index 000000000..0cfd82e42 --- /dev/null +++ b/src/ClassificationStore/Service/Configuration/KeyGroupRelationServiceInterface.php @@ -0,0 +1,44 @@ +keyConfigurationRepository->getListing( + $this->filterMapper->getFilterParameters($parameters), + $storeId + ); + $configs = $listing->load(); + $items = []; + + foreach ($configs as $config) { + $items[] = $this->getHydratedKeyDetail($config); + } + + return new Collection( + $listing->getTotalCount(), + $items + ); + } + + /** + * {@inheritdoc} + */ + public function createKey(KeyCreate $parameters): KeyDetail + { + $keyConfig = $this->keyConfigurationRepository->create( + $parameters->getName(), + $parameters->getStoreId() + ); + + return $this->getHydratedKeyDetail($keyConfig); + } + + /** + * {@inheritdoc} + */ + public function updateKey(int $id, KeyUpdate $parameters): KeyDetail + { + $keyConfig = $this->keyConfigurationRepository->update( + $id, + $parameters->getName(), + $parameters->getTitle(), + $parameters->getDescription(), + $parameters->getType(), + $parameters->getDefinition(), + ); + + return $this->getHydratedKeyDetail($keyConfig); + } + + /** + * {@inheritdoc} + */ + public function softDeleteKey(int $id): void + { + $this->keyConfigurationRepository->softDelete($id); + } + + /** + * {@inheritdoc} + */ + public function getPage(GetPageParameters $parameters): GetPageResponse + { + $page = $this->keyConfigurationRepository->getPageForId( + $parameters->getTable(), + $parameters->getId(), + $parameters->getStoreId(), + $parameters->getPageSize(), + $parameters->getSortKey(), + $parameters->getSortDir(), + ); + $response = $this->keyHydrator->hydrateGetPageResponse($page); + $this->eventDispatcher->dispatch( + new GetPageEvent($response), + GetPageEvent::EVENT_NAME + ); + + return $response; + } + + private function getHydratedKeyDetail(KeyConfig $keyConfig): KeyDetail + { + $keyDetail = $this->keyHydrator->hydrateKeyDetail($keyConfig); + $this->eventDispatcher->dispatch( + new KeyDetailEvent($keyDetail), + KeyDetailEvent::EVENT_NAME + ); + + return $keyDetail; + } +} diff --git a/src/ClassificationStore/Service/Configuration/KeyServiceInterface.php b/src/ClassificationStore/Service/Configuration/KeyServiceInterface.php new file mode 100644 index 000000000..3e8e6a4a6 --- /dev/null +++ b/src/ClassificationStore/Service/Configuration/KeyServiceInterface.php @@ -0,0 +1,64 @@ +storeConfigurationRepository->create($parameters->getName()); + + return $this->getHydratedStoreDetail($storeConfig); + } + + /** + * {@inheritdoc} + */ + public function updateStore(int $id, StoreUpdate $parameters): StoreDetail + { + $storeConfig = $this->storeConfigurationRepository->update( + $id, + $parameters->getName(), + $parameters->getDescription(), + ); + + return $this->getHydratedStoreDetail($storeConfig); + } + + /** + * {@inheritdoc} + */ + public function getStoreTree(): array + { + $stores = $this->storeConfigurationRepository->listStores(); + $treeNodes = []; + + foreach ($stores as $store) { + $treeNode = $this->storeHydrator->hydrateStoreTreeNode($store); + $this->eventDispatcher->dispatch( + new StoreTreeNodeEvent($treeNode), + StoreTreeNodeEvent::EVENT_NAME + ); + $treeNodes[] = $treeNode; + } + + return $treeNodes; + } + + private function getHydratedStoreDetail(StoreConfig $storeConfig): StoreDetail + { + $storeDetail = $this->storeHydrator->hydrateStoreDetail($storeConfig); + $this->eventDispatcher->dispatch( + new StoreDetailEvent($storeDetail), + StoreDetailEvent::EVENT_NAME + ); + + return $storeDetail; + } +} diff --git a/src/ClassificationStore/Service/Configuration/StoreServiceInterface.php b/src/ClassificationStore/Service/Configuration/StoreServiceInterface.php new file mode 100644 index 000000000..be880a57c --- /dev/null +++ b/src/ClassificationStore/Service/Configuration/StoreServiceInterface.php @@ -0,0 +1,46 @@ +addConditionParam('(' . implode(' OR ', $conditions) . ')', $preparedSearchTerms); } + public function applyKeySearchFilter(KeyConfigListing $listing, string $searchTerm): void + { + $listing->addConditionParam( + '(name LIKE ? OR description LIKE ?)', + ['%' . $searchTerm . '%', '%' . $searchTerm . '%'] + ); + } + + public function applyKeyGroupRelationSearchFilter( + KeyGroupRelationListing $listing, + string $searchTerm, + ): void { + $searchTerms = $this->getTranslatedSearchFilterTerms($searchTerm); + $searchFilterConditions = []; + + foreach ($searchTerms as $term) { + $searchFilterConditions[] = + KeyConfigDao::TABLE_NAME_KEYS . '.name LIKE ' . $listing->quote('%' . $term . '%') + . ' OR ' + . GroupConfigDao::TABLE_NAME_GROUPS . '.name LIKE ' . $listing->quote('%' . $term . '%') + . ' OR ' + . KeyConfigDao::TABLE_NAME_KEYS . '.description LIKE ' . $listing->quote('%' . $term . '%'); + } + + $listing->setResolveGroupName(true); + $listing->addConditionParam('(' . implode(' OR ', $searchFilterConditions) . ')'); + } + public function getTranslatedSearchFilterTerms(string $searchTerm): array { try { diff --git a/src/ClassificationStore/Service/SearchHelperServiceInterface.php b/src/ClassificationStore/Service/SearchHelperServiceInterface.php index 859befeb3..3b32bcc4e 100644 --- a/src/ClassificationStore/Service/SearchHelperServiceInterface.php +++ b/src/ClassificationStore/Service/SearchHelperServiceInterface.php @@ -15,6 +15,8 @@ use Pimcore\Model\DataObject\Classificationstore\CollectionConfig\Listing as CollectionConfigListing; use Pimcore\Model\DataObject\Classificationstore\GroupConfig\Listing as GroupConfigListing; +use Pimcore\Model\DataObject\Classificationstore\KeyConfig\Listing as KeyConfigListing; +use Pimcore\Model\DataObject\Classificationstore\KeyGroupRelation\Listing as KeyGroupRelationListing; /** * @internal @@ -23,5 +25,12 @@ interface SearchHelperServiceInterface { public function applySearchTermFilter(GroupConfigListing|CollectionConfigListing $list, string $searchTerm): void; + public function applyKeySearchFilter(KeyConfigListing $listing, string $searchTerm): void; + + public function applyKeyGroupRelationSearchFilter( + KeyGroupRelationListing $listing, + string $searchTerm, + ): void; + public function getTranslatedSearchFilterTerms(string $searchTerm): array; } diff --git a/src/ClassificationStore/Service/StoreService.php b/src/ClassificationStore/Service/StoreService.php index 697c7b25a..dc8da089d 100644 --- a/src/ClassificationStore/Service/StoreService.php +++ b/src/ClassificationStore/Service/StoreService.php @@ -13,43 +13,22 @@ namespace Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Service; -use Pimcore\Bundle\StaticResolverBundle\Models\DataObject\ClassDefinitionResolverInterface; -use Pimcore\Bundle\StaticResolverBundle\Models\DataObject\ConcreteObjectResolver; -use Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Event\GroupEvent; -use Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Event\GroupLayoutEvent; use Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Event\StoreConfigEvent; -use Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Hydrator\GroupHydratorInterface; -use Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Hydrator\GroupLayoutHydratorInterface; use Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Hydrator\StoreConfigHydratorInterface; -use Pimcore\Bundle\StudioBackendBundle\ClassificationStore\MappedParameter\LayoutParameter; -use Pimcore\Bundle\StudioBackendBundle\ClassificationStore\MappedParameter\ListClassificationStoreParameter; -use Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Repository\GroupConfigRepositoryInterface; -use Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Repository\KeyGroupRelationRepositoryInterface; -use Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Repository\StoreRepositoryInterface; -use Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Schema\GroupLayout; -use Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Schema\KeyLayout; -use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException; +use Pimcore\Bundle\StudioBackendBundle\ClassificationStore\Repository\Configuration\StoreRepositoryInterface; use Pimcore\Bundle\StudioBackendBundle\Response\Collection; -use Pimcore\Model\DataObject\ClassDefinition\Data\Classificationstore; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use function count; /** * @internal */ -final readonly class StoreService implements StoreServiceInterface, GroupServiceInterface +final readonly class StoreService implements StoreServiceInterface { public function __construct( private StoreRepositoryInterface $storeRepository, - private ConcreteObjectResolver $concreteObjectResolver, - private GroupConfigRepositoryInterface $groupConfigRepository, private EventDispatcherInterface $eventDispatcher, - private GroupHydratorInterface $groupHydrator, private StoreConfigHydratorInterface $storeConfigHydrator, - private KeyGroupRelationRepositoryInterface $keyGroupRelationRepository, - private KeyGroupLayoutServiceInterface $keyGroupLayoutService, - private GroupLayoutHydratorInterface $groupLayoutHydrator, - private ClassDefinitionResolverInterface $classDefinitionResolver, ) { } @@ -68,101 +47,4 @@ public function listStores(): Collection return new Collection(count($stores), $stores); } - - /** - * {@inheritdoc} - */ - public function getGroups(ListClassificationStoreParameter $parameter): Collection - { - $allowedGroupIds = $this->getAllowedGroupIds($parameter); - - if (count($allowedGroupIds) === 0) { - $allowedGroupIds = null; - } - - $groups = $this->groupConfigRepository->getPaginatedGroupsByStore( - $parameter->getStoreId(), - $parameter, - $allowedGroupIds, - $parameter->getSearchTerm() - ); - - $hydratedGroups = []; - foreach ($groups as $group) { - $hydratedGroup = $this->groupHydrator->hydrate($group); - $this->eventDispatcher->dispatch( - new GroupEvent($hydratedGroup), - GroupEvent::EVENT_NAME - ); - $hydratedGroups[] = $hydratedGroup; - } - - return new Collection( - totalItems: $this->groupConfigRepository->getCountByStoreId($parameter->getStoreId()), - items: $hydratedGroups - ); - } - - /** - * {@inheritdoc} - */ - public function getAllowedGroupIds(ListClassificationStoreParameter $parameter): array - { - if (!$parameter->getClassId()) { - return []; - } - - $class = $this->classDefinitionResolver->getById($parameter->getClassId()); - - if (!$class) { - throw new NotFoundException('Class', $parameter->getClassId()); - } - - $fieldDefinition = $class->getFieldDefinition($parameter->getFieldName()); - - if (!$fieldDefinition instanceof Classificationstore) { - throw new NotFoundException('field', $parameter->getFieldName()); - } - - return $fieldDefinition->getAllowedGroupIds(); - } - - /** - * {@inheritdoc} - */ - public function getLayoutDefinition(int $groupId, LayoutParameter $layoutParameter): GroupLayout - { - $keys = $this->keyGroupRelationRepository->getByGroupId($groupId); - $object = $this->concreteObjectResolver->getById($layoutParameter->getObjectId()); - - if (!$object) { - throw new NotFoundException('object', $layoutParameter->getObjectId()); - } - - $keyLayouts = []; - foreach ($keys as $key) { - $definition = $this->keyGroupLayoutService->getLayoutDefinition( - $key, - $layoutParameter->getFieldName(), - $object - ); - - $keyLayouts[] = new KeyLayout( - id: $key->getKeyId(), - name: $key->getName(), - description: $key->getDescription(), - definition: $definition, - ); - } - - $group = $this->groupConfigRepository->getById($groupId); - $groupLayout = $this->groupLayoutHydrator->hydrate($keyLayouts, $group); - - $this->eventDispatcher->dispatch( - new GroupLayoutEvent($groupLayout), - GroupLayoutEvent::EVENT_NAME - ); - - return $groupLayout; - } } diff --git a/src/ClassificationStore/Util/Trait/GroupInfoResolverTrait.php b/src/ClassificationStore/Util/Trait/GroupInfoResolverTrait.php new file mode 100644 index 000000000..524486ea9 --- /dev/null +++ b/src/ClassificationStore/Util/Trait/GroupInfoResolverTrait.php @@ -0,0 +1,63 @@ +getById($groupId); + + return [$groupConfig->getName(), $groupConfig->getDescription()]; + } catch (NotFoundException) { + return [null, null]; + } + } + + private function resolveGroupName(int $groupId, GroupRepositoryInterface $repository): ?string + { + try { + return $repository->getById($groupId)->getName(); + } catch (NotFoundException) { + return null; + } + } + + private function getKeyDefinition(KeyConfig $keyConfig): ?array + { + $definition = $keyConfig->getDefinition(); + + if ($definition === '') { + return null; + } + + try { + return json_decode($definition, true, 512, JSON_THROW_ON_ERROR); + } catch (JsonException) { + return null; + } + } +} diff --git a/src/Util/Constant/UserPermissions.php b/src/Util/Constant/UserPermissions.php index 206685f02..37891f20d 100644 --- a/src/Util/Constant/UserPermissions.php +++ b/src/Util/Constant/UserPermissions.php @@ -53,6 +53,7 @@ enum UserPermissions: string case WIDGET_EDITOR = 'studio_perspective_widget_editor'; case SELECT_OPTIONS = 'selectoptions'; case CLASS_DEFINITION = 'classes'; + case CLASSIFICATION_STORE = 'classificationstore'; case SYSTEM_APPEARANCE_SETTINGS = 'system_appearance_settings'; case SYSTEM_SETTINGS = 'system_settings'; } diff --git a/translations/studio_api_docs.en.yaml b/translations/studio_api_docs.en.yaml index 21bf8b379..37e0e4cbe 100644 --- a/translations/studio_api_docs.en.yaml +++ b/translations/studio_api_docs.en.yaml @@ -1699,6 +1699,90 @@ classification_store_get_layout_by_key_response: Layout definition classification_store_get_layout_by_collection_description: Get Layout definition for given collection classification_store_get_layout_by_collection_summary: Get Layout definition for given collection classification_store_get_layout_by_collection_response: Layout definition +classification_store_configuration_store_create_description: Create a new classification store configuration +classification_store_configuration_store_create_summary: Create a new store +classification_store_configuration_store_create_success_response: Created store configuration +classification_store_configuration_store_update_description: Update an existing classification store configuration by ID +classification_store_configuration_store_update_summary: Update a store +classification_store_configuration_store_update_success_response: Updated store configuration +classification_store_configuration_store_tree_description: Get all classification store configurations as a flat tree list +classification_store_configuration_store_tree_summary: Get store tree +classification_store_configuration_store_tree_success_response: List of store tree nodes +classification_store_configuration_group_collection_description: | + Get a paginated list of classification store group configurations. + You can specify filters, sorting and pagination in the request body. +classification_store_configuration_group_collection_summary: List group configurations +classification_store_configuration_group_collection_success_response: Paginated list of group configurations +classification_store_configuration_group_create_description: Create a new classification store group configuration within a store +classification_store_configuration_group_create_summary: Create a new group +classification_store_configuration_group_create_success_response: Created group configuration +classification_store_configuration_group_update_description: Update an existing classification store group configuration by ID +classification_store_configuration_group_update_summary: Update a group +classification_store_configuration_group_update_success_response: Updated group configuration +classification_store_configuration_group_delete_description: Delete a classification store group configuration by ID +classification_store_configuration_group_delete_summary: Delete a group +classification_store_configuration_group_delete_success_response: Successfully deleted group configuration +classification_store_configuration_key_collection_description: | + Get a paginated list of classification store key configurations. + Supports filtering, sorting, and pagination via the collection request body. +classification_store_configuration_key_collection_summary: List key configurations +classification_store_configuration_key_collection_success_response: Paginated list of key configurations +classification_store_configuration_key_create_description: Create a new classification store key configuration within a store +classification_store_configuration_key_create_summary: Create a new key +classification_store_configuration_key_create_success_response: Created key configuration +classification_store_configuration_key_update_description: Update an existing classification store key configuration by ID +classification_store_configuration_key_update_summary: Update a key +classification_store_configuration_key_update_success_response: Updated key configuration +classification_store_configuration_key_delete_description: | + Soft-delete a classification store key configuration by ID. + The key is not permanently removed but disabled (enabled is set to false). +classification_store_configuration_key_delete_summary: Disable a key (soft-delete) +classification_store_configuration_key_delete_success_response: Successfully disabled key configuration +classification_store_configuration_collection_collection_description: | + Get a paginated list of classification store collection configurations. + Supports filtering, sorting, and pagination via the collection filter parameter. +classification_store_configuration_collection_collection_summary: List collection configurations +classification_store_configuration_collection_collection_success_response: Paginated list of collection configurations +classification_store_configuration_collection_create_description: Create a new classification store collection configuration with a name and store ID +classification_store_configuration_collection_create_summary: Create a collection +classification_store_configuration_collection_create_success_response: Created collection configuration +classification_store_configuration_collection_update_description: Update an existing classification store collection configuration by ID +classification_store_configuration_collection_update_summary: Update a collection +classification_store_configuration_collection_update_success_response: Updated collection configuration +classification_store_configuration_collection_delete_description: | + Delete a classification store collection configuration by ID. + This also removes all associated collection-group relations. +classification_store_configuration_collection_delete_summary: Delete a collection +classification_store_configuration_collection_delete_success_response: Successfully deleted collection configuration +classification_store_configuration_collection_relation_collection_description: | + List collection-group relations for a given collection ID. + Supports filtering, sorting, and pagination via the collection filter parameter. + The colId query parameter is required. +classification_store_configuration_collection_relation_collection_summary: List collection-group relations +classification_store_configuration_collection_relation_collection_success_response: Paginated list of collection-group relations +classification_store_configuration_collection_relation_create_description: Create or update a collection-group relation with collection ID, group ID, and optional sorter +classification_store_configuration_collection_relation_create_summary: Create or update a collection-group relation +classification_store_configuration_collection_relation_create_success_response: Created or updated collection-group relation +classification_store_configuration_collection_relation_delete_description: Delete a collection-group relation by collection ID and group ID +classification_store_configuration_collection_relation_delete_summary: Delete a collection-group relation +classification_store_configuration_collection_relation_delete_success_response: Successfully deleted collection-group relation +classification_store_configuration_key_group_relation_collection_description: | + List key-group relations for a given group ID. + Supports filtering, sorting, and pagination via the collection filter parameter. + The groupId query parameter is required. Returns key details with layout definition. +classification_store_configuration_key_group_relation_collection_summary: List key-group relations +classification_store_configuration_key_group_relation_collection_success_response: Paginated list of key-group relations +classification_store_configuration_key_group_relation_create_description: Create or update a key-group relation with key ID, group ID, optional sorter and mandatory flag +classification_store_configuration_key_group_relation_create_summary: Create or update a key-group relation +classification_store_configuration_key_group_relation_create_success_response: Created or updated key-group relation +classification_store_configuration_key_group_relation_delete_description: Delete a key-group relation by key ID and group ID +classification_store_configuration_key_group_relation_delete_summary: Delete a key-group relation +classification_store_configuration_key_group_relation_delete_success_response: Successfully deleted key-group relation +classification_store_configuration_get_page_description: | + Calculate the page number where a specific item (key or group) is located within a paginated listing. + Useful for navigating directly to the page containing a specific item. +classification_store_configuration_get_page_summary: Get page number for a specific item +classification_store_configuration_get_page_success_response: Page number where the item is located data_object_get_grid_preview_description: Gives you a preview of an Advanced Column Grid for a given Data Object. data_object_get_grid_preview_summary: Get a preview of an Advanced Column Grid for a given Data Object. data_object_get_grid_preview_success_response: Preview of an Advanced Column Grid for a given Data Object.