Skip to content

Commit fabe108

Browse files
Merge branch 'MAGETWO-64315' into 2.3-develop-pr5
2 parents 5084541 + 08e14a6 commit fabe108

File tree

6 files changed

+283
-47
lines changed

6 files changed

+283
-47
lines changed

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

Lines changed: 51 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -119,39 +119,18 @@ public function save(\Magento\Catalog\Api\Data\ProductAttributeInterface $attrib
119119
$attribute->setIsUserDefined($existingModel->getIsUserDefined());
120120
$attribute->setFrontendInput($existingModel->getFrontendInput());
121121

122-
if (is_array($attribute->getFrontendLabels())) {
123-
$defaultFrontendLabel = $attribute->getDefaultFrontendLabel();
124-
$frontendLabel[0] = !empty($defaultFrontendLabel)
125-
? $defaultFrontendLabel
126-
: $existingModel->getDefaultFrontendLabel();
127-
foreach ($attribute->getFrontendLabels() as $item) {
128-
$frontendLabel[$item->getStoreId()] = $item->getLabel();
129-
}
130-
$attribute->setDefaultFrontendLabel($frontendLabel);
131-
}
122+
$this->updateDefaultFrontendLabel($attribute, $existingModel);
132123
} else {
133124
$attribute->setAttributeId(null);
134125

135126
if (!$attribute->getFrontendLabels() && !$attribute->getDefaultFrontendLabel()) {
136127
throw InputException::requiredField('frontend_label');
137128
}
138129

139-
$frontendLabels = [];
140-
if ($attribute->getDefaultFrontendLabel()) {
141-
$frontendLabels[0] = $attribute->getDefaultFrontendLabel();
142-
}
143-
if ($attribute->getFrontendLabels() && is_array($attribute->getFrontendLabels())) {
144-
foreach ($attribute->getFrontendLabels() as $label) {
145-
$frontendLabels[$label->getStoreId()] = $label->getLabel();
146-
}
147-
if (!isset($frontendLabels[0]) || !$frontendLabels[0]) {
148-
throw InputException::invalidFieldValue('frontend_label', null);
149-
}
130+
$frontendLabel = $this->updateDefaultFrontendLabel($attribute, null);
150131

151-
$attribute->setDefaultFrontendLabel($frontendLabels);
152-
}
153132
$attribute->setAttributeCode(
154-
$attribute->getAttributeCode() ?: $this->generateCode($frontendLabels[0])
133+
$attribute->getAttributeCode() ?: $this->generateCode($frontendLabel)
155134
);
156135
$this->validateCode($attribute->getAttributeCode());
157136
$this->validateFrontendInput($attribute->getFrontendInput());
@@ -275,4 +254,52 @@ protected function validateFrontendInput($frontendInput)
275254
throw InputException::invalidFieldValue('frontend_input', $frontendInput);
276255
}
277256
}
257+
258+
/**
259+
* This method sets default frontend value using given default frontend value or frontend value from admin store
260+
* if default frontend value is not presented.
261+
* If both default frontend label and admin store frontend label are not given it throws exception
262+
* for attribute creation process or sets existing attribute value for attribute update action.
263+
*
264+
* @param \Magento\Catalog\Api\Data\ProductAttributeInterface $attribute
265+
* @param \Magento\Catalog\Api\Data\ProductAttributeInterface|null $existingModel
266+
* @return string|null
267+
* @throws InputException
268+
*/
269+
private function updateDefaultFrontendLabel($attribute, $existingModel)
270+
{
271+
$frontendLabel = $attribute->getDefaultFrontendLabel();
272+
if (empty($frontendLabel)) {
273+
$frontendLabel = $this->extractAdminStoreFrontendLabel($attribute);
274+
if (empty($frontendLabel)) {
275+
if ($existingModel) {
276+
$frontendLabel = $existingModel->getDefaultFrontendLabel();
277+
} else {
278+
throw InputException::invalidFieldValue('frontend_label', null);
279+
}
280+
}
281+
$attribute->setDefaultFrontendLabel($frontendLabel);
282+
}
283+
return $frontendLabel;
284+
}
285+
286+
/**
287+
* This method extracts frontend label from FrontendLabel object for admin store.
288+
*
289+
* @param \Magento\Catalog\Api\Data\ProductAttributeInterface $attribute
290+
* @return string|null
291+
*/
292+
private function extractAdminStoreFrontendLabel($attribute)
293+
{
294+
$frontendLabel = [];
295+
$frontendLabels = $attribute->getFrontendLabels();
296+
if (isset($frontendLabels[0])
297+
&& $frontendLabels[0] instanceof \Magento\Eav\Api\Data\AttributeFrontendLabelInterface
298+
) {
299+
foreach ($attribute->getFrontendLabels() as $label) {
300+
$frontendLabel[$label->getStoreId()] = $label->getLabel();
301+
}
302+
}
303+
return $frontendLabel[0] ?? null;
304+
}
278305
}

app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/RepositoryTest.php

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
use Magento\Catalog\Api\Data\ProductAttributeInterface;
1111
use Magento\Catalog\Model\Product\Attribute\Repository;
1212
use Magento\Catalog\Model\ResourceModel\Eav\Attribute;
13-
use Magento\Eav\Api\Data\AttributeFrontendLabelInterface;
1413

1514
/**
1615
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
@@ -72,6 +71,9 @@ class RepositoryTest extends \PHPUnit\Framework\TestCase
7271
*/
7372
private $optionManagementMock;
7473

74+
/**
75+
* @inheritdoc
76+
*/
7577
protected function setUp()
7678
{
7779
$this->attributeResourceMock =
@@ -116,6 +118,9 @@ protected function setUp()
116118
);
117119
}
118120

121+
/**
122+
* @return void
123+
*/
119124
public function testGet()
120125
{
121126
$attributeCode = 'some attribute code';
@@ -128,6 +133,9 @@ public function testGet()
128133
$this->model->get($attributeCode);
129134
}
130135

136+
/**
137+
* @return void
138+
*/
131139
public function testGetList()
132140
{
133141
$searchCriteriaMock = $this->createMock(\Magento\Framework\Api\SearchCriteria::class);
@@ -141,6 +149,9 @@ public function testGetList()
141149
$this->model->getList($searchCriteriaMock);
142150
}
143151

152+
/**
153+
* @return void
154+
*/
144155
public function testDelete()
145156
{
146157
$attributeMock = $this->createMock(\Magento\Catalog\Model\ResourceModel\Eav\Attribute::class);
@@ -149,6 +160,9 @@ public function testDelete()
149160
$this->assertEquals(true, $this->model->delete($attributeMock));
150161
}
151162

163+
/**
164+
* @return void
165+
*/
152166
public function testDeleteById()
153167
{
154168
$attributeCode = 'some attribute code';
@@ -164,6 +178,9 @@ public function testDeleteById()
164178
$this->assertEquals(true, $this->model->deleteById($attributeCode));
165179
}
166180

181+
/**
182+
* @return void
183+
*/
167184
public function testGetCustomAttributesMetadata()
168185
{
169186
$searchCriteriaMock = $this->createMock(\Magento\Framework\Api\SearchCriteria::class);
@@ -235,15 +252,18 @@ public function testSaveInputExceptionInvalidFieldValue()
235252
);
236253
$attributeMock->expects($this->once())->method('getAttributeId')->willReturn(null);
237254
$attributeMock->expects($this->once())->method('setAttributeId')->with(null)->willReturnSelf();
238-
$labelMock = $this->createMock(\Magento\Eav\Api\Data\AttributeFrontendLabelInterface::class);
239-
$attributeMock->expects($this->exactly(4))->method('getFrontendLabels')->willReturn([$labelMock]);
240-
$attributeMock->expects($this->exactly(2))->method('getDefaultFrontendLabel')->willReturn('test');
255+
$labelMock = $this->createMock(\Magento\Eav\Model\Entity\Attribute\FrontendLabel::class);
256+
$attributeMock->expects($this->any())->method('getFrontendLabels')->willReturn([$labelMock]);
257+
$attributeMock->expects($this->any())->method('getDefaultFrontendLabel')->willReturn(null);
241258
$labelMock->expects($this->once())->method('getStoreId')->willReturn(0);
242259
$labelMock->expects($this->once())->method('getLabel')->willReturn(null);
243260

244261
$this->model->save($attributeMock);
245262
}
246263

264+
/**
265+
* @return void
266+
*/
247267
public function testSaveDoesNotSaveAttributeOptionsIfOptionsAreAbsentInPayload()
248268
{
249269
$attributeId = 1;
@@ -260,7 +280,7 @@ public function testSaveDoesNotSaveAttributeOptionsIfOptionsAreAbsentInPayload()
260280
->method('get')
261281
->with(ProductAttributeInterface::ENTITY_TYPE_CODE, $attributeCode)
262282
->willReturn($existingModelMock);
263-
283+
$existingModelMock->expects($this->once())->method('getDefaultFrontendLabel')->willReturn('default_label');
264284
// Attribute code must not be changed after attribute creation
265285
$attributeMock->expects($this->once())->method('setAttributeCode')->with($attributeCode);
266286
$this->attributeResourceMock->expects($this->once())->method('save')->with($attributeMock);
@@ -269,9 +289,12 @@ public function testSaveDoesNotSaveAttributeOptionsIfOptionsAreAbsentInPayload()
269289
$this->model->save($attributeMock);
270290
}
271291

292+
/**
293+
* @return void
294+
*/
272295
public function testSaveSavesDefaultFrontendLabelIfItIsPresentInPayload()
273296
{
274-
$labelMock = $this->createMock(AttributeFrontendLabelInterface::class);
297+
$labelMock = $this->createMock(\Magento\Eav\Api\Data\AttributeFrontendLabelInterface::class);
275298
$labelMock->expects($this->any())->method('getStoreId')->willReturn(1);
276299
$labelMock->expects($this->any())->method('getLabel')->willReturn('Store Scope Label');
277300

@@ -280,11 +303,12 @@ public function testSaveSavesDefaultFrontendLabelIfItIsPresentInPayload()
280303
$attributeMock = $this->createMock(Attribute::class);
281304
$attributeMock->expects($this->any())->method('getAttributeCode')->willReturn($attributeCode);
282305
$attributeMock->expects($this->any())->method('getAttributeId')->willReturn($attributeId);
283-
$attributeMock->expects($this->any())->method('getDefaultFrontendLabel')->willReturn('Default Label');
306+
$attributeMock->expects($this->any())->method('getDefaultFrontendLabel')->willReturn(null);
284307
$attributeMock->expects($this->any())->method('getFrontendLabels')->willReturn([$labelMock]);
285308
$attributeMock->expects($this->any())->method('getOptions')->willReturn([]);
286309

287310
$existingModelMock = $this->createMock(Attribute::class);
311+
$existingModelMock->expects($this->any())->method('getDefaultFrontendLabel')->willReturn('Default Label');
288312
$existingModelMock->expects($this->any())->method('getAttributeId')->willReturn($attributeId);
289313
$existingModelMock->expects($this->any())->method('getAttributeCode')->willReturn($attributeCode);
290314

@@ -295,12 +319,7 @@ public function testSaveSavesDefaultFrontendLabelIfItIsPresentInPayload()
295319

296320
$attributeMock->expects($this->once())
297321
->method('setDefaultFrontendLabel')
298-
->with(
299-
[
300-
0 => 'Default Label',
301-
1 => 'Store Scope Label'
302-
]
303-
);
322+
->with('Default Label');
304323
$this->attributeResourceMock->expects($this->once())->method('save')->with($attributeMock);
305324

306325
$this->model->save($attributeMock);

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

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,11 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens
119119
*/
120120
protected $dataObjectHelper;
121121

122+
/**
123+
* @var FrontendLabelFactory
124+
*/
125+
private $frontendLabelFactory;
126+
122127
/**
123128
* Serializer Instance.
124129
*
@@ -163,6 +168,7 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens
163168
* @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
164169
* @param array $data
165170
* @param \Magento\Eav\Api\Data\AttributeExtensionFactory|null $eavExtensionFactory
171+
* @param FrontendLabelFactory|null $frontendLabelFactory
166172
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
167173
* @codeCoverageIgnore
168174
*/
@@ -182,7 +188,8 @@ public function __construct(
182188
\Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
183189
\Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
184190
array $data = [],
185-
\Magento\Eav\Api\Data\AttributeExtensionFactory $eavExtensionFactory = null
191+
\Magento\Eav\Api\Data\AttributeExtensionFactory $eavExtensionFactory = null,
192+
FrontendLabelFactory $frontendLabelFactory = null
186193
) {
187194
parent::__construct(
188195
$context,
@@ -203,6 +210,8 @@ public function __construct(
203210
$this->dataObjectHelper = $dataObjectHelper;
204211
$this->eavExtensionFactory = $eavExtensionFactory ?: \Magento\Framework\App\ObjectManager::getInstance()
205212
->get(\Magento\Eav\Api\Data\AttributeExtensionFactory::class);
213+
$this->frontendLabelFactory = $frontendLabelFactory
214+
?: \Magento\Framework\App\ObjectManager::getInstance()->get(FrontendLabelFactory::class);
206215
}
207216

208217
/**
@@ -1234,6 +1243,19 @@ public function setDefaultFrontendLabel($defaultFrontendLabel)
12341243
*/
12351244
public function getFrontendLabels()
12361245
{
1246+
if ($this->getData(self::FRONTEND_LABELS) == null) {
1247+
$attributeId = $this->getAttributeId();
1248+
$storeLabels = $this->_getResource()->getStoreLabelsByAttributeId($attributeId);
1249+
1250+
$resultFrontedLabels = [];
1251+
foreach ($storeLabels as $i => $label) {
1252+
$frontendLabel = $this->frontendLabelFactory->create();
1253+
$frontendLabel->setStoreId($i);
1254+
$frontendLabel->setLabel($label);
1255+
$resultFrontedLabels[] = $frontendLabel;
1256+
}
1257+
$this->setData(self::FRONTEND_LABELS, $resultFrontedLabels);
1258+
}
12371259
return $this->_getData(self::FRONTEND_LABELS);
12381260
}
12391261

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

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,10 @@ protected function _beforeSave(AbstractModel $object)
171171
{
172172
$frontendLabel = $object->getFrontendLabel();
173173
if (is_array($frontendLabel)) {
174-
if (!isset($frontendLabel[0]) || $frontendLabel[0] === null || $frontendLabel[0] == '') {
175-
throw new \Magento\Framework\Exception\LocalizedException(__('The storefront label is not defined.'));
176-
}
174+
$this->checkDefaultFrontendLabelExists($frontendLabel, $frontendLabel);
177175
$object->setFrontendLabel($frontendLabel[0])->setStoreLabels($frontendLabel);
176+
} else {
177+
$this->setStoreLabels($object, $frontendLabel);
178178
}
179179

180180
/**
@@ -742,4 +742,43 @@ public function __wakeup()
742742
$this->_storeManager = \Magento\Framework\App\ObjectManager::getInstance()
743743
->get(\Magento\Store\Model\StoreManagerInterface::class);
744744
}
745+
746+
/**
747+
* This method extracts frontend labels into array and sets array values as storeLabels into an object.
748+
*
749+
* @param AbstractModel $object
750+
* @param string|null $frontendLabel
751+
* @return void
752+
* @throws \Magento\Framework\Exception\LocalizedException
753+
*/
754+
private function setStoreLabels(AbstractModel $object, $frontendLabel)
755+
{
756+
$resultLabel = [];
757+
$frontendLabels = $object->getFrontendLabels();
758+
if (isset($frontendLabels[0])
759+
&& $frontendLabels[0] instanceof \Magento\Eav\Model\Entity\Attribute\FrontendLabel
760+
) {
761+
foreach ($frontendLabels as $label) {
762+
$resultLabel[$label->getStoreId()] = $label->getLabel();
763+
}
764+
$this->checkDefaultFrontendLabelExists($frontendLabel, $resultLabel);
765+
$object->setStoreLabels($resultLabel);
766+
}
767+
}
768+
769+
/**
770+
* This method checks whether value for default frontend label exists in attribute data.
771+
*
772+
* @param array|string|null $frontendLabel
773+
* @param array $resultLabels
774+
* @return void
775+
* @throws \Magento\Framework\Exception\LocalizedException
776+
*/
777+
private function checkDefaultFrontendLabelExists($frontendLabel, $resultLabels)
778+
{
779+
$isAdminStoreLabel = (isset($resultLabels[0]) && !empty($resultLabels[0]));
780+
if (empty($frontendLabel) && !$isAdminStoreLabel) {
781+
throw new \Magento\Framework\Exception\LocalizedException(__('The storefront label is not defined.'));
782+
}
783+
}
745784
}

0 commit comments

Comments
 (0)