Skip to content

Commit a817f97

Browse files
author
Bohdan Korablov
committed
Merge remote-tracking branch 'mainline/develop' into MAGETWO-59433
2 parents 4723511 + 54882fe commit a817f97

File tree

20 files changed

+545
-48
lines changed

20 files changed

+545
-48
lines changed

app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Save.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ public function execute()
101101
}
102102
$model->save();
103103
$this->messageManager->addSuccess(__('You saved the attribute set.'));
104+
} catch (\Magento\Framework\Exception\AlreadyExistsException $e) {
105+
$this->messageManager->addErrorMessage($e->getMessage());
106+
$hasError = true;
104107
} catch (\Magento\Framework\Exception\LocalizedException $e) {
105108
$this->messageManager->addError($e->getMessage());
106109
$hasError = true;

app/code/Magento/Eav/Model/Entity/AbstractEntity.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
use Magento\Eav\Model\Entity\Attribute\Frontend\AbstractFrontend;
1414
use Magento\Eav\Model\Entity\Attribute\Source\AbstractSource;
1515
use Magento\Framework\App\Config\Element;
16-
use Magento\Framework\App\ResourceConnection\Config;
16+
use Magento\Framework\DB\Adapter\DuplicateException;
17+
use Magento\Framework\Exception\AlreadyExistsException;
1718
use Magento\Framework\Exception\LocalizedException;
1819
use Magento\Framework\Model\AbstractModel;
1920
use Magento\Framework\Model\ResourceModel\Db\ObjectRelationProcessor;
@@ -1108,6 +1109,7 @@ protected function _setAttributeValue($object, $valueRow)
11081109
* @param \Magento\Framework\Model\AbstractModel $object
11091110
* @return $this
11101111
* @throws \Exception
1112+
* @throws AlreadyExistsException
11111113
*/
11121114
public function save(\Magento\Framework\Model\AbstractModel $object)
11131115
{
@@ -1147,6 +1149,10 @@ public function save(\Magento\Framework\Model\AbstractModel $object)
11471149
}
11481150
$this->addCommitCallback([$object, 'afterCommitCallback'])->commit();
11491151
$object->setHasDataChanges(false);
1152+
} catch (DuplicateException $e) {
1153+
$this->rollBack();
1154+
$object->setHasDataChanges(true);
1155+
throw new AlreadyExistsException(__('Unique constraint violation found'), $e);
11501156
} catch (\Exception $e) {
11511157
$this->rollBack();
11521158
$object->setHasDataChanges(true);
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Eav\Model\Entity\Attribute;
7+
8+
use Magento\Framework\Exception\AlreadyExistsException;
9+
10+
/**
11+
* Class AttributeGroupAlreadyExistsException
12+
*/
13+
class AttributeGroupAlreadyExistsException extends AlreadyExistsException
14+
{
15+
}

app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute/Group.php

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
*/
66
namespace Magento\Eav\Model\ResourceModel\Entity\Attribute;
77

8+
use Magento\Eav\Model\Entity\Attribute\AttributeGroupAlreadyExistsException;
9+
use Magento\Framework\DB\Adapter\DuplicateException;
10+
use Magento\Framework\Model\AbstractModel;
11+
812
/**
913
* Eav Resource Entity Attribute Group
1014
*
@@ -50,10 +54,10 @@ public function itemExists($object)
5054
/**
5155
* Perform actions before object save
5256
*
53-
* @param \Magento\Framework\Model\AbstractModel $object
57+
* @param AbstractModel $object
5458
* @return \Magento\Framework\Model\ResourceModel\Db\AbstractDb
5559
*/
56-
protected function _beforeSave(\Magento\Framework\Model\AbstractModel $object)
60+
protected function _beforeSave(AbstractModel $object)
5761
{
5862
if (!$object->getSortOrder()) {
5963
$object->setSortOrder($this->_getMaxSortOrder($object) + 1);
@@ -64,10 +68,10 @@ protected function _beforeSave(\Magento\Framework\Model\AbstractModel $object)
6468
/**
6569
* Perform actions after object save
6670
*
67-
* @param \Magento\Framework\Model\AbstractModel $object
71+
* @param AbstractModel $object
6872
* @return \Magento\Framework\Model\ResourceModel\Db\AbstractDb
6973
*/
70-
protected function _afterSave(\Magento\Framework\Model\AbstractModel $object)
74+
protected function _afterSave(AbstractModel $object)
7175
{
7276
if ($object->getAttributes()) {
7377
foreach ($object->getAttributes() as $attribute) {
@@ -82,7 +86,7 @@ protected function _afterSave(\Magento\Framework\Model\AbstractModel $object)
8286
/**
8387
* Retrieve max sort order
8488
*
85-
* @param \Magento\Framework\Model\AbstractModel $object
89+
* @param AbstractModel $object
8690
* @return int
8791
*/
8892
protected function _getMaxSortOrder($object)
@@ -130,4 +134,38 @@ public function updateDefaultGroup($attributeSetId)
130134

131135
return $this;
132136
}
137+
138+
/**
139+
* {@inheritdoc}
140+
*/
141+
protected function saveNewObject(AbstractModel $object)
142+
{
143+
try {
144+
return parent::saveNewObject($object);
145+
} catch (DuplicateException $e) {
146+
throw new AttributeGroupAlreadyExistsException(
147+
__(
148+
'Attribute group with same code already exist. Please rename "%1" group',
149+
$object->getAttributeGroupName()
150+
)
151+
);
152+
}
153+
}
154+
155+
/**
156+
* {@inheritdoc}
157+
*/
158+
protected function updateObject(AbstractModel $object)
159+
{
160+
try {
161+
return parent::updateObject($object);
162+
} catch (DuplicateException $e) {
163+
throw new AttributeGroupAlreadyExistsException(
164+
__(
165+
'Attribute group with same code already exist. Please rename "%1" group',
166+
$object->getAttributeGroupName()
167+
)
168+
);
169+
}
170+
}
133171
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Eav\Setup;
8+
9+
use Magento\Framework\Setup\UpgradeSchemaInterface;
10+
use Magento\Framework\Setup\ModuleContextInterface;
11+
use Magento\Framework\Setup\SchemaSetupInterface;
12+
13+
/**
14+
* Upgrade the Eav module DB scheme
15+
*/
16+
class UpgradeSchema implements UpgradeSchemaInterface
17+
{
18+
/**
19+
* {@inheritdoc}
20+
*/
21+
public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context)
22+
{
23+
$setup->startSetup();
24+
25+
if (version_compare($context->getVersion(), '2.1.0', '<')) {
26+
$this->addUniqueKeyToEavAttributeGroupTable($setup);
27+
}
28+
$setup->endSetup();
29+
}
30+
31+
/**
32+
* @param SchemaSetupInterface $setup
33+
* @return void
34+
*/
35+
private function addUniqueKeyToEavAttributeGroupTable(SchemaSetupInterface $setup)
36+
{
37+
$setup->getConnection()->addIndex(
38+
$setup->getTable('eav_attribute_group'),
39+
$setup->getIdxName(
40+
'catalog_category_product',
41+
['attribute_set_id', 'attribute_group_code'],
42+
\Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE
43+
),
44+
['attribute_set_id', 'attribute_group_code'],
45+
\Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE
46+
);
47+
}
48+
}

app/code/Magento/Eav/Test/Unit/Model/Entity/AbstractEntityTest.php

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@
55
*/
66
namespace Magento\Eav\Test\Unit\Model\Entity;
77

8+
use Magento\Eav\Model\Entity\AbstractEntity;
9+
use Magento\Framework\DB\Adapter\AdapterInterface;
10+
use Magento\Framework\DB\Adapter\DuplicateException;
11+
use Magento\Framework\Model\AbstractModel;
812
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
913

1014
class AbstractEntityTest extends \PHPUnit_Framework_TestCase
1115
{
1216
/**
1317
* Entity model to be tested
14-
* @var \Magento\Eav\Model\Entity\AbstractEntity|\PHPUnit_Framework_MockObject_MockObject
18+
* @var AbstractEntity|\PHPUnit_Framework_MockObject_MockObject
1519
*/
1620
protected $_model;
1721

@@ -23,11 +27,11 @@ protected function setUp()
2327
$objectManager = new ObjectManager($this);
2428
$this->eavConfig = $this->getMock(\Magento\Eav\Model\Config::class, [], [], '', false);
2529
$arguments = $objectManager->getConstructArguments(
26-
\Magento\Eav\Model\Entity\AbstractEntity::class,
30+
AbstractEntity::class,
2731
['eavConfig' => $this->eavConfig]
2832
);
2933
$this->_model = $this->getMockForAbstractClass(
30-
\Magento\Eav\Model\Entity\AbstractEntity::class,
34+
AbstractEntity::class,
3135
$arguments
3236
);
3337
}
@@ -113,7 +117,7 @@ protected function _getAttributes()
113117
/**
114118
* Get adapter mock
115119
*
116-
* @return \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\DB\Adapter\AdapterInterface
120+
* @return \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\DB\Adapter\Pdo\Mysql
117121
*/
118122
protected function _getConnectionMock()
119123
{
@@ -300,7 +304,7 @@ public function testSave($attributeCode, $attributeSetId, $productData, $product
300304
$objectManager = new ObjectManager($this);
301305
$this->eavConfig = $this->getMock(\Magento\Eav\Model\Config::class, [], [], '', false);
302306
$arguments = $objectManager->getConstructArguments(
303-
\Magento\Eav\Model\Entity\AbstractEntity::class,
307+
AbstractEntity::class,
304308
[
305309
'eavConfig' => $eavConfig,
306310
'data' => [
@@ -310,8 +314,8 @@ public function testSave($attributeCode, $attributeSetId, $productData, $product
310314
]
311315
]
312316
);
313-
/** @var $model \Magento\Framework\Model\AbstractModel|\PHPUnit_Framework_MockObject_MockObject */
314-
$model = $this->getMockBuilder(\Magento\Eav\Model\Entity\AbstractEntity::class)
317+
/** @var $model AbstractEntity|\PHPUnit_Framework_MockObject_MockObject */
318+
$model = $this->getMockBuilder(AbstractEntity::class)
315319
->setConstructorArgs($arguments)
316320
->setMethods(['_getValue', 'beginTransaction', 'commit', 'rollback', 'getConnection'])
317321
->getMock();
@@ -353,4 +357,30 @@ public function productAttributesDataProvider()
353357
]
354358
];
355359
}
360+
361+
/**
362+
* @expectedException \Magento\Framework\Exception\AlreadyExistsException
363+
*/
364+
public function testDuplicateExceptionProcessingOnSave()
365+
{
366+
$connection = $this->getMock(AdapterInterface::class);
367+
$connection->expects($this->once())->method('rollback');
368+
369+
/** @var AbstractEntity|\PHPUnit_Framework_MockObject_MockObject $model */
370+
$model = $this->getMockBuilder(AbstractEntity::class)
371+
->disableOriginalConstructor()
372+
->setMethods(['getConnection'])
373+
->getMockForAbstractClass();
374+
$model->expects($this->any())->method('getConnection')->willReturn($connection);
375+
376+
/** @var AbstractModel|\PHPUnit_Framework_MockObject_MockObject $object */
377+
$object = $this->getMockBuilder(AbstractModel::class)
378+
->disableOriginalConstructor()
379+
->getMock();
380+
$object->expects($this->once())->method('hasDataChanges')->willReturn(true);
381+
$object->expects($this->once())->method('beforeSave')->willThrowException(new DuplicateException());
382+
$object->expects($this->once())->method('setHasDataChanges')->with(true);
383+
384+
$model->save($object);
385+
}
356386
}

app/code/Magento/Eav/etc/module.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*/
77
-->
88
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
9-
<module name="Magento_Eav" setup_version="2.0.0">
9+
<module name="Magento_Eav" setup_version="2.1.0">
1010
<sequence>
1111
<module name="Magento_Store"/>
1212
</sequence>
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Catalog\Controller\Adminhtml\Product\Set;
7+
8+
use Magento\Eav\Api\AttributeSetRepositoryInterface;
9+
use Magento\Eav\Api\Data\AttributeSetInterface;
10+
use Magento\Framework\Api\SearchCriteriaBuilder;
11+
use Magento\TestFramework\Helper\Bootstrap;
12+
13+
class SaveTest extends \Magento\TestFramework\TestCase\AbstractBackendController
14+
{
15+
/**
16+
* @magentoDataFixture Magento/Catalog/_files/attribute_set_with_renamed_group.php
17+
*/
18+
public function testAlreadyExistsExceptionProcessingWhenGroupCodeIsDuplicated()
19+
{
20+
$attributeSet = $this->getAttributeSetByName('attribute_set_test');
21+
$this->assertNotEmpty($attributeSet, 'Attribute set with name "attribute_set_test" is missed');
22+
23+
$this->getRequest()->setPostValue('data', json_encode([
24+
'attribute_set_name' => 'attribute_set_test',
25+
'groups' => [
26+
['ynode-418', 'attribute-group-name', 1],
27+
],
28+
'attributes' => [
29+
['9999', 'ynode-418', 1, null]
30+
],
31+
'not_attributes' => [],
32+
'removeGroups' => [],
33+
]));
34+
$this->dispatch('backend/catalog/product_set/save/id/' . $attributeSet->getAttributeSetId());
35+
36+
$jsonResponse = json_decode($this->getResponse()->getBody());
37+
$this->assertNotNull($jsonResponse);
38+
$this->assertEquals(1, $jsonResponse->error);
39+
$this->assertContains(
40+
'Attribute group with same code already exist. Please rename &quot;attribute-group-name&quot; group',
41+
$jsonResponse->message
42+
);
43+
}
44+
45+
/**
46+
* @param string $attributeSetName
47+
* @return AttributeSetInterface|null
48+
*/
49+
protected function getAttributeSetByName($attributeSetName)
50+
{
51+
$objectManager = Bootstrap::getObjectManager();
52+
53+
/** @var SearchCriteriaBuilder $searchCriteriaBuilder */
54+
$searchCriteriaBuilder = $objectManager->get(SearchCriteriaBuilder::class);
55+
$searchCriteriaBuilder->addFilter('attribute_set_name', $attributeSetName);
56+
57+
/** @var AttributeSetRepositoryInterface $attributeSetRepository */
58+
$attributeSetRepository = $objectManager->get(AttributeSetRepositoryInterface::class);
59+
$result = $attributeSetRepository->getList($searchCriteriaBuilder->create());
60+
61+
$items = $result->getItems();
62+
return $result->getTotalCount() ? array_pop($items) : null;
63+
}
64+
}

0 commit comments

Comments
 (0)