<?php



/**

  * Import tab for admin panel, AdminImport.php

  * @category admin

  *

  * @author PrestaShop <support@prestashop.com>

  * @copyright PrestaShop

  * @license http://www.opensource.org/licenses/osl-3.0.php Open-source licence 3.0

  * @version 1.0

  *

  */

include_once(PS_ADMIN_DIR.'/../classes/AdminTab.php');

define('MAX_LINE_SIZE', 4096);



// this value set the number of columns visible on each page

define('MAX_COLUMNS', 5);



class AdminImport extends AdminTab

{

	public static $available_fileds;

	public static $required_fields = array(

		'name',

		'price',

	);

	public static $columns = array(

		'id_tax' => 1,

		'description' => '',

		'description_short' => '',

		'meta_title' => '',

		'meta_keywords' => '',

		'meta_description' => '',

		'availability' => '',

		'category' => '1');

	public static $validators = array('price' => array('AdminImport', 'getPrice'),

		'name' => array('AdminImport', 'createMultiLangField'),

		'availability' => array('AdminImport', 'createMultiLangField'),

		'description' => array('AdminImport', 'createMultiLangField'),

		'description_short' => array('AdminImport', 'createMultiLangField'),

		'link_rewrite' => array('AdminImport', 'createMultiLangField'),

		'meta_title' => array('AdminImport', 'createMultiLangField'),

		'meta_keywords' => array('AdminImport', 'createMultiLangField'),

		'meta_description' => array('AdminImport', 'createMultiLangField'),

		'category' => array('AdminImport', 'splitCategories'),

		);



	private $column_mask;



	public function __construct()

	{

		$this->available_fields = array(

				'no' => $this->l('Ignore this column'),

				'id' => $this->l('ID'),

				'reference' => $this->l('Reference #'),

				'supplier_reference' => $this->l('Supplier Reference #'),

				'name' => $this->l('Name'),

				'ean13' => $this->l('EAN13'),

				'price' => $this->l('Price'),

				'weight' => $this->l('Weight'),

				'quantity' => $this->l('Quantity'),

				'description_short' => $this->l('Short description'),

				'description' => $this->l('Description'),

				'category' => $this->l('Category'),

		);

		parent::__construct();

	}



	private static function getPrice($field)

	{

		return (floatval(str_replace(',', '.', $field)));

	}



	private static function splitCategories($field)

	{

		$tab = explode(',', $field);

		$res = array_map('intval', $tab);

		return $tab;

	}



	private static function createMultiLangField($field)

	{

		$languages = Language::getLanguages();

		$res = array();

		foreach ($languages AS $lang)

			$res[$lang['id_lang']] = $field;

		return $res;

	}

	private function getMaskedRow($row)

	{

		$res = array();

		foreach ($this->column_mask as $type => $nb)

			$res[$type] = $row[$nb];

		return $res;

	}



	private static function fillProductInfo($infos, $key, $product)

	{

		$product->{$key} = (isset(self::$validators[$key]) ? call_user_func(self::$validators[$key], $infos) : $infos);

	}



	public static function setDefaultValues(&$info_product)

	{

		$info_product['link_rewrite'] = Tools::link_rewrite($info_product['name']);

		foreach (self::$columns as $k => $v)

			if (!isset($info_product[$k]))

				$info_product[$k] = $v;

	}



	public function productImport()

	{

		foreach ($_POST['type_value'] as $nb => $type)

			if ($type != 'no')

				$this->column_mask[$type] = $nb;

		$results = array_map(array($this, 'getMaskedRow'), $_POST['value']);

		foreach($results as $info_product)

		{

			self::setDefaultValues($info_product);

			$product = new Product();

			array_walk($info_product, array('AdminImport', 'fillProductInfo'), $product);

			$product->id_category_default = intval($product->category[0]);

			if (!$product->save())

				$this->_errors[] = mysql_error().$info_product['name'].(isset($info_product['id']) ? ' ('.$info_product['id'].')' : '').' '.Tools::displayError('cannot be saved');

			$product->updateCategories(array_map('intval', $product->category));

		}

	}



	private function getLinesFromFile($file)

	{

		$lines = array();

		$handle = @fopen($file, 'r');

		if ($handle)

		{

			while (!feof($handle))

			{

				$line = trim(fgets($handle, MAX_LINE_SIZE));

				if ($line)

					$lines[] = $line;

			}

			fclose($handle);

		}

		return $lines;

	}



	private function getContentTables()

	{

		$lines = $this->getLinesFromFile($_FILES['csv_product']['tmp_name']);

		$glue = (isset($_POST['separator']) ? strval($_POST['separator']) : ';');

		$tables = array();

		foreach ($lines AS $nb_l => $line)

		{

			$columns = $this->csvToArray($line, $glue);

			foreach($columns AS $nb_c => $column)

				$tables[intval($nb_c / MAX_COLUMNS)][$nb_l][$nb_c] = $column;

		}

		return $tables;

	}



	private function getTypeValuesOptions()

	{

		$options = '';

		foreach ($this->available_fields AS $k => $field)

			$options .= '

				<option value="'.$k.'">'.$field.'</option>';

		return $options;

	}



	private static function checkTab($tables)

	{

		$tmp = array_fill_keys(array_map('sizeof', $tables), true);

		if (next($tmp))

			return false;

		foreach ($tables AS $lines)

		{

			$tmp = array_fill_keys(array_map('sizeof', $lines), true);

			if (next($tmp))

				return false;

		}

		return true;

	}



	public function displayCSV()

	{

		global $currentIndex;



		$html = '<h2>'.$this->l('Your product data').'</h2>'.'

		<h3>'.$this->l('Please set the value type of each column').'</h3>';



		// errors

		$html .= '

		<div id="error_duplicate_type" class="warning warn" style="display:none;">

			<h3>'.$this->l('Columns cannot have the same value type').'</h3>

		</div>

		<div id="required_column" class="warning warn" style="display:none;">

			<h3>'.$this->l('Column').' <span id="missing_column">&nbsp;</span> '.$this->l('must be set').'</h3>

		</div>';

		$tables = $this->getContentTables();

		if (!self::checkTab($tables))

		{

			echo '

			<div class="warning warn">

				<h3>'.$this->l('Invalid CSV file or delimiter.').'</h3>'.'

			</div>

			';

			return false;

		}

		foreach ($tables AS $nb => $table)

		{

			$html_table = '

			<table id="table'.$nb.'" style="display: none;">

				<tr align="center">

				<td><!-- delete --></td>';

			//header

			foreach ($table[0] AS $nb_c => $column)

				$html_table .= '

					<td style="width: '.(800 / MAX_COLUMNS).'px;">

						<select style="width: '.(800 / MAX_COLUMNS).'px;" id="type_value['.$nb_c.']" name="type_value['.$nb_c.']">

							'.$this->getTypeValuesOptions().'

						</select>

					</td>';

			$html_table .= '

				</tr>';

			// data values

			$nb_table = sizeof($tables);

			foreach ($table AS $nb_l => $line)

			{

				$html_table .= '

				<tr id="table_'.$nb.'_line_'.$nb_l.'" align="center">

				<td><img onClick="for (i = 0; i < '.$nb_table.'; ++i) {var item = getE(\'table_\' + i + \'_line_'.$nb_l.'\'); item.parentNode.removeChild(item)}" src="../img/admin/delete.gif" alt="'.$this->l('Delete this line').'" title="'.$this->l('Delete this line').'"/></td>

				';

				foreach ($line AS $nb_c => $column)

					$html_table.= '

					<td><textarea style="width: 85%;" name="value['.$nb_l.']['.$nb_c.']" id="value['.$nb_l.']['.$nb_c.']">'.$column.'</textarea></td>

					';

				$html_table .= '

				</tr>';

			}

			$html_table .= '

			</table>

			';

			$html_tables[] = $html_table;

		}

		$res = array();

		foreach (self::$required_fields AS $elem)

			$res[] = '\''.$elem.'\'';



		// print return

		$html .= '

		<form action="'.$currentIndex.'&token='.$this->token.'" method="post" id="import_form" name="import_form">

			<div style="text-align:center; margin-bottom:10px;">

				<input name="import" type="submit" onclick="return (validateImportation(new Array('.implode(',', $res).')));" id="import" value="'.$this->l('Import CSV data').'" class="button" />

			</div>

			<script type="text/javascript">

				var current = 0;

				function showTable(nb)

				{

					getE(\'btn_left\').disabled = null;

					getE(\'btn_right\').disabled = null;

					if (nb <= 0)

					{

						nb = 0;

						getE(\'btn_left\').disabled = \'true\';

					}

					if (nb >= '.$nb_table.' - 1)

					{

						nb = '.$nb_table.' - 1;

						getE(\'btn_right\').disabled = \'true\';

					}

					toggle(getE(\'table\'+current), false);

					current = nb;

					toggle(getE(\'table\'+current), true);

				}

			</script>

			<table>

				<tr>

					<td valign="top" align="center"><input id="btn_left" value="'.$this->l('<<').'" type="button" class="button" onclick="showTable(current - 1)" /></td>

					<td align="left">'.implode("\n",$html_tables).'<td>

					<td valign="top" align="center"><input id="btn_right" value="'.$this->l('>>').'" type="button" class="button" onclick="showTable(current + 1)" /></td>

				</tr>

			</table>

			<script type="text/javascript">showTable(current);</script>

		</form>';

		echo $html;

	}



	public function postProcess()

	{

		if (!empty($_FILES['csv_product']['tmp_name']))

			$this->displayCSV();

		elseif (isset($_POST['import']))

		{

			$this->productImport();

		}

		parent::postProcess();

	}



	public function displayForm()

	{

		global $currentIndex;



		if (isset($_POST['import']) AND !sizeof($this->_errors))

			echo '<div class="module_confirmation conf confirm"><img src="../img/admin/ok.gif" alt="" title="" style="margin-right:5px; float:left;" />'.$this->l('The .CSV file has been imported into your shop.').'</div>';

		echo '

			<form id="preview_import" action="'.$currentIndex.'&token='.$this->token.'" method="post" class="width2" enctype="multipart/form-data" style="clear: both;">

				<fieldset>

					<legend><img src="../img/admin/import.gif" />'.$this->l('Import products').'</legend>

					<label class="clear">'.$this->l('Select your .CSV file:').' </label>

					<div class="margin-form">

						<input id="csv_product" name="csv_product" type="file" />

					</div>

					<label class="clear">'.$this->l('Column separator:').' </label>

					<div class="margin-form">

						<input name="separator" type="text" value=";" size="2" />

					</div>

					<div class="margin-form">

						<input type="submit" value="'.$this->l('Import file').'" class="button" />

					</div>

				</fieldset>

			</form>';

	}



	public function display()

	{

		$this->displayForm();

	}



	private function csvToArray($str, $glue)

	{

		return preg_replace("/^\"(.*)\"$/", "$1", preg_split("/".$glue."(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))/", trim($str)));

	}

}



?>