Skip to content

Commit

Permalink
Merge pull request #564 from magento-troll/MAGETWO-41796
Browse files Browse the repository at this point in the history
[Merchant Beta] MAGETWO-41796: Unable to import or export products with multi-select attributes
  • Loading branch information
Slabko,Michael(mslabko) committed Sep 2, 2015
2 parents 1bc2180 + 5d19555 commit 5202113
Show file tree
Hide file tree
Showing 9 changed files with 335 additions and 145 deletions.
12 changes: 10 additions & 2 deletions app/code/Magento/CatalogImportExport/Model/Export/Product.php
Original file line number Diff line number Diff line change
Expand Up @@ -880,8 +880,16 @@ protected function collectRawData()
ImportProduct::PAIR_NAME_VALUE_SEPARATOR . $attrValue;
}
$data[$itemId][$storeId][$fieldName] = $attrValue;
} else {
$this->collectMultiselectValues($item, $code, $storeId);
}
} else {
$this->collectMultiselectValues($item, $code, $storeId);
if (!empty($this->collectedMultiselectsData[$storeId][$itemId][$code])) {
$additionalAttributes[$code] = $fieldName
. ImportProduct::PAIR_NAME_VALUE_SEPARATOR
. implode(
ImportProduct::PSEUDO_MULTI_LINE_SEPARATOR,
$this->collectedMultiselectsData[$storeId][$itemId][$code]
);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,22 @@ public function getParams();
* @return mixed
*/
public function getParam($name);

/**
* Get product type by name
*
* @param string $type
*
* @return mixed
*/
public function retrieveProductTypeByName($type);

/**
* Get message template
*
* @param string $templateName
*
* @return mixed
*/
public function retrieveMessageTemplate($templateName);
}
77 changes: 23 additions & 54 deletions app/code/Magento/CatalogImportExport/Model/Import/Product.php
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,10 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity i
ValidatorInterface::ERROR_SUPER_PRODUCTS_SKU_NOT_FOUND => 'Product with specified super products SKU not found',
ValidatorInterface::ERROR_MEDIA_DATA_INCOMPLETE => 'Media data is incomplete',
ValidatorInterface::ERROR_INVALID_WEIGHT => 'Product weight is invalid',
ValidatorInterface::ERROR_EXCEEDED_MAX_LENGTH => 'Attribute %s exceeded max length',
ValidatorInterface::ERROR_INVALID_ATTRIBUTE_TYPE => 'Value for \'%s\' attribute contains incorrect value, acceptable values are in %s format',
ValidatorInterface::ERROR_DUPLICATE_UNIQUE_ATTRIBUTE => 'Duplicated unique attribute',
ValidatorInterface::ERROR_INVALID_ATTRIBUTE_OPTION => 'Value for \'%s\' attribute contains incorrect value, see acceptable values on settings specified for Admin',
];

/**
Expand All @@ -236,8 +240,6 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity i
protected $_fieldsMap = [
'image' => 'base_image',
'image_label' => "base_image_label",
'image' => 'base_image',
'image_label' => 'base_image_label',
'thumbnail' => 'thumbnail_image',
'thumbnail_label' => 'thumbnail_image_label',
self::COL_MEDIA_IMAGE => 'additional_images',
Expand Down Expand Up @@ -670,53 +672,17 @@ public function __construct(
* @param array $attrParams Attribute params
* @param array $rowData Row data
* @param int $rowNum
*
* @return boolean
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @return bool
*/
public function isAttributeValid($attrCode, array $attrParams, array $rowData, $rowNum)
{
switch ($attrParams['type']) {
case 'varchar':
$val = $this->string->cleanString($rowData[$attrCode]);
$valid = $this->string->strlen($val) < self::DB_MAX_VARCHAR_LENGTH;
break;
case 'decimal':
$val = trim($rowData[$attrCode]);
$valid = is_numeric($val);
break;
case 'select':
case 'multiselect':
$valid = isset($attrParams['options'][strtolower($rowData[$attrCode])]);
break;
case 'int':
$val = trim($rowData[$attrCode]);
$valid = (string)(int)$val === $val;
break;
case 'datetime':
$val = trim($rowData[$attrCode]);
$valid = strtotime($val) !== false;
break;
case 'text':
$val = $this->string->cleanString($rowData[$attrCode]);
$valid = $this->string->strlen($val) < self::DB_MAX_TEXT_LENGTH;
break;
default:
$valid = true;
break;
}

if (!$valid) {
$this->addRowError(__("Please correct the value for '%s'."), $rowNum, $attrCode);
} elseif (!empty($attrParams['is_unique'])) {
if (isset($this->_uniqueAttributes[$attrCode][$rowData[$attrCode]]) && ($this->_uniqueAttributes[$attrCode][$rowData[$attrCode]] != $rowData[self::COL_SKU])) {
$this->addRowError(__("Duplicate Unique Attribute for '%s'"), $rowNum, $attrCode);
return false;
if (!$this->validator->isAttributeValid($attrCode, $attrParams, $rowData)) {
foreach ($this->validator->getMessages() as $message) {
$this->addRowError($message, $rowNum, $attrCode);
}
$this->_uniqueAttributes[$attrCode][$rowData[$attrCode]] = $rowData[self::COL_SKU];
return false;
}
return (bool)$valid;
return true;
}

/**
Expand Down Expand Up @@ -1571,16 +1537,7 @@ protected function _saveProducts()
}
}
foreach ($storeIds as $storeId) {
if ('multiselect' == $attribute->getFrontendInput()) {
if (!isset($attributes[$attrTable][$rowSku][$attrId][$storeId])) {
$attributes[$attrTable][$rowSku][$attrId][$storeId] = '';
} else {
$attributes[$attrTable][$rowSku][$attrId][$storeId] .= ',';
}
$attributes[$attrTable][$rowSku][$attrId][$storeId] .= $attrValue;
} else {
$attributes[$attrTable][$rowSku][$attrId][$storeId] = $attrValue;
}
$attributes[$attrTable][$rowSku][$attrId][$storeId] = $attrValue;
}
// restore 'backend_model' to avoid 'default' setting
$attribute->setBackendModel($backModel);
Expand Down Expand Up @@ -2310,4 +2267,16 @@ public function getParam($name)
{
return isset($this->_parameters[$name]) ? $this->_parameters[$name] : null;
}

/**
* @param string $name
* @return mixed
*/
public function retrieveProductTypeByName($name)
{
if (isset($this->_productTypeModels[$name])) {
return $this->_productTypeModels[$name];
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ interface RowValidatorInterface extends \Magento\Framework\Validator\ValidatorIn

const ERROR_INVALID_WEIGHT = 'invalidWeight';

const ERROR_EXCEEDED_MAX_LENGTH = 'exceededMaxLength';

const ERROR_INVALID_ATTRIBUTE_TYPE = 'invalidAttributeType';

const ERROR_DUPLICATE_UNIQUE_ATTRIBUTE = 'duplicatedUniqueAttribute';

const ERROR_INVALID_ATTRIBUTE_OPTION = 'absentAttributeOption';

/**
* Value that means all entities (e.g. websites, groups etc.)
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
*/
namespace Magento\CatalogImportExport\Model\Import\Product\Type;

use Magento\CatalogImportExport\Model\Import\Product;

/**
* Import entity abstract product type model
*
Expand All @@ -19,6 +21,13 @@ abstract class AbstractType
*/
public static $commonAttributesCache = [];

/**
* Attribute Code to Id cache
*
* @var array
*/
public static $attributeCodeToId = [];

/**
* Product type attribute sets and attributes parameters.
*
Expand Down Expand Up @@ -358,6 +367,16 @@ public function isRowValid(array $rowData, $rowNum, $isNewProduct = true)
// check value for non-empty in the case of required attribute?
if (isset($rowData[$attrCode]) && strlen($rowData[$attrCode])) {
$error |= !$this->_entityModel->isAttributeValid($attrCode, $attrParams, $rowData, $rowNum);
$resultAttrs[$attrCode] = 'select' == $attrParams['type'] ? $attrParams['options'][strtolower(
$rowData[$attrCode]
)] : $rowData[$attrCode];
if ('multiselect' == $attrParams['type']) {
$resultAttrs[$attrCode] = [];
foreach (explode('|', $rowData[$attrCode]) as $value) {
$resultAttrs[$attrCode][] = $attrParams['options'][strtolower($value)];
}
$resultAttrs[$attrCode] = implode(',', $resultAttrs[$attrCode]);
}
} elseif ($this->_isAttributeRequiredCheckNeeded($attrCode) && $attrParams['is_required']) {
// For the default scope - if this is a new product or
// for an old product, if the imported doc has the column present for the attrCode
Expand Down Expand Up @@ -412,10 +431,16 @@ public function prepareAttributesWithDefaultValueForSave(array $rowData, $withDe
foreach ($this->_getProductAttributes($rowData) as $attrCode => $attrParams) {
if (!$attrParams['is_static']) {
if (isset($rowData[$attrCode]) && strlen($rowData[$attrCode])) {
$resultAttrs[$attrCode] = 'select' == $attrParams['type'] ||
'multiselect' == $attrParams['type'] ? $attrParams['options'][strtolower(
$rowData[$attrCode]
)] : $rowData[$attrCode];
$resultAttrs[$attrCode] = 'select' == $attrParams['type']
? $attrParams['options'][strtolower($rowData[$attrCode])]
: $rowData[$attrCode];
if ('multiselect' == $attrParams['type']) {
$resultAttrs[$attrCode] = [];
foreach (explode(Product::PSEUDO_MULTI_LINE_SEPARATOR, $rowData[$attrCode]) as $value) {
$resultAttrs[$attrCode][] = $attrParams['options'][strtolower($value)];
}
$resultAttrs[$attrCode] = implode(',', $resultAttrs[$attrCode]);
}
} elseif (array_key_exists($attrCode, $rowData)) {
$resultAttrs[$attrCode] = $rowData[$attrCode];
} elseif ($withDefaultValue && null !== $attrParams['default_value']) {
Expand Down Expand Up @@ -452,4 +477,21 @@ public function saveData()
{
return $this;
}

/**
* Retrieve attribute from cache
*
* @param string $attributeCode
* @return mixed
*/
public function retrieveAttributeFromCache($attributeCode)
{
if (isset(self::$attributeCodeToId[$attributeCode])) {
$id = self::$attributeCodeToId[$attributeCode];
if (isset(self::$commonAttributesCache[$id])) {
return self::$commonAttributesCache[$id];
}
}
return [];
}
}
Loading

0 comments on commit 5202113

Please sign in to comment.