From 1bd195ec2229aa25ccca4cb3200f2f84b6b70d65 Mon Sep 17 00:00:00 2001 From: Matthias Schuhmayer <38959016+mattamon@users.noreply.github.com> Date: Wed, 12 Jun 2024 12:51:44 +0200 Subject: [PATCH] [Feature] Custom metadata (#90) * Introduce custom meta data * Apply php-cs-fixer changes * Add return type and do not throw exception * Consistency check * Unify property data and metadata data, remove gdi meta data hydrator * Apply php-cs-fixer changes * Update tests and fix static * Remove unused constants and update tests * Apply php-cs-fixer changes * Data Extractor to resolver * Apply php-cs-fixer changes * Check with isset and add array type * Update tests * Update requestbody * Apply php-cs-fixer changes * Remove security * Add pre set event * Remove exception and getbypath * Activate permissions checks for assets --------- Co-authored-by: mattamon --- config/assets.yaml | 17 +++- config/data_index.yaml | 2 - config/resolver.yaml | 8 ++ .../Request/UpdateAssetRequestBody.php | 2 + src/Asset/Controller/CollectionController.php | 9 +-- .../Data/CustomMetadataController.php | 76 ++++++++++++++++++ .../{ => Data}/CustomSettingsController.php | 8 +- src/Asset/Controller/Data/TextController.php | 9 ++- src/Asset/Controller/GetController.php | 5 +- src/Asset/Controller/PatchController.php | 6 +- src/Asset/Controller/UpdateController.php | 5 +- .../Event/{ => PreResponse}/AssetEvent.php | 2 +- .../Event/PreResponse/CustomMetadataEvent.php | 40 ++++++++++ .../{ => PreResponse}/CustomSettingsEvent.php | 2 +- .../Event/PreSet/CustomMetadataEvent.php | 46 +++++++++++ src/Asset/Hydrator/CustomMetadataHydrator.php | 53 ++++++++++++ .../CustomMetadataHydratorInterface.php | 27 +++++++ src/Asset/Schema/Asset.php | 17 +--- src/Asset/Schema/CustomMetadata.php | 66 +++++++++++++++ src/Asset/Schema/Type/Document.php | 4 +- src/Asset/Schema/Type/Image.php | 4 +- src/Asset/Schema/Type/MetaData.php | 52 ------------ src/Asset/Schema/Type/Video.php | 4 +- src/Asset/Service/AssetService.php | 4 +- .../Service/Data/CustomMetadataService.php | 80 +++++++++++++++++++ .../Data/CustomMetadataServiceInterface.php} | 17 ++-- .../{ => Data}/CustomSettingsService.php | 4 +- .../CustomSettingsServiceInterface.php | 2 +- .../{DataService.php => Data/TextService.php} | 4 +- .../TextServiceInterface.php} | 4 +- .../Updater/Adapter/CustomMetadataAdapter.php | 66 +++++++++++++++ .../Hydrator/Asset/ArchiveHydrator.php | 3 +- .../Hydrator/Asset/AudioHydrator.php | 3 +- .../Hydrator/Asset/DocumentHydrator.php | 3 +- .../Hydrator/Asset/FolderHydrator.php | 3 +- .../Hydrator/Asset/ImageHydrator.php | 3 +- .../Hydrator/Asset/MetaDataHydrator.php | 42 ---------- src/DataIndex/Hydrator/Asset/TextHydrator.php | 3 +- .../Hydrator/Asset/UnknownHydrator.php | 3 +- .../Hydrator/Asset/VideoHydrator.php | 3 +- src/DataIndex/Hydrator/AssetHydrator.php | 4 +- .../PimcoreStudioBackendExtension.php | 1 + src/Property/Hydrator/PropertyHydrator.php | 27 ++----- src/Resolver/Element/ReferenceResolver.php | 56 +++++++++++++ .../Element/ReferenceResolverInterface.php | 23 ++++++ tests/Unit/Property/PropertyHydratorTest.php | 33 ++++++-- 46 files changed, 652 insertions(+), 203 deletions(-) create mode 100644 config/resolver.yaml create mode 100644 src/Asset/Controller/Data/CustomMetadataController.php rename src/Asset/Controller/{ => Data}/CustomSettingsController.php (88%) rename src/Asset/Event/{ => PreResponse}/AssetEvent.php (93%) create mode 100644 src/Asset/Event/PreResponse/CustomMetadataEvent.php rename src/Asset/Event/{ => PreResponse}/CustomSettingsEvent.php (93%) create mode 100644 src/Asset/Event/PreSet/CustomMetadataEvent.php create mode 100644 src/Asset/Hydrator/CustomMetadataHydrator.php create mode 100644 src/Asset/Hydrator/CustomMetadataHydratorInterface.php create mode 100644 src/Asset/Schema/CustomMetadata.php delete mode 100644 src/Asset/Schema/Type/MetaData.php create mode 100644 src/Asset/Service/Data/CustomMetadataService.php rename src/{DataIndex/Hydrator/Asset/MetaDataHydratorInterface.php => Asset/Service/Data/CustomMetadataServiceInterface.php} (54%) rename src/Asset/Service/{ => Data}/CustomSettingsService.php (93%) rename src/Asset/Service/{ => Data}/CustomSettingsServiceInterface.php (92%) rename src/Asset/Service/{DataService.php => Data/TextService.php} (92%) rename src/Asset/Service/{DataServiceInterface.php => Data/TextServiceInterface.php} (90%) create mode 100644 src/Asset/Updater/Adapter/CustomMetadataAdapter.php delete mode 100644 src/DataIndex/Hydrator/Asset/MetaDataHydrator.php create mode 100644 src/Resolver/Element/ReferenceResolver.php create mode 100644 src/Resolver/Element/ReferenceResolverInterface.php diff --git a/config/assets.yaml b/config/assets.yaml index 7324c58cc..9e059b64e 100644 --- a/config/assets.yaml +++ b/config/assets.yaml @@ -15,6 +15,9 @@ services: Pimcore\Bundle\StudioBackendBundle\Asset\Hydrator\CustomSettingsHydratorInterface: class: Pimcore\Bundle\StudioBackendBundle\Asset\Hydrator\CustomSettingsHydrator + Pimcore\Bundle\StudioBackendBundle\Asset\Hydrator\CustomMetadataHydratorInterface: + class: Pimcore\Bundle\StudioBackendBundle\Asset\Hydrator\CustomMetadataHydrator + # Encoder Pimcore\Bundle\StudioBackendBundle\Asset\Encoder\TextEncoderInterface: class: Pimcore\Bundle\StudioBackendBundle\Asset\Encoder\TextEncoder @@ -22,14 +25,20 @@ services: Pimcore\Bundle\StudioBackendBundle\Asset\Service\AssetServiceInterface: class: Pimcore\Bundle\StudioBackendBundle\Asset\Service\AssetService - Pimcore\Bundle\StudioBackendBundle\Asset\Service\CustomSettingsServiceInterface: - class: Pimcore\Bundle\StudioBackendBundle\Asset\Service\CustomSettingsService + Pimcore\Bundle\StudioBackendBundle\Asset\Service\Data\CustomSettingsServiceInterface: + class: Pimcore\Bundle\StudioBackendBundle\Asset\Service\Data\CustomSettingsService + + Pimcore\Bundle\StudioBackendBundle\Asset\Service\Data\CustomMetadataServiceInterface: + class: Pimcore\Bundle\StudioBackendBundle\Asset\Service\Data\CustomMetadataService - Pimcore\Bundle\StudioBackendBundle\Asset\Service\DataServiceInterface: - class: Pimcore\Bundle\StudioBackendBundle\Asset\Service\DataService + Pimcore\Bundle\StudioBackendBundle\Asset\Service\Data\TextServiceInterface: + class: Pimcore\Bundle\StudioBackendBundle\Asset\Service\Data\TextService Pimcore\Bundle\StudioBackendBundle\Asset\Updater\Adapter\ImageAdapter: tags: [ 'pimcore.studio_backend.update_adapter' ] + Pimcore\Bundle\StudioBackendBundle\Asset\Updater\Adapter\CustomMetadataAdapter: + tags: [ 'pimcore.studio_backend.update_adapter' ] + Pimcore\Bundle\StudioBackendBundle\Asset\Patcher\Adapter\MetadataAdapter: tags: [ 'pimcore.studio_backend.patch_adapter' ] \ No newline at end of file diff --git a/config/data_index.yaml b/config/data_index.yaml index 140ea00c7..8d807a226 100644 --- a/config/data_index.yaml +++ b/config/data_index.yaml @@ -21,8 +21,6 @@ services: class: Pimcore\Bundle\StudioBackendBundle\DataIndex\Hydrator\Asset\UnknownHydrator Pimcore\Bundle\StudioBackendBundle\DataIndex\Hydrator\Asset\VideoHydratorInterface: class: Pimcore\Bundle\StudioBackendBundle\DataIndex\Hydrator\Asset\VideoHydrator - Pimcore\Bundle\StudioBackendBundle\DataIndex\Hydrator\Asset\MetaDataHydratorInterface: - class: Pimcore\Bundle\StudioBackendBundle\DataIndex\Hydrator\Asset\MetaDataHydrator Pimcore\Bundle\StudioBackendBundle\DataIndex\Hydrator\AssetHydratorInterface: class: Pimcore\Bundle\StudioBackendBundle\DataIndex\Hydrator\AssetHydrator diff --git a/config/resolver.yaml b/config/resolver.yaml new file mode 100644 index 000000000..922d49219 --- /dev/null +++ b/config/resolver.yaml @@ -0,0 +1,8 @@ +services: + _defaults: + autowire: true + autoconfigure: true + public: false + + Pimcore\Bundle\StudioBackendBundle\Resolver\Element\ReferenceResolverInterface: + class: Pimcore\Bundle\StudioBackendBundle\Resolver\Element\ReferenceResolver \ No newline at end of file diff --git a/src/Asset/Attributes/Request/UpdateAssetRequestBody.php b/src/Asset/Attributes/Request/UpdateAssetRequestBody.php index edb5272bb..d3cd930df 100644 --- a/src/Asset/Attributes/Request/UpdateAssetRequestBody.php +++ b/src/Asset/Attributes/Request/UpdateAssetRequestBody.php @@ -21,6 +21,7 @@ use OpenApi\Attributes\Property; use OpenApi\Attributes\RequestBody; use Pimcore\Bundle\StudioBackendBundle\Asset\Attributes\Property\UpdateAssetImage; +use Pimcore\Bundle\StudioBackendBundle\Asset\Attributes\Property\UpdateCustomMetaData; use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Property\UpdateParentId; use Pimcore\Bundle\StudioBackendBundle\Property\Attributes\Property\UpdateElementProperties; @@ -40,6 +41,7 @@ public function __construct() new Property('data', properties: [ new UpdateParentId(), + new UpdateCustomMetaData(), new UpdateElementProperties(), new UpdateAssetImage(), ], diff --git a/src/Asset/Controller/CollectionController.php b/src/Asset/Controller/CollectionController.php index edb6639a8..333e94ddf 100644 --- a/src/Asset/Controller/CollectionController.php +++ b/src/Asset/Controller/CollectionController.php @@ -20,14 +20,11 @@ use Pimcore\Bundle\StudioBackendBundle\Asset\Attributes\Response\Property\AnyOfAsset; use Pimcore\Bundle\StudioBackendBundle\Asset\Service\AssetServiceInterface; use Pimcore\Bundle\StudioBackendBundle\Controller\AbstractApiController; -use Pimcore\Bundle\StudioBackendBundle\DataIndex\AssetSearchServiceInterface; -use Pimcore\Bundle\StudioBackendBundle\DataIndex\OpenSearchFilterInterface; use Pimcore\Bundle\StudioBackendBundle\DataIndex\Request\ElementParameters; use Pimcore\Bundle\StudioBackendBundle\Exception\InvalidFilterServiceTypeException; use Pimcore\Bundle\StudioBackendBundle\Exception\InvalidFilterTypeException; use Pimcore\Bundle\StudioBackendBundle\Exception\InvalidQueryTypeException; use Pimcore\Bundle\StudioBackendBundle\Exception\SearchException; -use Pimcore\Bundle\StudioBackendBundle\Filter\Service\FilterServiceProviderInterface; use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Parameters\Query\ExcludeFoldersParameter; use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Parameters\Query\IdSearchTermParameter; use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Parameters\Query\PageParameter; @@ -40,12 +37,13 @@ use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Response\DefaultResponses; use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Response\SuccessResponse; use Pimcore\Bundle\StudioBackendBundle\OpenApi\Config\Tags; -use Pimcore\Bundle\StudioBackendBundle\Util\Constants\ElementTypes; use Pimcore\Bundle\StudioBackendBundle\Util\Constants\HttpResponseCodes; +use Pimcore\Bundle\StudioBackendBundle\Util\Constants\UserPermissions; use Pimcore\Bundle\StudioBackendBundle\Util\Traits\PaginatedResponseTrait; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpKernel\Attribute\MapQueryString; use Symfony\Component\Routing\Attribute\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Serializer\SerializerInterface; /** @@ -66,8 +64,7 @@ public function __construct( * @throws InvalidFilterServiceTypeException|SearchException|InvalidQueryTypeException|InvalidFilterTypeException */ #[Route('/assets', name: 'pimcore_studio_api_assets', methods: ['GET'])] - //#[IsGranted('STUDIO_API')] - //#[IsGranted(UserPermissions::ASSETS->value)] + #[IsGranted(UserPermissions::ASSETS->value)] #[Get( path: self::API_PATH . '/assets', operationId: 'getAssets', diff --git a/src/Asset/Controller/Data/CustomMetadataController.php b/src/Asset/Controller/Data/CustomMetadataController.php new file mode 100644 index 000000000..cb9c2f11f --- /dev/null +++ b/src/Asset/Controller/Data/CustomMetadataController.php @@ -0,0 +1,76 @@ +value)] + #[GET( + path: self::API_PATH . '/assets/{id}/custom-metadata', + operationId: 'getAssetCustomMetadataById', + description: 'Get custom metadata of an asset by its id by path parameter', + summary: 'Get custom metadata of an asset by id', + tags: [Tags::Assets->name] + )] + #[IdParameter(type: 'asset')] + #[SuccessResponse( + description: 'Array of custom metadata', + content: new ItemsJson(CustomMetadata::class) + )] + #[DefaultResponses([ + HttpResponseCodes::UNAUTHORIZED, + HttpResponseCodes::NOT_FOUND, + ])] + public function getAssetCustomSettingsById(int $id): JsonResponse + { + return $this->jsonResponse(['items' => $this->customMetadataService->getCustomMetadata($id)]); + } +} diff --git a/src/Asset/Controller/CustomSettingsController.php b/src/Asset/Controller/Data/CustomSettingsController.php similarity index 88% rename from src/Asset/Controller/CustomSettingsController.php rename to src/Asset/Controller/Data/CustomSettingsController.php index 5d06f123d..3c7b73d44 100644 --- a/src/Asset/Controller/CustomSettingsController.php +++ b/src/Asset/Controller/Data/CustomSettingsController.php @@ -14,11 +14,11 @@ * @license http://www.pimcore.org/license GPLv3 and PCL */ -namespace Pimcore\Bundle\StudioBackendBundle\Asset\Controller; +namespace Pimcore\Bundle\StudioBackendBundle\Asset\Controller\Data; use OpenApi\Attributes\Get; use Pimcore\Bundle\StudioBackendBundle\Asset\Attributes\Response\Content\CustomSettingsJson; -use Pimcore\Bundle\StudioBackendBundle\Asset\Service\CustomSettingsServiceInterface; +use Pimcore\Bundle\StudioBackendBundle\Asset\Service\Data\CustomSettingsServiceInterface; use Pimcore\Bundle\StudioBackendBundle\Controller\AbstractApiController; use Pimcore\Bundle\StudioBackendBundle\Exception\AccessDeniedException; use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Parameters\Path\IdParameter; @@ -26,9 +26,11 @@ use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Response\SuccessResponse; use Pimcore\Bundle\StudioBackendBundle\OpenApi\Config\Tags; use Pimcore\Bundle\StudioBackendBundle\Util\Constants\HttpResponseCodes; +use Pimcore\Bundle\StudioBackendBundle\Util\Constants\UserPermissions; use Pimcore\Bundle\StudioBackendBundle\Util\Traits\ElementProviderTrait; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\Routing\Attribute\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Serializer\SerializerInterface; /** @@ -49,7 +51,7 @@ public function __construct( * @throws AccessDeniedException */ #[Route('/assets/{id}/custom-settings', name: 'pimcore_studio_api_get_asset_custom_settings', methods: ['GET'])] - //#[IsGranted('STUDIO_API')] + #[IsGranted(UserPermissions::ASSETS->value)] #[GET( path: self::API_PATH . '/assets/{id}/custom-settings', operationId: 'getAssetCustomSettingsById', diff --git a/src/Asset/Controller/Data/TextController.php b/src/Asset/Controller/Data/TextController.php index 24218e4e0..efa3da079 100644 --- a/src/Asset/Controller/Data/TextController.php +++ b/src/Asset/Controller/Data/TextController.php @@ -17,7 +17,7 @@ namespace Pimcore\Bundle\StudioBackendBundle\Asset\Controller\Data; use OpenApi\Attributes\Get; -use Pimcore\Bundle\StudioBackendBundle\Asset\Service\DataServiceInterface; +use Pimcore\Bundle\StudioBackendBundle\Asset\Service\Data\TextServiceInterface; use Pimcore\Bundle\StudioBackendBundle\Controller\AbstractApiController; use Pimcore\Bundle\StudioBackendBundle\Exception\ElementNotFoundException; use Pimcore\Bundle\StudioBackendBundle\Exception\InvalidElementTypeException; @@ -28,9 +28,11 @@ use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Response\SuccessResponse; use Pimcore\Bundle\StudioBackendBundle\OpenApi\Config\Tags; use Pimcore\Bundle\StudioBackendBundle\Util\Constants\HttpResponseCodes; +use Pimcore\Bundle\StudioBackendBundle\Util\Constants\UserPermissions; use Pimcore\Bundle\StudioBackendBundle\Util\Traits\ElementProviderTrait; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\Routing\Attribute\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Serializer\SerializerInterface; /** @@ -42,7 +44,7 @@ final class TextController extends AbstractApiController public function __construct( SerializerInterface $serializer, - private readonly DataServiceInterface $dataService + private readonly TextServiceInterface $dataService ) { parent::__construct($serializer); @@ -52,8 +54,7 @@ public function __construct( * @throws ElementNotFoundException|InvalidElementTypeException|MaxFileSizeExceededException */ #[Route('/assets/{id}/text', name: 'pimcore_studio_api_get_asset_data_text', methods: ['GET'])] - //#[IsGranted('STUDIO_API')] - //#[IsGranted(UserPermissions::ASSETS->value)] + #[IsGranted(UserPermissions::ASSETS->value)] #[Get( path: self::API_PATH . '/assets/{id}/text', operationId: 'getAssetDataTextById', diff --git a/src/Asset/Controller/GetController.php b/src/Asset/Controller/GetController.php index 2cb35d868..3b493b566 100644 --- a/src/Asset/Controller/GetController.php +++ b/src/Asset/Controller/GetController.php @@ -27,8 +27,10 @@ use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Response\SuccessResponse; use Pimcore\Bundle\StudioBackendBundle\OpenApi\Config\Tags; use Pimcore\Bundle\StudioBackendBundle\Util\Constants\HttpResponseCodes; +use Pimcore\Bundle\StudioBackendBundle\Util\Constants\UserPermissions; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\Routing\Attribute\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Serializer\SerializerInterface; /** @@ -47,8 +49,7 @@ public function __construct( * @throws ElementNotFoundException|SearchException */ #[Route('/assets/{id}', name: 'pimcore_studio_api_get_asset', methods: ['GET'])] - //#[IsGranted('STUDIO_API')] - //#[IsGranted(UserPermissions::ASSETS->value)] + #[IsGranted(UserPermissions::ASSETS->value)] #[Get( path: self::API_PATH . '/assets/{id}', operationId: 'getAssetById', diff --git a/src/Asset/Controller/PatchController.php b/src/Asset/Controller/PatchController.php index 96f58cd81..535714e65 100644 --- a/src/Asset/Controller/PatchController.php +++ b/src/Asset/Controller/PatchController.php @@ -19,7 +19,6 @@ use OpenApi\Attributes\Patch; use Pimcore\Bundle\StudioBackendBundle\Asset\Attributes\Request\PatchAssetRequestBody; use Pimcore\Bundle\StudioBackendBundle\Asset\MappedParameter\PatchAssetParameter; -use Pimcore\Bundle\StudioBackendBundle\Asset\Service\AssetServiceInterface; use Pimcore\Bundle\StudioBackendBundle\Controller\AbstractApiController; use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Response\Content\PatchErrorJson; use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Response\DefaultResponses; @@ -28,9 +27,11 @@ use Pimcore\Bundle\StudioBackendBundle\OpenApi\Config\Tags; use Pimcore\Bundle\StudioBackendBundle\Patcher\Service\PatchServiceInterface; use Pimcore\Bundle\StudioBackendBundle\Util\Constants\HttpResponseCodes; +use Pimcore\Bundle\StudioBackendBundle\Util\Constants\UserPermissions; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Attribute\MapRequestPayload; use Symfony\Component\Routing\Attribute\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Serializer\SerializerInterface; /** @@ -46,8 +47,7 @@ public function __construct( } #[Route('/assets', name: 'pimcore_studio_api_patch_asset', methods: ['PATCH'])] - //#[IsGranted('STUDIO_API')] - //#[IsGranted(UserPermissions::ASSETS->value)] + #[IsGranted(UserPermissions::ASSETS->value)] #[Patch( path: self::API_PATH . '/assets', operationId: 'patchAssetById', diff --git a/src/Asset/Controller/UpdateController.php b/src/Asset/Controller/UpdateController.php index 6b05f9b80..d12e07cff 100644 --- a/src/Asset/Controller/UpdateController.php +++ b/src/Asset/Controller/UpdateController.php @@ -28,9 +28,11 @@ use Pimcore\Bundle\StudioBackendBundle\OpenApi\Config\Tags; use Pimcore\Bundle\StudioBackendBundle\Updater\Service\UpdateServiceInterface; use Pimcore\Bundle\StudioBackendBundle\Util\Constants\HttpResponseCodes; +use Pimcore\Bundle\StudioBackendBundle\Util\Constants\UserPermissions; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpKernel\Attribute\MapRequestPayload; use Symfony\Component\Routing\Attribute\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Serializer\SerializerInterface; /** @@ -47,8 +49,7 @@ public function __construct( } #[Route('/assets/{id}', name: 'pimcore_studio_api_update_asset', methods: ['PUT'])] - //#[IsGranted('STUDIO_API')] - //#[IsGranted(UserPermissions::ASSETS->value)] + #[IsGranted(UserPermissions::ASSETS->value)] #[Put( path: self::API_PATH . '/assets/{id}', operationId: 'updateAssetById', diff --git a/src/Asset/Event/AssetEvent.php b/src/Asset/Event/PreResponse/AssetEvent.php similarity index 93% rename from src/Asset/Event/AssetEvent.php rename to src/Asset/Event/PreResponse/AssetEvent.php index 051e383e0..6f469b8ef 100644 --- a/src/Asset/Event/AssetEvent.php +++ b/src/Asset/Event/PreResponse/AssetEvent.php @@ -14,7 +14,7 @@ * @license http://www.pimcore.org/license GPLv3 and PCL */ -namespace Pimcore\Bundle\StudioBackendBundle\Asset\Event; +namespace Pimcore\Bundle\StudioBackendBundle\Asset\Event\PreResponse; use Pimcore\Bundle\StudioBackendBundle\Asset\Schema\Asset; use Pimcore\Bundle\StudioBackendBundle\Event\AbstractPreResponseEvent; diff --git a/src/Asset/Event/PreResponse/CustomMetadataEvent.php b/src/Asset/Event/PreResponse/CustomMetadataEvent.php new file mode 100644 index 000000000..2253eb687 --- /dev/null +++ b/src/Asset/Event/PreResponse/CustomMetadataEvent.php @@ -0,0 +1,40 @@ +customMetadata; + } +} diff --git a/src/Asset/Event/CustomSettingsEvent.php b/src/Asset/Event/PreResponse/CustomSettingsEvent.php similarity index 93% rename from src/Asset/Event/CustomSettingsEvent.php rename to src/Asset/Event/PreResponse/CustomSettingsEvent.php index ade8f1694..5ea259d64 100644 --- a/src/Asset/Event/CustomSettingsEvent.php +++ b/src/Asset/Event/PreResponse/CustomSettingsEvent.php @@ -14,7 +14,7 @@ * @license http://www.pimcore.org/license GPLv3 and PCL */ -namespace Pimcore\Bundle\StudioBackendBundle\Asset\Event; +namespace Pimcore\Bundle\StudioBackendBundle\Asset\Event\PreResponse; use Pimcore\Bundle\StudioBackendBundle\Asset\Schema\CustomSettings; use Pimcore\Bundle\StudioBackendBundle\Event\AbstractPreResponseEvent; diff --git a/src/Asset/Event/PreSet/CustomMetadataEvent.php b/src/Asset/Event/PreSet/CustomMetadataEvent.php new file mode 100644 index 000000000..b2781c4c6 --- /dev/null +++ b/src/Asset/Event/PreSet/CustomMetadataEvent.php @@ -0,0 +1,46 @@ +id; + } + + public function getCustomMetadata(): array + { + return $this->customMetadata; + } + + public function setCustomMetadata(array $customMetadata): void + { + $this->customMetadata = $customMetadata; + } +} diff --git a/src/Asset/Hydrator/CustomMetadataHydrator.php b/src/Asset/Hydrator/CustomMetadataHydrator.php new file mode 100644 index 000000000..b897605a9 --- /dev/null +++ b/src/Asset/Hydrator/CustomMetadataHydrator.php @@ -0,0 +1,53 @@ +resolveData( + $customMetadata['data'], + $customMetadata['type'] + ) + ); + } + + private function resolveData(mixed $data, string $type): mixed + { + return match (true) { + $data instanceof ElementInterface => $this->referenceResolver->resolve($data), + $type === 'checkbox' => (bool)$data, + default => $data, + }; + } +} diff --git a/src/Asset/Hydrator/CustomMetadataHydratorInterface.php b/src/Asset/Hydrator/CustomMetadataHydratorInterface.php new file mode 100644 index 000000000..8042d70d0 --- /dev/null +++ b/src/Asset/Hydrator/CustomMetadataHydratorInterface.php @@ -0,0 +1,27 @@ +mimeType; } - public function getMetadata(): array - { - return $this->metaData; - } - public function getHasMetaData(): bool { - return count($this->metaData) > 0; + return $this->hasMetaData; } public function getFullPath(): string diff --git a/src/Asset/Schema/CustomMetadata.php b/src/Asset/Schema/CustomMetadata.php new file mode 100644 index 000000000..dcee3f971 --- /dev/null +++ b/src/Asset/Schema/CustomMetadata.php @@ -0,0 +1,66 @@ +name; + } + + public function getLanguage(): string + { + return $this->language; + } + + public function getType(): string + { + return $this->type; + } + + public function getData(): mixed + { + return $this->data; + } +} diff --git a/src/Asset/Schema/Type/Document.php b/src/Asset/Schema/Type/Document.php index 1f9b3f6c7..e7a362e0f 100644 --- a/src/Asset/Schema/Type/Document.php +++ b/src/Asset/Schema/Type/Document.php @@ -46,7 +46,7 @@ public function __construct( string $type, string $filename, string $mimeType, - array $metaData, + bool $hasMetaData, bool $workflowWithPermissions, string $fullPath, int $id, @@ -66,7 +66,7 @@ public function __construct( $type, $filename, $mimeType, - $metaData, + $hasMetaData, $workflowWithPermissions, $fullPath, $id, diff --git a/src/Asset/Schema/Type/Image.php b/src/Asset/Schema/Type/Image.php index 8a86ac35f..b43ee7aa4 100644 --- a/src/Asset/Schema/Type/Image.php +++ b/src/Asset/Schema/Type/Image.php @@ -52,7 +52,7 @@ public function __construct( string $type, string $filename, string $mimeType, - array $metaData, + bool $hasMetaData, bool $workflowWithPermissions, string $fullPath, int $id, @@ -72,7 +72,7 @@ public function __construct( $type, $filename, $mimeType, - $metaData, + $hasMetaData, $workflowWithPermissions, $fullPath, $id, diff --git a/src/Asset/Schema/Type/MetaData.php b/src/Asset/Schema/Type/MetaData.php deleted file mode 100644 index 203999e80..000000000 --- a/src/Asset/Schema/Type/MetaData.php +++ /dev/null @@ -1,52 +0,0 @@ -name; - } - - public function getLanguage(): ?string - { - return $this->language; - } - - public function getData(): mixed - { - return $this->data; - } -} diff --git a/src/Asset/Schema/Type/Video.php b/src/Asset/Schema/Type/Video.php index 161a6a758..2fc2f2932 100644 --- a/src/Asset/Schema/Type/Video.php +++ b/src/Asset/Schema/Type/Video.php @@ -46,7 +46,7 @@ public function __construct( string $type, string $filename, string $mimeType, - array $metaData, + bool $hasMetaData, bool $workflowWithPermissions, string $fullPath, int $id, @@ -66,7 +66,7 @@ public function __construct( $type, $filename, $mimeType, - $metaData, + $hasMetaData, $workflowWithPermissions, $fullPath, $id, diff --git a/src/Asset/Service/AssetService.php b/src/Asset/Service/AssetService.php index b46f0e9d4..085ca0492 100644 --- a/src/Asset/Service/AssetService.php +++ b/src/Asset/Service/AssetService.php @@ -16,7 +16,7 @@ namespace Pimcore\Bundle\StudioBackendBundle\Asset\Service; -use Pimcore\Bundle\StudioBackendBundle\Asset\Event\AssetEvent; +use Pimcore\Bundle\StudioBackendBundle\Asset\Event\PreResponse\AssetEvent; use Pimcore\Bundle\StudioBackendBundle\Asset\Schema\Asset; use Pimcore\Bundle\StudioBackendBundle\Asset\Schema\Type\Archive; use Pimcore\Bundle\StudioBackendBundle\Asset\Schema\Type\Audio; @@ -36,9 +36,7 @@ use Pimcore\Bundle\StudioBackendBundle\Exception\SearchException; use Pimcore\Bundle\StudioBackendBundle\Filter\Service\FilterServiceProviderInterface; use Pimcore\Bundle\StudioBackendBundle\Response\Collection; -use Pimcore\Bundle\StudioBackendBundle\Security\Service\SecurityServiceInterface; use Pimcore\Bundle\StudioBackendBundle\Util\Constants\ElementTypes; -use Pimcore\Model\Element\ElementInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** diff --git a/src/Asset/Service/Data/CustomMetadataService.php b/src/Asset/Service/Data/CustomMetadataService.php new file mode 100644 index 000000000..a2d0ad769 --- /dev/null +++ b/src/Asset/Service/Data/CustomMetadataService.php @@ -0,0 +1,80 @@ + + */ + public function getCustomMetadata(int $id): array + { + /** @var Asset $asset */ + $asset = $this->getElement($this->serviceResolver, ElementTypes::TYPE_ASSET, $id); + + $this->securityService->hasElementPermission( + $asset, + $this->securityService->getCurrentUser(), + ElementPermissions::VIEW_PERMISSION + ); + + $customMetadata = []; + + $originalCustomMetadata = $asset->getMetadata(); + + foreach ($originalCustomMetadata as $metadata) { + $metadata = $this->hydrator->hydrate($metadata); + + $this->eventDispatcher->dispatch( + new CustomMetadataEvent($metadata), + CustomMetadataEvent::EVENT_NAME + ); + + $customMetadata[] = $metadata; + } + + return $customMetadata; + } +} diff --git a/src/DataIndex/Hydrator/Asset/MetaDataHydratorInterface.php b/src/Asset/Service/Data/CustomMetadataServiceInterface.php similarity index 54% rename from src/DataIndex/Hydrator/Asset/MetaDataHydratorInterface.php rename to src/Asset/Service/Data/CustomMetadataServiceInterface.php index 905a08670..261fae22b 100644 --- a/src/DataIndex/Hydrator/Asset/MetaDataHydratorInterface.php +++ b/src/Asset/Service/Data/CustomMetadataServiceInterface.php @@ -14,17 +14,20 @@ * @license http://www.pimcore.org/license GPLv3 and PCL */ -namespace Pimcore\Bundle\StudioBackendBundle\DataIndex\Hydrator\Asset; +namespace Pimcore\Bundle\StudioBackendBundle\Asset\Service\Data; -use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Asset\SearchResult\AssetMetaData; -use Pimcore\Bundle\StudioBackendBundle\Asset\Schema\Type\MetaData; +use Pimcore\Bundle\StudioBackendBundle\Asset\Schema\CustomMetadata; +use Pimcore\Bundle\StudioBackendBundle\Exception\AccessDeniedException; -interface MetaDataHydratorInterface +/** + * @internal + */ +interface CustomMetadataServiceInterface { /** - * @param array $metaData + * @throws AccessDeniedException * - * @return array + * @return array */ - public function hydrate(array $metaData): array; + public function getCustomMetadata(int $id): array; } diff --git a/src/Asset/Service/CustomSettingsService.php b/src/Asset/Service/Data/CustomSettingsService.php similarity index 93% rename from src/Asset/Service/CustomSettingsService.php rename to src/Asset/Service/Data/CustomSettingsService.php index ac6951798..6858e47dd 100644 --- a/src/Asset/Service/CustomSettingsService.php +++ b/src/Asset/Service/Data/CustomSettingsService.php @@ -14,10 +14,10 @@ * @license http://www.pimcore.org/license GPLv3 and PCL */ -namespace Pimcore\Bundle\StudioBackendBundle\Asset\Service; +namespace Pimcore\Bundle\StudioBackendBundle\Asset\Service\Data; use Pimcore\Bundle\StaticResolverBundle\Models\Element\ServiceResolverInterface; -use Pimcore\Bundle\StudioBackendBundle\Asset\Event\CustomSettingsEvent; +use Pimcore\Bundle\StudioBackendBundle\Asset\Event\PreResponse\CustomSettingsEvent; use Pimcore\Bundle\StudioBackendBundle\Asset\Hydrator\CustomSettingsHydratorInterface; use Pimcore\Bundle\StudioBackendBundle\Asset\Schema\CustomSettings; use Pimcore\Bundle\StudioBackendBundle\Exception\AccessDeniedException; diff --git a/src/Asset/Service/CustomSettingsServiceInterface.php b/src/Asset/Service/Data/CustomSettingsServiceInterface.php similarity index 92% rename from src/Asset/Service/CustomSettingsServiceInterface.php rename to src/Asset/Service/Data/CustomSettingsServiceInterface.php index 020bef5c7..406346584 100644 --- a/src/Asset/Service/CustomSettingsServiceInterface.php +++ b/src/Asset/Service/Data/CustomSettingsServiceInterface.php @@ -14,7 +14,7 @@ * @license http://www.pimcore.org/license GPLv3 and PCL */ -namespace Pimcore\Bundle\StudioBackendBundle\Asset\Service; +namespace Pimcore\Bundle\StudioBackendBundle\Asset\Service\Data; use Pimcore\Bundle\StudioBackendBundle\Asset\Schema\CustomSettings; use Pimcore\Bundle\StudioBackendBundle\Exception\AccessDeniedException; diff --git a/src/Asset/Service/DataService.php b/src/Asset/Service/Data/TextService.php similarity index 92% rename from src/Asset/Service/DataService.php rename to src/Asset/Service/Data/TextService.php index 641f7b375..9895b01a8 100644 --- a/src/Asset/Service/DataService.php +++ b/src/Asset/Service/Data/TextService.php @@ -14,7 +14,7 @@ * @license http://www.pimcore.org/license GPLv3 and PCL */ -namespace Pimcore\Bundle\StudioBackendBundle\Asset\Service; +namespace Pimcore\Bundle\StudioBackendBundle\Asset\Service\Data; use Pimcore\Bundle\StaticResolverBundle\Models\Element\ServiceResolverInterface; use Pimcore\Bundle\StudioBackendBundle\Asset\Encoder\TextEncoderInterface; @@ -26,7 +26,7 @@ /** * @internal */ -final class DataService implements DataServiceInterface +final class TextService implements TextServiceInterface { use ElementProviderTrait; diff --git a/src/Asset/Service/DataServiceInterface.php b/src/Asset/Service/Data/TextServiceInterface.php similarity index 90% rename from src/Asset/Service/DataServiceInterface.php rename to src/Asset/Service/Data/TextServiceInterface.php index 8c59258f7..75a2b4975 100644 --- a/src/Asset/Service/DataServiceInterface.php +++ b/src/Asset/Service/Data/TextServiceInterface.php @@ -14,7 +14,7 @@ * @license http://www.pimcore.org/license GPLv3 and PCL */ -namespace Pimcore\Bundle\StudioBackendBundle\Asset\Service; +namespace Pimcore\Bundle\StudioBackendBundle\Asset\Service\Data; use Pimcore\Bundle\StudioBackendBundle\Exception\ElementNotFoundException; use Pimcore\Bundle\StudioBackendBundle\Exception\InvalidElementTypeException; @@ -23,7 +23,7 @@ /** * @internal */ -interface DataServiceInterface +interface TextServiceInterface { /** * @throws ElementNotFoundException|InvalidElementTypeException|MaxFileSizeExceededException diff --git a/src/Asset/Updater/Adapter/CustomMetadataAdapter.php b/src/Asset/Updater/Adapter/CustomMetadataAdapter.php new file mode 100644 index 000000000..5b08f6f41 --- /dev/null +++ b/src/Asset/Updater/Adapter/CustomMetadataAdapter.php @@ -0,0 +1,66 @@ +getIndexKey(), $data)) { + return; + } + + $metadataEvent = new CustomMetadataEvent($element->getId(), $data[$this->getIndexKey()]); + + $this->eventDispatcher->dispatch($metadataEvent, CustomMetadataEvent::EVENT_NAME); + + $element->setMetadata($metadataEvent->getCustomMetadata()); + } + + public function getIndexKey(): string + { + return self::INDEX_KEY; + } + + public function supportedElementTypes(): array + { + return [ + ElementTypes::TYPE_ASSET, + ]; + } +} diff --git a/src/DataIndex/Hydrator/Asset/ArchiveHydrator.php b/src/DataIndex/Hydrator/Asset/ArchiveHydrator.php index 18a532e72..502d92a37 100644 --- a/src/DataIndex/Hydrator/Asset/ArchiveHydrator.php +++ b/src/DataIndex/Hydrator/Asset/ArchiveHydrator.php @@ -25,7 +25,6 @@ { public function __construct( private IconServiceInterface $iconService, - private MetaDataHydratorInterface $metaDataHydrator, private PermissionsHydratorInterface $permissionsHydrator ) { } @@ -38,7 +37,7 @@ public function hydrate(ArchiveItem $item): Archive $item->getType(), $item->getKey(), $item->getMimeType(), - $this->metaDataHydrator->hydrate($item->getMetaData()), + !empty($item->getMetaData()), $item->isHasWorkflowWithPermissions(), $item->getFullPath(), $item->getId(), diff --git a/src/DataIndex/Hydrator/Asset/AudioHydrator.php b/src/DataIndex/Hydrator/Asset/AudioHydrator.php index 2a0667e0a..8c7176f95 100644 --- a/src/DataIndex/Hydrator/Asset/AudioHydrator.php +++ b/src/DataIndex/Hydrator/Asset/AudioHydrator.php @@ -25,7 +25,6 @@ { public function __construct( private IconServiceInterface $iconService, - private MetaDataHydratorInterface $metaDataHydrator, private PermissionsHydratorInterface $permissionsHydrator ) { } @@ -38,7 +37,7 @@ public function hydrate(AudioItem $item): Audio $item->getType(), $item->getKey(), $item->getMimeType(), - $this->metaDataHydrator->hydrate($item->getMetaData()), + !empty($item->getMetaData()), $item->isHasWorkflowWithPermissions(), $item->getFullPath(), $item->getId(), diff --git a/src/DataIndex/Hydrator/Asset/DocumentHydrator.php b/src/DataIndex/Hydrator/Asset/DocumentHydrator.php index 7a644d605..a25108b93 100644 --- a/src/DataIndex/Hydrator/Asset/DocumentHydrator.php +++ b/src/DataIndex/Hydrator/Asset/DocumentHydrator.php @@ -25,7 +25,6 @@ { public function __construct( private IconServiceInterface $iconService, - private MetaDataHydratorInterface $metaDataHydrator, private PermissionsHydratorInterface $permissionsHydrator ) { } @@ -40,7 +39,7 @@ public function hydrate(DocumentItem $item): Document $item->getType(), $item->getKey(), $item->getMimeType(), - $this->metaDataHydrator->hydrate($item->getMetaData()), + !empty($item->getMetaData()), $item->isHasWorkflowWithPermissions(), $item->getFullPath(), $item->getId(), diff --git a/src/DataIndex/Hydrator/Asset/FolderHydrator.php b/src/DataIndex/Hydrator/Asset/FolderHydrator.php index 892efe66b..c09a72ba1 100644 --- a/src/DataIndex/Hydrator/Asset/FolderHydrator.php +++ b/src/DataIndex/Hydrator/Asset/FolderHydrator.php @@ -25,7 +25,6 @@ { public function __construct( private IconServiceInterface $iconService, - private MetaDataHydratorInterface $metaDataHydrator, private PermissionsHydratorInterface $permissionsHydrator ) { } @@ -38,7 +37,7 @@ public function hydrate(FolderItem $item): Folder $item->getType(), $item->getKey(), $item->getMimeType(), - $this->metaDataHydrator->hydrate($item->getMetaData()), + !empty($item->getMetaData()), $item->isHasWorkflowWithPermissions(), $item->getFullPath(), $item->getId(), diff --git a/src/DataIndex/Hydrator/Asset/ImageHydrator.php b/src/DataIndex/Hydrator/Asset/ImageHydrator.php index dd7d8a6a1..8c1920066 100644 --- a/src/DataIndex/Hydrator/Asset/ImageHydrator.php +++ b/src/DataIndex/Hydrator/Asset/ImageHydrator.php @@ -25,7 +25,6 @@ { public function __construct( private IconServiceInterface $iconService, - private MetaDataHydratorInterface $metaDataHydrator, private PermissionsHydratorInterface $permissionsHydrator ) { } @@ -44,7 +43,7 @@ public function hydrate(ImageItem $item): Image $item->getType(), $item->getKey(), $item->getMimeType(), - $this->metaDataHydrator->hydrate($item->getMetaData()), + !empty($item->getMetaData()), $item->isHasWorkflowWithPermissions(), $item->getFullPath(), $item->getId(), diff --git a/src/DataIndex/Hydrator/Asset/MetaDataHydrator.php b/src/DataIndex/Hydrator/Asset/MetaDataHydrator.php deleted file mode 100644 index a4a652c69..000000000 --- a/src/DataIndex/Hydrator/Asset/MetaDataHydrator.php +++ /dev/null @@ -1,42 +0,0 @@ - $metaData - * - * @return array - */ - public function hydrate(array $metaData): array - { - $result = []; - foreach ($metaData as $item) { - $result[] = new MetaData( - $item->getName(), - $item->getLanguage(), - $item->getData() - ); - } - - return $result; - } -} diff --git a/src/DataIndex/Hydrator/Asset/TextHydrator.php b/src/DataIndex/Hydrator/Asset/TextHydrator.php index 210585a02..c3dfe241d 100644 --- a/src/DataIndex/Hydrator/Asset/TextHydrator.php +++ b/src/DataIndex/Hydrator/Asset/TextHydrator.php @@ -25,7 +25,6 @@ { public function __construct( private IconServiceInterface $iconService, - private MetaDataHydratorInterface $metaDataHydrator, private PermissionsHydratorInterface $permissionsHydrator ) { } @@ -38,7 +37,7 @@ public function hydrate(TextItem $item): Text $item->getType(), $item->getKey(), $item->getMimeType(), - $this->metaDataHydrator->hydrate($item->getMetaData()), + !empty($item->getMetaData()), $item->isHasWorkflowWithPermissions(), $item->getFullPath(), $item->getId(), diff --git a/src/DataIndex/Hydrator/Asset/UnknownHydrator.php b/src/DataIndex/Hydrator/Asset/UnknownHydrator.php index 80f76b491..a9f0ca1e1 100644 --- a/src/DataIndex/Hydrator/Asset/UnknownHydrator.php +++ b/src/DataIndex/Hydrator/Asset/UnknownHydrator.php @@ -25,7 +25,6 @@ { public function __construct( private IconServiceInterface $iconService, - private MetaDataHydratorInterface $metaDataHydrator, private PermissionsHydratorInterface $permissionsHydrator ) { } @@ -38,7 +37,7 @@ public function hydrate(UnknownItem $item): Unknown $item->getType(), $item->getKey(), $item->getMimeType(), - $this->metaDataHydrator->hydrate($item->getMetaData()), + !empty($item->getMetaData()), $item->isHasWorkflowWithPermissions(), $item->getFullPath(), $item->getId(), diff --git a/src/DataIndex/Hydrator/Asset/VideoHydrator.php b/src/DataIndex/Hydrator/Asset/VideoHydrator.php index 638806af3..298bb6968 100644 --- a/src/DataIndex/Hydrator/Asset/VideoHydrator.php +++ b/src/DataIndex/Hydrator/Asset/VideoHydrator.php @@ -25,7 +25,6 @@ { public function __construct( private IconServiceInterface $iconService, - private MetaDataHydratorInterface $metaDataHydrator, private PermissionsHydratorInterface $permissionsHydrator ) { } @@ -42,7 +41,7 @@ public function hydrate(VideoItem $item): Video $item->getType(), $item->getKey(), $item->getMimeType(), - $this->metaDataHydrator->hydrate($item->getMetaData()), + !empty($item->getMetaData()), $item->isHasWorkflowWithPermissions(), $item->getFullPath(), $item->getId(), diff --git a/src/DataIndex/Hydrator/AssetHydrator.php b/src/DataIndex/Hydrator/AssetHydrator.php index 7908d60bb..61cb4e0bf 100644 --- a/src/DataIndex/Hydrator/AssetHydrator.php +++ b/src/DataIndex/Hydrator/AssetHydrator.php @@ -18,14 +18,12 @@ use Pimcore\Bundle\GenericDataIndexBundle\Model\Search\Asset\SearchResult\AssetSearchResultItem; use Pimcore\Bundle\StudioBackendBundle\Asset\Schema\Asset; -use Pimcore\Bundle\StudioBackendBundle\DataIndex\Hydrator\Asset\MetaDataHydratorInterface; use Pimcore\Bundle\StudioBackendBundle\Icon\Service\IconServiceInterface; final readonly class AssetHydrator implements AssetHydratorInterface { public function __construct( private IconServiceInterface $iconService, - private MetaDataHydratorInterface $metaDataHydrator, private PermissionsHydratorInterface $permissionsHydrator ) { } @@ -38,7 +36,7 @@ public function hydrate(AssetSearchResultItem $item): Asset $item->getType(), $item->getKey(), $item->getMimeType(), - $this->metaDataHydrator->hydrate($item->getMetaData()), + !empty($item->getMetaData()), $item->isHasWorkflowWithPermissions(), $item->getFullPath(), $item->getId(), diff --git a/src/DependencyInjection/PimcoreStudioBackendExtension.php b/src/DependencyInjection/PimcoreStudioBackendExtension.php index 677dfb4fb..b4385a3a3 100644 --- a/src/DependencyInjection/PimcoreStudioBackendExtension.php +++ b/src/DependencyInjection/PimcoreStudioBackendExtension.php @@ -66,6 +66,7 @@ public function load(array $configs, ContainerBuilder $container): void $loader->load('open_api.yaml'); $loader->load('patcher.yaml'); $loader->load('properties.yaml'); + $loader->load('resolver.yaml'); $loader->load('schedules.yaml'); $loader->load('security.yaml'); $loader->load('services.yaml'); diff --git a/src/Property/Hydrator/PropertyHydrator.php b/src/Property/Hydrator/PropertyHydrator.php index 9c85a6d34..d66ad0391 100644 --- a/src/Property/Hydrator/PropertyHydrator.php +++ b/src/Property/Hydrator/PropertyHydrator.php @@ -19,6 +19,7 @@ use Pimcore\Bundle\StaticResolverBundle\Models\Predefined\PredefinedResolverInterface; use Pimcore\Bundle\StudioBackendBundle\Property\Schema\ElementProperty; use Pimcore\Bundle\StudioBackendBundle\Property\Schema\PredefinedProperty; +use Pimcore\Bundle\StudioBackendBundle\Resolver\Element\ReferenceResolverInterface; use Pimcore\Model\Asset; use Pimcore\Model\DataObject\AbstractObject; use Pimcore\Model\Document; @@ -30,14 +31,6 @@ */ final readonly class PropertyHydrator implements PropertyHydratorInterface { - private const ALLOWED_MODEL_PROPERTIES = [ - 'key', - 'filename', - 'path', - 'id', - 'type', - ]; - private const EXCLUDED_PROPERTIES = [ 'cid', 'ctype', @@ -46,7 +39,8 @@ ]; public function __construct( - private PredefinedResolverInterface $predefinedResolver + private PredefinedResolverInterface $predefinedResolver, + private ReferenceResolverInterface $referenceResolver ) { } @@ -69,7 +63,7 @@ public function hydratePredefinedProperty(Predefined $property): PredefinedPrope public function hydrateElementProperty(Property $property): ElementProperty { - $propertyData = $this->extractData($property); + $propertyData = $this->resolveData($property); return new ElementProperty( $propertyData['name'], @@ -83,33 +77,28 @@ public function hydrateElementProperty(Property $property): ElementProperty ); } - private function extractData(Property $property): array + private function resolveData(Property $property): array { $data['modelData'] = match (true) { $property->getData() instanceof Document || $property->getData() instanceof Asset || - $property->getData() instanceof AbstractObject => $this->extractDataFromModel($property->getData()), + $property->getData() instanceof AbstractObject => $this->referenceResolver->resolve($property->getData()), default => null, }; return [ ... $this->excludeProperties($property->getObjectVars()), ... $data, - ... $this->extractPredefinedPropertyData($property), + ... $this->resolvePredefinedPropertyData($property), ]; } - private function extractDataFromModel(Document|Asset|AbstractObject $data): array - { - return array_intersect_key($data->getObjectVars(), array_flip(self::ALLOWED_MODEL_PROPERTIES)); - } - private function excludeProperties(array $values): array { return array_diff_key($values, array_flip(self::EXCLUDED_PROPERTIES)); } - private function extractPredefinedPropertyData(Property $property): array + private function resolvePredefinedPropertyData(Property $property): array { $empty = ['config' => null, 'predefinedName' => null, 'description' => null]; if (!$property->getName() || !$property->getType()) { diff --git a/src/Resolver/Element/ReferenceResolver.php b/src/Resolver/Element/ReferenceResolver.php new file mode 100644 index 000000000..5c0adac56 --- /dev/null +++ b/src/Resolver/Element/ReferenceResolver.php @@ -0,0 +1,56 @@ + + */ + private array $cache = []; + + public function resolve(ElementInterface $element): array + { + if (isset($this->cache[$element->getId()])) { + return $this->cache[$element->getId()]; + } + + /** + * @var AbstractElement $element + */ + $data = array_intersect_key( + $element->getObjectVars(), + array_flip(self::ALLOWED_MODEL_PROPERTIES) + ); + + $data['fullPath'] = $element->getFullPath(); + + $this->cache[$element->getId()] = $data; + + return $data; + } +} diff --git a/src/Resolver/Element/ReferenceResolverInterface.php b/src/Resolver/Element/ReferenceResolverInterface.php new file mode 100644 index 000000000..81301ffca --- /dev/null +++ b/src/Resolver/Element/ReferenceResolverInterface.php @@ -0,0 +1,23 @@ +mockPredefinedResolver()); + return new PropertyHydrator($this->mockPredefinedResolver(), $this->mockDataResolver()); } /** @@ -85,11 +86,31 @@ private function getHydrator(): PropertyHydratorInterface */ private function mockPredefinedResolver(): PredefinedResolverInterface { - return $this->makeEmpty(PredefinedResolverInterface::class, - [ - 'getById' => $this->getPredefined(), - 'getByKey' => $this->getPredefined(), - ]); + return $this->makeEmpty( + PredefinedResolverInterface::class, + [ + 'getById' => $this->getPredefined(), + 'getByKey' => $this->getPredefined(), + ] + ); + } + + /** + * @throws Exception + */ + private function mockDataResolver(): ReferenceResolverInterface + { + return $this->makeEmpty( + ReferenceResolverInterface::class, + [ + 'resolve' => [ + 'path' => '/test', + 'id' => 1, + 'type' => 'page', + 'key' => 'test', + ], + ] + ); } private function getPredefined(): Predefined