From 900f021563e9f5e0b5113b65e77efd2919eb009d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Mu=CC=88ller?= Date: Thu, 4 Jan 2024 14:42:38 +0100 Subject: [PATCH 1/2] FEATURE: Extensible followup after asset replacement Allows implementing custom handlers to be called after an asset resource was replaced. This allows decoupling redirects for the replaced asset from the media package. Fixes: #4815 --- .../Model/AdjustmentCapableInterface.php | 17 +++ .../Model/Dto/AssetResourceReplaced.php | 18 +++ .../Classes/Domain/Model/ImageVariant.php | 2 +- .../Domain/Model/PresetVariantInterface.php | 32 +++++ ...etResourceReplacementFollowUpInterface.php | 12 ++ .../Classes/Domain/Service/AssetService.php | 120 ++++++++++-------- .../Domain/Service/AssetVariantGenerator.php | 2 +- 7 files changed, 150 insertions(+), 53 deletions(-) create mode 100644 Neos.Media/Classes/Domain/Model/AdjustmentCapableInterface.php create mode 100644 Neos.Media/Classes/Domain/Model/Dto/AssetResourceReplaced.php create mode 100644 Neos.Media/Classes/Domain/Model/PresetVariantInterface.php create mode 100644 Neos.Media/Classes/Domain/Service/AssetResourceReplacementFollowUpInterface.php diff --git a/Neos.Media/Classes/Domain/Model/AdjustmentCapableInterface.php b/Neos.Media/Classes/Domain/Model/AdjustmentCapableInterface.php new file mode 100644 index 00000000000..e19af242111 --- /dev/null +++ b/Neos.Media/Classes/Domain/Model/AdjustmentCapableInterface.php @@ -0,0 +1,17 @@ +getResource()->setMediaType($resourceMediaType); } - $uriMapping = []; - $redirectHandlerEnabled = isset($options['generateRedirects']) && (boolean)$options['generateRedirects'] === true && $this->packageManager->isPackageAvailable('Neos.RedirectHandler'); - if ($redirectHandlerEnabled) { - $originalAssetResourceUri = new Uri($this->resourceManager->getPublicPersistentResourceUri($originalAssetResource)); - $newAssetResourceUri = new Uri($this->resourceManager->getPublicPersistentResourceUri($asset->getResource())); - $uriMapping[$originalAssetResourceUri->getPath()] = $newAssetResourceUri->getPath(); - } + $replacedResources = []; + + $replacedResources[] = new AssetResourceReplaced($asset, $originalAssetResource, $resource); - if (method_exists($asset, 'getVariants')) { + if ($asset instanceof VariantSupportInterface) { $variants = $asset->getVariants(); /** @var AssetVariantInterface $variant */ foreach ($variants as $variant) { + $newVariant = null; $originalVariantResource = $variant->getResource(); - $presetIdentifier = $variant->getPresetIdentifier(); - $variantName = $variant->getPresetVariantName(); - if (isset($presetIdentifier, $variantName)) { - try { - $variant = $this->assetVariantGenerator->recreateVariant($asset, $presetIdentifier, $variantName); - if ($variant === null) { - $this->logger->debug( - sprintf('No variant returned when recreating asset variant %s::%s for %s', $presetIdentifier, $variantName, $asset->getTitle()), - LogEnvironment::fromMethodName(__METHOD__) - ); - continue; - } - } catch (AssetVariantGeneratorException $exception) { - $this->logger->error( - sprintf('Error when recreating asset variant: %s', $exception->getMessage()), - LogEnvironment::fromMethodName(__METHOD__) - ); - continue; - } - } else { - $variant->refresh(); - foreach ($variant->getAdjustments() as $adjustment) { - if (method_exists($adjustment, 'refit') && $this->imageService->getImageSize($originalAssetResource) !== $this->imageService->getImageSize($resource)) { - if ($asset instanceof ImageInterface && $asset->getWidth() !== null && $asset->getHeight() !== null) { - $adjustment->refit($asset); - } - } - } - $this->getRepository($variant)->update($variant); + if ($variant instanceof PresetVariantInterface && !empty($variant->getPresetIdentifier()) && !empty($variant->getPresetVariantName())) { + $newVariant = $this->refreshPresetVariant($asset, $variant); } - if ($redirectHandlerEnabled) { - $originalVariantResourceUri = new Uri($this->resourceManager->getPublicPersistentResourceUri($originalVariantResource)); - $newVariantResourceUri = new Uri($this->resourceManager->getPublicPersistentResourceUri($variant->getResource())); - $uriMapping[$originalVariantResourceUri->getPath()] = $newVariantResourceUri->getPath(); + if ( + ($newVariant === null && $variant instanceof AdjustmentCapableInterface) + && $this->imageService->getImageSize($originalAssetResource) !== $this->imageService->getImageSize($resource) + ) { + $newVariant = $this->refitAdjustmentsForVariant($asset, $variant); } + + $replacedResources[] = new AssetResourceReplaced($newVariant, $originalVariantResource, $newVariant->getResource()); } } - if ($redirectHandlerEnabled) { - /** @var RedirectStorageInterface $redirectStorage */ - $redirectStorage = $this->objectManager->get(RedirectStorageInterface::class); - foreach ($uriMapping as $originalUri => $newUri) { - $existingRedirect = $redirectStorage->getOneBySourceUriPathAndHost($originalUri); - if ($existingRedirect === null && $originalUri !== $newUri) { - $redirectStorage->addRedirect($originalUri, $newUri, 301); + try { + $assetResourceReplacementFollowUp = $this->objectManager->get(AssetResourceReplacementFollowUpInterface::class); + if ($assetResourceReplacementFollowUp !== null) { + foreach ($replacedResources as $assetResourceReplaced) { + $assetResourceReplacementFollowUp->handle($assetResourceReplaced); } } - } + } catch (UnknownObjectException $exception) {} $this->getRepository($asset)->update($asset); $this->emitAssetResourceReplaced($asset); } + protected function refreshPresetVariant(AssetInterface $asset, PresetVariantInterface $variant): ?AssetVariantInterface + { + $presetIdentifier = $variant->getPresetIdentifier(); + $variantName = $variant->getPresetVariantName(); + + try { + $variant = $this->assetVariantGenerator->recreateVariant($asset, $presetIdentifier, $variantName); + } catch (AssetVariantGeneratorException $exception) { + $this->logger->error( + sprintf('Error when recreating asset variant: %s', $exception->getMessage()), + LogEnvironment::fromMethodName(__METHOD__) + ); + return null; + } + + if ($variant === null) { + $this->logger->debug( + sprintf('No variant returned when recreating asset variant %s::%s for %s', $presetIdentifier, $variantName, $asset->getTitle()), + LogEnvironment::fromMethodName(__METHOD__) + ); + + return null; + } + + return $variant; + } + + protected function refitAdjustmentsForVariant(AssetInterface $asset, AssetInterface $variant): AssetInterface + { + $variant->refresh(); + if (!($asset instanceof ImageInterface) || !($variant instanceof AdjustmentCapableInterface) || $asset->getWidth() < 1 || $asset->getHeight() < 1) { + $this->getRepository($variant)->update($variant); + return $variant; + } + + foreach ($variant->getAdjustments() as $adjustment) { + if (method_exists($adjustment, 'refit')) { + $adjustment->refit($asset); + } + } + $this->getRepository($variant)->update($variant); + return $variant; + } + /** * Signals that an asset was added. * diff --git a/Neos.Media/Classes/Domain/Service/AssetVariantGenerator.php b/Neos.Media/Classes/Domain/Service/AssetVariantGenerator.php index e5700aa101a..f6d21005f14 100644 --- a/Neos.Media/Classes/Domain/Service/AssetVariantGenerator.php +++ b/Neos.Media/Classes/Domain/Service/AssetVariantGenerator.php @@ -147,7 +147,7 @@ public function createVariant(AssetInterface $asset, string $presetIdentifier, s * @param AssetInterface $asset * @param string $presetIdentifier * @param string $variantIdentifier - * @return AssetVariantInterface The created variant (if any) + * @return AssetVariantInterface|null The created variant (if any) * @throws AssetVariantGeneratorException */ public function recreateVariant(AssetInterface $asset, string $presetIdentifier, string $variantIdentifier): ?AssetVariantInterface From 9007bdd31a996a89ca75297943bac5d8a8f8cdce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20M=C3=BCller?= Date: Mon, 15 Jan 2024 10:17:53 +0100 Subject: [PATCH 2/2] Syntax improvements Co-authored-by: Marc Henry Schultz <85400359+mhsdesign@users.noreply.github.com> --- .../Classes/Domain/Model/AdjustmentCapableInterface.php | 3 ++- Neos.Media/Classes/Domain/Model/Dto/AssetResourceReplaced.php | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Neos.Media/Classes/Domain/Model/AdjustmentCapableInterface.php b/Neos.Media/Classes/Domain/Model/AdjustmentCapableInterface.php index e19af242111..5eeaf709759 100644 --- a/Neos.Media/Classes/Domain/Model/AdjustmentCapableInterface.php +++ b/Neos.Media/Classes/Domain/Model/AdjustmentCapableInterface.php @@ -5,7 +5,8 @@ interface AdjustmentCapableInterface { - public function getAdjustments(): \IteratorAggregate; + /** @return iterable */ + public function getAdjustments(): iterable; public function addAdjustment(ImageAdjustmentInterface $adjustment): void; diff --git a/Neos.Media/Classes/Domain/Model/Dto/AssetResourceReplaced.php b/Neos.Media/Classes/Domain/Model/Dto/AssetResourceReplaced.php index 092a2e846c6..ba529258cd4 100644 --- a/Neos.Media/Classes/Domain/Model/Dto/AssetResourceReplaced.php +++ b/Neos.Media/Classes/Domain/Model/Dto/AssetResourceReplaced.php @@ -13,6 +13,6 @@ public function __construct( public AssetInterface $asset, public PersistentResource $previousResource, public PersistentResource $newResource - ) - {} + ) { + } }