From b15d62d85d8dfff5d5317ad58cfbd264b58196ef Mon Sep 17 00:00:00 2001 From: lukmzig Date: Thu, 28 Nov 2024 15:38:33 +0100 Subject: [PATCH 1/6] feat: add endpoint to list available sites --- config/documents.yaml | 25 ++++++- .../Video/ImageThumbnailStreamController.php | 2 +- .../Attribute/Response/AvailableSitesJson.php | 44 +++++++++++ .../Controller/AvailableSitesController.php | 74 ++++++++++++++++++ src/Document/Event/PreResponse/SiteEvent.php | 39 ++++++++++ .../ExcludeMainSiteParameter.php | 34 +++++++++ .../Query/ExcludeMainSiteParameter.php | 35 +++++++++ src/Document/Repository/SiteRepository.php | 35 +++++++++ .../Repository/SiteRepositoryInterface.php | 29 +++++++ src/Document/Schema/Site.php | 75 +++++++++++++++++++ src/Document/Service/SiteService.php | 70 +++++++++++++++++ src/Document/Service/SiteServiceInterface.php | 31 ++++++++ src/OpenApi/Config/Tags.php | 5 ++ translations/studio_api_docs.en.yaml | 5 ++ 14 files changed, 500 insertions(+), 3 deletions(-) create mode 100644 src/Document/Attribute/Response/AvailableSitesJson.php create mode 100644 src/Document/Controller/AvailableSitesController.php create mode 100644 src/Document/Event/PreResponse/SiteEvent.php create mode 100644 src/Document/MappedParameter/ExcludeMainSiteParameter.php create mode 100644 src/Document/OpenApi/Attribute/Parameter/Query/ExcludeMainSiteParameter.php create mode 100644 src/Document/Repository/SiteRepository.php create mode 100644 src/Document/Repository/SiteRepositoryInterface.php create mode 100644 src/Document/Schema/Site.php create mode 100644 src/Document/Service/SiteService.php create mode 100644 src/Document/Service/SiteServiceInterface.php diff --git a/config/documents.yaml b/config/documents.yaml index 1bce398c..9e073012 100644 --- a/config/documents.yaml +++ b/config/documents.yaml @@ -4,6 +4,27 @@ services: autoconfigure: true public: false - # Secvices + # controllers are imported separately to make sure they're public + # and have a tag that allows actions to type-hint services + Pimcore\Bundle\StudioBackendBundle\Document\Controller\: + resource: '../src/Document/Controller' + public: true + tags: [ 'controller.service_arguments' ] + + # + # Services + # + Pimcore\Bundle\StudioBackendBundle\Document\Service\DocumentServiceInterface: - class: Pimcore\Bundle\StudioBackendBundle\Document\Service\DocumentService \ No newline at end of file + class: Pimcore\Bundle\StudioBackendBundle\Document\Service\DocumentService + + Pimcore\Bundle\StudioBackendBundle\Document\Service\SiteServiceInterface: + class: Pimcore\Bundle\StudioBackendBundle\Document\Service\SiteService + + + # + # Repositories + # + + Pimcore\Bundle\StudioBackendBundle\Document\Repository\SiteRepositoryInterface: + class: Pimcore\Bundle\StudioBackendBundle\Document\Repository\SiteRepository \ No newline at end of file diff --git a/src/Asset/Controller/Video/ImageThumbnailStreamController.php b/src/Asset/Controller/Video/ImageThumbnailStreamController.php index 200af814..828c77ea 100644 --- a/src/Asset/Controller/Video/ImageThumbnailStreamController.php +++ b/src/Asset/Controller/Video/ImageThumbnailStreamController.php @@ -81,7 +81,7 @@ public function __construct( operationId: 'asset_video_image_thumbnail_stream', description: 'asset_video_image_thumbnail_stream_description', summary: 'asset_video_image_thumbnail_stream_summary', - tags: [Tags::Assets->name] + tags: [Tags::Assets->value] )] #[IdParameter(type: 'video')] #[WidthParameter('Width of the video image thumbnail', 265)] diff --git a/src/Document/Attribute/Response/AvailableSitesJson.php b/src/Document/Attribute/Response/AvailableSitesJson.php new file mode 100644 index 00000000..f911b43a --- /dev/null +++ b/src/Document/Attribute/Response/AvailableSitesJson.php @@ -0,0 +1,44 @@ +value)] + #[Get( + path: self::PREFIX . '/documents/sites/list-available', + operationId: 'documents_list_available_sites', + description: 'documents_list_available_sites_description', + summary: 'documents_list_available_sites_summary', + tags: [Tags::Documents->value] + )] + #[ExcludeMainSiteParameter] + #[SuccessResponse( + description: 'documents_list_available_sites_success_response', + content: new AvailableSitesJson() + )] + #[DefaultResponses([ + HttpResponseCodes::UNAUTHORIZED + ])] + public function getAvailableSites( + #[MapQueryString] MappedParameter $parameter + ): JsonResponse { + return $this->jsonResponse(['items' => $this->siteService->getAvailableSites($parameter)]); + } +} diff --git a/src/Document/Event/PreResponse/SiteEvent.php b/src/Document/Event/PreResponse/SiteEvent.php new file mode 100644 index 00000000..d6300e3a --- /dev/null +++ b/src/Document/Event/PreResponse/SiteEvent.php @@ -0,0 +1,39 @@ +site; + } +} diff --git a/src/Document/MappedParameter/ExcludeMainSiteParameter.php b/src/Document/MappedParameter/ExcludeMainSiteParameter.php new file mode 100644 index 00000000..6710a8b8 --- /dev/null +++ b/src/Document/MappedParameter/ExcludeMainSiteParameter.php @@ -0,0 +1,34 @@ +excludeMainSite === 'true'; // TODO: symfony 7.1 will support bool type + } +} diff --git a/src/Document/OpenApi/Attribute/Parameter/Query/ExcludeMainSiteParameter.php b/src/Document/OpenApi/Attribute/Parameter/Query/ExcludeMainSiteParameter.php new file mode 100644 index 00000000..68a8cf55 --- /dev/null +++ b/src/Document/OpenApi/Attribute/Parameter/Query/ExcludeMainSiteParameter.php @@ -0,0 +1,35 @@ +load(); + } + +} \ No newline at end of file diff --git a/src/Document/Repository/SiteRepositoryInterface.php b/src/Document/Repository/SiteRepositoryInterface.php new file mode 100644 index 00000000..aafb6fc8 --- /dev/null +++ b/src/Document/Repository/SiteRepositoryInterface.php @@ -0,0 +1,29 @@ +id; + } + + public function getRootId(): ?int + { + return $this->rootId; + } + + public function getRootPath(): ?string + { + return $this->rootPath; + } + + public function getDomains(): array + { + return $this->domains; + } + + public function getDomain(): string + { + return $this->domain; + } +} diff --git a/src/Document/Service/SiteService.php b/src/Document/Service/SiteService.php new file mode 100644 index 00000000..29350027 --- /dev/null +++ b/src/Document/Service/SiteService.php @@ -0,0 +1,70 @@ +getExcludeMainSite() === false) { + $sites[] = $this->getMainSite(); + } + + $siteList = $this->siteRepository->listSites(); + foreach ($siteList as $siteEntry) { + $site = new Site( + $siteEntry->getId(), + $siteEntry->getRootId(), + $siteEntry->getRootPath(), + $siteEntry->getDomains(), + $siteEntry->getMainDomain() + ); + + $this->eventDispatcher->dispatch(new SiteEvent($site), SiteEvent::EVENT_NAME); + $sites[] = $site; + } + + return $sites; + } + + private function getMainSite(): Site + { + return new Site(0,1,'/',[],'main_site'); + } +} diff --git a/src/Document/Service/SiteServiceInterface.php b/src/Document/Service/SiteServiceInterface.php new file mode 100644 index 00000000..f5ff2af8 --- /dev/null +++ b/src/Document/Service/SiteServiceInterface.php @@ -0,0 +1,31 @@ +value, description: 'tag_dependencies_description' )] +#[Tag( + name: Tags::Documents->value, + description: 'tag_documents_description' +)] #[Tag( name: Tags::Elements->value, description: 'tag_elements_description' @@ -127,6 +131,7 @@ enum Tags: string case DataObjects = 'Data Objects'; case DataObjectsGrid = 'Data Object Grid'; case Dependencies = 'Dependencies'; + case Documents = 'Documents'; case Elements = 'Elements'; case ExecutionEngine = 'Execution Engine'; case Emails = 'E-Mails'; diff --git a/translations/studio_api_docs.en.yaml b/translations/studio_api_docs.en.yaml index 193ba08c..b3179401 100644 --- a/translations/studio_api_docs.en.yaml +++ b/translations/studio_api_docs.en.yaml @@ -201,6 +201,10 @@ data_object_update_by_id_description: | Update needs to have the complete data present.
You can create/update/delete list entries like properties.
If you want to update only a single field, use the PATCH method. data_object_update_by_id_success_response: Successfully updated data object data_object_update_by_id_summary: Update a data object by ID +documents_list_available_sites_description: | + List all available sites +documents_list_available_sites_success_response: List of available sites +documents_list_available_sites_summary: List all available sites element_delete_created_response: Successfully created jobRun for deleting element and its children element_delete_description: | @@ -434,6 +438,7 @@ tag_delete_by_id_description: | tag_delete_by_id_success_response: ID of successfully deleted tag tag_delete_by_id_summary: Delete a specific tag tag_dependencies_description: Get dependencies for a single element +tag_documents_description: Document operations to get/update/create/delete documents tag_elements_description: Get element properties for a single element based on its type and provided parameters tag_emails_description: E-mail operations to get/update/create/delete/test emails and From 634f93d83d39bc2755090a93b859215604a77fe2 Mon Sep 17 00:00:00 2001 From: lukmzig Date: Thu, 28 Nov 2024 14:40:33 +0000 Subject: [PATCH 2/6] Apply php-cs-fixer changes --- src/Document/Attribute/Response/AvailableSitesJson.php | 1 - src/Document/Controller/AvailableSitesController.php | 2 +- src/Document/MappedParameter/ExcludeMainSiteParameter.php | 3 +-- src/Document/Repository/SiteRepository.php | 3 +-- src/Document/Repository/SiteRepositoryInterface.php | 1 + src/Document/Schema/Site.php | 3 +-- src/Document/Service/SiteService.php | 2 +- 7 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/Document/Attribute/Response/AvailableSitesJson.php b/src/Document/Attribute/Response/AvailableSitesJson.php index f911b43a..99a62603 100644 --- a/src/Document/Attribute/Response/AvailableSitesJson.php +++ b/src/Document/Attribute/Response/AvailableSitesJson.php @@ -19,7 +19,6 @@ use OpenApi\Attributes\Items; use OpenApi\Attributes\JsonContent; use OpenApi\Attributes\Property; -use Pimcore\Bundle\StudioBackendBundle\Class\Schema\QuantityValueUnit; use Pimcore\Bundle\StudioBackendBundle\Document\Schema\Site; /** diff --git a/src/Document/Controller/AvailableSitesController.php b/src/Document/Controller/AvailableSitesController.php index eb125c3f..989eea9e 100644 --- a/src/Document/Controller/AvailableSitesController.php +++ b/src/Document/Controller/AvailableSitesController.php @@ -64,7 +64,7 @@ public function __construct( content: new AvailableSitesJson() )] #[DefaultResponses([ - HttpResponseCodes::UNAUTHORIZED + HttpResponseCodes::UNAUTHORIZED, ])] public function getAvailableSites( #[MapQueryString] MappedParameter $parameter diff --git a/src/Document/MappedParameter/ExcludeMainSiteParameter.php b/src/Document/MappedParameter/ExcludeMainSiteParameter.php index 6710a8b8..f16bc75f 100644 --- a/src/Document/MappedParameter/ExcludeMainSiteParameter.php +++ b/src/Document/MappedParameter/ExcludeMainSiteParameter.php @@ -23,8 +23,7 @@ { public function __construct( private ?string $excludeMainSite = null - ) - { + ) { } public function getExcludeMainSite(): bool diff --git a/src/Document/Repository/SiteRepository.php b/src/Document/Repository/SiteRepository.php index be58ce6f..8c937924 100644 --- a/src/Document/Repository/SiteRepository.php +++ b/src/Document/Repository/SiteRepository.php @@ -31,5 +31,4 @@ public function listSites(): array { return (new Listing())->load(); } - -} \ No newline at end of file +} diff --git a/src/Document/Repository/SiteRepositoryInterface.php b/src/Document/Repository/SiteRepositoryInterface.php index aafb6fc8..9a6b4ce9 100644 --- a/src/Document/Repository/SiteRepositoryInterface.php +++ b/src/Document/Repository/SiteRepositoryInterface.php @@ -15,6 +15,7 @@ */ namespace Pimcore\Bundle\StudioBackendBundle\Document\Repository; + use Pimcore\Model\Site; /** diff --git a/src/Document/Schema/Site.php b/src/Document/Schema/Site.php index 99d53aa5..3866d624 100644 --- a/src/Document/Schema/Site.php +++ b/src/Document/Schema/Site.php @@ -44,8 +44,7 @@ public function __construct( private readonly array $domains, #[Property(description: 'Domain', type: 'string', example: 'main_site')] private readonly string $domain, - ) - { + ) { } public function getId(): int diff --git a/src/Document/Service/SiteService.php b/src/Document/Service/SiteService.php index 29350027..a61de939 100644 --- a/src/Document/Service/SiteService.php +++ b/src/Document/Service/SiteService.php @@ -65,6 +65,6 @@ public function getAvailableSites(ExcludeMainSiteParameter $parameter): array private function getMainSite(): Site { - return new Site(0,1,'/',[],'main_site'); + return new Site(0, 1, '/', [], 'main_site'); } } From 27234fec4c5beb1f05d56c222989481027349b8f Mon Sep 17 00:00:00 2001 From: lukmzig Date: Thu, 28 Nov 2024 15:43:08 +0100 Subject: [PATCH 3/6] fix: sonar --- src/Document/Schema/Site.php | 8 ++++---- src/Document/Service/SiteService.php | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Document/Schema/Site.php b/src/Document/Schema/Site.php index 3866d624..fead9cd1 100644 --- a/src/Document/Schema/Site.php +++ b/src/Document/Schema/Site.php @@ -36,14 +36,14 @@ final class Site implements AdditionalAttributesInterface public function __construct( #[Property(description: 'ID', type: 'integer', example: 0)] private readonly int $id, - #[Property(description: 'ID of the root', type: 'integer', example: 1)] - private readonly ?int $rootId = null, - #[Property(description: 'Root path', type: 'string', example: '/')] - private readonly ?string $rootPath = null, #[Property(description: 'Domains', type: 'array', items: new Items(type: 'string'), example: ['other_domain'])] private readonly array $domains, #[Property(description: 'Domain', type: 'string', example: 'main_site')] private readonly string $domain, + #[Property(description: 'ID of the root', type: 'integer', example: 1)] + private readonly ?int $rootId = null, + #[Property(description: 'Root path', type: 'string', example: '/')] + private readonly ?string $rootPath = null, ) { } diff --git a/src/Document/Service/SiteService.php b/src/Document/Service/SiteService.php index a61de939..d740f276 100644 --- a/src/Document/Service/SiteService.php +++ b/src/Document/Service/SiteService.php @@ -50,10 +50,10 @@ public function getAvailableSites(ExcludeMainSiteParameter $parameter): array foreach ($siteList as $siteEntry) { $site = new Site( $siteEntry->getId(), + $siteEntry->getDomains(), + $siteEntry->getMainDomain(), $siteEntry->getRootId(), $siteEntry->getRootPath(), - $siteEntry->getDomains(), - $siteEntry->getMainDomain() ); $this->eventDispatcher->dispatch(new SiteEvent($site), SiteEvent::EVENT_NAME); @@ -65,6 +65,6 @@ public function getAvailableSites(ExcludeMainSiteParameter $parameter): array private function getMainSite(): Site { - return new Site(0, 1, '/', [], 'main_site'); + return new Site(0, [], 'main_site', 1, '/'); } } From a117ac97c1006db20647a4051669562864f08384 Mon Sep 17 00:00:00 2001 From: lukmzig Date: Fri, 29 Nov 2024 08:23:45 +0100 Subject: [PATCH 4/6] apply review feedback --- config/documents.yaml | 10 ++++- .../LayoutDefinitionService.php | 10 ++--- src/Document/Hydrator/SiteHydrator.php | 37 +++++++++++++++++++ .../Hydrator/SiteHydratorInterface.php | 28 ++++++++++++++ src/Document/Schema/Site.php | 3 ++ src/Document/Service/SiteService.php | 10 ++--- 6 files changed, 85 insertions(+), 13 deletions(-) create mode 100644 src/Document/Hydrator/SiteHydrator.php create mode 100644 src/Document/Hydrator/SiteHydratorInterface.php diff --git a/config/documents.yaml b/config/documents.yaml index 9e073012..f198214c 100644 --- a/config/documents.yaml +++ b/config/documents.yaml @@ -27,4 +27,12 @@ services: # Pimcore\Bundle\StudioBackendBundle\Document\Repository\SiteRepositoryInterface: - class: Pimcore\Bundle\StudioBackendBundle\Document\Repository\SiteRepository \ No newline at end of file + class: Pimcore\Bundle\StudioBackendBundle\Document\Repository\SiteRepository + + + # + # Hydrators + # + + Pimcore\Bundle\StudioBackendBundle\Document\Hydrator\SiteHydratorInterface: + class: Pimcore\Bundle\StudioBackendBundle\Document\Hydrator\SiteHydrator \ No newline at end of file diff --git a/src/Class/Service/FieldCollection/LayoutDefinitionService.php b/src/Class/Service/FieldCollection/LayoutDefinitionService.php index 7aa5b9ad..be1907e4 100644 --- a/src/Class/Service/FieldCollection/LayoutDefinitionService.php +++ b/src/Class/Service/FieldCollection/LayoutDefinitionService.php @@ -21,7 +21,7 @@ use Pimcore\Bundle\StaticResolverBundle\Models\DataObject\DataObjectResolverInterface; use Pimcore\Bundle\StaticResolverBundle\Models\DataObject\FieldCollection\DefinitionResolverInterface; use Pimcore\Bundle\StudioBackendBundle\Class\Event\FieldCollection\LayoutDefinitionEvent; -use Pimcore\Bundle\StudioBackendBundle\Class\Hydrator\FieldCollection\LayoutDefinitionHydratorInterface; +use Pimcore\Bundle\StudioBackendBundle\Class\Hydrator\FieldCollection\SiteHydratorInterface; use Pimcore\Bundle\StudioBackendBundle\Class\Schema\LayoutDefinition; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException; use Pimcore\Model\DataObject; @@ -34,11 +34,11 @@ final class LayoutDefinitionService implements LayoutDefinitionServiceInterface { public function __construct( - private readonly DataObjectResolverInterface $dataObjectResolver, + private readonly DataObjectResolverInterface $dataObjectResolver, private readonly ClassDefinitionResolverInterface $classDefinitionResolver, - private readonly DefinitionResolverInterface $definitionResolver, - private readonly LayoutDefinitionHydratorInterface $layoutDefinitionHydrator, - private readonly EventDispatcherInterface $eventDispatcher, + private readonly DefinitionResolverInterface $definitionResolver, + private readonly SiteHydratorInterface $layoutDefinitionHydrator, + private readonly EventDispatcherInterface $eventDispatcher, ) { } diff --git a/src/Document/Hydrator/SiteHydrator.php b/src/Document/Hydrator/SiteHydrator.php new file mode 100644 index 00000000..577d1337 --- /dev/null +++ b/src/Document/Hydrator/SiteHydrator.php @@ -0,0 +1,37 @@ +getId(), + $siteModel->getDomains(), + $siteModel->getMainDomain(), + $siteModel->getRootId(), + $siteModel->getRootPath(), + ); + } +} diff --git a/src/Document/Hydrator/SiteHydratorInterface.php b/src/Document/Hydrator/SiteHydratorInterface.php new file mode 100644 index 00000000..5c456805 --- /dev/null +++ b/src/Document/Hydrator/SiteHydratorInterface.php @@ -0,0 +1,28 @@ +siteRepository->listSites(); foreach ($siteList as $siteEntry) { - $site = new Site( - $siteEntry->getId(), - $siteEntry->getDomains(), - $siteEntry->getMainDomain(), - $siteEntry->getRootId(), - $siteEntry->getRootPath(), - ); + $site = $this->siteHydrator->hydrate($siteEntry); $this->eventDispatcher->dispatch(new SiteEvent($site), SiteEvent::EVENT_NAME); $sites[] = $site; From 385b092da444c2131a6d4e6496f7be3a0978eea4 Mon Sep 17 00:00:00 2001 From: lukmzig Date: Fri, 29 Nov 2024 07:24:20 +0000 Subject: [PATCH 5/6] Apply php-cs-fixer changes --- .../Service/FieldCollection/LayoutDefinitionService.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Class/Service/FieldCollection/LayoutDefinitionService.php b/src/Class/Service/FieldCollection/LayoutDefinitionService.php index be1907e4..fead0be5 100644 --- a/src/Class/Service/FieldCollection/LayoutDefinitionService.php +++ b/src/Class/Service/FieldCollection/LayoutDefinitionService.php @@ -34,11 +34,11 @@ final class LayoutDefinitionService implements LayoutDefinitionServiceInterface { public function __construct( - private readonly DataObjectResolverInterface $dataObjectResolver, + private readonly DataObjectResolverInterface $dataObjectResolver, private readonly ClassDefinitionResolverInterface $classDefinitionResolver, - private readonly DefinitionResolverInterface $definitionResolver, - private readonly SiteHydratorInterface $layoutDefinitionHydrator, - private readonly EventDispatcherInterface $eventDispatcher, + private readonly DefinitionResolverInterface $definitionResolver, + private readonly SiteHydratorInterface $layoutDefinitionHydrator, + private readonly EventDispatcherInterface $eventDispatcher, ) { } From 821253a8ef79b136a99af803cf16fa097b435ee0 Mon Sep 17 00:00:00 2001 From: lukmzig Date: Fri, 29 Nov 2024 08:27:16 +0100 Subject: [PATCH 6/6] fix: renaming issue --- src/Class/Service/FieldCollection/LayoutDefinitionService.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Class/Service/FieldCollection/LayoutDefinitionService.php b/src/Class/Service/FieldCollection/LayoutDefinitionService.php index fead0be5..7aa5b9ad 100644 --- a/src/Class/Service/FieldCollection/LayoutDefinitionService.php +++ b/src/Class/Service/FieldCollection/LayoutDefinitionService.php @@ -21,7 +21,7 @@ use Pimcore\Bundle\StaticResolverBundle\Models\DataObject\DataObjectResolverInterface; use Pimcore\Bundle\StaticResolverBundle\Models\DataObject\FieldCollection\DefinitionResolverInterface; use Pimcore\Bundle\StudioBackendBundle\Class\Event\FieldCollection\LayoutDefinitionEvent; -use Pimcore\Bundle\StudioBackendBundle\Class\Hydrator\FieldCollection\SiteHydratorInterface; +use Pimcore\Bundle\StudioBackendBundle\Class\Hydrator\FieldCollection\LayoutDefinitionHydratorInterface; use Pimcore\Bundle\StudioBackendBundle\Class\Schema\LayoutDefinition; use Pimcore\Bundle\StudioBackendBundle\Exception\Api\NotFoundException; use Pimcore\Model\DataObject; @@ -37,7 +37,7 @@ public function __construct( private readonly DataObjectResolverInterface $dataObjectResolver, private readonly ClassDefinitionResolverInterface $classDefinitionResolver, private readonly DefinitionResolverInterface $definitionResolver, - private readonly SiteHydratorInterface $layoutDefinitionHydrator, + private readonly LayoutDefinitionHydratorInterface $layoutDefinitionHydrator, private readonly EventDispatcherInterface $eventDispatcher, ) { }