diff --git a/app/code/Magento/MediaStorage/Console/Command/ImagesResizeCommand.php b/app/code/Magento/MediaStorage/Console/Command/ImagesResizeCommand.php index 4ed84829c2ad0..16df14119cab3 100644 --- a/app/code/Magento/MediaStorage/Console/Command/ImagesResizeCommand.php +++ b/app/code/Magento/MediaStorage/Console/Command/ImagesResizeCommand.php @@ -18,7 +18,7 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Command\Command; -use Magento\Catalog\Model\ResourceModel\Product\Image as ProductImage; + /** * Resizes product images according to theme view definitions. @@ -30,6 +30,11 @@ class ImagesResizeCommand extends Command */ const ASYNC_RESIZE = 'async'; + /** + * Do not process images marked as hidden from product page + */ + const SKIP_HIDDEN_IMAGES = 'skip_hidden_images'; + /** * @var ImageResizeScheduler */ @@ -51,31 +56,28 @@ class ImagesResizeCommand extends Command private $progressBarFactory; /** - * @var ProductImage + * @var bool */ - private $productImage; + private $skipHiddenImages = false; /** * @param State $appState * @param ImageResize $imageResize * @param ImageResizeScheduler $imageResizeScheduler * @param ProgressBarFactory $progressBarFactory - * @param ProductImage $productImage * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function __construct( State $appState, ImageResize $imageResize, ImageResizeScheduler $imageResizeScheduler, - ProgressBarFactory $progressBarFactory, - ProductImage $productImage + ProgressBarFactory $progressBarFactory ) { parent::__construct(); $this->appState = $appState; $this->imageResize = $imageResize; $this->imageResizeScheduler = $imageResizeScheduler; $this->progressBarFactory = $progressBarFactory; - $this->productImage = $productImage; } /** @@ -102,6 +104,12 @@ private function getOptionsList() : array InputOption::VALUE_NONE, 'Resize image in asynchronous mode' ), + new InputOption( + self::SKIP_HIDDEN_IMAGES, + null, + InputOption::VALUE_NONE, + 'Do not process images marked as hidden from product page' + ), ]; } @@ -112,6 +120,7 @@ private function getOptionsList() : array */ protected function execute(InputInterface $input, OutputInterface $output) { + $this->skipHiddenImages = $input->getOption(self::SKIP_HIDDEN_IMAGES); $result = $input->getOption(self::ASYNC_RESIZE) ? $this->executeAsync($output) : $this->executeSync($output); @@ -129,7 +138,7 @@ private function executeSync(OutputInterface $output): int try { $errors = []; $this->appState->setAreaCode(Area::AREA_GLOBAL); - $generator = $this->imageResize->resizeFromThemes(); + $generator = $this->imageResize->resizeFromThemes(null, $this->skipHiddenImages); /** @var ProgressBar $progress */ $progress = $this->progressBarFactory->create( @@ -194,7 +203,7 @@ private function executeAsync(OutputInterface $output): int $progress = $this->progressBarFactory->create( [ 'output' => $output, - 'max' => $this->productImage->getCountUsedProductImages() + 'max' => $this->imageResize->getCountProductImages($this->skipHiddenImages) ] ); $progress->setFormat( @@ -205,7 +214,7 @@ private function executeAsync(OutputInterface $output): int $progress->setOverwrite(false); } - $productImages = $this->productImage->getUsedProductImages(); + $productImages = $this->imageResize->getProductImages($this->skipHiddenImages); foreach ($productImages as $image) { $result = $this->imageResizeScheduler->schedule($image['filepath']); diff --git a/app/code/Magento/MediaStorage/Service/ImageResize.php b/app/code/Magento/MediaStorage/Service/ImageResize.php index 9b0adcd161339..436d23eb7fb64 100644 --- a/app/code/Magento/MediaStorage/Service/ImageResize.php +++ b/app/code/Magento/MediaStorage/Service/ImageResize.php @@ -171,17 +171,18 @@ public function resizeFromImageName(string $originalImageName) * Create resized images of different sizes from themes. * * @param array|null $themes + * @param bool $skipHiddenImages * @return Generator * @throws NotFoundException */ - public function resizeFromThemes(array $themes = null): Generator + public function resizeFromThemes(array $themes = null, bool $skipHiddenImages = false): Generator { - $count = $this->productImage->getCountUsedProductImages(); + $count = $this->getCountProductImages($skipHiddenImages); if (!$count) { throw new NotFoundException(__('Cannot resize images - product images not found')); } - $productImages = $this->productImage->getUsedProductImages(); + $productImages = $this->getProductImages($skipHiddenImages); $viewImages = $this->getViewImages($themes ?? $this->getThemesInUse()); foreach ($productImages as $image) { @@ -210,6 +211,26 @@ public function resizeFromThemes(array $themes = null): Generator } } + /** + * @param bool $skipHiddenImages + * @return int + */ + public function getCountProductImages(bool $skipHiddenImages = false): int + { + return $skipHiddenImages ? + $this->productImage->getCountUsedProductImages() : $this->productImage->getCountAllProductImages(); + } + + /** + * @param bool $skipHiddenImages + * @return Generator + */ + public function getProductImages(bool $skipHiddenImages = false): \Generator + { + return $skipHiddenImages ? + $this->productImage->getUsedProductImages() : $this->productImage->getAllProductImages(); + } + /** * Search the current theme. * diff --git a/app/code/Magento/MediaStorage/Test/Unit/Service/ImageResizeTest.php b/app/code/Magento/MediaStorage/Test/Unit/Service/ImageResizeTest.php index 5df2269f8f80e..3ea3c9e88bc96 100644 --- a/app/code/Magento/MediaStorage/Test/Unit/Service/ImageResizeTest.php +++ b/app/code/Magento/MediaStorage/Test/Unit/Service/ImageResizeTest.php @@ -119,11 +119,22 @@ class ImageResizeTest extends TestCase * @var string */ private $testfilepath; + + /** + * @var string + */ + private $testImageHiddenFilename; + /** * @var MockObject|StoreManagerInterface */ private $storeManager; + /** + * @var string + */ + private $testImageHiddenfilepath; + /** * @inheritDoc * @SuppressWarnings(PHPMD.ExcessiveMethodLength) @@ -131,7 +142,10 @@ class ImageResizeTest extends TestCase protected function setUp(): void { $this->testfilename = "image.jpg"; + $this->testImageHiddenFilename = "image_hidden.jpg"; $this->testfilepath = "/image.jpg"; + $this->testImageHiddenfilepath = "/image_hidden.jpg"; + $this->appStateMock = $this->createMock(State::class); $this->imageConfigMock = $this->createMock(MediaConfig::class); @@ -160,7 +174,7 @@ protected function setUp(): void $this->assetImageMock->expects($this->any()) ->method('getPath') - ->willReturn($this->testfilepath); + ->willReturnOnConsecutiveCalls($this->testfilepath, $this->testImageHiddenfilepath); $this->assetImageFactoryMock->expects($this->any()) ->method('create') ->willReturn($this->assetImageMock); @@ -182,16 +196,15 @@ protected function setUp(): void $this->imageConfigMock->expects($this->any()) ->method('getMediaPath') - ->with($this->testfilename) - ->willReturn($this->testfilepath); + ->withConsecutive([$this->testfilename], [$this->testImageHiddenFilename]) + ->willReturnOnConsecutiveCalls($this->testfilepath, $this->testImageHiddenfilepath); $this->mediaDirectoryMock->expects($this->any()) ->method('getAbsolutePath') - ->with($this->testfilepath) - ->willReturn($this->testfilepath); + ->withConsecutive([$this->testfilepath], [$this->testImageHiddenfilepath]) + ->willReturnOnConsecutiveCalls($this->testfilepath, $this->testImageHiddenfilepath); $this->mediaDirectoryMock->expects($this->any()) ->method('getRelativePath') - ->with($this->testfilepath) - ->willReturn($this->testfilepath); + ->willReturnOnConsecutiveCalls($this->testfilepath, $this->testImageHiddenfilepath); $this->viewMock->expects($this->any()) ->method('getMediaEntities') @@ -248,7 +261,7 @@ public function testResizeFromThemesMediaStorageDatabase() ->willReturn(false); $imageMock = $this->createMock(Image::class); - $this->imageFactoryMock->expects($this->once()) + $this->imageFactoryMock->expects($this->any()) ->method('create') ->willReturn($imageMock); @@ -268,17 +281,17 @@ function () { $this->mediaDirectoryMock->expects($this->any()) ->method('isFile') - ->with($this->testfilepath) + ->withConsecutive([$this->testfilepath], [$this->testImageHiddenfilepath]) ->willReturn(true); - $this->databaseMock->expects($this->once()) + $this->databaseMock->expects($this->any()) ->method('saveFileToFilesystem') - ->with($this->testfilepath); - $this->databaseMock->expects($this->once()) + ->withConsecutive([$this->testfilepath], [$this->testImageHiddenfilepath]); + $this->databaseMock->expects($this->any()) ->method('saveFile') - ->with($this->testfilepath); + ->withConsecutive([$this->testfilepath], [$this->testImageHiddenfilepath]); - $generator = $this->service->resizeFromThemes(['test-theme']); + $generator = $this->service->resizeFromThemes(['test-theme'], true); while ($generator->valid()) { $resizeInfo = $generator->key(); $this->assertEquals('image.jpg', $resizeInfo['filename']); @@ -287,6 +300,73 @@ function () { } } + public function testResizeFromThemesHiddenImagesMediaStorageDatabase() + { + $this->databaseMock->expects($this->any()) + ->method('checkDbUsage') + ->willReturn(true); + $this->databaseMock->expects($this->any()) + ->method('fileExists') + ->willReturn(false); + + $imageMock = $this->createMock(Image::class); + $this->imageFactoryMock->expects($this->any()) + ->method('create') + ->willReturn($imageMock); + + $this->productImageMock->expects($this->any()) + ->method('getCountUsedProductImages') + ->willReturn(1); + $this->productImageMock->expects($this->any()) + ->method('getUsedProductImages') + ->willReturnCallback( + function () { + $data = [[ 'filepath' => $this->testfilename ]]; + foreach ($data as $e) { + yield $e; + } + } + ); + + $this->productImageMock->expects($this->any()) + ->method('getCountAllProductImages') + ->willReturn(2); + $this->productImageMock->expects($this->any()) + ->method('getAllProductImages') + ->willReturnCallback( + function () { + $data = [[ 'filepath' => $this->testfilename ], [ 'filepath' => $this->testImageHiddenFilename ]]; + foreach ($data as $e) { + yield $e; + } + } + ); + + $this->mediaDirectoryMock->expects($this->any()) + ->method('isFile') + ->withConsecutive([$this->testfilepath], [$this->testImageHiddenfilepath]) + ->willReturn(true); + + $this->databaseMock->expects($this->any()) + ->method('saveFileToFilesystem') + ->withConsecutive([$this->testfilepath], [$this->testImageHiddenfilepath]); + $this->databaseMock->expects($this->any()) + ->method('saveFile') + ->withConsecutive([$this->testfilepath], [$this->testImageHiddenfilepath]); + + $this->assertEquals(2, $this->service->getCountProductImages()); + $this->assertEquals(1, $this->service->getCountProductImages(true)); + + $generator = $this->service->resizeFromThemes(['test-theme']); + while ($generator->valid()) { + $resizeInfo = $generator->key(); + $this->assertContains($resizeInfo['filename'], [$this->testfilename, $this->testImageHiddenFilename]); + $this->assertEmpty($resizeInfo['error']); + $generator->next(); + } + + } + public function testResizeFromThemesUnsupportedImage() { $this->databaseMock->expects($this->any()) @@ -296,7 +376,7 @@ public function testResizeFromThemesUnsupportedImage() ->method('fileExists') ->willReturn(false); - $this->imageFactoryMock->expects($this->once()) + $this->imageFactoryMock->expects($this->any()) ->method('create') ->willThrowException(new \InvalidArgumentException('Unsupported image format.')); @@ -316,10 +396,10 @@ function () { $this->mediaDirectoryMock->expects($this->any()) ->method('isFile') - ->with($this->testfilepath) + ->withConsecutive([$this->testfilepath], [$this->testImageHiddenfilepath]) ->willReturn(true); - $generator = $this->service->resizeFromThemes(['test-theme']); + $generator = $this->service->resizeFromThemes(['test-theme'], true); while ($generator->valid()) { $resizeInfo = $generator->key(); $this->assertEquals('Unsupported image format.', $resizeInfo['error']);