Skip to content

Commit

Permalink
MAGETWO-84808: 12110: Missing cascade into attribute set deletion. #1…
Browse files Browse the repository at this point in the history
  • Loading branch information
ishakhsuvarov authored Dec 7, 2017
2 parents 82dab39 + c02ff99 commit 48e3a06
Show file tree
Hide file tree
Showing 8 changed files with 258 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?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;
}
}
22 changes: 22 additions & 0 deletions app/code/Magento/Catalog/Setup/UpgradeSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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();
}

Expand Down Expand Up @@ -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')
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?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));
}
}
3 changes: 3 additions & 0 deletions app/code/Magento/Catalog/etc/adminhtml/di.xml
Original file line number Diff line number Diff line change
Expand Up @@ -184,4 +184,7 @@
<argument name="scopeOverriddenValue" xsi:type="object">Magento\Catalog\Model\Attribute\ScopeOverriddenValue</argument>
</arguments>
</type>
<type name="Magento\Eav\Api\AttributeSetRepositoryInterface">
<plugin name="remove_products" type="Magento\Catalog\Plugin\Model\AttributeSetRepository\RemoveProducts"/>
</type>
</config>
2 changes: 1 addition & 1 deletion app/code/Magento/Catalog/etc/module.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/
-->
<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>
<module name="Magento_Eav"/>
<module name="Magento_Cms"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?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());
}
}
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';

0 comments on commit 48e3a06

Please sign in to comment.