Skip to content
Snippets Groups Projects
Commit c02ff99b authored by Stanislav Idolov's avatar Stanislav Idolov
Browse files

MAGETWO-84808: 12110: Missing cascade into attribute set deletion. #12167

 - Merge Pull Request magento/magento2#12167 from nmalevanec/magento2:12110
 - Merged commits:
   1. 817bc5fb
   2. 5cd27574
   3. 95f11ae2
   4. 14132ce0
   5. 88f218d3
   6. dd4dec86
   7. 3143bbb0
   8. 9df89df5
   9. c14e9e36
   10. c7fbbccc
parents 9eb883d8 c7fbbccc
Branches
No related merge requests found
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Catalog\Plugin\Model\AttributeSetRepository;
use Magento\Catalog\Model\ResourceModel\Product\Collection;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\Eav\Api\AttributeSetRepositoryInterface;
use Magento\Eav\Api\Data\AttributeSetInterface;
/**
* Delete related products after attribute set successfully removed.
*/
class RemoveProducts
{
/**
* Retrieve products related to specific attribute set.
*
* @var CollectionFactory
*/
private $collectionFactory;
/**
* RemoveProducts constructor.
*
* @param CollectionFactory $collectionFactory
*/
public function __construct(CollectionFactory $collectionFactory)
{
$this->collectionFactory = $collectionFactory;
}
/**
* Delete related to specific attribute set products, if attribute set was removed successfully.
*
* @param AttributeSetRepositoryInterface $subject
* @param bool $result
* @param AttributeSetInterface $attributeSet
* @return bool
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function afterDelete(
AttributeSetRepositoryInterface $subject,
bool $result,
AttributeSetInterface $attributeSet
) {
/** @var Collection $productCollection */
$productCollection = $this->collectionFactory->create();
$productCollection->addFieldToFilter('attribute_set_id', ['eq' => $attributeSet->getId()]);
$productCollection->delete();
return $result;
}
}
...@@ -21,6 +21,8 @@ class UpgradeSchema implements UpgradeSchemaInterface ...@@ -21,6 +21,8 @@ class UpgradeSchema implements UpgradeSchemaInterface
/** /**
* {@inheritdoc} * {@inheritdoc}
* @SuppressWarnings(PHPMD.ExcessiveMethodLength) * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.NPathComplexity)
*/ */
public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context) public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context)
{ {
...@@ -126,6 +128,10 @@ class UpgradeSchema implements UpgradeSchemaInterface ...@@ -126,6 +128,10 @@ class UpgradeSchema implements UpgradeSchemaInterface
$this->fixCustomerGroupIdColumn($setup); $this->fixCustomerGroupIdColumn($setup);
} }
if (version_compare($context->getVersion(), '2.2.4', '<')) {
$this->removeAttributeSetRelation($setup);
}
$setup->endSetup(); $setup->endSetup();
} }
...@@ -699,4 +705,20 @@ class UpgradeSchema implements UpgradeSchemaInterface ...@@ -699,4 +705,20 @@ class UpgradeSchema implements UpgradeSchemaInterface
); );
$setup->getConnection()->query($sql); $setup->getConnection()->query($sql);
} }
/**
* Remove foreign key between catalog_product_entity and eav_attribute_set tables.
* Drop foreign key to delegate cascade on delete to plugin.
* @see \Magento\Catalog\Plugin\Model\AttributeSetRepository\RemoveProducts
*
* @param SchemaSetupInterface $setup
* @return void
*/
private function removeAttributeSetRelation(SchemaSetupInterface $setup)
{
$setup->getConnection()->dropForeignKey(
$setup->getTable('catalog_product_entity'),
$setup->getFkName('catalog_product_entity', 'attribute_set_id', 'eav_attribute_set', 'attribute_set_id')
);
}
} }
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Catalog\Test\Unit\Plugin\Model\AttributeSetRepository;
use Magento\Catalog\Model\ResourceModel\Product\Collection;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\Catalog\Plugin\Model\AttributeSetRepository\RemoveProducts;
use Magento\Eav\Api\AttributeSetRepositoryInterface;
use Magento\Eav\Api\Data\AttributeSetInterface;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
use PHPUnit\Framework\TestCase;
/**
* Provide tests for RemoveProducts plugin.
*/
class RemoveProductsTest extends TestCase
{
/**
* @var RemoveProducts
*/
private $testSubject;
/**
* @var CollectionFactory|\PHPUnit_Framework_MockObject_MockObject
*/
private $collectionFactory;
/**
* @inheritdoc
*/
protected function setUp()
{
$objectManager = new ObjectManager($this);
$this->collectionFactory = $this->getMockBuilder(CollectionFactory::class)
->disableOriginalConstructor()
->setMethods(['create'])
->getMock();
$this->testSubject = $objectManager->getObject(
RemoveProducts::class,
[
'collectionFactory' => $this->collectionFactory,
]
);
}
/**
* Test plugin will delete all related products for given attribute set.
*/
public function testAfterDelete()
{
$attributeSetId = '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('delete');
$this->collectionFactory->expects(self::once())
->method('create')
->willReturn($collection);
/** @var AttributeSetRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject $attributeSetRepository */
$attributeSetRepository = $this->getMockBuilder(AttributeSetRepositoryInterface::class)
->disableOriginalConstructor()
->getMockForAbstractClass();
/** @var AttributeSetInterface|\PHPUnit_Framework_MockObject_MockObject $attributeSet */
$attributeSet = $this->getMockBuilder(AttributeSetInterface::class)
->setMethods(['getId'])
->disableOriginalConstructor()
->getMockForAbstractClass();
$attributeSet->expects(self::once())
->method('getId')
->willReturn($attributeSetId);
self::assertTrue($this->testSubject->afterDelete($attributeSetRepository, true, $attributeSet));
}
}
...@@ -184,4 +184,7 @@ ...@@ -184,4 +184,7 @@
<argument name="scopeOverriddenValue" xsi:type="object">Magento\Catalog\Model\Attribute\ScopeOverriddenValue</argument> <argument name="scopeOverriddenValue" xsi:type="object">Magento\Catalog\Model\Attribute\ScopeOverriddenValue</argument>
</arguments> </arguments>
</type> </type>
<type name="Magento\Eav\Api\AttributeSetRepositoryInterface">
<plugin name="remove_products" type="Magento\Catalog\Plugin\Model\AttributeSetRepository\RemoveProducts"/>
</type>
</config> </config>
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
*/ */
--> -->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Magento_Catalog" setup_version="2.2.3"> <module name="Magento_Catalog" setup_version="2.2.4">
<sequence> <sequence>
<module name="Magento_Eav"/> <module name="Magento_Eav"/>
<module name="Magento_Cms"/> <module name="Magento_Cms"/>
......
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Catalog\Plugin\Model\AttributeSetRepository;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
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 RemoveProducts plugin.
* @magentoAppArea adminhtml
*/
class RemoveProductsTest extends TestCase
{
/**
* @return void
*/
public function testRemoveProductsIsRegistered()
{
$pluginInfo = Bootstrap::getObjectManager()->get(PluginList::class)
->get(AttributeSetRepositoryInterface::class, []);
self::assertSame(RemoveProducts::class, $pluginInfo['remove_products']['instance']);
}
/**
* Test related to given attribute set products will be removed, if attribute set will be deleted.
*
* @magentoDataFixture Magento/Catalog/_files/attribute_set_with_product.php
*/
public function testAfterDelete()
{
$attributeSet = Bootstrap::getObjectManager()->get(Set::class);
$attributeSet->load('empty_attribute_set', 'attribute_set_name');
$productRepository = Bootstrap::getObjectManager()->get(ProductRepositoryInterface::class);
$product = $productRepository->get('simple');
$productCollection = Bootstrap::getObjectManager()->get(CollectionFactory::class)->create();
$productCollection->addIdFilter($product->getId());
$urlRewriteCollection = Bootstrap::getObjectManager()->get(UrlRewriteCollectionFactory::class)->create();
$urlRewriteCollection->addFieldToFilter('entity_type', 'product');
$urlRewriteCollection->addFieldToFilter('entity_id', $product->getId());
self::assertSame(1, $urlRewriteCollection->getSize());
self::assertSame(1, $productCollection->getSize());
$attributeSetRepository = Bootstrap::getObjectManager()->get(AttributeSetRepositoryInterface::class);
$attributeSetRepository->deleteById($attributeSet->getAttributeSetId());
$productCollection = Bootstrap::getObjectManager()->get(CollectionFactory::class)->create();
$productCollection->addIdFilter($product->getId());
$urlRewriteCollection = Bootstrap::getObjectManager()->get(UrlRewriteCollectionFactory::class)->create();
$urlRewriteCollection->addFieldToFilter('entity_type', 'product');
$urlRewriteCollection->addFieldToFilter('entity_id', $product->getId());
self::assertSame(0, $urlRewriteCollection->getSize());
self::assertSame(0, $productCollection->getSize());
}
}
<?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();
<?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';
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment