Skip to content

12110: Missing cascade into attribute set deletion. #12167

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Dec 7, 2017
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

namespace Magento\CatalogUrlRewrite\Plugin\Eav\AttributeSetRepository;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move plugin to Catalog module

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


use Magento\Catalog\Model\ResourceModel\Product\Collection;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\CatalogUrlRewrite\Model\ProductUrlRewriteGenerator;
use Magento\Eav\Api\AttributeSetRepositoryInterface;
use Magento\Eav\Api\Data\AttributeSetInterface;
use Magento\UrlRewrite\Model\UrlPersistInterface;
use Magento\UrlRewrite\Service\V1\Data\UrlRewrite;

/**
* Remove url rewrites for products with given attribute set.
*/
class RemoveProductUrlRewrite
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename plugin to RemoveProducts

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

{
/**
* @var int
*/
private $chunkSize = 1000;

/**
* @var UrlPersistInterface
*/
private $urlPersist;

/**
* @var CollectionFactory
*/
private $collectionFactory;

/**
* ProductUrlRewriteProcessor constructor.
*
* @param UrlPersistInterface $urlPersist
* @param CollectionFactory $collectionFactory
*/
public function __construct(UrlPersistInterface $urlPersist, CollectionFactory $collectionFactory)
{
$this->urlPersist = $urlPersist;
$this->collectionFactory = $collectionFactory;
}

/**
* Remove url rewrites for products with given attribute set.
*
* @param AttributeSetRepositoryInterface $subject
* @param \Closure $proceed
* @param AttributeSetInterface $attributeSet
* @return bool
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function aroundDelete(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use after plugin instead of around

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, may be I have missed something. But, if I'll use after plugin I won't have attribute set id in results, only bool true and instance of AttributeSetRepository. And I need attribute set id in order to filter product collection.

AttributeSetRepositoryInterface $subject,
\Closure $proceed,
AttributeSetInterface $attributeSet
) {
/** @var Collection $productCollection */
$productCollection = $this->collectionFactory->create();
$productCollection->addFieldToFilter('attribute_set_id', ['eq' => $attributeSet->getId()]);
$productIds = $productCollection->getAllIds();
$result = $proceed($attributeSet);
if (!empty($productIds)) {
$productIds = array_chunk($productIds, $this->chunkSize);
foreach ($productIds as $ids) {
$this->urlPersist->deleteByData(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove products from db

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

[
UrlRewrite::ENTITY_ID => $ids,
UrlRewrite::ENTITY_TYPE => ProductUrlRewriteGenerator::ENTITY_TYPE,
]
);
}
}

return $result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

namespace Magento\CatalogUrlRewrite\Test\Unit\Plugin\Eav\AttributeSetRepository;

use Magento\Catalog\Model\ResourceModel\Product\Collection;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\CatalogUrlRewrite\Model\ProductUrlRewriteGenerator;
use Magento\CatalogUrlRewrite\Plugin\Eav\AttributeSetRepository\RemoveProductUrlRewrite;
use Magento\Eav\Api\AttributeSetRepositoryInterface;
use Magento\Eav\Api\Data\AttributeSetInterface;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
use Magento\UrlRewrite\Model\UrlPersistInterface;
use Magento\UrlRewrite\Service\V1\Data\UrlRewrite;
use PHPUnit\Framework\TestCase;

/**
* Provide tests for RemoveProductUrlRewrite plugin.
*/
class RemoveProductUrlRewriteTest extends TestCase
{
/**
* @var RemoveProductUrlRewrite
*/
private $testSubject;

/**
* @var CollectionFactory|\PHPUnit_Framework_MockObject_MockObject
*/
private $collectionFactory;

/**
* @var UrlPersistInterface|\PHPUnit_Framework_MockObject_MockObject
*/
private $urlPersist;

/**
* @inheritdoc
*/
protected function setUp()
{
$objectManager = new ObjectManager($this);
$this->collectionFactory = $this->getMockBuilder(CollectionFactory::class)
->disableOriginalConstructor()
->setMethods(['create'])
->getMock();
$this->urlPersist = $this->getMockBuilder(UrlPersistInterface::class)
->disableOriginalConstructor()
->getMockForAbstractClass();
$this->testSubject = $objectManager->getObject(
RemoveProductUrlRewrite::class,
[
'collectionFactory' => $this->collectionFactory,
'urlPersist' => $this->urlPersist,
]
);
}

/**
* Test plugin will delete all url rewrites for products with given attribute set.
*/
public function testAroundDelete()
{
$attributeSetId = '1';
$productId = '1';

/** @var Collection|\PHPUnit_Framework_MockObject_MockObject $collection */
$collection = $this->getMockBuilder(Collection::class)
->disableOriginalConstructor()
->getMock();
$collection->expects(self::once())
->method('addFieldToFilter')
->with(self::identicalTo('attribute_set_id'), self::identicalTo(['eq' => $attributeSetId]));
$collection->expects(self::once())
->method('getAllIds')
->willReturn([$productId]);

$this->collectionFactory->expects(self::once())
->method('create')
->willReturn($collection);

$this->urlPersist->expects(self::once())
->method('deleteByData')
->with(self::identicalTo(
[
UrlRewrite::ENTITY_ID => [$productId],
UrlRewrite::ENTITY_TYPE => ProductUrlRewriteGenerator::ENTITY_TYPE,
]
));
/** @var AttributeSetRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject $attributeSetRepository */
$attributeSetRepository = $this->getMockBuilder(AttributeSetRepositoryInterface::class)
->disableOriginalConstructor()
->getMockForAbstractClass();

$proceed = function () {
return true;
};

/** @var AttributeSetInterface|\PHPUnit_Framework_MockObject_MockObject $attributeSet */
$attributeSet = $this->getMockBuilder(AttributeSetInterface::class)
->setMethods(['getId'])
->disableOriginalConstructor()
->getMockForAbstractClass();
$attributeSet->expects(self::once())
->method('getId')
->willReturn($attributeSetId);

$this->testSubject->aroundDelete($attributeSetRepository, $proceed, $attributeSet);
}
}
3 changes: 3 additions & 0 deletions app/code/Magento/CatalogUrlRewrite/etc/adminhtml/di.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
<type name="Magento\Catalog\Model\Category\DataProvider">
<plugin name="category_ui_form_url_key_plugin" type="Magento\CatalogUrlRewrite\Plugin\Catalog\Block\Adminhtml\Category\Tab\Attributes"/>
</type>
<type name="Magento\Eav\Api\AttributeSetRepositoryInterface">
<plugin name="attribute_set_delete_plugin" type="Magento\CatalogUrlRewrite\Plugin\Eav\AttributeSetRepository\RemoveProductUrlRewrite"/>
</type>
<virtualType name="Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Pool">
<arguments>
<argument name="modifiers" xsi:type="array">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

namespace Magento\CatalogUrlRewrite\Plugin\Eav\AttributeSetRepository;

use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Eav\Api\AttributeSetRepositoryInterface;
use Magento\Eav\Model\Entity\Attribute\Set;
use Magento\TestFramework\Helper\Bootstrap;
use Magento\TestFramework\Interception\PluginList;
use Magento\UrlRewrite\Model\ResourceModel\UrlRewriteCollectionFactory;
use PHPUnit\Framework\TestCase;

/**
* Provide tests for RemoveProductUrlRewrite plugin.
* @magentoAppArea adminhtml
*/
class RemoveProductUrlRewriteTest extends TestCase
{
/**
* @return void
*/
public function testRemoveProductUrlRewriteIsRegistered()
{
$pluginInfo = Bootstrap::getObjectManager()->get(PluginList::class)
->get(AttributeSetRepositoryInterface::class, []);
self::assertSame(RemoveProductUrlRewrite::class, $pluginInfo['attribute_set_delete_plugin']['instance']);
}

/**
* Test url rewrite will be removed for product with given attribute set, if one will be deleted.
*
* @magentoDataFixture Magento/CatalogUrlRewrite/_files/attribute_set_with_product.php
* @magentoDbIsolation enabled
*/
public function testAroundDelete()
{
$attributeSet = Bootstrap::getObjectManager()->get(Set::class);
$attributeSet->load('empty_attribute_set', 'attribute_set_name');

$productRepository = Bootstrap::getObjectManager()->get(ProductRepositoryInterface::class);
$product = $productRepository->get('simple');

$urlRewriteCollection = Bootstrap::getObjectManager()->get(UrlRewriteCollectionFactory::class)->create();
$urlRewriteCollection->addFieldToFilter('entity_type', 'product');
$urlRewriteCollection->addFieldToFilter('entity_id', $product->getId());

self::assertSame(1, $urlRewriteCollection->getSize());

$attributeSetRepository = Bootstrap::getObjectManager()->get(AttributeSetRepositoryInterface::class);
$attributeSetRepository->deleteById($attributeSet->getAttributeSetId());

$urlRewriteCollection = Bootstrap::getObjectManager()->get(UrlRewriteCollectionFactory::class)->create();
$urlRewriteCollection->addFieldToFilter('entity_type', 'product');
$urlRewriteCollection->addFieldToFilter('entity_id', $product->getId());

self::assertSame(0, $urlRewriteCollection->getSize());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

require __DIR__ . '/../../Eav/_files/empty_attribute_set.php';
require __DIR__ . '/../../Catalog/_files/product_simple.php';

$product->setAttributeSetId($attributeSet->getId());
$product->save();
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

require __DIR__ . '/../../Catalog/_files/product_simple_rollback.php';
require __DIR__ . '/../../Eav/_files/empty_attribute_set_rollback.php';