Skip to content

Commit 1bcbcfe

Browse files
authored
Merge pull request #5891 from magento-tsg-csl3/2.3-develop-pr52
[TSG-CSL3] For 2.3 (pr52)
2 parents e7268db + d468b9a commit 1bcbcfe

File tree

24 files changed

+807
-227
lines changed

24 files changed

+807
-227
lines changed

app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php

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

78
namespace Magento\Catalog\Controller\Adminhtml\Product\Attribute;
89

10+
use Magento\Backend\App\Action\Context;
911
use Magento\Catalog\Controller\Adminhtml\Product\Attribute as AttributeAction;
12+
use Magento\Catalog\Model\ResourceModel\Eav\Attribute;
13+
use Magento\Eav\Model\Entity\Attribute\Set;
1014
use Magento\Eav\Model\Validator\Attribute\Code as AttributeCodeValidator;
1115
use Magento\Framework\App\Action\HttpGetActionInterface;
1216
use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface;
1317
use Magento\Framework\App\ObjectManager;
18+
use Magento\Framework\Cache\FrontendInterface;
19+
use Magento\Framework\Controller\Result\JsonFactory;
20+
use Magento\Framework\Controller\ResultInterface;
1421
use Magento\Framework\DataObject;
1522
use Magento\Framework\Escaper;
23+
use Magento\Framework\Registry;
1624
use Magento\Framework\Serialize\Serializer\FormData;
25+
use Magento\Framework\View\LayoutFactory;
26+
use Magento\Framework\View\Result\PageFactory;
1727

1828
/**
1929
* Product attribute validate controller.
@@ -25,12 +35,12 @@ class Validate extends AttributeAction implements HttpGetActionInterface, HttpPo
2535
const DEFAULT_MESSAGE_KEY = 'message';
2636

2737
/**
28-
* @var \Magento\Framework\Controller\Result\JsonFactory
38+
* @var JsonFactory
2939
*/
3040
protected $resultJsonFactory;
3141

3242
/**
33-
* @var \Magento\Framework\View\LayoutFactory
43+
* @var LayoutFactory
3444
*/
3545
protected $layoutFactory;
3646

@@ -57,25 +67,25 @@ class Validate extends AttributeAction implements HttpGetActionInterface, HttpPo
5767
/**
5868
* Constructor
5969
*
60-
* @param \Magento\Backend\App\Action\Context $context
61-
* @param \Magento\Framework\Cache\FrontendInterface $attributeLabelCache
62-
* @param \Magento\Framework\Registry $coreRegistry
63-
* @param \Magento\Framework\View\Result\PageFactory $resultPageFactory
64-
* @param \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory
65-
* @param \Magento\Framework\View\LayoutFactory $layoutFactory
70+
* @param Context $context
71+
* @param FrontendInterface $attributeLabelCache
72+
* @param Registry $coreRegistry
73+
* @param PageFactory $resultPageFactory
74+
* @param JsonFactory $resultJsonFactory
75+
* @param LayoutFactory $layoutFactory
6676
* @param array $multipleAttributeList
6777
* @param FormData|null $formDataSerializer
6878
* @param AttributeCodeValidator|null $attributeCodeValidator
6979
* @param Escaper $escaper
7080
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
7181
*/
7282
public function __construct(
73-
\Magento\Backend\App\Action\Context $context,
74-
\Magento\Framework\Cache\FrontendInterface $attributeLabelCache,
75-
\Magento\Framework\Registry $coreRegistry,
76-
\Magento\Framework\View\Result\PageFactory $resultPageFactory,
77-
\Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
78-
\Magento\Framework\View\LayoutFactory $layoutFactory,
83+
Context $context,
84+
FrontendInterface $attributeLabelCache,
85+
Registry $coreRegistry,
86+
PageFactory $resultPageFactory,
87+
JsonFactory $resultJsonFactory,
88+
LayoutFactory $layoutFactory,
7989
array $multipleAttributeList = [],
8090
FormData $formDataSerializer = null,
8191
AttributeCodeValidator $attributeCodeValidator = null,
@@ -96,7 +106,7 @@ public function __construct(
96106
/**
97107
* @inheritdoc
98108
*
99-
* @return \Magento\Framework\Controller\ResultInterface
109+
* @return ResultInterface
100110
* @SuppressWarnings(PHPMD.NPathComplexity)
101111
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
102112
*/
@@ -118,14 +128,22 @@ public function execute()
118128

119129
$attributeCode = $this->getRequest()->getParam('attribute_code');
120130
$frontendLabel = $this->getRequest()->getParam('frontend_label');
121-
$attributeCode = $attributeCode ?: $this->generateCode($frontendLabel[0]);
122131
$attributeId = $this->getRequest()->getParam('attribute_id');
123-
$attribute = $this->_objectManager->create(
124-
\Magento\Catalog\Model\ResourceModel\Eav\Attribute::class
125-
)->loadByCode(
126-
$this->_entityTypeId,
127-
$attributeCode
128-
);
132+
133+
if ($attributeId) {
134+
$attribute = $this->_objectManager->create(
135+
Attribute::class
136+
)->load($attributeId);
137+
$attributeCode = $attribute->getAttributeCode();
138+
} else {
139+
$attributeCode = $attributeCode ?: $this->generateCode($frontendLabel[0]);
140+
$attribute = $this->_objectManager->create(
141+
Attribute::class
142+
)->loadByCode(
143+
$this->_entityTypeId,
144+
$attributeCode
145+
);
146+
}
129147

130148
if ($attribute->getId() && !$attributeId || $attributeCode === 'product_type' || $attributeCode === 'type_id') {
131149
$message = strlen($this->getRequest()->getParam('attribute_code'))
@@ -145,8 +163,8 @@ public function execute()
145163

146164
if ($this->getRequest()->has('new_attribute_set_name')) {
147165
$setName = $this->getRequest()->getParam('new_attribute_set_name');
148-
/** @var $attributeSet \Magento\Eav\Model\Entity\Attribute\Set */
149-
$attributeSet = $this->_objectManager->create(\Magento\Eav\Model\Entity\Attribute\Set::class);
166+
/** @var $attributeSet Set */
167+
$attributeSet = $this->_objectManager->create(Set::class);
150168
$attributeSet->setEntityTypeId($this->_entityTypeId)->load($setName, 'attribute_set_name');
151169
if ($attributeSet->getId()) {
152170
$setName = $this->escaper->escapeHtml($setName);
@@ -252,7 +270,7 @@ private function checkUniqueOption(DataObject $response, array $options = null)
252270
private function checkEmptyOption(DataObject $response, array $optionsForCheck = null)
253271
{
254272
foreach ($optionsForCheck as $optionValues) {
255-
if (isset($optionValues[0]) && trim($optionValues[0]) == '') {
273+
if (isset($optionValues[0]) && trim((string)$optionValues[0]) == '') {
256274
$this->setMessageToResponse($response, [__("The value of Admin scope can't be empty.")]);
257275
$response->setError(true);
258276
}

app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/ValidateTest.php

Lines changed: 86 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
7+
68
namespace Magento\Catalog\Test\Unit\Controller\Adminhtml\Product\Attribute;
79

810
use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Validate;
911
use Magento\Eav\Model\Validator\Attribute\Code as AttributeCodeValidator;
12+
use Magento\Framework\Exception\NotFoundException;
1013
use Magento\Framework\Serialize\Serializer\FormData;
1114
use Magento\Catalog\Model\ResourceModel\Eav\Attribute;
1215
use Magento\Catalog\Test\Unit\Controller\Adminhtml\Product\AttributeTest;
@@ -17,59 +20,60 @@
1720
use Magento\Framework\ObjectManagerInterface;
1821
use Magento\Framework\View\LayoutFactory;
1922
use Magento\Framework\View\LayoutInterface;
23+
use PHPUnit\Framework\MockObject\MockObject;
2024

2125
/**
2226
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2327
*/
2428
class ValidateTest extends AttributeTest
2529
{
2630
/**
27-
* @var ResultJsonFactory|\PHPUnit_Framework_MockObject_MockObject
31+
* @var ResultJsonFactory|MockObject
2832
*/
2933
protected $resultJsonFactoryMock;
3034

3135
/**
32-
* @var ResultJson|\PHPUnit_Framework_MockObject_MockObject
36+
* @var ResultJson|MockObject
3337
*/
3438
protected $resultJson;
3539

3640
/**
37-
* @var LayoutFactory|\PHPUnit_Framework_MockObject_MockObject
41+
* @var LayoutFactory|MockObject
3842
*/
3943
protected $layoutFactoryMock;
4044

4145
/**
42-
* @var ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject
46+
* @var ObjectManagerInterface|MockObject
4347
*/
4448
protected $objectManagerMock;
4549

4650
/**
47-
* @var Attribute|\PHPUnit_Framework_MockObject_MockObject
51+
* @var Attribute|MockObject
4852
*/
4953
protected $attributeMock;
5054

5155
/**
52-
* @var AttributeSet|\PHPUnit_Framework_MockObject_MockObject
56+
* @var AttributeSet|MockObject
5357
*/
5458
protected $attributeSetMock;
5559

5660
/**
57-
* @var Escaper|\PHPUnit_Framework_MockObject_MockObject
61+
* @var Escaper|MockObject
5862
*/
5963
protected $escaperMock;
6064

6165
/**
62-
* @var LayoutInterface|\PHPUnit_Framework_MockObject_MockObject
66+
* @var LayoutInterface|MockObject
6367
*/
6468
protected $layoutMock;
6569

6670
/**
67-
* @var FormData|\PHPUnit_Framework_MockObject_MockObject
71+
* @var FormData|MockObject
6872
*/
6973
private $formDataSerializerMock;
7074

7175
/**
72-
* @var AttributeCodeValidator|\PHPUnit_Framework_MockObject_MockObject
76+
* @var AttributeCodeValidator|MockObject
7377
*/
7478
private $attributeCodeValidatorMock;
7579

@@ -148,8 +152,8 @@ public function testExecute()
148152
->method('create')
149153
->willReturnMap(
150154
[
151-
[\Magento\Catalog\Model\ResourceModel\Eav\Attribute::class, [], $this->attributeMock],
152-
[\Magento\Eav\Model\Entity\Attribute\Set::class, [], $this->attributeSetMock]
155+
[Attribute::class, [], $this->attributeMock],
156+
[AttributeSet::class, [], $this->attributeSetMock]
153157
]
154158
);
155159
$this->attributeMock->expects($this->once())
@@ -184,11 +188,74 @@ public function testExecute()
184188
$this->assertInstanceOf(ResultJson::class, $this->getModel()->execute());
185189
}
186190

191+
/**
192+
* Test that editing existing attribute loads attribute by id
193+
*
194+
* @return void
195+
* @throws NotFoundException
196+
*/
197+
public function testExecuteEditExisting(): void
198+
{
199+
$serializedOptions = '{"key":"value"}';
200+
$this->requestMock->expects($this->any())
201+
->method('getParam')
202+
->willReturnMap(
203+
[
204+
['frontend_label', null, 'test_frontend_label'],
205+
['attribute_id', null, 10],
206+
['attribute_code', null, 'test_attribute_code'],
207+
['new_attribute_set_name', null, 'test_attribute_set_name'],
208+
['serialized_options', '[]', $serializedOptions],
209+
]
210+
);
211+
$this->objectManagerMock->expects($this->exactly(2))
212+
->method('create')
213+
->willReturnMap(
214+
[
215+
[Attribute::class, [], $this->attributeMock],
216+
[AttributeSet::class, [], $this->attributeSetMock]
217+
]
218+
);
219+
$this->attributeMock->expects($this->once())
220+
->method('load')
221+
->willReturnSelf();
222+
$this->attributeMock->expects($this->once())
223+
->method('getAttributeCode')
224+
->willReturn('test_attribute_code');
225+
226+
$this->attributeCodeValidatorMock->expects($this->once())
227+
->method('isValid')
228+
->with('test_attribute_code')
229+
->willReturn(true);
230+
231+
$this->requestMock->expects($this->once())
232+
->method('has')
233+
->with('new_attribute_set_name')
234+
->willReturn(true);
235+
$this->attributeSetMock->expects($this->once())
236+
->method('setEntityTypeId')
237+
->willReturnSelf();
238+
$this->attributeSetMock->expects($this->once())
239+
->method('load')
240+
->willReturnSelf();
241+
$this->attributeSetMock->expects($this->once())
242+
->method('getId')
243+
->willReturn(false);
244+
$this->resultJsonFactoryMock->expects($this->once())
245+
->method('create')
246+
->willReturn($this->resultJson);
247+
$this->resultJson->expects($this->once())
248+
->method('setJsonData')
249+
->willReturnSelf();
250+
251+
$this->assertInstanceOf(ResultJson::class, $this->getModel()->execute());
252+
}
253+
187254
/**
188255
* @dataProvider provideUniqueData
189256
* @param array $options
190257
* @param boolean $isError
191-
* @throws \Magento\Framework\Exception\NotFoundException
258+
* @throws NotFoundException
192259
*/
193260
public function testUniqueValidation(array $options, $isError)
194261
{
@@ -330,7 +397,7 @@ public function provideUniqueData()
330397
*
331398
* @dataProvider provideEmptyOption
332399
* @param array $options
333-
* @throws \Magento\Framework\Exception\NotFoundException
400+
* @throws NotFoundException
334401
*/
335402
public function testEmptyOption(array $options, $result)
336403
{
@@ -453,7 +520,7 @@ public function provideEmptyOption()
453520
* @dataProvider provideWhitespaceOption
454521
* @param array $options
455522
* @param $result
456-
* @throws \Magento\Framework\Exception\NotFoundException
523+
* @throws NotFoundException
457524
*/
458525
public function testWhitespaceOption(array $options, $result)
459526
{
@@ -571,7 +638,7 @@ public function provideWhitespaceOption()
571638
}
572639

573640
/**
574-
* @throws \Magento\Framework\Exception\NotFoundException
641+
* @throws NotFoundException
575642
*/
576643
public function testExecuteWithOptionsDataError()
577644
{
@@ -600,8 +667,8 @@ public function testExecuteWithOptionsDataError()
600667
->method('create')
601668
->willReturnMap(
602669
[
603-
[\Magento\Catalog\Model\ResourceModel\Eav\Attribute::class, [], $this->attributeMock],
604-
[\Magento\Eav\Model\Entity\Attribute\Set::class, [], $this->attributeSetMock]
670+
[Attribute::class, [], $this->attributeMock],
671+
[AttributeSet::class, [], $this->attributeSetMock]
605672
]
606673
);
607674

@@ -639,7 +706,7 @@ public function testExecuteWithOptionsDataError()
639706
* @dataProvider provideInvalidAttributeCodes
640707
* @param string $attributeCode
641708
* @param $result
642-
* @throws \Magento\Framework\Exception\NotFoundException
709+
* @throws NotFoundException
643710
*/
644711
public function testExecuteWithInvalidAttributeCode($attributeCode, $result)
645712
{

app/code/Magento/CatalogImportExport/Model/Import/Product.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3074,6 +3074,9 @@ private function formatStockDataForRow(array $rowData): array
30743074
);
30753075

30763076
if ($this->stockConfiguration->isQty($this->skuProcessor->getNewSku($sku)['type_id'])) {
3077+
if (isset($rowData['qty']) && $rowData['qty'] == 0) {
3078+
$row['is_in_stock'] = 0;
3079+
}
30773080
$stockItemDo->setData($row);
30783081
$row['is_in_stock'] = $row['is_in_stock'] ?? $this->stockStateProvider->verifyStock($stockItemDo);
30793082
if ($this->stockStateProvider->verifyNotification($stockItemDo)) {

app/code/Magento/Checkout/view/frontend/web/js/model/address-converter.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,8 @@ define([
135135
quoteAddressToFormAddressData: function (addrs) {
136136
var self = this,
137137
output = {},
138-
streetObject;
138+
streetObject,
139+
customAttributesObject;
139140

140141
$.each(addrs, function (key) {
141142
if (addrs.hasOwnProperty(key) && !$.isFunction(addrs[key])) {
@@ -151,6 +152,16 @@ define([
151152
output.street = streetObject;
152153
}
153154

155+
//jscs:disable requireCamelCaseOrUpperCaseIdentifiers
156+
if ($.isArray(addrs.customAttributes)) {
157+
customAttributesObject = {};
158+
addrs.customAttributes.forEach(function (value) {
159+
customAttributesObject[value.attribute_code] = value.value;
160+
});
161+
output.custom_attributes = customAttributesObject;
162+
}
163+
//jscs:enable requireCamelCaseOrUpperCaseIdentifiers
164+
154165
return output;
155166
},
156167

0 commit comments

Comments
 (0)