diff --git a/config/properties.yaml b/config/properties.yaml index 25dc6a415..08c20358e 100644 --- a/config/properties.yaml +++ b/config/properties.yaml @@ -22,8 +22,8 @@ services: Pimcore\Bundle\StudioBackendBundle\Property\Service\PropertyServiceInterface: class: Pimcore\Bundle\StudioBackendBundle\Property\Service\PropertyService - Pimcore\Bundle\StudioBackendBundle\Property\Hydrator\DataPropertyHydratorInterface: - class: Pimcore\Bundle\StudioBackendBundle\Property\Hydrator\DataPropertyHydrator + Pimcore\Bundle\StudioBackendBundle\Property\Hydrator\ElementPropertyHydratorInterface: + class: Pimcore\Bundle\StudioBackendBundle\Property\Hydrator\ElementPropertyHydrator Pimcore\Bundle\StudioBackendBundle\Property\Hydrator\PredefinedPropertyHydratorInterface: class: Pimcore\Bundle\StudioBackendBundle\Property\Hydrator\PredefinedPropertyHydrator diff --git a/src/OpenApi/Attributes/Request/ElementPropertyRequestBody.php b/src/OpenApi/Attributes/Request/ElementPropertyRequestBody.php new file mode 100644 index 000000000..f19eec518 --- /dev/null +++ b/src/OpenApi/Attributes/Request/ElementPropertyRequestBody.php @@ -0,0 +1,38 @@ +name, - description: 'Get properties for elements' + description: 'Property operations to get/update/create/delete properties' +)] +#[Tag( + name: Tags::PropertiesForElement->value, + description: 'Property operations to get/update properties for an element' )] #[Tag( name: Tags::Translation->name, @@ -45,12 +49,13 @@ name: Tags::Versions->name, description: 'Versions operations to get/list/publish/delete and cleanup versions' )] -enum Tags +enum Tags: string { - case Assets; - case Authorization; - case DataObjects; - case Properties; - case Translation; - case Versions; + case Assets = 'Assets'; + case Authorization = 'Authorization'; + case DataObjects = 'DataObjects'; + case Properties = 'Properties'; + case PropertiesForElement = 'Properties for Element'; + case Translation = 'Translation'; + case Versions = 'Versions'; } diff --git a/src/Property/Controller/GetController.php b/src/Property/Controller/Element/GetController.php similarity index 90% rename from src/Property/Controller/GetController.php rename to src/Property/Controller/Element/GetController.php index b3e4a31b5..e7f150453 100644 --- a/src/Property/Controller/GetController.php +++ b/src/Property/Controller/Element/GetController.php @@ -14,7 +14,7 @@ * @license http://www.pimcore.org/license GPLv3 and PCL */ -namespace Pimcore\Bundle\StudioBackendBundle\Property\Controller; +namespace Pimcore\Bundle\StudioBackendBundle\Property\Controller\Element; use OpenApi\Attributes\Get; use Pimcore\Bundle\StudioBackendBundle\Controller\AbstractApiController; @@ -28,7 +28,7 @@ use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Response\Error\UnsupportedMediaTypeResponse; use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Response\SuccessResponse; use Pimcore\Bundle\StudioBackendBundle\OpenApi\Config\Tags; -use Pimcore\Bundle\StudioBackendBundle\Property\Schema\DataProperty; +use Pimcore\Bundle\StudioBackendBundle\Property\Schema\ElementProperty; use Pimcore\Bundle\StudioBackendBundle\Property\Service\PropertyHydratorServiceInterface; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\Routing\Attribute\Route; @@ -46,20 +46,20 @@ public function __construct( parent::__construct($serializer); } - #[Route('/properties/{elementType}/{id}', name: 'pimcore_studio_api_get_properties', methods: ['GET'])] + #[Route('/properties/{elementType}/{id}', name: 'pimcore_studio_api_get_element_properties', methods: ['GET'])] //#[IsGranted('STUDIO_API')] #[Get( path: self::API_PATH . '/properties/{elementType}/{id}', - operationId: 'getPropertiesByTypeAndId', + operationId: 'getPropertiesForElementByTypeAndId', summary: 'Get properties for an element based on the element type and the element id', security: self::SECURITY_SCHEME, - tags: [Tags::Properties->name] + tags: [Tags::PropertiesForElement->value] )] #[ElementTypeParameter] #[IdParameter(type: 'element')] #[SuccessResponse( description: 'Element Properties data as json', - content: new ItemsJson(DataProperty::class) + content: new ItemsJson(ElementProperty::class) )] #[UnauthorizedResponse] #[NotFoundResponse] diff --git a/src/Property/Controller/Element/PutController.php b/src/Property/Controller/Element/PutController.php new file mode 100644 index 000000000..e76baf34b --- /dev/null +++ b/src/Property/Controller/Element/PutController.php @@ -0,0 +1,84 @@ +value] + )] + #[ElementTypeParameter] + #[IdParameter(type: 'element')] + #[ElementPropertyRequestBody] + #[SuccessResponse( + description: 'Element Properties data as json', + content: new ItemsJson(ElementProperty::class) + )] + #[UnauthorizedResponse] + #[NotFoundResponse] + #[MethodNotAllowedResponse] + #[UnsupportedMediaTypeResponse] + #[UnprocessableContentResponse] + public function updateProperties( + string $elementType, + int $id, + #[MapRequestPayload] UpdateElementProperties $items + ): JsonResponse + { + $this->propertyService->updateElementProperties($elementType, $id, $items); + return $this->jsonResponse($this->hydratorService->getHydratedPropertyForElement($elementType, $id)); + } +} diff --git a/src/Property/Controller/PutController.php b/src/Property/Controller/PutController.php index 4188abb05..2030d24b9 100644 --- a/src/Property/Controller/PutController.php +++ b/src/Property/Controller/PutController.php @@ -22,7 +22,7 @@ use Pimcore\Bundle\StudioBackendBundle\Controller\AbstractApiController; use Pimcore\Bundle\StudioBackendBundle\Exception\PropertyNotFoundException; use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Parameters\Path\IdParameter; -use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Request\PropertyRequestBody; +use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Request\PredefinedPropertyRequestBody; use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Response\Error\BadRequestResponse; use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Response\Error\MethodNotAllowedResponse; use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Response\Error\UnauthorizedResponse; @@ -61,7 +61,7 @@ public function __construct( tags: [Tags::Properties->name] )] #[IdParameter(type: 'property', schema: new Schema(type: 'string', example: 'alpha-numerical'))] - #[PropertyRequestBody] + #[PredefinedPropertyRequestBody] #[SuccessResponse( description: 'Updated property', content: new JsonContent(ref: PredefinedProperty::class, type: 'object') diff --git a/src/Property/Hydrator/DataPropertyHydrator.php b/src/Property/Hydrator/ElementPropertyHydrator.php similarity index 78% rename from src/Property/Hydrator/DataPropertyHydrator.php rename to src/Property/Hydrator/ElementPropertyHydrator.php index eea349edb..aeb5b418b 100644 --- a/src/Property/Hydrator/DataPropertyHydrator.php +++ b/src/Property/Hydrator/ElementPropertyHydrator.php @@ -17,31 +17,31 @@ namespace Pimcore\Bundle\StudioBackendBundle\Property\Hydrator; use Pimcore\Bundle\StudioBackendBundle\Property\Extractor\PropertyDataExtractorInterface; -use Pimcore\Bundle\StudioBackendBundle\Property\Schema\DataProperty; +use Pimcore\Bundle\StudioBackendBundle\Property\Schema\ElementProperty; use Pimcore\Model\Property; /** * @internal */ -final readonly class DataPropertyHydrator implements DataPropertyHydratorInterface +final readonly class ElementPropertyHydrator implements ElementPropertyHydratorInterface { public function __construct( private PropertyDataExtractorInterface $dataExtractor ) { } - public function hydrate(Property $property): DataProperty + public function hydrate(Property $property): ElementProperty { $propertyData = $this->dataExtractor->extractData($property); - return new DataProperty( + return new ElementProperty( $propertyData['name'], $propertyData['modelData'] ?? $propertyData['data'], $propertyData['type'], $propertyData['inheritable'], $propertyData['inherited'], $propertyData['config'], - $propertyData['predefinedName'], + $propertyData['predefinedName'] ?? 'Custom', $propertyData['description'] ); } diff --git a/src/Property/Hydrator/DataPropertyHydratorInterface.php b/src/Property/Hydrator/ElementPropertyHydratorInterface.php similarity index 76% rename from src/Property/Hydrator/DataPropertyHydratorInterface.php rename to src/Property/Hydrator/ElementPropertyHydratorInterface.php index 78ea76aaf..02397128d 100644 --- a/src/Property/Hydrator/DataPropertyHydratorInterface.php +++ b/src/Property/Hydrator/ElementPropertyHydratorInterface.php @@ -16,13 +16,13 @@ namespace Pimcore\Bundle\StudioBackendBundle\Property\Hydrator; -use Pimcore\Bundle\StudioBackendBundle\Property\Schema\DataProperty; +use Pimcore\Bundle\StudioBackendBundle\Property\Schema\ElementProperty; use Pimcore\Model\Property; /** * @internal */ -interface DataPropertyHydratorInterface +interface ElementPropertyHydratorInterface { - public function hydrate(Property $property): DataProperty; + public function hydrate(Property $property): ElementProperty; } diff --git a/src/Property/Request/UpdateElementProperties.php b/src/Property/Request/UpdateElementProperties.php new file mode 100644 index 000000000..12df3f1bf --- /dev/null +++ b/src/Property/Request/UpdateElementProperties.php @@ -0,0 +1,45 @@ +properties = array_map(static function(array $propertyData) { + return new UpdateElementProperty( + $propertyData['key'], + $propertyData['data'], + $propertyData['type'], + $propertyData['inheritable'], + ); + }, $items); + } + + public function getProperties(): array + { + return $this->properties; + } +} diff --git a/src/Property/Schema/DataProperty.php b/src/Property/Schema/ElementProperty.php similarity index 87% rename from src/Property/Schema/DataProperty.php rename to src/Property/Schema/ElementProperty.php index 45ce4b97c..ce4869002 100644 --- a/src/Property/Schema/DataProperty.php +++ b/src/Property/Schema/ElementProperty.php @@ -23,11 +23,11 @@ title: 'DataProperty', type: 'object' )] -final readonly class DataProperty +final readonly class ElementProperty { public function __construct( - #[Property(description: 'name', type: 'string', example: 'Mister Proper')] - private string $name, + #[Property(description: 'key', type: 'string', example: 'key_of_the_property')] + private string $key, #[Property(description: 'data', type: 'mixed', example: '123')] private mixed $data, #[Property(description: 'type', type: 'string', example: 'document')] @@ -45,9 +45,9 @@ public function __construct( ) { } - public function getName(): string + public function getKey(): string { - return $this->name; + return $this->key; } public function getData(): mixed @@ -60,12 +60,12 @@ public function getType(): string return $this->type; } - public function getIsInheritable(): bool + public function isInheritable(): bool { return $this->inheritable; } - public function getIsInherited(): bool + public function isInherited(): bool { return $this->inherited; } diff --git a/src/Property/Schema/PredefinedProperty.php b/src/Property/Schema/PredefinedProperty.php index bf98d83ed..25acfbbbc 100644 --- a/src/Property/Schema/PredefinedProperty.php +++ b/src/Property/Schema/PredefinedProperty.php @@ -94,7 +94,7 @@ public function getCtype(): string return $this->ctype; } - public function getInheritable(): bool + public function isInheritable(): bool { return $this->inheritable; } diff --git a/src/Property/Schema/UpdateElementProperty.php b/src/Property/Schema/UpdateElementProperty.php new file mode 100644 index 000000000..bcc71324d --- /dev/null +++ b/src/Property/Schema/UpdateElementProperty.php @@ -0,0 +1,59 @@ +key; + } + + public function getData(): mixed + { + return $this->data; + } + + public function getType(): string + { + return $this->type; + } + + public function getInheritable(): bool + { + return $this->inheritable; + } +} diff --git a/src/Property/Schema/UpdatePredefinedProperty.php b/src/Property/Schema/UpdatePredefinedProperty.php index edf20e562..8b5df22bc 100644 --- a/src/Property/Schema/UpdatePredefinedProperty.php +++ b/src/Property/Schema/UpdatePredefinedProperty.php @@ -83,7 +83,7 @@ public function getCtype(): string return $this->ctype; } - public function getInheritable(): bool + public function isInheritable(): bool { return $this->inheritable; } diff --git a/src/Property/Service/PropertyHydratorService.php b/src/Property/Service/PropertyHydratorService.php index c4cfad138..0b1800717 100644 --- a/src/Property/Service/PropertyHydratorService.php +++ b/src/Property/Service/PropertyHydratorService.php @@ -17,7 +17,7 @@ namespace Pimcore\Bundle\StudioBackendBundle\Property\Service; use Pimcore\Bundle\StaticResolverBundle\Models\Element\ServiceResolver; -use Pimcore\Bundle\StudioBackendBundle\Property\Hydrator\DataPropertyHydratorInterface; +use Pimcore\Bundle\StudioBackendBundle\Property\Hydrator\ElementPropertyHydratorInterface; use Pimcore\Bundle\StudioBackendBundle\Property\Hydrator\PredefinedPropertyHydratorInterface; use Pimcore\Bundle\StudioBackendBundle\Property\RepositoryInterface; use Pimcore\Bundle\StudioBackendBundle\Property\Request\PropertiesParameters; @@ -32,7 +32,7 @@ public function __construct( private RepositoryInterface $repository, private ServiceResolver $serviceResolver, - private DataPropertyHydratorInterface $dataPropertyHydrator, + private ElementPropertyHydratorInterface $dataPropertyHydrator, private PredefinedPropertyHydratorInterface $predefinedPropertyHydrator, ) { } diff --git a/src/Property/Service/PropertyService.php b/src/Property/Service/PropertyService.php index af1e0a30b..29c041c66 100644 --- a/src/Property/Service/PropertyService.php +++ b/src/Property/Service/PropertyService.php @@ -16,9 +16,13 @@ namespace Pimcore\Bundle\StudioBackendBundle\Property\Service; +use Pimcore\Bundle\StaticResolverBundle\Models\Element\ServiceResolver; use Pimcore\Bundle\StudioBackendBundle\Exception\PropertyNotFoundException; use Pimcore\Bundle\StudioBackendBundle\Property\RepositoryInterface; +use Pimcore\Bundle\StudioBackendBundle\Property\Request\UpdateElementProperties; use Pimcore\Bundle\StudioBackendBundle\Property\Schema\UpdatePredefinedProperty; +use Pimcore\Bundle\StudioBackendBundle\Util\Traits\ElementProviderTrait; +use Pimcore\Model\Property; use Pimcore\Model\Property\Predefined; /** @@ -26,9 +30,12 @@ */ final readonly class PropertyService implements PropertyServiceInterface { - public function __construct(private RepositoryInterface $repository) - { + use ElementProviderTrait; + public function __construct( + private RepositoryInterface $repository, + private ServiceResolver $serviceResolver, + ){ } /** @@ -39,6 +46,22 @@ public function updatePredefinedProperty(string $id, UpdatePredefinedProperty $p return $this->repository->updatePredefinedProperty($id, $property); } + public function updateElementProperties(string $elementType, int $id, UpdateElementProperties $items): void + { + $element = $this->getElement($this->serviceResolver, $elementType, $id); + $properties = []; + foreach($items->getProperties() as $updateProperty) { + $property = new Property(); + $property->setType($updateProperty->getType()); + $property->setName($updateProperty->getKey()); + $property->setData($updateProperty->getData()); + $property->setInheritable($updateProperty->getInheritable()); + $properties[] = $property; + } + $element->setProperties($properties); + $element->save(); + } + /** * @throws PropertyNotFoundException */ @@ -46,4 +69,6 @@ public function deletePredefinedProperty(string $id): void { $this->repository->deletePredefinedProperty($id); } + + } diff --git a/src/Property/Service/PropertyServiceInterface.php b/src/Property/Service/PropertyServiceInterface.php index 7c7c65831..bee1dd995 100644 --- a/src/Property/Service/PropertyServiceInterface.php +++ b/src/Property/Service/PropertyServiceInterface.php @@ -17,6 +17,7 @@ namespace Pimcore\Bundle\StudioBackendBundle\Property\Service; use Pimcore\Bundle\StudioBackendBundle\Exception\PropertyNotFoundException; +use Pimcore\Bundle\StudioBackendBundle\Property\Request\UpdateElementProperties; use Pimcore\Bundle\StudioBackendBundle\Property\Schema\UpdatePredefinedProperty; use Pimcore\Model\Property\Predefined; @@ -30,6 +31,8 @@ interface PropertyServiceInterface */ public function updatePredefinedProperty(string $id, UpdatePredefinedProperty $property): Predefined; + public function updateElementProperties(string $elementType, int $id, UpdateElementProperties $items): void; + /** * @throws PropertyNotFoundException */