Kurzinfo


Andreas von Studnitz

mehr »

Andreas von Studnitz arbeitet seit 2012 als Geschäftsführer und Entwickler für die Magento-Agentur integer_net GmbH. Aktuelle Informationen finden Sie unter www.integer-net.de

Kontakt

Bitte kontaktieren Sie mich über die Website von integer_net.

mehr »

< Magento-Module deaktivieren - the right way

Magento ImportExport: Der Visibility-Bug

18.06.2012 10:35

Die Sichtbarkeit ("visility") wird beim Produktupdate gesetzt, obwohl sie in den Importdaten nicht enthalten ist? Schuld ist ein Bug in Magento, für den ich hier einen Fix bereit stelle.

Beim Produktimport mit der ImportExport-Schnittstelle von Magento (seit 1.5 CE bzw. 1.10 EE) gibt es mit manchen Attributen Probleme, wenn diese in den Importdaten nicht enthalten sind. Unter folgenden Bedingungen tritt das Problem auf:

  • Das Produkt wird aktualisiert, nicht neu angelegt
  • Eine Spalte mit dem Attribut fehlt oder ist leer für das fragliche Produkt
  • Das Attribut hat einen Standardwert (neben "visibility" betrifft das im Magento-Standard nur weniger genutzte Attribute, wie "enable_googlecheckout", "links_exist", "msrp_enabled", "msrp_display_actual_price_type" und "options_container")

Die Schnittstelle prüft in allen Fällen, in denen es für ein Attribut keine Importdaten gibt, ob es einen Standardwert gibt. Ist dies der Fall, so wird dieser gesetzt. Der Bug besteht darin, dass dies auch beim Aktualisieren eines Produktes passiert (wenn z.B. nur der Lagerbestand oder der Preis aktualisiert wird), wo das Produkt bereits einen Attributwert hat, und nicht nur beim Neuanlegen.

Der zum Beheben des Bugs zu ändernde Code befindet sich in der Klasse Mage_ImportExport_Model_Import_Entity_Product_Type_Abstract, Methode prepareAttributesForSave. Diese Methode kann wie folgt ersetzt werden:

/**
* Prepare attributes values for save: remove non-existent, remove empty values, remove static.
*
* @param array $rowData
* @return array
*/
public function prepareAttributesForSave(array $rowData)
{
$resultAttrs = array();

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];
} elseif (null !== $attrParams['default_value']) {
if ($this->_isSkuNew($rowData['sku'])) {
$resultAttrs[$attrCode] = $attrParams['default_value'];
}
}
}
}
return $resultAttrs;
}

/**
* Check if the given sku belongs to a new product or an existing one
*
* @param $sku
* @return bool
*/
protected function _isSkuNew($sku)
{
$oldSkus = $this->_entityModel->getOldSku();
return !isset($oldSkus[$sku]);
}

Für eine saubere, updatefähige Lösung ohne Überschreiben von kompletten Core-Dateien reicht ein Rewrite leider nicht aus, da es sich um eine abstrakte Klasse handelt. Stattdessen müssen alle drei davon abgeleiteten Klassen überschreiben werden. Das passiert entweder über einen "normalen" Rewrite von

  • importexport/import_entity_product_type_simple
  • importexport/import_entity_product_type_configurable
  • importexport/import_entity_product_type_grouped

oder durch ein Überschreiben der Klassen für die einzelnen Produkttypen in der config.xml. Das sieht dann z.B. wie folgt aus:

<global>
[...]
<importexport>
<import_product_types>
<simple>fastsimpleimport/import_entity_product_type_simple</simple>
<configurable>fastsimpleimport/import_entity_product_type_configurable</configurable>
<virtual>fastsimpleimport/import_entity_product_type_simple</virtual>
<grouped>fastsimpleimport/import_entity_product_type_grouped</grouped>
</import_product_types>
</importexport>
</global>

Das Modul mit dem Model-Shortcut "fastsimpleimport" enthält dabei die neuen Klassen, die jeweils von den alten ableiten.

Anschließend muss der Cache geleert werden.

Eine entsprechende Lösung habe ich in meinem Modul AvS_FastSimpleImport, das im Prinzip ein ArrayAdapter für ImportExport ist, umgesetzt. Auch werde ich die Lösung Magento als Contributor zur Verfügung stellen.

Kommentare