How to export additional images for products

Many people have described how to import additional images in Magento store. The question often arises as to how export additional images for products in Magento store.

Magento’s architecture is module-based, which means that you can easily modify existing and add new functions by creating your own modules.

Used example
For this howto, I will create a module that overrides the “unparse()” function, which returns the csv Data for a export products. This module has been written for Magento 1.4 but should work on 1.3 as well. This will NOT work on version 1.7.x. It was written for 1.4 and I have yet to write an updated version. Sorry.

1. Create directories

First of all, you need to create some directory structure that will hold your module files. Go to /app/code/local and create a directory representing your’s or your company’s name. All your modules will go into that directory. I will use this for the example:
/app/code/local/CDL.
Now we need to create the module directory. The module directory represents the name your module gets. I will use:
/app/code/local/CDL/Export in this example.
Every module needs a configuration file. This file is located under the etc/ subdirectory, so you need to create that directory as well. In my example it is:
/app/code/local/CDL/Export/etc.

The last needed directory is the Model/ subdirectory. I will explain what this is for later.

2. Config File

Now that we have all the directories we need, we can create a new file named config.xml inside the etc/ directory. This file will be used by the Magento module system to know what your module does and where the needed files are located. Here is the config.xml that we will need for our example:
[sourcecode language=”xml”]
<?xml version="1.0"?>
<config>
<modules>
<CDL_Export>
<version>0.1.0</version>
</CDL_Export>
</modules>
<global>
<models>
<dataflow>
<rewrite>
<convert_parser_csv>CDL_Export_Model_Export</convert_parser_csv>
</rewrite>
</dataflow>
</models>
</global>
</config>
[/sourcecode]

As you can see, we will override the “Convert/Parser/Csv.php” model inside the “Dataflow” Module. Note that the underscores in represent the directory structure the core model is in. This is the same with CDL_Export_Model_Export, which points to CDL/Export/Model/Export.php.

3. Create the Model

Now we need to create the model. As you can see in the config.xml file, we have to create a new file named Export.php in the Model/ subdirectory. Here is the content of the file:

[sourcecode language=”php”]
class CDL_Export_Model_Export extends Mage_Dataflow_Model_Convert_Parser_Abstract
{
protected $_fields;
protected $_mapfields = array();
public function parse()
{
// fixed for multibyte characters
setlocale(LC_ALL, Mage::app()->getLocale()->getLocaleCode().’.UTF-8′);
$fDel = $this->getVar(‘delimiter’, ‘,’);
$fEnc = $this->getVar(‘enclose’, ‘"’);
if ($fDel == ‘\t’) {
$fDel = "\t";
}
$adapterName = $this->getVar(‘adapter’, null);
$adapterMethod = $this->getVar(‘method’, ‘saveRow’);
if (!$adapterName || !$adapterMethod) {
$message = Mage::helper(‘dataflow’)->__(‘Please declare "adapter" and "method" node first’);
$this->addException($message, Mage_Dataflow_Model_Convert_Exception::FATAL);
return $this;
}
try {
$adapter = Mage::getModel($adapterName);
}
catch (Exception $e) {
$message = Mage::helper(‘dataflow’)->__(‘Declared adapter %s not found’, $adapterName);
$this->addException($message, Mage_Dataflow_Model_Convert_Exception::FATAL);
return $this;
}
if (!is_callable(array($adapter, $adapterMethod))) {
$message = Mage::helper(‘dataflow’)->__(‘Method "%s" not defined in adapter %s’, $adapterMethod, $adapterName);
$this->addException($message, Mage_Dataflow_Model_Convert_Exception::FATAL);
return $this;
}
$batchModel = $this->getBatchModel();
$batchIoAdapter = $this->getBatchModel()->getIoAdapter();
if (Mage::app()->getRequest()->getParam(‘files’)) {
$file = Mage::app()->getConfig()->getTempVarDir().’/import/’
. urldecode(Mage::app()->getRequest()->getParam(‘files’));
$this->_copy($file);
}
$batchIoAdapter->open(false);
$isFieldNames = $this->getVar(‘fieldnames’, ”) == ‘true’ ? true : false;
if (!$isFieldNames && is_array($this->getVar(‘map’))) {
$fieldNames = $this->getVar(‘map’);
}
else {
$fieldNames = array();
foreach ($batchIoAdapter->read(true, $fDel, $fEnc) as $v) {
$fieldNames[$v] = $v;
}
}
$countRows = 0;
while (($csvData = $batchIoAdapter->read(true, $fDel, $fEnc)) !== false) {
if (count($csvData) == 1 && $csvData[0] === null) {
continue;
}
$itemData = array();
$countRows ++; $i = 0;
foreach ($fieldNames as $field) {
$itemData[$field] = isset($csvData[$i]) ? $csvData[$i] : null;
$i ++;
}
$batchImportModel = $this->getBatchImportModel()
->setId(null)
->setBatchId($this->getBatchModel()->getId())
->setBatchData($itemData)
->setStatus(1)
->save();
}
$this->addException(Mage::helper(‘dataflow’)->__(‘Found %d rows’, $countRows));
$this->addException(Mage::helper(‘dataflow’)->__(‘Starting %s :: %s’, $adapterName, $adapterMethod));
$batchModel->setParams($this->getVars())
->setAdapter($adapterName)
->save();
//$adapter->$adapterMethod();
return $this;
// // fix for field mapping
// if ($mapfields = $this->getProfile()->getDataflowProfile()) {
// $this->_mapfields = array_values($mapfields[‘gui_data’][‘map’][$mapfields[‘entity_type’]][‘db’]);
// } // end
//
// if (!$this->getVar(‘fieldnames’) && !$this->_mapfields) {
// $this->addException(‘Please define field mapping’, Mage_Dataflow_Model_Convert_Exception::FATAL);
// return;
// }
//
// if ($this->getVar(‘adapter’) && $this->getVar(‘method’)) {
// $adapter = Mage::getModel($this->getVar(‘adapter’));
// }
//
// $i = 0;
// while (($line = fgetcsv($fh, null, $fDel, $fEnc)) !== FALSE) {
// $row = $this->parseRow($i, $line);
//
// if (!$this->getVar(‘fieldnames’) && $i == 0 && $row) {
// $i = 1;
// }
//
// if ($row) {
// $loadMethod = $this->getVar(‘method’);
// $adapter->$loadMethod(compact(‘i’, ‘row’));
// }
// $i++;
// }
//
// return $this;
}
public function parseRow($i, $line)
{
if (sizeof($line) == 1) return false;
if (0==$i) {
if ($this->getVar(‘fieldnames’)) {
$this->_fields = $line;
return;
} else {
foreach ($line as $j=>$f) {
// $this->_fields[$j] = ‘column’.($j+1);
$this->_fields[$j] = $this->_mapfields[$j];
}
}
}
$resultRow = array();
foreach ($this->_fields as $j=>$f) {
$resultRow[$f] = isset($line[$j]) ? $line[$j] : ”;
}
return $resultRow;
}
/**
* Read data collection and write to temporary file
*
* @return Mage_Dataflow_Model_Convert_Parser_Csv
*/
public function unparse()
{
$batchExport = $this->getBatchExportModel()
->setBatchId($this->getBatchModel()->getId());
$fieldList = $this->getBatchModel()->getFieldList();
/* CDL Export start*/
$fieldList[‘gallery’] = ‘gallery’;
/* CDL Export finish*/
$batchExportIds = $batchExport->getIdCollection();
if (!$batchExportIds) {
return $this;
}
$io = $this->getBatchModel()->getIoAdapter();
$io->open();
if ($this->getVar(‘fieldnames’)) {
$csvData = $this->getCsvString($fieldList);
$io->write($csvData);
}
foreach ($batchExportIds as $batchExportId) {
$csvData = array();
$batchExport->load($batchExportId);
$row = $batchExport->getBatchData();
/* CDL Export start*/
$productid = Mage::getModel(‘catalog/product’)->getIdBySku($row[‘sku’]);
// Initiate product model
$product = Mage::getModel(‘catalog/product’);
// Load specific product whose tier price want to update
$product->load($productid);
$mediaGallery = $product->getMediaGallery();
$mediaGallery = $mediaGallery[‘images’];
$add_images = ”;
foreach ($mediaGallery as $add_image) {
if (!$add_image[‘disabled’]){
$add_images .= $add_image[‘file’].’;’;
}
}
// Remove last ‘;’ from images list
$add_images = substr_replace($add_images ,"",-1);

$row[‘gallery’] = $add_images;
/* CDL Export finish*/
foreach ($fieldList as $field) {
$csvData[] = isset($row[$field]) ? $row[$field] : ”;
}
$csvData = $this->getCsvString($csvData);
$io->write($csvData);
}
$io->close();
return $this;
}
public function unparseRow($args)
{
$i = $args[‘i’];
$row = $args[‘row’];
$fDel = $this->getVar(‘delimiter’, ‘,’);
$fEnc = $this->getVar(‘enclose’, ‘"’);
$fEsc = $this->getVar(‘escape’, ‘\\’);
$lDel = "\r\n";
if ($fDel == ‘\t’) {
$fDel = "\t";
}
$line = array();
foreach ($this->_fields as $f) {
$v = isset($row[$f]) ? str_replace(array(‘"’, ‘\\’), array($fEnc.’"’, $fEsc.’\\’), $row[$f]) : ”;
$line[] = $fEnc.$v.$fEnc;
}
return join($fDel, $line);
}
/**
* Retrieve csv string from array
*
* @param array $fields
* @return sting
*/
public function getCsvString($fields = array()) {
$delimiter = $this->getVar(‘delimiter’, ‘,’);
$enclosure = $this->getVar(‘enclose’, ”);
$escapeChar = $this->getVar(‘escape’, ‘\\’);
if ($delimiter == ‘\t’) {
$delimiter = "\t";
}
$str = ”;
foreach ($fields as $value) {
if (strpos($value, $delimiter) !== false ||
empty($enclosure) ||
strpos($value, $enclosure) !== false ||
strpos($value, "\n") !== false ||
strpos($value, "\r") !== false ||
strpos($value, "\t") !== false ||
strpos($value, ‘ ‘) !== false) {
$str2 = $enclosure;
$escaped = 0;
$len = strlen($value);
for ($i=0;$i<$len;$i++) {
if ($value[$i] == $escapeChar) {
$escaped = 1;
} else if (!$escaped && $value[$i] == $enclosure) {
$str2 .= $enclosure;
} else {
$escaped = 0;
}
$str2 .= $value[$i];
}
$str2 .= $enclosure;
$str .= $str2.$delimiter;
} else {
$str .= $enclosure.$value.$enclosure.$delimiter;
}
}
return substr($str, 0, -1) . "\n";
}
}
[/sourcecode]

As you can see, we create a new model class which extends the core model class. that means your new class will have all the properties and functions the core class has. all functions you put in your class will be used instead of the core classes functions, and your can also add completely new functions to it. For now we changed the unparse() function, so it will return additional images for products (during Export Products).

4. Load your module

Now we finished our module, but Magento doesn’t know of it’s existence yet. We have to create a file in /app/etc/Modules that loads our module. Name that file CDL_Export.xml and put this in it:

[sourcecode language=”xml”]
<?xml version="1.0"?>
<config>
<modules>
<CDL_Export>
<active>true</active>
<codePool>local</codePool>
</CDL_Export>
</modules>
</config>
[/sourcecode]

All xml files inside /app/etc/Modules will be loaded automatically. By placing the above file in that directory, Magento will know that is has to look for a config.xml in /app/code/local/CDL/Export/etc and load your module.

Step 4

Test it out! Please clear cash before. This is how it works: Use the Magento product export functionality (Admin >> System >> Import/Export >> Profiles >> Export All Products). Check your file. You can see, we added a column ”gallery” and pictures are separated with “;”