Skip to content

Commit 84295f7

Browse files
authored
Merge pull request #3814 from magento-tsg-csl3/2.2-develop-pr22
[TSG-CSL3] For 2.2 (pr22)
2 parents e895838 + ff983b7 commit 84295f7

File tree

13 files changed

+414
-202
lines changed

13 files changed

+414
-202
lines changed

app/code/Magento/Backend/Model/Session/Quote.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,8 @@ public function getQuote()
149149
$this->_quote = $this->quoteFactory->create();
150150
if ($this->getStoreId()) {
151151
if (!$this->getQuoteId()) {
152-
$this->_quote->setCustomerGroupId($this->groupManagement->getDefaultGroup()->getId());
152+
$customerGroupId = $this->groupManagement->getDefaultGroup($this->getStoreId())->getId();
153+
$this->_quote->setCustomerGroupId($customerGroupId);
153154
$this->_quote->setIsActive(false);
154155
$this->_quote->setStoreId($this->getStoreId());
155156

app/code/Magento/Backend/Test/Unit/Model/Session/QuoteTest.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,10 @@ public function testGetQuoteWithoutQuoteId()
267267
$cartInterfaceMock->expects($this->atLeastOnce())->method('getId')->willReturn($quoteId);
268268
$defaultGroup = $this->getMockBuilder(\Magento\Customer\Api\Data\GroupInterface::class)->getMock();
269269
$defaultGroup->expects($this->any())->method('getId')->will($this->returnValue($customerGroupId));
270-
$this->groupManagementMock->expects($this->any())->method('getDefaultGroup')->willReturn($defaultGroup);
270+
$this->groupManagementMock
271+
->method('getDefaultGroup')
272+
->with($storeId)
273+
->willReturn($defaultGroup);
271274

272275
$dataCustomerMock = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)
273276
->disableOriginalConstructor()

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

Lines changed: 77 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
67
namespace Magento\CatalogImportExport\Model\Import;
78

89
use Magento\Catalog\Model\Config as CatalogConfig;
910
use Magento\Catalog\Model\Product\Visibility;
1011
use Magento\CatalogImportExport\Model\Import\Product\MediaGalleryProcessor;
1112
use Magento\CatalogImportExport\Model\Import\Product\RowValidatorInterface as ValidatorInterface;
13+
use Magento\CatalogImportExport\Model\StockItemImporterInterface;
1214
use Magento\CatalogInventory\Api\Data\StockItemInterface;
1315
use Magento\Framework\App\Filesystem\DirectoryList;
1416
use Magento\Framework\Exception\LocalizedException;
@@ -638,6 +640,13 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
638640
*/
639641
private $_logger;
640642

643+
/**
644+
* "Duplicate multiselect values" error array key
645+
*
646+
* @var string
647+
*/
648+
private static $errorDuplicateMultiselectValues = 'duplicatedMultiselectValues';
649+
641650
/**
642651
* {@inheritdoc}
643652
*/
@@ -767,7 +776,6 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
767776
* @param CatalogConfig $catalogConfig
768777
* @param MediaGalleryProcessor $mediaProcessor
769778
* @param ProductRepositoryInterface|null $productRepository
770-
* @throws \Magento\Framework\Exception\LocalizedException
771779
*
772780
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
773781
*/
@@ -857,18 +865,18 @@ public function __construct(
857865
$string,
858866
$errorAggregator
859867
);
860-
$this->_optionEntity = isset(
861-
$data['option_entity']
862-
) ? $data['option_entity'] : $optionFactory->create(
863-
['data' => ['product_entity' => $this]]
864-
);
868+
$this->_optionEntity = $data['option_entity']
869+
?? $optionFactory->create(['data' => ['product_entity' => $this]]);
865870

866871
$this->_initAttributeSets()
867872
->_initTypeModels()
868873
->_initSkus();
869874
$this->validator->init($this);
870875
$this->productRepository = $productRepository ?? \Magento\Framework\App\ObjectManager::getInstance()
871876
->get(ProductRepositoryInterface::class);
877+
878+
$errorMessageText = __('Value for multiselect attribute %s contains duplicated values');
879+
$this->_messageTemplates[self::$errorDuplicateMultiselectValues] = $errorMessageText;
872880
}
873881

874882
/**
@@ -884,7 +892,7 @@ public function isAttributeValid($attrCode, array $attrParams, array $rowData, $
884892
{
885893
if (!$this->validator->isAttributeValid($attrCode, $attrParams, $rowData)) {
886894
foreach ($this->validator->getMessages() as $message) {
887-
$this->addRowError($message, $rowNum, $attrCode);
895+
$this->skipRow($rowNum, $message, ProcessingError::ERROR_LEVEL_NOT_CRITICAL, $attrCode);
888896
}
889897
return false;
890898
}
@@ -1592,7 +1600,7 @@ protected function _saveProducts()
15921600
if (!empty($rowData[self::URL_KEY])) {
15931601
// If url_key column and its value were in the CSV file
15941602
$rowData[self::URL_KEY] = $urlKey;
1595-
} else if ($this->isNeedToChangeUrlKey($rowData)) {
1603+
} elseif ($this->isNeedToChangeUrlKey($rowData)) {
15961604
// If url_key column was empty or even not declared in the CSV file but by the rules it is need to
15971605
// be setteed. In case when url_key is generating from name column we have to ensure that the bunch
15981606
// of products will pass for the event with url_key column.
@@ -1604,7 +1612,9 @@ protected function _saveProducts()
16041612
if (null === $rowSku) {
16051613
$this->getErrorAggregator()->addRowToSkip($rowNum);
16061614
continue;
1607-
} elseif (self::SCOPE_STORE == $rowScope) {
1615+
}
1616+
1617+
if (self::SCOPE_STORE == $rowScope) {
16081618
// set necessary data from SCOPE_DEFAULT row
16091619
$rowData[self::COL_TYPE] = $this->skuProcessor->getNewSku($rowSku)['type_id'];
16101620
$rowData['attribute_set_id'] = $this->skuProcessor->getNewSku($rowSku)['attr_set_id'];
@@ -1740,13 +1750,7 @@ protected function _saveProducts()
17401750
$uploadedImages[$columnImage] = $uploadedFile;
17411751
} else {
17421752
unset($rowData[$column]);
1743-
$this->addRowError(
1744-
ValidatorInterface::ERROR_MEDIA_URL_NOT_ACCESSIBLE,
1745-
$rowNum,
1746-
null,
1747-
null,
1748-
ProcessingError::ERROR_LEVEL_NOT_CRITICAL
1749-
);
1753+
$this->skipRow($rowNum, ValidatorInterface::ERROR_MEDIA_URL_NOT_ACCESSIBLE);
17501754
}
17511755
} else {
17521756
$uploadedFile = $uploadedImages[$columnImage];
@@ -2380,32 +2384,35 @@ public function validateRow(array $rowData, $rowNum)
23802384
// BEHAVIOR_DELETE and BEHAVIOR_REPLACE use specific validation logic
23812385
if (Import::BEHAVIOR_REPLACE == $this->getBehavior()) {
23822386
if (self::SCOPE_DEFAULT == $rowScope && !$this->isSkuExist($sku)) {
2383-
$this->addRowError(ValidatorInterface::ERROR_SKU_NOT_FOUND_FOR_DELETE, $rowNum);
2387+
$this->skipRow($rowNum, ValidatorInterface::ERROR_SKU_NOT_FOUND_FOR_DELETE);
23842388
return false;
23852389
}
23862390
}
23872391
if (Import::BEHAVIOR_DELETE == $this->getBehavior()) {
23882392
if (self::SCOPE_DEFAULT == $rowScope && !$this->isSkuExist($sku)) {
2389-
$this->addRowError(ValidatorInterface::ERROR_SKU_NOT_FOUND_FOR_DELETE, $rowNum);
2393+
$this->skipRow($rowNum, ValidatorInterface::ERROR_SKU_NOT_FOUND_FOR_DELETE);
23902394
return false;
23912395
}
23922396
return true;
23932397
}
23942398

2399+
// if product doesn't exist, need to throw critical error else all errors should be not critical.
2400+
$errorLevel = $this->getValidationErrorLevel($sku);
2401+
23952402
if (!$this->validator->isValid($rowData)) {
23962403
foreach ($this->validator->getMessages() as $message) {
2397-
$this->addRowError($message, $rowNum, $this->validator->getInvalidAttribute());
2404+
$this->skipRow($rowNum, $message, $errorLevel, $this->validator->getInvalidAttribute());
23982405
}
23992406
}
24002407

24012408
if (null === $sku) {
2402-
$this->addRowError(ValidatorInterface::ERROR_SKU_IS_EMPTY, $rowNum);
2409+
$this->skipRow($rowNum, ValidatorInterface::ERROR_SKU_IS_EMPTY, $errorLevel);
24032410
} elseif (false === $sku) {
2404-
$this->addRowError(ValidatorInterface::ERROR_ROW_IS_ORPHAN, $rowNum);
2411+
$this->skipRow($rowNum, ValidatorInterface::ERROR_ROW_IS_ORPHAN, $errorLevel);
24052412
} elseif (self::SCOPE_STORE == $rowScope
24062413
&& !$this->storeResolver->getStoreCodeToId($rowData[self::COL_STORE])
24072414
) {
2408-
$this->addRowError(ValidatorInterface::ERROR_INVALID_STORE, $rowNum);
2415+
$this->skipRow($rowNum, ValidatorInterface::ERROR_INVALID_STORE, $errorLevel);
24092416
}
24102417

24112418
// SKU is specified, row is SCOPE_DEFAULT, new product block begins
@@ -2420,19 +2427,15 @@ public function validateRow(array $rowData, $rowNum)
24202427
$this->prepareNewSkuData($sku)
24212428
);
24222429
} else {
2423-
$this->addRowError(ValidatorInterface::ERROR_TYPE_UNSUPPORTED, $rowNum);
2430+
$this->skipRow($rowNum, ValidatorInterface::ERROR_TYPE_UNSUPPORTED, $errorLevel);
24242431
}
24252432
} else {
24262433
// validate new product type and attribute set
2427-
if (!isset($rowData[self::COL_TYPE]) || !isset($this->_productTypeModels[$rowData[self::COL_TYPE]])) {
2428-
$this->addRowError(ValidatorInterface::ERROR_INVALID_TYPE, $rowNum);
2429-
} elseif (!isset(
2430-
$rowData[self::COL_ATTR_SET]
2431-
) || !isset(
2432-
$this->_attrSetNameToId[$rowData[self::COL_ATTR_SET]]
2433-
)
2434+
if (!isset($rowData[self::COL_TYPE], $this->_productTypeModels[$rowData[self::COL_TYPE]])) {
2435+
$this->skipRow($rowNum, ValidatorInterface::ERROR_INVALID_TYPE, $errorLevel);
2436+
} elseif (!isset($rowData[self::COL_ATTR_SET], $this->_attrSetNameToId[$rowData[self::COL_ATTR_SET]])
24342437
) {
2435-
$this->addRowError(ValidatorInterface::ERROR_INVALID_ATTR_SET, $rowNum);
2438+
$this->skipRow($rowNum, ValidatorInterface::ERROR_INVALID_ATTR_SET, $errorLevel);
24362439
} elseif (is_null($this->skuProcessor->getNewSku($sku))) {
24372440
$this->skuProcessor->addNewSku(
24382441
$sku,
@@ -2488,8 +2491,11 @@ public function validateRow(array $rowData, $rowNum)
24882491
ValidatorInterface::ERROR_DUPLICATE_URL_KEY,
24892492
$rowNum,
24902493
$rowData[self::COL_NAME],
2491-
$message
2492-
);
2494+
$message,
2495+
$errorLevel
2496+
)
2497+
->getErrorAggregator()
2498+
->addRowToSkip($rowNum);
24932499
}
24942500
}
24952501
}
@@ -2499,9 +2505,10 @@ public function validateRow(array $rowData, $rowNum)
24992505
$newFromTimestamp = strtotime($this->dateTime->formatDate($rowData[self::COL_NEW_FROM_DATE], false));
25002506
$newToTimestamp = strtotime($this->dateTime->formatDate($rowData[self::COL_NEW_TO_DATE], false));
25012507
if ($newFromTimestamp > $newToTimestamp) {
2502-
$this->addRowError(
2503-
ValidatorInterface::ERROR_NEW_TO_DATE,
2508+
$this->skipRow(
25042509
$rowNum,
2510+
ValidatorInterface::ERROR_NEW_TO_DATE,
2511+
$errorLevel,
25052512
$rowData[self::COL_NEW_TO_DATE]
25062513
);
25072514
}
@@ -3029,4 +3036,39 @@ private function retrieveProductBySku(string $sku)
30293036

30303037
return $product;
30313038
}
3039+
3040+
/**
3041+
* Add row as skipped
3042+
*
3043+
* @param int $rowNum
3044+
* @param string $errorCode Error code or simply column name
3045+
* @param string $errorLevel error level
3046+
* @param string|null $colName optional column name
3047+
* @return $this
3048+
*/
3049+
private function skipRow(
3050+
int $rowNum,
3051+
string $errorCode,
3052+
string $errorLevel = ProcessingError::ERROR_LEVEL_NOT_CRITICAL,
3053+
$colName = null
3054+
): self {
3055+
$this->addRowError($errorCode, $rowNum, $colName, null, $errorLevel);
3056+
$this->getErrorAggregator()
3057+
->addRowToSkip($rowNum);
3058+
3059+
return $this;
3060+
}
3061+
3062+
/**
3063+
* Returns errorLevel for validation
3064+
*
3065+
* @param string|bool|null $sku
3066+
* @return string
3067+
*/
3068+
private function getValidationErrorLevel($sku): string
3069+
{
3070+
return (!$this->isSkuExist($sku) && Import::BEHAVIOR_REPLACE !== $this->getBehavior())
3071+
? ProcessingError::ERROR_LEVEL_CRITICAL
3072+
: ProcessingError::ERROR_LEVEL_NOT_CRITICAL;
3073+
}
30323074
}

0 commit comments

Comments
 (0)