From fd87cc2a2c89ba68ed6b5f6262fd9cf692877eef Mon Sep 17 00:00:00 2001 From: mattamon Date: Wed, 13 Mar 2024 11:44:27 +0100 Subject: [PATCH] WIP: showcase patch method --- .../api_platform/resources/asset/image.yaml | 2 +- config/services.yaml | 2 +- src/Dto/Asset.php | 9 +++- src/Dto/Element.php | 7 ++- src/Service/AssetService.php | 46 +++++++++++++++++-- src/Service/AssetServiceInterface.php | 2 +- .../V1/Hydrator/AssetHydratorService.php | 2 +- ....php => AssetHydratorServiceInterface.php} | 2 +- src/State/Asset/Processor.php | 17 +++++-- 9 files changed, 74 insertions(+), 15 deletions(-) rename src/Service/CoreData/V1/Hydrator/{AssetHydratorInterface.php => AssetHydratorServiceInterface.php} (94%) diff --git a/config/api_platform/resources/asset/image.yaml b/config/api_platform/resources/asset/image.yaml index 59f9f5934..b9c4e5484 100644 --- a/config/api_platform/resources/asset/image.yaml +++ b/config/api_platform/resources/asset/image.yaml @@ -6,7 +6,7 @@ resources: ApiPlatform\Metadata\Get: normalizationContext: groups: ['image:read', 'asset:read', 'asset:item:get', 'dependency:read', 'property:read', 'element:read', 'element:item:get' ] - ApiPlatform\Metadata\Put: + ApiPlatform\Metadata\Patch: properties: id: identifier: true diff --git a/config/services.yaml b/config/services.yaml index 5f5f4180c..627c39367 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -26,7 +26,7 @@ services: Pimcore\Bundle\StudioApiBundle\State\VersionProvider: ~ # Processors - + Pimcore\Bundle\StudioApiBundle\State\Asset\Processor: ~ Pimcore\Bundle\StudioApiBundle\State\ResetPasswordProcessor: ~ Pimcore\Bundle\StudioApiBundle\State\Token\Create\Processor: ~ Pimcore\Bundle\StudioApiBundle\State\Token\Refresh\Processor: ~ diff --git a/src/Dto/Asset.php b/src/Dto/Asset.php index 3f69a8fac..aa85ed450 100644 --- a/src/Dto/Asset.php +++ b/src/Dto/Asset.php @@ -25,7 +25,7 @@ public function __construct( private readonly string $iconName, private readonly bool $hasChildren, private readonly string $type, - private readonly string $filename, + private string $filename, private readonly ?string $mimeType, private readonly array $metaData, private readonly bool $workflowWithPermissions, @@ -70,11 +70,16 @@ public function hasWorkflowWithPermissions(): bool return $this->workflowWithPermissions; } - public function getFilename(): ?string + public function getFilename(): string { return $this->filename; } + public function setFilename(string $filename): void + { + $this->filename = $filename; + } + public function getType(): string { return $this->type; diff --git a/src/Dto/Element.php b/src/Dto/Element.php index 3a5d30092..cd0ab53bc 100644 --- a/src/Dto/Element.php +++ b/src/Dto/Element.php @@ -23,7 +23,7 @@ class Element { public function __construct( private readonly int $id, - private readonly int $parentId, + private int $parentId, private readonly string $path, private readonly int $userOwner, private readonly int $userModification, @@ -45,6 +45,11 @@ public function getParentId(): int return $this->parentId; } + public function setParentId(int $parentId): void + { + $this->parentId = $parentId; + } + public function getPath(): string { return $this->path; diff --git a/src/Service/AssetService.php b/src/Service/AssetService.php index eb8e425a8..444f0ff63 100644 --- a/src/Service/AssetService.php +++ b/src/Service/AssetService.php @@ -16,25 +16,63 @@ namespace Pimcore\Bundle\StudioApiBundle\Service; +use Pimcore\Bundle\GenericDataIndexBundle\Service\SearchIndex\IndexQueue\SynchronousProcessingServiceInterface; use Pimcore\Bundle\StaticResolverBundle\Models\Asset\AssetResolverInterface; use Pimcore\Bundle\StudioApiBundle\Dto\Asset; -use Pimcore\Model\Asset as CoreAsset; +use Pimcore\Model\Element\DuplicateFullPathException; use Pimcore\Model\Exception\NotFoundException; +use Pimcore\Model\Asset as CoreAsset; final readonly class AssetService implements AssetServiceInterface { - public function __construct(private AssetResolverInterface $assetResolver) + public function __construct( + private AssetResolverInterface $assetResolver, + private SynchronousProcessingServiceInterface $synchronousProcessingService + ) { } - public function processAsset(int $id, Asset $data): CoreAsset + /** + * @throws DuplicateFullPathException + */ + public function processAsset(Asset $data): CoreAsset { - $asset = $this->assetResolver->getById($id); + $asset = $this->assetResolver->getById($data->getId()); if(!$asset) { throw new NotFoundException('Asset not found'); } + $differences = $this->compare($asset, $data); + foreach($differences as $field => $difference) { + $setter = 'set' . $field; + $asset->$setter($difference['new']); + } + $this->synchronousProcessingService->enable(); + $asset->save(); return $asset; } + + + private function compare(CoreAsset $current, Asset $data): array + { + $fieldsToCheck = $this->fieldsToCheck(get_class_methods($data)); + $differences = []; + foreach($fieldsToCheck as $field) { + if($current->$field() !== $data->$field()) { + $fieldName = str_replace('get', '', $field); + $differences[$fieldName] = [ + 'current' => $current->$field(), + 'new' => $data->$field() + ]; + } + } + return $differences; + } + + private function fieldsToCheck(array $methods): array + { + $setters = array_filter($methods, static fn ($method) => str_starts_with($method, 'set')); + return array_map(static fn ($setter) => str_replace('set', 'get', $setter), $setters); + } } \ No newline at end of file diff --git a/src/Service/AssetServiceInterface.php b/src/Service/AssetServiceInterface.php index 500ccf4a1..7c8311994 100644 --- a/src/Service/AssetServiceInterface.php +++ b/src/Service/AssetServiceInterface.php @@ -20,5 +20,5 @@ interface AssetServiceInterface { - public function processAsset(int $id, Asset $data): CoreAsset; + public function processAsset(Asset $data): CoreAsset; } \ No newline at end of file diff --git a/src/Service/CoreData/V1/Hydrator/AssetHydratorService.php b/src/Service/CoreData/V1/Hydrator/AssetHydratorService.php index 40901d62b..144c16eaa 100644 --- a/src/Service/CoreData/V1/Hydrator/AssetHydratorService.php +++ b/src/Service/CoreData/V1/Hydrator/AssetHydratorService.php @@ -6,7 +6,7 @@ use Pimcore\Model\Asset as CoreAsset; use Symfony\Contracts\Service\ServiceProviderInterface; -final readonly class AssetHydratorService implements AssetHydratorInterface +final readonly class AssetHydratorService implements AssetHydratorServiceInterface { public function __construct( private ServiceProviderInterface $assetHydratorLocator, diff --git a/src/Service/CoreData/V1/Hydrator/AssetHydratorInterface.php b/src/Service/CoreData/V1/Hydrator/AssetHydratorServiceInterface.php similarity index 94% rename from src/Service/CoreData/V1/Hydrator/AssetHydratorInterface.php rename to src/Service/CoreData/V1/Hydrator/AssetHydratorServiceInterface.php index 45d05bdc2..2e64e6ed0 100644 --- a/src/Service/CoreData/V1/Hydrator/AssetHydratorInterface.php +++ b/src/Service/CoreData/V1/Hydrator/AssetHydratorServiceInterface.php @@ -19,7 +19,7 @@ use Pimcore\Bundle\StudioApiBundle\Dto\Asset; use Pimcore\Model\Asset as CoreAsset; -interface AssetHydratorInterface +interface AssetHydratorServiceInterface { /** * @param CoreAsset $item diff --git a/src/State/Asset/Processor.php b/src/State/Asset/Processor.php index 4ec91bda7..2ba9bbed2 100644 --- a/src/State/Asset/Processor.php +++ b/src/State/Asset/Processor.php @@ -4,23 +4,34 @@ use ApiPlatform\Exception\OperationNotFoundException; use ApiPlatform\Metadata\Operation; -use ApiPlatform\Metadata\Put; +use ApiPlatform\Metadata\Patch; use ApiPlatform\State\ProcessorInterface; use Pimcore\Bundle\StudioApiBundle\Dto\Asset; +use Pimcore\Bundle\StudioApiBundle\Service\AssetSearchServiceInterface; +use Pimcore\Bundle\StudioApiBundle\Service\AssetServiceInterface; +use Pimcore\Bundle\StudioApiBundle\Service\CoreData\V1\Hydrator\AssetHydratorServiceInterface; final readonly class Processor implements ProcessorInterface { + public function __construct( + private AssetServiceInterface $assetService, + private AssetHydratorServiceInterface $assetHydratorService + ) + { + } + public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): Asset { if ( - !$operation instanceof Put || + !$operation instanceof Patch || !$data instanceof Asset ) { // wrong operation throw new OperationNotFoundException(); } + $asset = $this->assetService->processAsset($data); - + return $this->assetHydratorService->hydrate($asset); } } \ No newline at end of file