Skip to content

Commit 4623b60

Browse files
committed
Merge remote-tracking branch 'mpi/MC-18701' into pr_vk_2019_08_16
2 parents c8abcdd + 8ee02ee commit 4623b60

File tree

5 files changed

+118
-83
lines changed

5 files changed

+118
-83
lines changed

app/code/Magento/Catalog/Model/Product/Attribute/OptionManagement.php

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,6 @@ public function getItems($attributeCode)
4343
*/
4444
public function add($attributeCode, $option)
4545
{
46-
/** @var \Magento\Eav\Api\Data\AttributeOptionInterface[] $currentOptions */
47-
$currentOptions = $this->getItems($attributeCode);
48-
if (is_array($currentOptions)) {
49-
array_walk($currentOptions, function (&$attributeOption) {
50-
/** @var \Magento\Eav\Api\Data\AttributeOptionInterface $attributeOption */
51-
$attributeOption = $attributeOption->getLabel();
52-
});
53-
if (in_array($option->getLabel(), $currentOptions, true)) {
54-
return false;
55-
}
56-
}
5746
return $this->eavOptionManagement->add(
5847
\Magento\Catalog\Api\Data\ProductAttributeInterface::ENTITY_TYPE_CODE,
5948
$attributeCode,

app/code/Magento/Eav/Model/Entity/Attribute/OptionManagement.php

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
67

78
namespace Magento\Eav\Model\Entity\Attribute;
89

10+
use Magento\Eav\Api\Data\AttributeInterface as EavAttributeInterface;
911
use Magento\Framework\Exception\InputException;
1012
use Magento\Framework\Exception\NoSuchEntityException;
1113
use Magento\Framework\Exception\StateException;
@@ -39,7 +41,16 @@ public function __construct(
3941
}
4042

4143
/**
42-
* @inheritdoc
44+
* Add option to attribute.
45+
*
46+
* @param int $entityType
47+
* @param string $attributeCode
48+
* @param \Magento\Eav\Api\Data\AttributeOptionInterface $option
49+
* @return string
50+
* @throws InputException
51+
* @throws NoSuchEntityException
52+
* @throws StateException
53+
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
4354
*/
4455
public function add($entityType, $attributeCode, $option)
4556
{
@@ -64,6 +75,15 @@ public function add($entityType, $attributeCode, $option)
6475
}
6576
}
6677

78+
if (!$this->isAttributeOptionLabelExists($attribute, (string) $options['value'][$optionId][0])) {
79+
throw new InputException(
80+
__(
81+
'Admin store attribute option label "%1" is already exists.',
82+
$options['value'][$optionId][0]
83+
)
84+
);
85+
}
86+
6787
if ($option->getIsDefault()) {
6888
$attribute->setDefault([$optionId]);
6989
}
@@ -134,10 +154,10 @@ public function getItems($entityType, $attributeCode)
134154
/**
135155
* Validate option
136156
*
137-
* @param \Magento\Eav\Api\Data\AttributeInterface $attribute
157+
* @param EavAttributeInterface $attribute
138158
* @param int $optionId
139-
* @throws NoSuchEntityException
140159
* @return void
160+
* @throws NoSuchEntityException
141161
*/
142162
protected function validateOption($attribute, $optionId)
143163
{
@@ -167,13 +187,13 @@ private function getOptionId(\Magento\Eav\Api\Data\AttributeOptionInterface $opt
167187
* Set option value
168188
*
169189
* @param \Magento\Eav\Api\Data\AttributeOptionInterface $option
170-
* @param \Magento\Eav\Api\Data\AttributeInterface $attribute
190+
* @param EavAttributeInterface $attribute
171191
* @param string $optionLabel
172192
* @return void
173193
*/
174194
private function setOptionValue(
175195
\Magento\Eav\Api\Data\AttributeOptionInterface $option,
176-
\Magento\Eav\Api\Data\AttributeInterface $attribute,
196+
EavAttributeInterface $attribute,
177197
string $optionLabel
178198
) {
179199
$optionId = $attribute->getSource()->getOptionId($optionLabel);
@@ -188,4 +208,28 @@ private function setOptionValue(
188208
}
189209
}
190210
}
211+
212+
/**
213+
* Checks if the incoming attribute option label for admin store is already exists.
214+
*
215+
* @param EavAttributeInterface $attribute
216+
* @param string $adminStoreLabel
217+
* @param int $storeId
218+
* @return bool
219+
*/
220+
private function isAttributeOptionLabelExists(
221+
EavAttributeInterface $attribute,
222+
string $adminStoreLabel,
223+
int $storeId = 0
224+
) :bool {
225+
$attribute->setStoreId($storeId);
226+
227+
foreach ($attribute->getSource()->toOptionArray() as $existingAttributeOption) {
228+
if ($existingAttributeOption['label'] === $adminStoreLabel) {
229+
return false;
230+
}
231+
}
232+
233+
return true;
234+
}
191235
}

app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/OptionManagementTest.php

Lines changed: 67 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@
66

77
namespace Magento\Eav\Test\Unit\Model\Entity\Attribute;
88

9+
use Magento\Eav\Api\Data\AttributeOptionInterface as EavAttributeOptionInterface;
10+
use Magento\Eav\Api\Data\AttributeOptionLabelInterface as EavAttributeOptionLabelInterface;
11+
use Magento\Eav\Model\Entity\Attribute\AbstractAttribute as EavAbstractAttribute;
12+
use Magento\Eav\Model\Entity\Attribute\Source\Table as EavAttributeSource;
13+
use PHPUnit\Framework\MockObject\MockObject as MockObject;
14+
915
class OptionManagementTest extends \PHPUnit\Framework\TestCase
1016
{
1117
/**
@@ -38,25 +44,9 @@ public function testAdd()
3844
{
3945
$entityType = 42;
4046
$attributeCode = 'atrCde';
41-
$optionMock = $this->getMockForAbstractClass(
42-
\Magento\Eav\Api\Data\AttributeOptionInterface::class,
43-
[],
44-
'',
45-
false,
46-
false,
47-
true,
48-
['getSourceLabels']
49-
);
50-
$attributeMock = $this->getMockForAbstractClass(
51-
\Magento\Framework\Model\AbstractModel::class,
52-
[],
53-
'',
54-
false,
55-
false,
56-
true,
57-
['usesSource', 'setDefault', 'setOption']
58-
);
59-
$labelMock = $this->createMock(\Magento\Eav\Api\Data\AttributeOptionLabelInterface::class);
47+
$attributeMock = $this->getAttribute();
48+
$optionMock = $this->getAttributeOption();
49+
$labelMock = $this->getAttributeOptionLabel();
6050
$option =
6151
['value' => [
6252
'id_new_option' => [
@@ -92,15 +82,7 @@ public function testAddWithEmptyAttributeCode()
9282
{
9383
$entityType = 42;
9484
$attributeCode = '';
95-
$optionMock = $this->getMockForAbstractClass(
96-
\Magento\Eav\Api\Data\AttributeOptionInterface::class,
97-
[],
98-
'',
99-
false,
100-
false,
101-
true,
102-
['getSourceLabels']
103-
);
85+
$optionMock = $this->getAttributeOption();
10486
$this->resourceModelMock->expects($this->never())->method('save');
10587
$this->model->add($entityType, $attributeCode, $optionMock);
10688
}
@@ -113,24 +95,8 @@ public function testAddWithWrongOptions()
11395
{
11496
$entityType = 42;
11597
$attributeCode = 'testAttribute';
116-
$optionMock = $this->getMockForAbstractClass(
117-
\Magento\Eav\Api\Data\AttributeOptionInterface::class,
118-
[],
119-
'',
120-
false,
121-
false,
122-
true,
123-
['getSourceLabels']
124-
);
125-
$attributeMock = $this->getMockForAbstractClass(
126-
\Magento\Framework\Model\AbstractModel::class,
127-
[],
128-
'',
129-
false,
130-
false,
131-
true,
132-
['usesSource', 'setDefault', 'setOption']
133-
);
98+
$attributeMock = $this->getAttribute();
99+
$optionMock = $this->getAttributeOption();
134100
$this->attributeRepositoryMock->expects($this->once())->method('get')->with($entityType, $attributeCode)
135101
->willReturn($attributeMock);
136102
$attributeMock->expects($this->once())->method('usesSource')->willReturn(false);
@@ -146,25 +112,9 @@ public function testAddWithCannotSaveException()
146112
{
147113
$entityType = 42;
148114
$attributeCode = 'atrCde';
149-
$optionMock = $this->getMockForAbstractClass(
150-
\Magento\Eav\Api\Data\AttributeOptionInterface::class,
151-
[],
152-
'',
153-
false,
154-
false,
155-
true,
156-
['getSourceLabels']
157-
);
158-
$attributeMock = $this->getMockForAbstractClass(
159-
\Magento\Framework\Model\AbstractModel::class,
160-
[],
161-
'',
162-
false,
163-
false,
164-
true,
165-
['usesSource', 'setDefault', 'setOption']
166-
);
167-
$labelMock = $this->createMock(\Magento\Eav\Api\Data\AttributeOptionLabelInterface::class);
115+
$optionMock = $this->getAttributeOption();
116+
$attributeMock = $this->getAttribute();
117+
$labelMock = $this->getAttributeOptionLabel();
168118
$option =
169119
['value' => [
170120
'id_new_option' => [
@@ -340,7 +290,7 @@ public function testGetItems()
340290
true,
341291
['getOptions']
342292
);
343-
$optionsMock = [$this->createMock(\Magento\Eav\Api\Data\AttributeOptionInterface::class)];
293+
$optionsMock = [$this->createMock(EavAttributeOptionInterface::class)];
344294
$this->attributeRepositoryMock->expects($this->once())->method('get')->with($entityType, $attributeCode)
345295
->willReturn($attributeMock);
346296
$attributeMock->expects($this->once())->method('getOptions')->willReturn($optionsMock);
@@ -380,4 +330,55 @@ public function testGetItemsWithEmptyAttributeCode()
380330
$attributeCode = '';
381331
$this->model->getItems($entityType, $attributeCode);
382332
}
333+
334+
/**
335+
* Returns attribute entity mock.
336+
*
337+
* @param array $attributeOptions attribute options for return
338+
* @return MockObject|EavAbstractAttribute
339+
*/
340+
private function getAttribute(array $attributeOptions = [])
341+
{
342+
$attribute = $this->getMockBuilder(EavAbstractAttribute::class)
343+
->disableOriginalConstructor()
344+
->setMethods(
345+
[
346+
'usesSource',
347+
'setDefault',
348+
'setOption',
349+
'setStoreId',
350+
'getSource',
351+
]
352+
)
353+
->getMock();
354+
$source = $this->getMockBuilder(EavAttributeSource::class)
355+
->disableOriginalConstructor()
356+
->getMock();
357+
358+
$attribute->method('getSource')->willReturn($source);
359+
$source->method('toOptionArray')->willReturn($attributeOptions);
360+
361+
return $attribute;
362+
}
363+
364+
/**
365+
* Return attribute option entity mock.
366+
*
367+
* @return MockObject|EavAttributeOptionInterface
368+
*/
369+
private function getAttributeOption()
370+
{
371+
return $this->getMockBuilder(EavAttributeOptionInterface::class)
372+
->setMethods(['getSourceLabels'])
373+
->getMockForAbstractClass();
374+
}
375+
376+
/**
377+
* @return MockObject|EavAttributeOptionLabelInterface
378+
*/
379+
private function getAttributeOptionLabel()
380+
{
381+
return $this->getMockBuilder(EavAttributeOptionLabelInterface::class)
382+
->getMockForAbstractClass();
383+
}
383384
}

app/code/Magento/Eav/i18n/en_US.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,4 @@ hello,hello
143143
"The value of attribute not valid","The value of attribute not valid"
144144
"EAV types and attributes","EAV types and attributes"
145145
"Entity types declaration cache","Entity types declaration cache"
146+
"Admin store attribute option label ""%1"" is already exists.","Admin store attribute option label ""%1"" is already exists."

dev/tests/integration/testsuite/Magento/Swatches/Model/SwatchAttributeOptionAddTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public function testSwatchOptionAdd()
3636
$attribute = $this->objectManager
3737
->create(\Magento\Catalog\Model\ResourceModel\Eav\Attribute::class)
3838
->load('color_swatch', 'attribute_code');
39-
$optionsPerAttribute = 3;
39+
$optionsPerAttribute = 4;
4040

4141
$data['options']['option'] = array_reduce(
4242
range(10, $optionsPerAttribute),

0 commit comments

Comments
 (0)