Skip to content

Commit 8fa06d2

Browse files
author
Joan He
committed
Merge remote-tracking branch 'upstream/2.3-qwerty' into MC-5895
2 parents c5a7120 + b820ddf commit 8fa06d2

File tree

269 files changed

+7483
-3916
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

269 files changed

+7483
-3916
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ atlassian*
4848
/pub/media/import/*
4949
!/pub/media/import/.htaccess
5050
/pub/media/logo/*
51+
/pub/media/custom_options/*
52+
!/pub/media/custom_options/.htaccess
5153
/pub/media/theme/*
5254
/pub/media/theme_customization/*
5355
!/pub/media/theme_customization/.htaccess

app/code/Magento/AsynchronousOperations/Model/MassSchedule.php

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Psr\Log\LoggerInterface;
2121
use Magento\AsynchronousOperations\Model\ResourceModel\Operation\OperationRepository;
2222
use Magento\Authorization\Model\UserContextInterface;
23+
use Magento\Framework\Encryption\Encryptor;
2324

2425
/**
2526
* Class MassSchedule used for adding multiple entities as Operations to Bulk Management with the status tracking
@@ -63,6 +64,11 @@ class MassSchedule
6364
*/
6465
private $userContext;
6566

67+
/**
68+
* @var Encryptor
69+
*/
70+
private $encryptor;
71+
6672
/**
6773
* Initialize dependencies.
6874
*
@@ -73,6 +79,7 @@ class MassSchedule
7379
* @param LoggerInterface $logger
7480
* @param OperationRepository $operationRepository
7581
* @param UserContextInterface $userContext
82+
* @param Encryptor|null $encryptor
7683
*/
7784
public function __construct(
7885
IdentityGeneratorInterface $identityService,
@@ -81,7 +88,8 @@ public function __construct(
8188
BulkManagementInterface $bulkManagement,
8289
LoggerInterface $logger,
8390
OperationRepository $operationRepository,
84-
UserContextInterface $userContext = null
91+
UserContextInterface $userContext = null,
92+
Encryptor $encryptor = null
8593
) {
8694
$this->identityService = $identityService;
8795
$this->itemStatusInterfaceFactory = $itemStatusInterfaceFactory;
@@ -90,6 +98,7 @@ public function __construct(
9098
$this->logger = $logger;
9199
$this->operationRepository = $operationRepository;
92100
$this->userContext = $userContext ?: ObjectManager::getInstance()->get(UserContextInterface::class);
101+
$this->encryptor = $encryptor ?: ObjectManager::getInstance()->get(Encryptor::class);
93102
}
94103

95104
/**
@@ -130,9 +139,13 @@ public function publishMass($topicName, array $entitiesArray, $groupId = null, $
130139
$requestItem = $this->itemStatusInterfaceFactory->create();
131140

132141
try {
133-
$operations[] = $this->operationRepository->createByTopic($topicName, $entityParams, $groupId);
142+
$operation = $this->operationRepository->createByTopic($topicName, $entityParams, $groupId);
143+
$operations[] = $operation;
134144
$requestItem->setId($key);
135145
$requestItem->setStatus(ItemStatusInterface::STATUS_ACCEPTED);
146+
$requestItem->setDataHash(
147+
$this->encryptor->hash($operation->getSerializedData(), Encryptor::HASH_VERSION_SHA256)
148+
);
136149
$requestItems[] = $requestItem;
137150
} catch (\Exception $exception) {
138151
$this->logger->error($exception);

app/code/Magento/Backend/Block/Widget/Grid/Massaction/AbstractMassaction.php

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -282,25 +282,23 @@ public function getGridIdsJson()
282282
if (!$this->getUseSelectAll()) {
283283
return '';
284284
}
285-
/** @var \Magento\Framework\Data\Collection $allIdsCollection */
286-
$allIdsCollection = clone $this->getParentBlock()->getCollection();
287285

288-
if ($this->getMassactionIdField()) {
289-
$massActionIdField = $this->getMassactionIdField();
286+
/** @var \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection $collection */
287+
$collection = clone $this->getParentBlock()->getCollection();
288+
289+
if ($collection instanceof AbstractDb) {
290+
$idsSelect = clone $collection->getSelect();
291+
$idsSelect->reset(\Magento\Framework\DB\Select::ORDER);
292+
$idsSelect->reset(\Magento\Framework\DB\Select::LIMIT_COUNT);
293+
$idsSelect->reset(\Magento\Framework\DB\Select::LIMIT_OFFSET);
294+
$idsSelect->reset(\Magento\Framework\DB\Select::COLUMNS);
295+
$idsSelect->columns($this->getMassactionIdField(), 'main_table');
296+
$idList = $collection->getConnection()->fetchCol($idsSelect);
290297
} else {
291-
$massActionIdField = $this->getParentBlock()->getMassactionIdField();
298+
$idList = $collection->setPageSize(0)->getColumnValues($this->getMassactionIdField());
292299
}
293300

294-
if ($allIdsCollection instanceof AbstractDb) {
295-
$allIdsCollection->getSelect()->limit();
296-
$allIdsCollection->clear();
297-
}
298-
299-
$gridIds = $allIdsCollection->setPageSize(0)->getColumnValues($massActionIdField);
300-
if (!empty($gridIds)) {
301-
return join(",", $gridIds);
302-
}
303-
return '';
301+
return implode(',', $idList);
304302
}
305303

306304
/**

app/code/Magento/Backend/Test/Unit/Block/Widget/Grid/MassactionTest.php

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -269,62 +269,6 @@ public function testGetGridIdsJsonWithoutUseSelectAll()
269269
$this->assertEmpty($this->_block->getGridIdsJson());
270270
}
271271

272-
/**
273-
* @param array $items
274-
* @param string $result
275-
*
276-
* @dataProvider dataProviderGetGridIdsJsonWithUseSelectAll
277-
*/
278-
public function testGetGridIdsJsonWithUseSelectAll(array $items, $result)
279-
{
280-
$this->_block->setUseSelectAll(true);
281-
282-
if ($this->_block->getMassactionIdField()) {
283-
$massActionIdField = $this->_block->getMassactionIdField();
284-
} else {
285-
$massActionIdField = $this->_block->getParentBlock()->getMassactionIdField();
286-
}
287-
288-
$collectionMock = $this->getMockBuilder(\Magento\Framework\Data\Collection::class)
289-
->disableOriginalConstructor()
290-
->getMock();
291-
292-
$this->_gridMock->expects($this->once())
293-
->method('getCollection')
294-
->willReturn($collectionMock);
295-
$collectionMock->expects($this->once())
296-
->method('setPageSize')
297-
->with(0)
298-
->willReturnSelf();
299-
$collectionMock->expects($this->once())
300-
->method('getColumnValues')
301-
->with($massActionIdField)
302-
->willReturn($items);
303-
304-
$this->assertEquals($result, $this->_block->getGridIdsJson());
305-
}
306-
307-
/**
308-
* @return array
309-
*/
310-
public function dataProviderGetGridIdsJsonWithUseSelectAll()
311-
{
312-
return [
313-
[
314-
[],
315-
'',
316-
],
317-
[
318-
[1],
319-
'1',
320-
],
321-
[
322-
[1, 2, 3],
323-
'1,2,3',
324-
],
325-
];
326-
}
327-
328272
/**
329273
* @param string $itemId
330274
* @param array|\Magento\Framework\DataObject $item

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

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -195,25 +195,6 @@ public function execute()
195195
? $model->getAttributeCode()
196196
: $this->getRequest()->getParam('attribute_code');
197197
$attributeCode = $attributeCode ?: $this->generateCode($this->getRequest()->getParam('frontend_label')[0]);
198-
if (strlen($attributeCode) > 0) {
199-
$validatorAttrCode = new \Zend_Validate_Regex(
200-
['pattern' => '/^[a-zA-Z\x{600}-\x{6FF}][a-zA-Z\x{600}-\x{6FF}_0-9]{0,30}$/u']
201-
);
202-
if (!$validatorAttrCode->isValid($attributeCode)) {
203-
$this->messageManager->addErrorMessage(
204-
__(
205-
'Attribute code "%1" is invalid. Please use only letters (a-z or A-Z), ' .
206-
'numbers (0-9) or underscore(_) in this field, first character should be a letter.',
207-
$attributeCode
208-
)
209-
);
210-
return $this->returnResult(
211-
'catalog/*/edit',
212-
['attribute_id' => $attributeId, '_current' => true],
213-
['error' => true]
214-
);
215-
}
216-
}
217198
$data['attribute_code'] = $attributeCode;
218199

219200
//validate frontend_input

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

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@
77

88
namespace Magento\Catalog\Controller\Adminhtml\Product\Attribute;
99

10-
use Magento\Framework\Serialize\Serializer\FormData;
10+
use Magento\Catalog\Controller\Adminhtml\Product\Attribute as AttributeAction;
11+
use Magento\Eav\Model\Validator\Attribute\Code as AttributeCodeValidator;
1112
use Magento\Framework\App\Action\HttpGetActionInterface;
1213
use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface;
1314
use Magento\Framework\App\ObjectManager;
1415
use Magento\Framework\DataObject;
15-
use Magento\Catalog\Controller\Adminhtml\Product\Attribute as AttributeAction;
16+
use Magento\Framework\Serialize\Serializer\FormData;
1617

1718
/**
1819
* Product attribute validate controller.
@@ -43,6 +44,11 @@ class Validate extends AttributeAction implements HttpGetActionInterface, HttpPo
4344
*/
4445
private $formDataSerializer;
4546

47+
/**
48+
* @var AttributeCodeValidator
49+
*/
50+
private $attributeCodeValidator;
51+
4652
/**
4753
* Constructor
4854
*
@@ -54,6 +60,7 @@ class Validate extends AttributeAction implements HttpGetActionInterface, HttpPo
5460
* @param \Magento\Framework\View\LayoutFactory $layoutFactory
5561
* @param array $multipleAttributeList
5662
* @param FormData|null $formDataSerializer
63+
* @param AttributeCodeValidator|null $attributeCodeValidator
5764
*/
5865
public function __construct(
5966
\Magento\Backend\App\Action\Context $context,
@@ -63,14 +70,18 @@ public function __construct(
6370
\Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
6471
\Magento\Framework\View\LayoutFactory $layoutFactory,
6572
array $multipleAttributeList = [],
66-
FormData $formDataSerializer = null
73+
FormData $formDataSerializer = null,
74+
AttributeCodeValidator $attributeCodeValidator = null
6775
) {
6876
parent::__construct($context, $attributeLabelCache, $coreRegistry, $resultPageFactory);
6977
$this->resultJsonFactory = $resultJsonFactory;
7078
$this->layoutFactory = $layoutFactory;
7179
$this->multipleAttributeList = $multipleAttributeList;
7280
$this->formDataSerializer = $formDataSerializer ?: ObjectManager::getInstance()
7381
->get(FormData::class);
82+
$this->attributeCodeValidator = $attributeCodeValidator ?: ObjectManager::getInstance()->get(
83+
AttributeCodeValidator::class
84+
);
7485
}
7586

7687
/**
@@ -115,6 +126,12 @@ public function execute()
115126
$response->setError(true);
116127
$response->setProductAttribute($attribute->toArray());
117128
}
129+
130+
if (!$this->attributeCodeValidator->isValid($attributeCode)) {
131+
$this->setMessageToResponse($response, $this->attributeCodeValidator->getMessages());
132+
$response->setError(true);
133+
}
134+
118135
if ($this->getRequest()->has('new_attribute_set_name')) {
119136
$setName = $this->getRequest()->getParam('new_attribute_set_name');
120137
/** @var $attributeSet \Magento\Eav\Model\Entity\Attribute\Set */

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ public function execute()
159159
if ($redirectBack === 'duplicate') {
160160
$product->unsetData('quantity_and_stock_status');
161161
$newProduct = $this->productCopier->copy($product);
162+
$this->checkUniqueAttributes($product);
162163
$this->messageManager->addSuccessMessage(__('You duplicated the product.'));
163164
}
164165
} catch (\Magento\Framework\Exception\LocalizedException $e) {
@@ -343,4 +344,25 @@ private function persistMediaData(ProductInterface $product, array $data)
343344

344345
return $data;
345346
}
347+
348+
/**
349+
* Check unique attributes and add error to message manager
350+
*
351+
* @param \Magento\Catalog\Model\Product $product
352+
*/
353+
private function checkUniqueAttributes(\Magento\Catalog\Model\Product $product)
354+
{
355+
$uniqueLabels = [];
356+
foreach ($product->getAttributes() as $attribute) {
357+
if ($attribute->getIsUnique() && $attribute->getIsUserDefined()
358+
&& $product->getData($attribute->getAttributeCode()) !== null
359+
) {
360+
$uniqueLabels[] = $attribute->getDefaultFrontendLabel();
361+
}
362+
}
363+
if ($uniqueLabels) {
364+
$uniqueLabels = implode('", "', $uniqueLabels);
365+
$this->messageManager->addErrorMessage(__('The value of attribute(s) "%1" must be unique', $uniqueLabels));
366+
}
367+
}
346368
}

app/code/Magento/Catalog/Model/Product/ProductFrontendAction/Synchronizer.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ private function getProductIdsByActions(array $actions)
143143
$productIds = [];
144144

145145
foreach ($actions as $action) {
146-
if (isset($action['product_id']) && is_int($action['product_id'])) {
146+
if (isset($action['product_id'])) {
147147
$productIds[] = $action['product_id'];
148148
}
149149
}

app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCustomProductAttributeWithDropdownFieldTest.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
<severity value="CRITICAL"/>
1717
<testCaseId value="MC-10905"/>
1818
<group value="mtf_migrated"/>
19+
<skip>
20+
<issueId value="MC-15474"/>
21+
</skip>
1922
</annotations>
2023

2124
<before>

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
use Magento\Catalog\Api\Data\ProductAttributeInterface;
99
use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save;
10+
use Magento\Eav\Model\Validator\Attribute\Code as AttributeCodeValidator;
1011
use Magento\Framework\Serialize\Serializer\FormData;
1112
use Magento\Catalog\Test\Unit\Controller\Adminhtml\Product\AttributeTest;
1213
use Magento\Catalog\Model\Product\AttributeSet\BuildFactory;
@@ -94,6 +95,11 @@ class SaveTest extends AttributeTest
9495
*/
9596
private $productAttributeMock;
9697

98+
/**
99+
* @var AttributeCodeValidator|\PHPUnit_Framework_MockObject_MockObject
100+
*/
101+
private $attributeCodeValidatorMock;
102+
97103
protected function setUp()
98104
{
99105
parent::setUp();
@@ -138,6 +144,9 @@ protected function setUp()
138144
$this->formDataSerializerMock = $this->getMockBuilder(FormData::class)
139145
->disableOriginalConstructor()
140146
->getMock();
147+
$this->attributeCodeValidatorMock = $this->getMockBuilder(AttributeCodeValidator::class)
148+
->disableOriginalConstructor()
149+
->getMock();
141150
$this->productAttributeMock = $this->getMockBuilder(ProductAttributeInterface::class)
142151
->setMethods(['getId', 'get'])
143152
->getMockForAbstractClass();
@@ -171,6 +180,7 @@ protected function getModel()
171180
'groupCollectionFactory' => $this->groupCollectionFactoryMock,
172181
'layoutFactory' => $this->layoutFactoryMock,
173182
'formDataSerializer' => $this->formDataSerializerMock,
183+
'attributeCodeValidator' => $this->attributeCodeValidatorMock
174184
]);
175185
}
176186

@@ -224,6 +234,10 @@ public function testExecute()
224234
$this->productAttributeMock
225235
->method('getAttributeCode')
226236
->willReturn('test_code');
237+
$this->attributeCodeValidatorMock
238+
->method('isValid')
239+
->with('test_code')
240+
->willReturn(true);
227241
$this->requestMock->expects($this->once())
228242
->method('getPostValue')
229243
->willReturn($data);

0 commit comments

Comments
 (0)