Skip to content

Commit

Permalink
ISSUE-16198: Category image remain after deleted.
Browse files Browse the repository at this point in the history
  • Loading branch information
p-bystritsky committed Jan 10, 2019
1 parent 523a83e commit 3b4581c
Show file tree
Hide file tree
Showing 6 changed files with 293 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\Catalog\Model\ResourceModel\Category;

use Magento\Catalog\Api\CategoryListInterface;
use Magento\Framework\Api\SearchCriteriaBuilder;

/**
* Check if Image is currently used in any category as Category Image.
*/
class RedundantCategoryImageChecker
{
/**
* @var SearchCriteriaBuilder
*/
private $searchCriteriaBuilder;

/**
* @var CategoryListInterface
*/
private $categoryList;

public function __construct(
CategoryListInterface $categoryList,
SearchCriteriaBuilder $searchCriteriaBuilder
) {
$this->categoryList = $categoryList;
$this->searchCriteriaBuilder = $searchCriteriaBuilder;
}

/**
* Checks if Image is currently used in any category as Category Image.
*
* Returns true if not.
*
* @param string $imageName
* @return bool
*/
public function execute(string $imageName): bool
{
/** @var SearchCriteriaBuilder $searchCriteriaBuilder */
$searchCriteria = $this->searchCriteriaBuilder->addFilter('image', $imageName)->create();
$categories = $this->categoryList->getList($searchCriteria)->getItems();

return empty($categories);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\Catalog\Plugin\Model\ResourceModel\Category;

use Magento\Catalog\Model\ResourceModel\Category as CategoryResource;
use Magento\Catalog\Model\ImageUploader;
use Magento\Catalog\Model\ResourceModel\Category\RedundantCategoryImageChecker;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Filesystem;
use Magento\Framework\Model\AbstractModel;

/**
* Remove old Category Image file from pub/media/catalog/category directory if such Image is not used anymore.
*/
class RemoveRedundantImagePlugin
{
/**
* @var Filesystem
*/
private $filesystem;

/**
* @var ImageUploader
*/
private $imageUploader;

/**
* @var RedundantCategoryImageChecker
*/
private $redundantCategoryImageChecker;

public function __construct(
Filesystem $filesystem,
ImageUploader $imageUploader,
RedundantCategoryImageChecker $redundantCategoryImageChecker
) {
$this->filesystem = $filesystem;
$this->imageUploader = $imageUploader;
$this->redundantCategoryImageChecker = $redundantCategoryImageChecker;
}

/**
* Removes Image file if it is not used anymore.
*
* @param CategoryResource $subject
* @param CategoryResource $result
* @param AbstractModel $category
* @return CategoryResource
*
* @throws \Magento\Framework\Exception\FileSystemException
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function afterSave(CategoryResource $subject, CategoryResource $result, AbstractModel $category): CategoryResource
{
$originalImage = $category->getOrigData('image');
if (
null !== $originalImage
&& $originalImage !== $category->getImage()
&& $this->redundantCategoryImageChecker->execute($originalImage)
) {
$basePath = $this->imageUploader->getBasePath();
$baseImagePath = $this->imageUploader->getFilePath($basePath, $originalImage);
/** @var \Magento\Framework\Filesystem\Directory\WriteInterface $mediaDirectory */
$mediaDirectory = $this->filesystem->getDirectoryWrite(DirectoryList::MEDIA);
$mediaDirectory->delete($baseImagePath);
}

return $result;
}
}
8 changes: 8 additions & 0 deletions app/code/Magento/Catalog/etc/di.xml
Original file line number Diff line number Diff line change
Expand Up @@ -907,6 +907,14 @@
<type name="Magento\Quote\Model\Quote\Item\ToOrderItem">
<plugin name="copy_quote_files_to_order" type="Magento\Catalog\Model\Plugin\QuoteItemProductOption"/>
</type>
<type name="Magento\Catalog\Model\ResourceModel\Category">
<plugin name="remove_redundant_image" type="Magento\Catalog\Plugin\Model\ResourceModel\Category\RemoveRedundantImagePlugin"/>
</type>
<type name="Magento\Catalog\Plugin\Model\ResourceModel\Category\RemoveRedundantImagePlugin">
<arguments>
<argument name="imageUploader" xsi:type="object">Magento\Catalog\CategoryImageUpload</argument>
</arguments>
</type>
<preference for="Magento\Catalog\Model\ResourceModel\Product\BaseSelectProcessorInterface" type="Magento\Catalog\Model\ResourceModel\Product\CompositeWithWebsiteProcessor" />
<type name="Magento\Catalog\Model\ResourceModel\Product\CompositeBaseSelectProcessor">
<arguments>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\Catalog\Model;

use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Filesystem;
use Magento\Framework\Filesystem\Directory\WriteInterface;
use Magento\Framework\ObjectManagerInterface;

/**
* Test removing old Category Image file from pub/media/catalog/category directory if such Image is not used anymore.
*/
class RemoveRedundantImageTest extends \PHPUnit\Framework\TestCase
{
/**
* @var ObjectManagerInterface
*/
private $objectManager;

/**
* @var Filesystem
*/
private $filesystem;

/**
* @var WriteInterface
*/
private $mediaDirectory;

/**
* @var CategoryRepository
*/
private $categoryRepository;

protected function setUp()
{
$this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
/** @var Filesystem $filesystem */
$this->filesystem = $this->objectManager->get(Filesystem::class);
$this->mediaDirectory = $this->filesystem->getDirectoryWrite(DirectoryList::MEDIA);
$this->categoryRepository = $this->objectManager->get(CategoryRepository::class);
}

/**
* Tests removing Image file if it is not used anymore.
*
* @magentoDataFixture Magento/Catalog/_files/categories_with_image.php
*
* @magentoAppIsolation enabled
* @magentoDbIsolation enabled
*/
public function testRemoveRedundantImage()
{
$imagesPath = 'catalog' . DIRECTORY_SEPARATOR . 'category';
$absoluteImagesPath = $this->mediaDirectory->getAbsolutePath($imagesPath);
$filePath1 = $absoluteImagesPath . DIRECTORY_SEPARATOR . 'test_image_1.jpg';
$filePath2 = $absoluteImagesPath . DIRECTORY_SEPARATOR . 'test_image_2.jpg';
$this->mediaDirectory->create($absoluteImagesPath);
$this->mediaDirectory->touch($filePath1);
$this->mediaDirectory->touch($filePath2);

$category1 = $this->categoryRepository->get(3);
$category1->setImage('test_image_3.jpg');
$this->categoryRepository->save($category1);
$category2 = $this->categoryRepository->get(5);
$category2->setImage('test_image_3.jpg');
$this->categoryRepository->save($category2);

$this->assertTrue($this->mediaDirectory->isExist($filePath1));
$this->assertFalse($this->mediaDirectory->isExist($filePath2));
}

protected function tearDown()
{
$this->mediaDirectory->delete();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();

/**
* After installation system has two categories: root one with ID:1 and Default category with ID:2
*/
/** @var $category \Magento\Catalog\Model\Category */
$category = $objectManager->create(\Magento\Catalog\Model\Category::class);
$category->isObjectNew(true);
$category->setId(3)
->setName('Category 1')
->setParentId(2)
->setPath('1/2/3')
->setLevel(2)
->setAvailableSortBy('name')
->setDefaultSortBy('name')
->setIsActive(true)
->setPosition(1)
->setImage('test_image_1.jpg')
->save();

$category = $objectManager->create(\Magento\Catalog\Model\Category::class);
$category->isObjectNew(true);
$category->setId(4)
->setName('Category 1.1')
->setParentId(3)
->setPath('1/2/3/4')
->setLevel(3)
->setAvailableSortBy('name')
->setDefaultSortBy('name')
->setIsActive(true)
->setIsAnchor(true)
->setPosition(1)
->setImage('test_image_1.jpg')
->save();

$category = $objectManager->create(\Magento\Catalog\Model\Category::class);
$category->isObjectNew(true);
$category->setId(5)
->setName('Category 2')
->setParentId(2)
->setPath('1/2/5')
->setLevel(2)
->setAvailableSortBy('name')
->setDefaultSortBy('name')
->setIsActive(true)
->setPosition(2)
->setImage('test_image_2.jpg')
->save();
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
/** @var \Magento\Framework\Registry $registry */
$registry = $objectManager->get(\Magento\Framework\Registry::class);

$registry->unregister('isSecureArea');
$registry->register('isSecureArea', true);

//Remove categories
/** @var Magento\Catalog\Model\ResourceModel\Category\Collection $collection */
$collection = $objectManager->create(\Magento\Catalog\Model\ResourceModel\Category\Collection::class);
$collection
->addAttributeToFilter('level', 2)
->load()
->delete();

$registry->unregister('isSecureArea');
$registry->register('isSecureArea', false);

0 comments on commit 3b4581c

Please sign in to comment.