Files
PrestaShop/controllers/admin/AdminImportController.php
Rémi Gaillard e7286c44f2 // typo
2013-09-18 18:08:22 +02:00

889 lines
32 KiB
PHP

<?php
/*
* 2007-2013 PrestaShop
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to http://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2013 PrestaShop SA
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
@ini_set('max_execution_time', 0);
/** No max line limit since the lines can be more than 4096. Performance impact is not significant. */
define('MAX_LINE_SIZE', 0);
/** Used for validatefields diying without user friendly error or not */
define('UNFRIENDLY_ERROR', false);
/** this value set the number of columns visible on each page */
define('MAX_COLUMNS', 6);
/** correct Mac error on eof */
@ini_set('auto_detect_line_endings', '1');
class AdminImportControllerCore extends AdminController
{
public static $column_mask;
public $entities = array();
public $available_fields = array();
public $required_fields = array('name');
public $cache_image_deleted = array();
public static $default_values = array();
public static $validators = array(
'active' => array('AdminImportController', 'getBoolean'),
'tax_rate' => array('AdminImportController', 'getPrice'),
/** Tax excluded */
'price_tex' => array('AdminImportController', 'getPrice'),
/** Tax included */
'price_tin' => array('AdminImportController', 'getPrice'),
'reduction_price' => array('AdminImportController', 'getPrice'),
'reduction_percent' => array('AdminImportController', 'getPrice'),
'wholesale_price' => array('AdminImportController', 'getPrice'),
'ecotax' => array('AdminImportController', 'getPrice'),
'name' => array('AdminImportController', 'createMultiLangField'),
'description' => array('AdminImportController', 'createMultiLangField'),
'description_short' => array('AdminImportController', 'createMultiLangField'),
'meta_title' => array('AdminImportController', 'createMultiLangField'),
'meta_keywords' => array('AdminImportController', 'createMultiLangField'),
'meta_description' => array('AdminImportController', 'createMultiLangField'),
'link_rewrite' => array('AdminImportController', 'createMultiLangField'),
'available_now' => array('AdminImportController', 'createMultiLangField'),
'available_later' => array('AdminImportController', 'createMultiLangField'),
'category' => array('AdminImportController', 'split'),
'online_only' => array('AdminImportController', 'getBoolean')
);
public $separator;
public $multiple_value_separator;
public function __construct()
{
$this->entities = array(
$this->l('Categories'),
$this->l('Products'),
$this->l('Combinations'),
$this->l('Customers'),
$this->l('Addresses'),
$this->l('Manufacturers'),
$this->l('Suppliers'),
);
// @since 1.5.0
if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT'))
{
$this->entities = array_merge(
$this->entities,
array(
$this->l('Supply Orders'),
$this->l('Supply Order Details'),
)
);
}
$this->entities = array_flip($this->entities);
switch ((int)Tools::getValue('entity'))
{
case $this->entities[$this->l('Combinations')]:
$this->required_fields = array(
'id_product',
'group',
'attribute'
);
$this->available_fields = array(
'no' => array('label' => $this->l('Ignore this column')),
'id_product' => array('label' => $this->l('Product ID').'*'),
'group' => array(
'label' => $this->l('Attribute (Name:Type:Position)').'*'
),
'attribute' => array(
'label' => $this->l('Value (Value:Position)').'*'
),
'supplier_reference' => array('label' => $this->l('Supplier reference')),
'reference' => array('label' => $this->l('Reference')),
'ean13' => array('label' => $this->l('EAN13')),
'upc' => array('label' => $this->l('UPC')),
'wholesale_price' => array('label' => $this->l('Wholesale price')),
'price' => array('label' => $this->l('Impact on price')),
'ecotax' => array('label' => $this->l('Ecotax')),
'quantity' => array('label' => $this->l('Quantity')),
'minimal_quantity' => array('label' => $this->l('Minimal quantity')),
'weight' => array('label' => $this->l('Impact on weight')),
'default_on' => array('label' => $this->l('Default (0 = No, 1 = Yes)')),
'image_position' => array(
'label' => $this->l('Image position')
),
'image_url' => array('label' => $this->l('Image URL')),
'delete_existing_images' => array(
'label' => $this->l('Delete existing images (0 = No, 1 = Yes)')
),
'shop' => array(
'label' => $this->l('ID / Name of shop'),
'help' => $this->l('Ignore this field if you don\'t use the Multistore tool. If you leave this field empty, the default shop will be used.'),
)
);
self::$default_values = array(
'reference' => '',
'supplier_reference' => '',
'ean13' => '',
'upc' => '',
'wholesale_price' => 0,
'price' => 0,
'ecotax' => 0,
'quantity' => 0,
'minimal_quantity' => 1,
'weight' => 0,
'default_on' => 0,
);
break;
case $this->entities[$this->l('Categories')]:
$this->available_fields = array(
'no' => array('label' => $this->l('Ignore this column')),
'id' => array('label' => $this->l('ID')),
'active' => array('label' => $this->l('Active (0/1)')),
'name' => array('label' => $this->l('Name *')),
'parent' => array('label' => $this->l('Parent category')),
'is_root_category' => array(
'label' => $this->l('Root category (0/1)'),
'help' => $this->l('A category root is where a category tree can begin. This is used with multistore.')
),
'description' => array('label' => $this->l('Description')),
'meta_title' => array('label' => $this->l('Meta title')),
'meta_keywords' => array('label' => $this->l('Meta keywords')),
'meta_description' => array('label' => $this->l('Meta description')),
'link_rewrite' => array('label' => $this->l('URL rewritten')),
'image' => array('label' => $this->l('Image URL')),
'shop' => array(
'label' => $this->l('ID / Name of shop'),
'help' => $this->l('Ignore this field if you don\'t use the Multistore tool. If you leave this field empty, the default shop will be used.'),
),
);
self::$default_values = array(
'active' => '1',
'parent' => Configuration::get('PS_HOME_CATEGORY'),
'link_rewrite' => ''
);
break;
case $this->entities[$this->l('Products')]:
self::$validators['image'] = array(
'AdminImportController',
'split'
);
$this->available_fields = array(
'no' => array('label' => $this->l('Ignore this column')),
'id' => array('label' => $this->l('ID')),
'active' => array('label' => $this->l('Active (0/1)')),
'name' => array('label' => $this->l('Name *')),
'category' => array('label' => $this->l('Categories (x,y,z...)')),
'price_tex' => array('label' => $this->l('Price tax excluded')),
'price_tin' => array('label' => $this->l('Price tax included')),
'id_tax_rules_group' => array('label' => $this->l('Tax rules ID')),
'wholesale_price' => array('label' => $this->l('Wholesale price')),
'on_sale' => array('label' => $this->l('On sale (0/1)')),
'reduction_price' => array('label' => $this->l('Discount amount')),
'reduction_percent' => array('label' => $this->l('Discount percent')),
'reduction_from' => array('label' => $this->l('Discount from (yyyy-mm-dd)')),
'reduction_to' => array('label' => $this->l('Discount to (yyyy-mm-dd)')),
'reference' => array('label' => $this->l('Reference #')),
'supplier_reference' => array('label' => $this->l('Supplier reference #')),
'supplier' => array('label' => $this->l('Supplier')),
'manufacturer' => array('label' => $this->l('Manufacturer')),
'ean13' => array('label' => $this->l('EAN13')),
'upc' => array('label' => $this->l('UPC')),
'ecotax' => array('label' => $this->l('Ecotax')),
'weight' => array('label' => $this->l('Weight')),
'quantity' => array('label' => $this->l('Quantity')),
'description_short' => array('label' => $this->l('Short description')),
'description' => array('label' => $this->l('Description')),
'tags' => array('label' => $this->l('Tags (x,y,z...)')),
'meta_title' => array('label' => $this->l('Meta title')),
'meta_keywords' => array('label' => $this->l('Meta keywords')),
'meta_description' => array('label' => $this->l('Meta description')),
'link_rewrite' => array('label' => $this->l('URL rewritten')),
'available_now' => array('label' => $this->l('Text when in stock')),
'available_later' => array('label' => $this->l('Text when backorder allowed')),
'available_for_order' => array('label' => $this->l('Available for order (0 = No, 1 = Yes)')),
'date_add' => array('label' => $this->l('Product creation date')),
'show_price' => array('label' => $this->l('Show price (0 = No, 1 = Yes)')),
'image' => array('label' => $this->l('Image URLs (x,y,z...)')),
'delete_existing_images' => array(
'label' => $this->l('Delete existing images (0 = No, 1 = Yes)')
),
'features' => array('label' => $this->l('Feature(Name:Value:Position)')),
'online_only' => array('label' => $this->l('Available online only (0 = No, 1 = Yes)')),
'condition' => array('label' => $this->l('Condition')),
'shop' => array(
'label' => $this->l('ID / Name of shop'),
'help' => $this->l('Ignore this field if you don\'t use the Multistore tool. If you leave this field empty, the default shop will be used.'),
)
);
self::$default_values = array(
'id_category' => array((int)Configuration::get('PS_HOME_CATEGORY')),
'id_category_default' => (int)Configuration::get('PS_HOME_CATEGORY'),
'active' => '1',
'quantity' => 0,
'price' => 0,
'id_tax_rules_group' => 0,
'description_short' => array((int)Configuration::get('PS_LANG_DEFAULT') => ''),
'link_rewrite' => array((int)Configuration::get('PS_LANG_DEFAULT') => ''),
'online_only' => 0,
'condition' => 'new',
'date_add' => date('Y-m-d H:i:s'),
'condition' => 'new',
);
break;
case $this->entities[$this->l('Customers')]:
//Overwrite required_fields AS only email is required whereas other entities
$this->required_fields = array('email', 'passwd', 'lastname', 'firstname');
$this->available_fields = array(
'no' => array('label' => $this->l('Ignore this column')),
'id' => array('label' => $this->l('ID')),
'active' => array('label' => $this->l('Active (0/1)')),
'id_gender' => array('label' => $this->l('Titles ID (Mr = 1, Ms = 2, else 0)')),
'email' => array('label' => $this->l('Email *')),
'passwd' => array('label' => $this->l('Password *')),
'birthday' => array('label' => $this->l('Birthday (yyyy-mm-dd)')),
'lastname' => array('label' => $this->l('Last Name *')),
'firstname' => array('label' => $this->l('First Name *')),
'newsletter' => array('label' => $this->l('Newsletter (0/1)')),
'optin' => array('label' => $this->l('Opt-in (0/1)')),
'id_shop' => array(
'label' => $this->l('ID / Name of shop'),
'help' => $this->l('Ignore this field if you don\'t use the Multistore tool. If you leave this field empty, the default shop will be used.'),
),
);
self::$default_values = array(
'active' => '1',
'id_shop' => Configuration::get('PS_SHOP_DEFAULT'),
);
break;
case $this->entities[$this->l('Addresses')]:
//Overwrite required_fields
$this->required_fields = array(
'lastname',
'firstname',
'address1',
'postcode',
'country',
'customer_email',
'city'
);
$this->available_fields = array(
'no' => array('label' => $this->l('Ignore this column')),
'id' => array('label' => $this->l('ID')),
'alias' => array('label' => $this->l('Alias *')),
'active' => array('label' => $this->l('Active (0/1)')),
'customer_email' => array('label' => $this->l('Customer email')),
'id_customer' => array('label' => $this->l('Customer ID:')),
'manufacturer' => array('label' => $this->l('Manufacturer')),
'supplier' => array('label' => $this->l('Supplier')),
'company' => array('label' => $this->l('Company')),
'lastname' => array('label' => $this->l('Last Name *')),
'firstname' => array('label' => $this->l('First Name *')),
'address1' => array('label' => $this->l('Address 1 *')),
'address2' => array('label' => $this->l('Address 2')),
'postcode' => array('label' => $this->l('Postal code / Zipcode*')),
'city' => array('label' => $this->l('City *')),
'country' => array('label' => $this->l('Country *')),
'state' => array('label' => $this->l('State')),
'other' => array('label' => $this->l('Other')),
'phone' => array('label' => $this->l('Phone')),
'phone_mobile' => array('label' => $this->l('Mobile Phone')),
'vat_number' => array('label' => $this->l('VAT number')),
);
self::$default_values = array(
'alias' => 'Alias',
'postcode' => 'X'
);
break;
case $this->entities[$this->l('Manufacturers')]:
case $this->entities[$this->l('Suppliers')]:
//Overwrite validators AS name is not MultiLangField
self::$validators = array(
'description' => array('AdminImportController', 'createMultiLangField'),
'short_description' => array('AdminImportController', 'createMultiLangField'),
'meta_title' => array('AdminImportController', 'createMultiLangField'),
'meta_keywords' => array('AdminImportController', 'createMultiLangField'),
'meta_description' => array('AdminImportController', 'createMultiLangField'),
);
$this->available_fields = array(
'no' => array('label' => $this->l('Ignore this column')),
'id' => array('label' => $this->l('ID')),
'active' => array('label' => $this->l('Active (0/1)')),
'name' => array('label' => $this->l('Name *')),
'description' => array('label' => $this->l('Description')),
'short_description' => array('label' => $this->l('Short description')),
'meta_title' => array('label' => $this->l('Meta title')),
'meta_keywords' => array('label' => $this->l('Meta keywords')),
'meta_description' => array('label' => $this->l('Meta description')),
'shop' => array(
'label' => $this->l('ID / Name of group shop'),
'help' => $this->l('Ignore this field if you don\'t use the Multistore tool. If you leave this field empty, the default shop will be used.'),
),
);
self::$default_values = array(
'shop' => Shop::getGroupFromShop(Configuration::get('PS_SHOP_DEFAULT')),
);
break;
// @since 1.5.0
case $this->entities[$this->l('Supply Orders')]:
if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT'))
{
// required fields
$this->required_fields = array(
'id_supplier',
'id_warehouse',
'reference',
'date_delivery_expected',
);
// available fields
$this->available_fields = array(
'no' => array('label' => $this->l('Ignore this column')),
'id' => array('label' => $this->l('ID')),
'id_supplier' => array('label' => $this->l('Supplier ID *')),
'id_lang' => array('label' => $this->l('Lang ID')),
'id_warehouse' => array('label' => $this->l('Warehouse ID *')),
'id_currency' => array('label' => $this->l('Currency ID *')),
'reference' => array('label' => $this->l('Supply Order Reference *')),
'date_delivery_expected' => array('label' => $this->l('Delivery Date (Y-M-D)*')),
'discount_rate' => array('label' => $this->l('Discount Rate')),
'is_template' => array('label' => $this->l('Template')),
);
// default values
self::$default_values = array(
'id_lang' => (int)Configuration::get('PS_LANG_DEFAULT'),
'id_currency' => Currency::getDefaultCurrency()->id,
'discount_rate' => '0',
'is_template' => '0',
);
}
break;
// @since 1.5.0
case $this->entities[$this->l('Supply Order Details')]:
if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT'))
{
// required fields
$this->required_fields = array(
'supply_order_reference',
'id_product',
'unit_price_te',
'quantity_expected',
);
// available fields
$this->available_fields = array(
'no' => array('label' => $this->l('Ignore this column')),
'supply_order_reference' => array('label' => $this->l('Supply Order Reference *')),
'id_product' => array('label' => $this->l('Product ID *')),
'id_product_attribute' => array('label' => $this->l('Product Attribute ID')),
'unit_price_te' => array('label' => $this->l('Unit Price (tax excl.)*')),
'quantity_expected' => array('label' => $this->l('Quantity Expected *')),
'discount_rate' => array('label' => $this->l('Discount Rate')),
'tax_rate' => array('label' => $this->l('Tax Rate')),
);
// default values
self::$default_values = array(
'discount_rate' => '0',
'tax_rate' => '0',
);
}
}
$this->separator = strval(trim(Tools::getValue('separator', ';')));
if (is_null(Tools::getValue('multiple_value_separator')) || trim(Tools::getValue('multiple_value_separator')) == '')
$this->multiple_value_separator = ',';
else
$this->multiple_value_separator = Tools::getValue('multiple_value_separator');
parent::__construct();
}
public function renderForm()
{
if (!is_writable(_PS_ADMIN_DIR_.'/import/'))
$this->displayWarning($this->l('Directory import on admin directory must be writable (CHMOD 755 / 777)'));
if (isset($this->warnings) && count($this->warnings))
{
$warnings = array();
foreach ($this->warnings as $warning)
$warnings[] = $warning;
}
$files_to_import = scandir(_PS_ADMIN_DIR_.'/import/');
uasort($files_to_import, array('AdminImportController', 'usortFiles'));
foreach ($files_to_import as $k => &$filename)
//exclude . .. .svn and index.php and all hidden files
if (preg_match('/^\..*|index\.php/i', $filename))
unset($files_to_import[$k]);
unset($filename);
$this->fields_form = array('');
$this->toolbar_scroll = false;
$this->toolbar_btn = array();
// adds fancybox
$this->addCSS(_PS_CSS_DIR_.'jquery.fancybox-1.3.4.css', 'screen');
$this->addJqueryPlugin(array('fancybox'));
$entity_selected = 0;
if (isset($this->entities[$this->l(Tools::ucfirst(Tools::getValue('import_type')))]))
{
$entity_selected = $this->entities[$this->l(Tools::ucfirst(Tools::getValue('import_type')))];
$this->context->cookie->entity_selected = $entity_selected;
}
elseif(isset($this->context->cookie->entity_selected))
$entity_selected = (int)$this->context->cookie->entity_selected;
$this->tpl_form_vars = array(
'module_confirmation' => (Tools::getValue('import')) && (isset($this->warnings) && !count($this->warnings)),
'path_import' => _PS_ADMIN_DIR_.'/import/',
'entities' => $this->entities,
'entity_selected' => $entity_selected,
'files_to_import' => $files_to_import,
'languages' => Language::getLanguages(false),
'id_language' => $this->context->language->id,
'available_fields' => $this->getAvailableFields(),
'truncateAuthorized' => (Shop::isFeatureActive() && $this->context->employee->isSuperAdmin()) || !Shop::isFeatureActive(),
'PS_ADVANCED_STOCK_MANAGEMENT' => Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT'),
);
return parent::renderForm();
}
public function renderView()
{
$this->addJS(_PS_JS_DIR_.'adminImport.js');
$handle = $this->openCsvFile();
$nb_column = $this->getNbrColumn($handle, $this->separator);
$nb_table = ceil($nb_column / MAX_COLUMNS);
$res = array();
foreach ($this->required_fields as $elem)
$res[] = '\''.$elem.'\'';
$data = array();
for ($i = 0; $i < $nb_table; $i++)
$data[$i] = $this->generateContentTable($i, $nb_column, $handle, $this->separator);
if ($entity_selected = (int)Tools::getValue('entity'))
$this->context->cookie->entity_selected = $entity_selected;
$this->tpl_view_vars = array(
'import_matchs' => Db::getInstance()->executeS('SELECT * FROM '._DB_PREFIX_.'import_match'),
'fields_value' => array(
'csv' => Tools::getValue('csv'),
'convert' => Tools::getValue('convert'),
'entity' => (int)Tools::getValue('entity'),
'iso_lang' => Tools::getValue('iso_lang'),
'truncate' => Tools::getValue('truncate'),
'forceIDs' => Tools::getValue('forceIDs'),
'match_ref' => Tools::getValue('match_ref'),
'separator' => $this->separator,
'multiple_value_separator' => $this->multiple_value_separator
),
'nb_table' => $nb_table,
'nb_column' => $nb_column,
'res' => implode(',', $res),
'max_columns' => MAX_COLUMNS,
'no_pre_select' => array('price_tin', 'feature'),
'available_fields' => $this->available_fields,
'data' => $data
);
return parent::renderView();
}
public function initToolbar()
{
switch ($this->display)
{
case 'import':
// Default cancel button - like old back link
$back = Tools::safeOutput(Tools::getValue('back', ''));
if (empty($back))
$back = self::$currentIndex.'&token='.$this->token;
$this->toolbar_btn['cancel'] = array(
'href' => $back,
'desc' => $this->l('Cancel')
);
// Default save button - action dynamically handled in javascript
$this->toolbar_btn['save-import'] = array(
'href' => '#',
'desc' => $this->l('Import .CSV data')
);
break;
}
}
protected function generateContentTable($current_table, $nb_column, $handle, $glue)
{
$html = '<table id="table'.$current_table.'" style="display: none;" class="table" cellspacing="0" cellpadding="0">
<tr>';
// Header
for ($i = 0; $i < $nb_column; $i++)
if (MAX_COLUMNS * (int)$current_table <= $i && (int)$i < MAX_COLUMNS * ((int)$current_table + 1))
$html .= '<th style="width: '.(900 / MAX_COLUMNS).'px; vertical-align: top; padding: 4px">
<select onchange="askFeatureName(this, '.$i.');"
style="width: '.(900 / MAX_COLUMNS).'px;"
id="type_value['.$i.']"
name="type_value['.$i.']"
class="type_value">
'.$this->getTypeValuesOptions($i).'
</select>
<div id="features_'.$i.'" style="display: none;">
<input style="width: 90px" type="text" name="" id="feature_name_'.$i.'">
<input type="button" value="ok" onclick="replaceFeature($(\'#feature_name_'.$i.'\').attr(\'name\'), '.$i.');">
</div>
</th>';
$html .= '</tr>';
AdminImportController::setLocale();
for ($current_line = 0; $current_line < 10 && $line = fgetcsv($handle, MAX_LINE_SIZE, $glue); $current_line++)
{
/* UTF-8 conversion */
if (Tools::getValue('convert'))
$line = $this->utf8EncodeArray($line);
$html .= '<tr id="table_'.$current_table.'_line_'.$current_line.'" style="padding: 4px">';
foreach ($line as $nb_c => $column)
if ((MAX_COLUMNS * (int)$current_table <= $nb_c) && ((int)$nb_c < MAX_COLUMNS * ((int)$current_table + 1)))
$html .= '<td>'.htmlentities(substr($column, 0, 200), ENT_QUOTES, 'UTF-8').'</td>';
$html .= '</tr>';
}
$html .= '</table>';
AdminImportController::rewindBomAware($handle);
return $html;
}
public function init()
{
parent::init();
if (Tools::isSubmit('submitImportFile'))
$this->display = 'import';
}
public function initContent()
{
// toolbar (save, cancel, new, ..)
$this->initToolbar();
if ($this->display == 'import')
if (Tools::getValue('csv'))
$this->content .= $this->renderView();
else
{
$this->errors[] = $this->l('You must upload a file in order to proceed to the next step');
$this->content .= $this->renderForm();
}
else
$this->content .= $this->renderForm();
$this->context->smarty->assign(array(
'content' => $this->content,
'url_post' => self::$currentIndex.'&token='.$this->token,
));
}
protected static function rewindBomAware($handle)
{
// A rewind wrapper that skip BOM signature wrongly
rewind($handle);
if (($bom = fread($handle, 3)) != "\xEF\xBB\xBF")
rewind($handle);
}
protected static function getBoolean($field)
{
return (boolean)$field;
}
protected static function getPrice($field)
{
$field = ((float)str_replace(',', '.', $field));
$field = ((float)str_replace('%', '', $field));
return $field;
}
protected static function split($field)
{
if (empty($field))
return array();
$separator = Tools::getValue('multiple_value_separator');
if (is_null($separator) || trim($separator) == '')
$separator = ',';
do $uniqid_path = _PS_UPLOAD_DIR_.uniqid(); while (file_exists($uniqid_path));
file_put_contents($uniqid_path, $field);
$tab = '';
if (!empty($uniqid_path))
{
$fd = fopen($uniqid_path, 'r');
$tab = fgetcsv($fd, MAX_LINE_SIZE, $separator);
fclose($fd);
unlink($uniqid_path);
}
if (empty($tab) || (!is_array($tab)))
return array();
return $tab;
}
protected static function createMultiLangField($field)
{
$languages = Language::getLanguages(false);
$res = array();
foreach ($languages as $lang)
$res[$lang['id_lang']] = $field;
return $res;
}
protected function getTypeValuesOptions($nb_c)
{
$i = 0;
$no_pre_select = array('price_tin', 'feature');
$options = '';
foreach ($this->available_fields as $k => $field)
{
$options .= '<option value="'.$k.'"';
if ($k === 'price_tin')
++$nb_c;
if ($i === ($nb_c + 1) && (!in_array($k, $no_pre_select)))
$options .= ' selected="selected"';
$options .= '>'.$field['label'].'</option>';
++$i;
}
return $options;
}
/*
* Return fields to be display AS piece of advise
*
* @param $in_array boolean
* @return string or return array
*/
public function getAvailableFields($in_array = false)
{
$i = 0;
$fields = array();
$keys = array_keys($this->available_fields);
array_shift($keys);
foreach ($this->available_fields as $k => $field)
{
if ($k === 'no')
continue;
if ($k === 'price_tin')
$fields[$i - 1] = '<div>'.$this->available_fields[$keys[$i - 1]]['label'].' '.$this->l('or').' '.$field['label'].'<span style="margin-left:16px"></span></div>';
else
{
if (isset($field['help']))
$html = '&nbsp;<a href="#" class="info_import" title="'.$this->l('Info').'|'.$field['help'].'"><img src="'._PS_ADMIN_IMG_.'information.png"></a>';
else
$html = '<span style="margin-left:16px"></span>';
$fields[] = '<div>'.$field['label'].$html.'</div>';
}
++$i;
}
if ($in_array)
return $fields;
else
return implode("\n\r", $fields);
}
protected function receiveTab()
{
$type_value = Tools::getValue('type_value') ? Tools::getValue('type_value') : array();
foreach ($type_value as $nb => $type)
if ($type != 'no')
self::$column_mask[$type] = $nb;
}
public static function getMaskedRow($row)
{
$res = array();
if (is_array(self::$column_mask))
foreach (self::$column_mask as $type => $nb)
$res[$type] = isset($row[$nb]) ? $row[$nb] : null;
if (Tools::getValue('forceIds')) // if you choose to force table before import the column id is remove from the CSV file.
unset($res['id']);
return $res;
}
protected static function setDefaultValues(&$info)
{
foreach (self::$default_values as $k => $v)
if (!isset($info[$k]) || $info[$k] == '')
$info[$k] = $v;
}
protected static function setEntityDefaultValues(&$entity)
{
$members = get_object_vars($entity);
foreach (self::$default_values as $k => $v)
if ((array_key_exists($k, $members) && $entity->$k === null) || !array_key_exists($k, $members))
$entity->$k = $v;
}
protected static function fillInfo($infos, $key, &$entity)
{
$infos = trim($infos);
if (isset(self::$validators[$key][1]) && self::$validators[$key][1] == 'createMultiLangField' && Tools::getValue('iso_lang'))
{
$id_lang = Language::getIdByIso(Tools::getValue('iso_lang'));
$tmp = call_user_func(self::$validators[$key], $infos);
foreach ($tmp as $id_lang_tmp => $value)
if (empty($entity->{$key}[$id_lang_tmp]) || $id_lang_tmp == $id_lang)
$entity->{$key}[$id_lang_tmp] = $value;
}
else
if (!empty($infos) || $infos == '0') // ($infos == '0') => if you want to disable a product by using "0" in active because empty('0') return true
$entity->{$key} = isset(self::$validators[$key]) ? call_user_func(self::$validators[$key], $infos) : $infos;
return true;
}
public static function arrayWalk(&$array, $funcname, &$user_data = false)
{
if (!is_callable($funcname)) return false;
foreach ($array as $k => $row)
if (!call_user_func_array($funcname, array($row, $k, $user_data)))
return false;
return true;
}
/**
* copyImg copy an image located in $url and save it in a path
* according to $entity->$id_entity .
* $id_image is used if we need to add a watermark
*
* @param int $id_entity id of product or category (set in entity)
* @param int $id_image (default null) id of the image if watermark enabled.
* @param string $url path or url to use
* @param string entity 'products' or 'categories'
* @return void
*/
protected static function copyImg($id_entity, $id_image = null, $url, $entity = 'products')
{
$tmpfile = tempnam(_PS_TMP_IMG_DIR_, 'ps_import');
$watermark_types = explode(',', Configuration::get('WATERMARK_TYPES'));
switch ($entity)
{
default:
case 'products':
$image_obj = new Image($id_image);
$path = $image_obj->getPathForCreation();
break;
case 'categories':
$path = _PS_CAT_IMG_DIR_.(int)$id_entity;
break;
}
$url = str_replace(' ', '%20', trim($url));
// Evaluate the memory required to resize the image: if it's too much, you can't resize it.
if (!ImageManager::checkImageMemoryLimit($url))
return false;
// 'file_exists' doesn't work on distant file, and getimagesize make the import slower.
// Just hide the warning, the traitment will be the same.
if (Tools::copy($url, $tmpfile))
{
ImageManager::resize($tmpfile, $path.'.jpg');
$images_types = ImageType::getImagesTypes($entity);
foreach ($images_types as $image_type)
ImageManager::resize($tmpfile, $path.'-'.stripslashes($image_type['name']).'.jpg', $image_type['width'], $image_type['height']);
if (in_array($image_type['id_image_type'], $watermark_types))
Hook::exec('actionWatermark', array('id_image' => $id_image, 'id_product' => $id_entity));
}
else
{
unlink($tmpfile);
return false;
}
unlink($tmpfile);
return true;
}
public function categoryImport()
{
$cat_moved = array();
$this->receiveTab();
$handle = $this->openCsvFile();
$default_language_id = (int)Configuration::get('PS_LANG_DEFAULT');
AdminImportController::setLocale();
for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); $current_line++)
{
if (Tools::getValue('convert'))
$line = $this->utf8EncodeArray($line);
$info = AdminImportController::getMaskedRow($line);
$tab_categ = array(Configuration::get('PS_HOME_CATEGORY'), Configuration::get('PS_ROOT_CATEGORY'));
if (isset($info['id']) && in_array((int)$info['id'], $tab_categ))
{
$this->errors[] = Tools::displayError('The ID category cannot be the same as the ID Root category or the ID Home category.');
continue;
}
AdminImportController::setDefaultValues($info);
if (Tools::getValue('forceIDs') && isset($info['id']) && (int)$info['id'])
$category = new Category((int)$info['id']);
else
{
if (isset($info['id']) && (int)$info['id'] && Category::existsInDatabase((int)$info['id'], 'category'))
$category = new Category((int)$info['id']);
else
$category = new Category();
}
AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $category);
if (isset($category->parent) && is_numeric($category->parent))
{
if (isset($cat_moved[$category->parent