From c8d4bb598179a96cd1b0321cc1f65a0481afa675 Mon Sep 17 00:00:00 2001 From: lukmzig <30526586+lukmzig@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:54:07 +0100 Subject: [PATCH] [DataObject]: Add endpoint to list data object layouts (#520) * feat: add endpoint to list data object layouts * Apply php-cs-fixer changes --------- Co-authored-by: lukmzig --- config/data_objects.yaml | 4 + src/DataIndex/Hydrator/HydratorService.php | 2 +- .../Controller/LayoutController.php | 80 ++++++++ .../Event/PreResponse/LayoutEvent.php | 39 ++++ src/DataObject/Schema/Layout.php | 183 ++++++++++++++++++ src/DataObject/Service/LayoutService.php | 109 +++++++++++ .../Service/LayoutServiceInterface.php | 31 +++ src/Icon/Service/IconService.php | 9 + src/Icon/Service/IconServiceInterface.php | 2 + translations/studio_api_docs.en.yaml | 4 + 10 files changed, 462 insertions(+), 1 deletion(-) create mode 100644 src/DataObject/Controller/LayoutController.php create mode 100644 src/DataObject/Event/PreResponse/LayoutEvent.php create mode 100644 src/DataObject/Schema/Layout.php create mode 100644 src/DataObject/Service/LayoutService.php create mode 100644 src/DataObject/Service/LayoutServiceInterface.php diff --git a/config/data_objects.yaml b/config/data_objects.yaml index c95e000e4..c9cf10b11 100644 --- a/config/data_objects.yaml +++ b/config/data_objects.yaml @@ -38,6 +38,9 @@ services: Pimcore\Bundle\StudioBackendBundle\DataObject\Service\DataAdapterLoaderInterface: class: Pimcore\Bundle\StudioBackendBundle\DataObject\Service\Loader\TaggedIteratorDataAdapter + Pimcore\Bundle\StudioBackendBundle\DataObject\Service\LayoutServiceInterface: + class: Pimcore\Bundle\StudioBackendBundle\DataObject\Service\LayoutService + # # Data Adapters # @@ -161,6 +164,7 @@ services: Pimcore\Bundle\StudioBackendBundle\DataObject\Data\Adapter\FieldCollectionsAdapter: tags: [ 'pimcore.studio_backend.data_adapter' ] + # # Handler # diff --git a/src/DataIndex/Hydrator/HydratorService.php b/src/DataIndex/Hydrator/HydratorService.php index a6b157237..2c49636f7 100644 --- a/src/DataIndex/Hydrator/HydratorService.php +++ b/src/DataIndex/Hydrator/HydratorService.php @@ -66,7 +66,7 @@ public function hydrateDataObjects(DataObjectSearchResultItem $item): DataObject return $this->dataObjectHydrator->hydrate($item); } - public function hydradeDocuments(DocumentSearchResultItem $item): IndexDocument + public function hydrateDocuments(DocumentSearchResultItem $item): IndexDocument { // TODO: Add Service Locator for different document types diff --git a/src/DataObject/Controller/LayoutController.php b/src/DataObject/Controller/LayoutController.php new file mode 100644 index 000000000..e9c701fcb --- /dev/null +++ b/src/DataObject/Controller/LayoutController.php @@ -0,0 +1,80 @@ +value)] + #[Get( + path: self::PREFIX . '/data-objects/{id}/layout', + operationId: 'data_object_get_layout_by_id', + description: 'data_object_get_layout_by_id_description', + summary: 'data_object_get_layout_by_id_summary', + tags: [Tags::DataObjects->value] + )] + #[IdParameter(type: 'data-object')] + #[SuccessResponse( + description: 'data_object_get_layout_by_id_success_response', + content: new JsonContent(ref: Layout::class) + )] + #[DefaultResponses([ + HttpResponseCodes::UNAUTHORIZED, + HttpResponseCodes::NOT_FOUND, + ])] + public function getDataObjectLayoutById(int $id): JsonResponse + { + return $this->jsonResponse($this->layoutService->getDataObjectLayout($id)); + } +} diff --git a/src/DataObject/Event/PreResponse/LayoutEvent.php b/src/DataObject/Event/PreResponse/LayoutEvent.php new file mode 100644 index 000000000..8e31ebd4e --- /dev/null +++ b/src/DataObject/Event/PreResponse/LayoutEvent.php @@ -0,0 +1,39 @@ +layout); + } + + /** + * Use this to get additional infos out of the response object + */ + public function getLayout(): Layout + { + return $this->layout; + } +} diff --git a/src/DataObject/Schema/Layout.php b/src/DataObject/Schema/Layout.php new file mode 100644 index 000000000..5aada15f0 --- /dev/null +++ b/src/DataObject/Schema/Layout.php @@ -0,0 +1,183 @@ +name; + } + + public function getTitle(): ?string + { + return $this->title; + } + + public function getDataType(): string + { + return $this->dataType; + } + + public function getFieldType(): string + { + return $this->fieldType; + } + + public function getType(): ?string + { + return $this->type; + } + + public function getLayout(): ?string + { + return $this->layout; + } + + public function getRegion(): ?string + { + return $this->region; + } + + public function getWidth(): int + { + return $this->width; + } + + public function getHeight(): int + { + return $this->height; + } + + public function getCollapsible(): bool + { + return $this->collapsible; + } + + public function getCollapsed(): bool + { + return $this->collapsed; + } + + public function getBodyStyle(): ?string + { + return $this->bodyStyle; + } + + public function getBorder(): bool + { + return $this->border; + } + + public function getIcon(): ?ElementIcon + { + return $this->icon; + } + + public function getLabelWidth(): int + { + return $this->labelWidth; + } + + public function getLabelAlign(): string + { + return $this->labelAlign; + } + + public function getLocked(): bool + { + return $this->locked; + } + + public function getChildren(): array + { + return $this->children; + } +} diff --git a/src/DataObject/Service/LayoutService.php b/src/DataObject/Service/LayoutService.php new file mode 100644 index 000000000..37c99241c --- /dev/null +++ b/src/DataObject/Service/LayoutService.php @@ -0,0 +1,109 @@ +securityService->getCurrentUser(); + $dataObject = $this->dataObjectService->getDataObjectElement( + $user, + $id + ); + + $dataObject = $this->getLatestVersionForUser($dataObject, $user); + if (!$dataObject instanceof Concrete) { + throw new InvalidElementTypeException( + sprintf('DataObject class (%s) is not a concrete object', get_class($dataObject)) + ); + } + + try { + $layout = $dataObject->getClass()->getLayoutDefinitions(); + } catch (Exception) { + throw new NotFoundException(type: 'class for data object', id: $id); + } + + if (!$layout instanceof Panel) { + throw new NotFoundException(type: 'class layout for data object', id: $id); + } + + //ToDo: Consider custom layouts once implemented + $hydratedLayout = $this->hydrateLayout($layout); + $this->eventDispatcher->dispatch(new LayoutEvent($hydratedLayout), LayoutEvent::EVENT_NAME); + + return $hydratedLayout; + } + + private function hydrateLayout( + Panel $panel + ): Layout { + return new Layout( + $panel->getName(), + $panel->getDatatype(), + $panel->fieldtype, + $panel->getType(), + $panel->getLayout(), + $panel->getRegion(), + $panel->getTitle(), + $panel->getWidth(), + $panel->getHeight(), + $panel->getCollapsible(), + $panel->getCollapsed(), + $panel->getBodyStyle(), + $panel->getLocked(), + $panel->getChildren(), + $this->iconService->getIconForLayout($panel->getIcon()), + $panel->getLabelAlign(), + $panel->getLabelWidth(), + $panel->getBorder() + ); + } +} diff --git a/src/DataObject/Service/LayoutServiceInterface.php b/src/DataObject/Service/LayoutServiceInterface.php new file mode 100644 index 000000000..8b3d0b77f --- /dev/null +++ b/src/DataObject/Service/LayoutServiceInterface.php @@ -0,0 +1,31 @@ +value, $iconPath); + } } diff --git a/src/Icon/Service/IconServiceInterface.php b/src/Icon/Service/IconServiceInterface.php index 3f6691966..9b348ad76 100644 --- a/src/Icon/Service/IconServiceInterface.php +++ b/src/Icon/Service/IconServiceInterface.php @@ -26,4 +26,6 @@ public function getIconForAsset(string $assetType, string $mimeType): ElementIco public function getIconForDataObject(DataObjectSearchResultItem $dataObject): ElementIcon; public function getIconForTag(): string; + + public function getIconForLayout(?string $iconPath): ?ElementIcon; } diff --git a/translations/studio_api_docs.en.yaml b/translations/studio_api_docs.en.yaml index 9ba7db82d..9bc445bdb 100644 --- a/translations/studio_api_docs.en.yaml +++ b/translations/studio_api_docs.en.yaml @@ -177,6 +177,10 @@ data_object_get_by_id_description: | Retrieves a specific data object based on the given {id}.
The {id} must be an ID of existing data object or folder. data_object_get_by_id_success_response: Successfully retrieved data object data as JSON data_object_get_by_id_summary: Get a specific data object by ID +data_object_get_layout_by_id_description: | + Retrieves the layout of a specific data object based on the given {id}.
The {id} must be an ID of existing data object. +data_object_get_layout_by_id_success_response: Successfully retrieved data object layout data as JSON +data_object_get_layout_by_id_summary: Get layout of a data object by ID data_object_get_tree_description: | Listing of all data objects and data object folders in the system.
Returns only data which are relevant for the tree