diff --git a/eZ/Bundle/EzPublishCoreBundle/DependencyInjection/Configuration.php b/eZ/Bundle/EzPublishCoreBundle/DependencyInjection/Configuration.php index 3008830ec0a..94761cb83a9 100644 --- a/eZ/Bundle/EzPublishCoreBundle/DependencyInjection/Configuration.php +++ b/eZ/Bundle/EzPublishCoreBundle/DependencyInjection/Configuration.php @@ -618,6 +618,9 @@ private function addImagePlaceholderSection(ArrayNodeDefinition $rootNode) ->variableNode('options') ->defaultValue([]) ->end() + ->booleanNode('verify_binary_data_availability') + ->defaultFalse() + ->end() ->end() ->end() ->end() diff --git a/eZ/Bundle/EzPublishCoreBundle/Imagine/PlaceholderAliasGenerator.php b/eZ/Bundle/EzPublishCoreBundle/Imagine/PlaceholderAliasGenerator.php index ae9e728d26d..aa982dedd63 100644 --- a/eZ/Bundle/EzPublishCoreBundle/Imagine/PlaceholderAliasGenerator.php +++ b/eZ/Bundle/EzPublishCoreBundle/Imagine/PlaceholderAliasGenerator.php @@ -8,6 +8,8 @@ use eZ\Publish\API\Repository\Values\Content\Field; use eZ\Publish\API\Repository\Values\Content\VersionInfo; +use eZ\Publish\API\Repository\Exceptions\NotFoundException; +use eZ\Publish\API\Repository\Exceptions\InvalidArgumentException as APIInvalidArgumentException; use eZ\Publish\Core\FieldType\Image\Value as ImageValue; use eZ\Publish\Core\FieldType\Value; use eZ\Publish\Core\IO\IOServiceInterface; @@ -33,18 +35,14 @@ class PlaceholderAliasGenerator implements VariationHandler /** @var array */ private $placeholderOptions = []; - /** - * PlaceholderAliasGenerator constructor. - * - * @param \eZ\Publish\SPI\Variation\VariationHandler $aliasGenerator - * @param \Liip\ImagineBundle\Imagine\Cache\Resolver\ResolverInterface $ioResolver - * @param \eZ\Publish\Core\IO\IOServiceInterface $ioService - */ + /** @var bool */ + private $verifyBinaryDataAvailability = false; + public function __construct( VariationHandler $aliasGenerator, ResolverInterface $ioResolver, - IOServiceInterface $ioService) - { + IOServiceInterface $ioService + ) { $this->aliasGenerator = $aliasGenerator; $this->ioResolver = $ioResolver; $this->ioService = $ioService; @@ -62,10 +60,7 @@ public function getVariation(Field $field, VersionInfo $versionInfo, $variationN throw new InvalidArgumentException("Value for field #{$field->id} ($field->fieldDefIdentifier) cannot be used for image placeholder generation."); } - try { - $this->ioResolver->resolve($imageValue->id, IORepositoryResolver::VARIATION_ORIGINAL); - } catch (NotResolvableException $e) { - // Generate placeholder for original image + if (!$this->isOriginalImageAvailable($imageValue)) { $binary = $this->ioService->newBinaryCreateStructFromLocalFile( $this->placeholderProvider->getPlaceholder($imageValue, $this->placeholderOptions) ); @@ -84,8 +79,40 @@ public function setPlaceholderProvider(PlaceholderProvider $provider, array $opt $this->placeholderOptions = $options; } + /** + * Enable/disable binary data availability verification. + * + * If enabled then binary data storage will be used to check if original file exists. Required for DFS setup. + * + * @param bool $verifyBinaryDataAvailability + */ + public function setVerifyBinaryDataAvailability(bool $verifyBinaryDataAvailability): void + { + $this->verifyBinaryDataAvailability = $verifyBinaryDataAvailability; + } + public function supportsValue(Value $value): bool { return $value instanceof ImageValue; } + + private function isOriginalImageAvailable(ImageValue $imageValue): bool + { + try { + $this->ioResolver->resolve($imageValue->id, IORepositoryResolver::VARIATION_ORIGINAL); + } catch (NotResolvableException $e) { + return false; + } + + if ($this->verifyBinaryDataAvailability) { + try { + // Try to open input stream to original file + $this->ioService->getFileInputStream($this->ioService->loadBinaryFile($imageValue->id)); + } catch (NotFoundException | APIInvalidArgumentException $e) { + return false; + } + } + + return true; + } } diff --git a/eZ/Bundle/EzPublishCoreBundle/Imagine/PlaceholderAliasGeneratorConfigurator.php b/eZ/Bundle/EzPublishCoreBundle/Imagine/PlaceholderAliasGeneratorConfigurator.php index 04c18c9ca58..d3553291c1d 100644 --- a/eZ/Bundle/EzPublishCoreBundle/Imagine/PlaceholderAliasGeneratorConfigurator.php +++ b/eZ/Bundle/EzPublishCoreBundle/Imagine/PlaceholderAliasGeneratorConfigurator.php @@ -19,15 +19,11 @@ class PlaceholderAliasGeneratorConfigurator /** @var array */ private $providersConfig; - /** - * PlaceholderAliasGeneratorConfigurator constructor. - * - * @param \eZ\Publish\Core\MVC\ConfigResolverInterface $configResolver - * @param \eZ\Bundle\EzPublishCoreBundle\Imagine\PlaceholderProviderRegistry $providerRegistry - * @param array $providersConfig - */ - public function __construct(ConfigResolverInterface $configResolver, PlaceholderProviderRegistry $providerRegistry, array $providersConfig) - { + public function __construct( + ConfigResolverInterface $configResolver, + PlaceholderProviderRegistry $providerRegistry, + array $providersConfig + ) { $this->configResolver = $configResolver; $this->providerRegistry = $providerRegistry; $this->providersConfig = $providersConfig; @@ -38,10 +34,12 @@ public function configure(PlaceholderAliasGenerator $generator) $binaryHandlerName = $this->configResolver->getParameter('io.binarydata_handler'); if (isset($this->providersConfig[$binaryHandlerName])) { - $providersConfig = $this->providersConfig[$binaryHandlerName]; + $config = $this->providersConfig[$binaryHandlerName]; + + $provider = $this->providerRegistry->getProvider($config['provider']); - $provider = $this->providerRegistry->getProvider($providersConfig['provider']); - $generator->setPlaceholderProvider($provider, $providersConfig['options']); + $generator->setPlaceholderProvider($provider, $config['options']); + $generator->setVerifyBinaryDataAvailability($config['verify_binary_data_availability'] ?? false); } } } diff --git a/eZ/Bundle/EzPublishCoreBundle/Tests/DependencyInjection/EzPublishCoreExtensionTest.php b/eZ/Bundle/EzPublishCoreBundle/Tests/DependencyInjection/EzPublishCoreExtensionTest.php index 19d745859ed..678632ce893 100644 --- a/eZ/Bundle/EzPublishCoreBundle/Tests/DependencyInjection/EzPublishCoreExtensionTest.php +++ b/eZ/Bundle/EzPublishCoreBundle/Tests/DependencyInjection/EzPublishCoreExtensionTest.php @@ -232,6 +232,7 @@ public function testImagePlaceholderConfiguration() 'foo' => 'Foo', 'bar' => 'Bar', ], + 'verify_binary_data_availability' => true, ], 'fancy' => [ 'provider' => 'remote', @@ -246,10 +247,12 @@ public function testImagePlaceholderConfiguration() 'foo' => 'Foo', 'bar' => 'Bar', ], + 'verify_binary_data_availability' => true, ], 'fancy' => [ 'provider' => 'remote', 'options' => [], + 'verify_binary_data_availability' => false, ], ], $this->container->getParameter('image_alias.placeholder_providers')); } diff --git a/eZ/Bundle/EzPublishCoreBundle/Tests/Imagine/PlaceholderAliasGeneratorTest.php b/eZ/Bundle/EzPublishCoreBundle/Tests/Imagine/PlaceholderAliasGeneratorTest.php index d1cf1371c99..990d095c827 100644 --- a/eZ/Bundle/EzPublishCoreBundle/Tests/Imagine/PlaceholderAliasGeneratorTest.php +++ b/eZ/Bundle/EzPublishCoreBundle/Tests/Imagine/PlaceholderAliasGeneratorTest.php @@ -9,6 +9,7 @@ use eZ\Bundle\EzPublishCoreBundle\Imagine\IORepositoryResolver; use eZ\Bundle\EzPublishCoreBundle\Imagine\PlaceholderAliasGenerator; use eZ\Bundle\EzPublishCoreBundle\Imagine\PlaceholderProvider; +use eZ\Publish\API\Repository\Exceptions\NotFoundException; use eZ\Publish\API\Repository\Values\Content\Field; use eZ\Publish\API\Repository\Values\Content\VersionInfo as APIVersionInfo; use eZ\Publish\Core\FieldType\Image\Value as ImageValue; @@ -16,6 +17,7 @@ use eZ\Publish\Core\FieldType\Value as FieldTypeValue; use eZ\Publish\Core\FieldType\Value; use eZ\Publish\Core\IO\IOServiceInterface; +use eZ\Publish\Core\IO\Values\BinaryFile; use eZ\Publish\Core\IO\Values\BinaryFileCreateStruct; use eZ\Publish\Core\Repository\Values\Content\VersionInfo; use eZ\Publish\SPI\Variation\Values\ImageVariation; @@ -188,6 +190,74 @@ public function testGetVariationOriginalNotFound(Field $field, APIVersionInfo $v $this->assertEquals($expectedVariation, $actualVariation); } + /** + * @dataProvider getVariationProvider + */ + public function testGetVariationReturnsPlaceholderIfBinaryDataIsNotAvailable( + Field $field, + APIVersionInfo $versionInfo, + string $variationName, + array $parameters + ): void { + $this->aliasGenerator->setVerifyBinaryDataAvailability(true); + + $placeholderPath = '/tmp/placeholder.jpg'; + $binaryCreateStruct = new BinaryFileCreateStruct(); + $expectedVariation = $this->createMock(ImageVariation::class); + $binaryFile = $this->createMock(BinaryFile::class); + + $this->ioResolver + ->expects($this->once()) + ->method('resolve') + ->with($field->value->id, IORepositoryResolver::VARIATION_ORIGINAL) + ->willReturn('/path/to/original/image.png'); + + $this->ioService + ->method('loadBinaryFile') + ->with($field->value->id) + ->willReturn($binaryFile); + + $this->ioService + ->method('getFileInputStream') + ->with($binaryFile) + ->willThrowException($this->createMock(NotFoundException::class)); + + $this->placeholderProvider + ->expects($this->once()) + ->method('getPlaceholder') + ->with($field->value, $this->placeholderOptions) + ->willReturn($placeholderPath); + + $this->ioService + ->expects($this->once()) + ->method('newBinaryCreateStructFromLocalFile') + ->with($placeholderPath) + ->willReturn($binaryCreateStruct); + + $this->ioService + ->expects($this->once()) + ->method('createBinaryFile') + ->with($binaryCreateStruct); + + $this->aliasGenerator->setPlaceholderProvider( + $this->placeholderProvider, + $this->placeholderOptions + ); + + $this->innerAliasGenerator + ->expects($this->once()) + ->method('getVariation') + ->with($field, $versionInfo, $variationName, $parameters) + ->willReturn($expectedVariation); + + $actualVariation = $this->aliasGenerator->getVariation( + $field, $versionInfo, $variationName, $parameters + ); + + $this->assertEquals($field->value->id, $binaryCreateStruct->id); + $this->assertEquals($expectedVariation, $actualVariation); + } + /** * @dataProvider supportsValueProvider */