Skip to content

Commit d301755

Browse files
committed
ACP2E-2261: [Cloud] Product import fails with custom separator value
1 parent 22fb3bc commit d301755

File tree

2 files changed

+41
-26
lines changed

2 files changed

+41
-26
lines changed

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

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -938,7 +938,7 @@ public function __construct(
938938
$this->_optionEntity = $data['option_entity'] ??
939939
$optionFactory->create(['data' => ['product_entity' => $this]]);
940940
$this->skuStorage = $skuStorage ?? ObjectManager::getInstance()
941-
->get(SkuStorage::class);
941+
->get(SkuStorage::class);
942942
$this->_initAttributeSets()
943943
->_initTypeModels()
944944
->_initSkus()
@@ -948,7 +948,7 @@ public function __construct(
948948
$this->productRepository = $productRepository ?? ObjectManager::getInstance()
949949
->get(ProductRepositoryInterface::class);
950950
$this->stockItemProcessor = $stockItemProcessor ?? ObjectManager::getInstance()
951-
->get(StockItemProcessorInterface::class);
951+
->get(StockItemProcessorInterface::class);
952952
}
953953

954954
/**
@@ -2002,8 +2002,8 @@ private function saveProductMediaGalleryPhase(
20022002
private function saveProductAttributesPhase(
20032003
array $rowData,
20042004
int $rowScope,
2005-
&$previousType,
2006-
&$prevAttributeSet,
2005+
&$previousType,
2006+
&$prevAttributeSet,
20072007
array &$attributes
20082008
) : void {
20092009
$rowSku = $rowData[self::COL_SKU];
@@ -2836,7 +2836,7 @@ private function prepareNewSkuData($sku)
28362836
*
28372837
* @return array
28382838
*/
2839-
private function _parseAdditionalAttributes($rowData)
2839+
private function _parseAdditionalAttributes(array $rowData): array
28402840
{
28412841
if (empty($rowData['additional_attributes'])) {
28422842
return $rowData;
@@ -2846,7 +2846,7 @@ private function _parseAdditionalAttributes($rowData)
28462846
$rowData[mb_strtolower($key)] = $value;
28472847
}
28482848
} else {
2849-
$rowData = array_merge($rowData, $this->getAdditionalAttributes($rowData['additional_attributes']));
2849+
$rowData = array_merge($rowData, $this->getAdditionalAttributes($rowData));
28502850
}
28512851
return $rowData;
28522852
}
@@ -2860,14 +2860,14 @@ private function _parseAdditionalAttributes($rowData)
28602860
* codeN => valueN
28612861
* ]
28622862
*
2863-
* @param string $additionalAttributes Attributes data that will be parsed
2863+
* @param array $rowData
28642864
* @return array
28652865
*/
2866-
private function getAdditionalAttributes($additionalAttributes)
2866+
private function getAdditionalAttributes(array $rowData): array
28672867
{
28682868
return empty($this->_parameters[Import::FIELDS_ENCLOSURE])
2869-
? $this->parseAttributesWithoutWrappedValues($additionalAttributes)
2870-
: $this->parseAttributesWithWrappedValues($additionalAttributes);
2869+
? $this->parseAttributesWithoutWrappedValues($rowData['additional_attributes'], $rowData['product_type'])
2870+
: $this->parseAttributesWithWrappedValues($rowData['additional_attributes']);
28712871
}
28722872

28732873
/**
@@ -2881,9 +2881,10 @@ private function getAdditionalAttributes($additionalAttributes)
28812881
*
28822882
* @param string $attributesData Attributes data that will be parsed. It keeps data in format:
28832883
* code=value,code2=value2...,codeN=valueN
2884+
* @param string $productType
28842885
* @return array
28852886
*/
2886-
private function parseAttributesWithoutWrappedValues($attributesData)
2887+
private function parseAttributesWithoutWrappedValues(string $attributesData, string $productType): array
28872888
{
28882889
$attributeNameValuePairs = explode($this->getMultipleValueSeparator(), $attributesData);
28892890
$preparedAttributes = [];
@@ -2894,21 +2895,21 @@ private function parseAttributesWithoutWrappedValues($attributesData)
28942895
if (!$code) {
28952896
continue;
28962897
}
2897-
//concatenate attribute values with last used separator in case of array
2898-
if (is_array($preparedAttributes[$code])
2899-
&& str_contains($attributesData, self::PSEUDO_MULTI_LINE_SEPARATOR)) {
2900-
$preparedAttributes[$code] = implode(
2901-
self::PSEUDO_MULTI_LINE_SEPARATOR,
2902-
$preparedAttributes[$code]
2903-
);
2904-
}
29052898
$preparedAttributes[$code] .= $this->getMultipleValueSeparator() . $attributeData;
29062899
continue;
29072900
}
29082901
list($code, $value) = explode(self::PAIR_NAME_VALUE_SEPARATOR, $attributeData, 2);
29092902
$code = mb_strtolower($code);
2910-
if (str_contains($value, self::PSEUDO_MULTI_LINE_SEPARATOR)) {
2911-
$value = $this->parseMultiselectValues($value, self::PSEUDO_MULTI_LINE_SEPARATOR);
2903+
2904+
$entityTypeModel = $this->retrieveProductTypeByName($productType);
2905+
if ($entityTypeModel) {
2906+
$attrParams = $entityTypeModel->retrieveAttributeFromCache($code);
2907+
if (!empty($attrParams) && $attrParams['type'] == 'multiselect') {
2908+
$parsedValue = $this->parseMultiselectValues($value, self::PSEUDO_MULTI_LINE_SEPARATOR);
2909+
if (count($parsedValue) > 1) {
2910+
$value = $parsedValue;
2911+
}
2912+
}
29122913
}
29132914
$preparedAttributes[$code] = $value;
29142915
}

app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/ProductTest.php

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
use Magento\CatalogInventory\Api\StockConfigurationInterface;
2626
use Magento\CatalogInventory\Api\StockRegistryInterface;
2727
use Magento\CatalogInventory\Model\Spi\StockStateProviderInterface;
28+
use Magento\ConfigurableImportExport\Model\Import\Product\Type\Configurable;
2829
use Magento\Eav\Model\Config;
2930
use Magento\Eav\Model\Entity\Attribute\AbstractAttribute;
3031
use Magento\Eav\Model\Entity\Attribute\Set;
@@ -1471,19 +1472,32 @@ public function testGetImagesFromRow($rowData, $expectedResult): void
14711472
*/
14721473
public function testParseAttributesWithoutWrappedValuesWillReturnsLowercasedAttributeCodes(): void
14731474
{
1475+
$entityTypeModel = $this->createPartialMock(
1476+
Configurable::class,
1477+
['retrieveAttributeFromCache']
1478+
);
1479+
$entityTypeModel->expects($this->exactly(2))->method('retrieveAttributeFromCache')->willReturn([
1480+
'type' => 'multiselect'
1481+
]);
1482+
$importProduct = $this->getMockBuilder(Product::class)
1483+
->disableOriginalConstructor()
1484+
->onlyMethods(['retrieveProductTypeByName'])
1485+
->getMock();
1486+
$importProduct->expects($this->exactly(2))->method('retrieveProductTypeByName')->willReturn($entityTypeModel);
1487+
14741488
$attributesData = 'PARAM1=value1,param2=value2|value3';
14751489
$preparedAttributes = $this->invokeMethod(
1476-
$this->importProduct,
1490+
$importProduct,
14771491
'parseAttributesWithoutWrappedValues',
1478-
[$attributesData]
1492+
[$attributesData, 'configurable']
14791493
);
14801494

14811495
$this->assertArrayHasKey('param1', $preparedAttributes);
14821496
$this->assertEquals('value1', $preparedAttributes['param1']);
14831497

14841498
$this->assertArrayHasKey('param2', $preparedAttributes);
1485-
$this->assertTrue(in_array('value2', $preparedAttributes['param2']));
1486-
$this->assertTrue(in_array('value3', $preparedAttributes['param2']));
1499+
$this->assertEquals('value2', $preparedAttributes['param2'][0]);
1500+
$this->assertEquals('value3', $preparedAttributes['param2'][1]);
14871501

14881502
$this->assertArrayNotHasKey('PARAM1', $preparedAttributes);
14891503
}
@@ -1685,7 +1699,7 @@ public function productCategoriesDataProvider()
16851699
],
16861700
'catalog_category_product',
16871701
[
1688-
[2, 5],
1702+
[2, 5],
16891703
[
16901704
[
16911705
'product_id' => 2,

0 commit comments

Comments
 (0)