diff --git a/app/code/Magento/Catalog/Plugin/Model/AttributeSetRepository/RemoveProducts.php b/app/code/Magento/Catalog/Plugin/Model/AttributeSetRepository/RemoveProducts.php new file mode 100644 index 0000000000000..342b703ded0a5 --- /dev/null +++ b/app/code/Magento/Catalog/Plugin/Model/AttributeSetRepository/RemoveProducts.php @@ -0,0 +1,58 @@ +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; + } +} diff --git a/app/code/Magento/Catalog/Setup/UpgradeSchema.php b/app/code/Magento/Catalog/Setup/UpgradeSchema.php index 616bee43de00e..d08108d1fc22b 100755 --- a/app/code/Magento/Catalog/Setup/UpgradeSchema.php +++ b/app/code/Magento/Catalog/Setup/UpgradeSchema.php @@ -21,6 +21,8 @@ class UpgradeSchema implements UpgradeSchemaInterface /** * {@inheritdoc} * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) */ public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context) { @@ -126,6 +128,10 @@ public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $con $this->fixCustomerGroupIdColumn($setup); } + if (version_compare($context->getVersion(), '2.2.4', '<')) { + $this->removeAttributeSetRelation($setup); + } + $setup->endSetup(); } @@ -699,4 +705,20 @@ private function addReplicaTable(SchemaSetupInterface $setup, $existingTable, $r ); $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') + ); + } } diff --git a/app/code/Magento/Catalog/Test/Unit/Plugin/Model/AttributeSetRepository/RemoveProductsTest.php b/app/code/Magento/Catalog/Test/Unit/Plugin/Model/AttributeSetRepository/RemoveProductsTest.php new file mode 100644 index 0000000000000..712aeba59dffe --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Plugin/Model/AttributeSetRepository/RemoveProductsTest.php @@ -0,0 +1,87 @@ +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)); + } +} diff --git a/app/code/Magento/Catalog/etc/adminhtml/di.xml b/app/code/Magento/Catalog/etc/adminhtml/di.xml index b97e6fc1aa318..34d089580906f 100644 --- a/app/code/Magento/Catalog/etc/adminhtml/di.xml +++ b/app/code/Magento/Catalog/etc/adminhtml/di.xml @@ -184,4 +184,7 @@ Magento\Catalog\Model\Attribute\ScopeOverriddenValue + + + diff --git a/app/code/Magento/Catalog/etc/module.xml b/app/code/Magento/Catalog/etc/module.xml index 18671a32bb4fb..26ed173420adb 100644 --- a/app/code/Magento/Catalog/etc/module.xml +++ b/app/code/Magento/Catalog/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Plugin/Model/AttributeSetRepository/RemoveProductsTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Plugin/Model/AttributeSetRepository/RemoveProductsTest.php new file mode 100644 index 0000000000000..4e8eaf70824db --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Plugin/Model/AttributeSetRepository/RemoveProductsTest.php @@ -0,0 +1,68 @@ +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()); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/attribute_set_with_product.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/attribute_set_with_product.php new file mode 100644 index 0000000000000..95f277c7124bd --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/attribute_set_with_product.php @@ -0,0 +1,11 @@ +setAttributeSetId($attributeSet->getId()); +$product->save(); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/attribute_set_with_product_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/attribute_set_with_product_rollback.php new file mode 100644 index 0000000000000..cd579bdb76f57 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/attribute_set_with_product_rollback.php @@ -0,0 +1,8 @@ +