Magento2: CatalogImportExport doesn't support empty row values

Created on 17 Nov 2016  路  7Comments  路  Source: magento/magento2

If you have an attribute that has a value and you import an empty string because the value needs to be empty, the attribute will not be overwritten with the empty string.

Preconditions

  1. MG2.1.2
  2. PHP7.0

Steps to reproduce

  1. Enter a value for an attribute for a product through the backend of Magento
    (I'm using description as my example)
  2. Create an import csv and leave the column for the attribute blank
  3. Import the csv with Add/Update behaviour

Expected result

  1. Product attribute value should be empty

Actual result

  1. Product attribute keeps the previous value

This issue can be traced back to \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType where the clearEmptyData function unsets all empty rows.

public function clearEmptyData(array $rowData)
{
    foreach ($this->_getProductAttributes($rowData) as $attrCode => $attrParams) {
        if (!$attrParams['is_static'] && empty($rowData[$attrCode])) {
            unset($rowData[$attrCode]);
        }
    }
    return $rowData;
}

It is my opinion that support for empty rows should be allowed.
My suggested fix is adding a constant to the AbstractType class and set the row values that contain that constant value to an empty string. That way if the constant value is used in the import csv, the importer will know which fields are just empty and which fields contain empty values.

CONST EMPTY_ROW_VALUE = '__EMPTY__';

public function clearEmptyData(array $rowData)
{
    foreach ($this->_getProductAttributes($rowData) as $attrCode => $attrParams) {
        if (!$attrParams['is_static'] && empty($rowData[$attrCode])) {
            unset($rowData[$attrCode]);
            continue;
        }

        if ($rowData[$attrCode] === self::EMPTY_ROW_VALUE) {
            $rowData[$attrCode] = '';
        }
    }
    return $rowData;
}

It would be even better to allow for setting custom values for the EMPTY_ROW_VALUE constant through the backend.

ImportExport Clear Description Confirmed Format is valid Ready for Work Reproduced on 2.1.x Reproduced on 2.2.x Reproduced on 2.3.x bug report

Most helpful comment

Addendum to this;

If chosen to support the constant value, support should also be implemented in \Magento\CatalogImportExport\Model\Import\Product\Validator in the isAttributeValid function.
To allow for every type of attribute to have support for empty values, something like this should be added

...
if (!strlen(trim($rowData[$attrCode]))) {
    return true;
}

if ($rowData[$attrCode] === \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType::EMPTY_ROW_VALUE) {
    return true;
}

switch ($attrParams['type']) {
...

All 7 comments

Addendum to this;

If chosen to support the constant value, support should also be implemented in \Magento\CatalogImportExport\Model\Import\Product\Validator in the isAttributeValid function.
To allow for every type of attribute to have support for empty values, something like this should be added

...
if (!strlen(trim($rowData[$attrCode]))) {
    return true;
}

if ($rowData[$attrCode] === \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType::EMPTY_ROW_VALUE) {
    return true;
}

switch ($attrParams['type']) {
...

@koenner01 thank you for your feedback.
Internal issue created: MAGETWO-61593

I have found a problem when using the empty logic;

If you try to import an empty value '' for a product's special_price, it will result in special_price 0.

The problem is an insert being doing in \Magento\CatalogImportExport\Model\Import\Product in function _saveProductAttributes:

protected function _saveProductAttributes(array $attributesData)
{
    foreach ($attributesData as $tableName => $skuData) {
        $tableData = [];
        foreach ($skuData as $sku => $attributes) {
            $linkId = $this->_connection->fetchOne(
                $this->_connection->select()
                    ->from($this->getResource()->getTable('catalog_product_entity'))
                    ->where('sku = ?', $sku)
                    ->columns($this->getProductEntityLinkField())
            );

            foreach ($attributes as $attributeId => $storeValues) {
                foreach ($storeValues as $storeId => $storeValue) {
                    $tableData[] = [
                        $this->getProductEntityLinkField() => $linkId,
                        'attribute_id' => $attributeId,
                        'store_id' => $storeId,
                        'value' => $storeValue,
                    ];
                }
            }
        }
        $this->_connection->insertOnDuplicate($tableName, $tableData, ['value']);
    }
    return $this;
}

If an empty string value is being inserted into the entity_int or entity_decimal tables they result into value 0.

Another issue in the same clearEmptyData function https://github.com/magento/magento2/issues/10006

Any update on this from the Magento team?

@koenner01, thank you for your report.
We've created internal ticket(s) MAGETWO-61593 to track progress on the issue.

This issue was moved to magento-engcom/import-export-improvements#49

Was this page helpful?
0 / 5 - 0 ratings