*  @copyright  2007-2011 PrestaShop SA
*  @version  Release: $Revision: 7793 $
*  @license    http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
*  International Registered Trademark & Property of PrestaShop SA
*/
include_once(PS_ADMIN_DIR.'/tabs/AdminProfiles.php');
class AdminProducts extends AdminTab
{
	protected $maxImageSize = 2000000;
	protected $maxFileSize  = 10000000;
	private $_category;
	public function __construct()
	{
		global $currentIndex;
		$this->table = 'product';
		$this->className = 'Product';
		$this->lang = true;
		$this->edit = true;
	 	$this->delete = true;
		$this->view = false;
		$this->duplicate = true;
		$this->imageType = 'jpg';
		
		$this->fieldsDisplay = array(
			'id_product' => array('title' => $this->l('ID'), 'align' => 'center', 'width' => 20),
			'image' => array('title' => $this->l('Photo'), 'align' => 'center', 'image' => 'p', 'width' => 45, 'orderby' => false, 'filter' => false, 'search' => false),
			'name' => array('title' => $this->l('Name'), 'width' => 220, 'filter_key' => 'b!name'),
			'reference' => array('title' => $this->l('Reference'), 'align' => 'center', 'width' => 20),
			'price' => array('title' => $this->l('Base price'), 'width' => 70, 'price' => true, 'align' => 'right', 'filter_key' => 'a!price'),
			'price_final' => array('title' => $this->l('Final price'), 'width' => 70, 'price' => true, 'align' => 'right', 'havingFilter' => true, 'orderby' => false),
			'quantity' => array('title' => $this->l('Quantity'), 'width' => 30, 'align' => 'right', 'filter_key' => 'a!quantity', 'type' => 'decimal'),
			'position' => array('title' => $this->l('Position'), 'width' => 40,'filter_key' => 'cp!position', 'align' => 'center', 'position' => 'position'),
			'a!active' => array('title' => $this->l('Displayed'), 'active' => 'status', 'filter_key' => 'a!active', 'align' => 'center', 'type' => 'bool', 'orderby' => false));
		/* Join categories table */
		$this->_category = AdminCatalog::getCurrentCategory();
		$this->_join = '
		LEFT JOIN `'._DB_PREFIX_.'image` i ON (i.`id_product` = a.`id_product` AND i.`cover` = 1)
		LEFT JOIN `'._DB_PREFIX_.'category_product` cp ON (cp.`id_product` = a.`id_product`)
		LEFT JOIN `'._DB_PREFIX_.'tax_rule` tr ON (a.`id_tax_rules_group` = tr.`id_tax_rules_group` AND tr.`id_country` = '.(int)Country::getDefaultCountryId().' AND tr.`id_state` = 0)
		LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = tr.`id_tax`)';
		$this->_filter = 'AND cp.`id_category` = '.(int)($this->_category->id);
		$this->_select = 'cp.`position`, i.`id_image`, (a.`price` * ((100 + (t.`rate`))/100)) AS price_final';
		parent::__construct();
	}
	private function _cleanMetaKeywords($keywords)
	{
		if (!empty($keywords) && $keywords != '')
		{
			$out = array();
			$words = explode(',', $keywords);
			foreach($words as $word_item)
			{
				$word_item = trim($word_item);
				if (!empty($word_item) && $word_item != '')
					$out[] = $word_item;
			}
			return ((count($out) > 0) ? implode(', ', $out) : '');
		}
		else
			return '';
	}
	protected function copyFromPost(&$object, $table)
	{
		parent::copyFromPost($object, $table);
		if (get_class($object) != 'Product')
			return;
		/* Additional fields */
		$languages = Language::getLanguages(false);
		foreach ($languages as $language)
			if (isset($_POST['meta_keywords_'.$language['id_lang']]))
			{
				$_POST['meta_keywords_'.$language['id_lang']] = $this->_cleanMetaKeywords(Tools::strtolower($_POST['meta_keywords_'.$language['id_lang']])); // preg_replace('/ *,? +,* /', ',', strtolower($_POST['meta_keywords_'.$language['id_lang']]));
				$object->meta_keywords[$language['id_lang']] = $_POST['meta_keywords_'.$language['id_lang']];
			}
		$_POST['width'] = empty($_POST['width']) ? '0' : str_replace(',', '.', $_POST['width']);
		$_POST['height'] = empty($_POST['height']) ? '0' : str_replace(',', '.', $_POST['height']);
		$_POST['depth'] = empty($_POST['depth']) ? '0' : str_replace(',', '.', $_POST['depth']);
		$_POST['weight'] = empty($_POST['weight']) ? '0' : str_replace(',', '.', $_POST['weight']);
		if ($_POST['unit_price'] != NULL)
			$object->unit_price = str_replace(',', '.', $_POST['unit_price']);
		if (array_key_exists('ecotax', $_POST) && $_POST['ecotax'] != NULL)
			$object->ecotax = str_replace(',', '.', $_POST['ecotax']);
		$object->available_for_order = (int)(Tools::isSubmit('available_for_order'));
		$object->show_price = $object->available_for_order ? 1 : (int)(Tools::isSubmit('show_price'));
		$object->on_sale = Tools::isSubmit('on_sale');
		$object->online_only = Tools::isSubmit('online_only');
	}
	public function getList($id_lang, $orderBy = NULL, $orderWay = NULL, $start = 0, $limit = NULL)
	{
		global $cookie;
		$orderByPriceFinal = (empty($orderBy) ? ($cookie->__get($this->table.'Orderby') ? $cookie->__get($this->table.'Orderby') : 'id_'.$this->table) : $orderBy);
		$orderWayPriceFinal = (empty($orderWay) ? ($cookie->__get($this->table.'Orderway') ? $cookie->__get($this->table.'Orderby') : 'ASC') : $orderWay);
		if ($orderByPriceFinal == 'price_final')
		{
			$orderBy = 'id_'.$this->table;
			$orderWay = 'ASC';
		}
		parent::getList($id_lang, $orderBy, $orderWay, $start, $limit);
		/* update product quantity with attributes ...*/
		if ($this->_list)
		{
			$nb = count ($this->_list);
			for ($i = 0; $i < $nb; $i++)
				Attribute::updateQtyProduct($this->_list[$i]);
			/* update product final price */
			for ($i = 0; $i < $nb; $i++)
				$this->_list[$i]['price_tmp'] = Product::getPriceStatic($this->_list[$i]['id_product'], true, NULL, 6, NULL, false, true, 1, true);
		}
		if ($orderByPriceFinal == 'price_final')
		{
			if (strtolower($orderWayPriceFinal) == 'desc')
				uasort($this->_list, 'cmpPriceDesc');
			else
				uasort($this->_list, 'cmpPriceAsc');
		}
		for ($i = 0; $this->_list AND $i < $nb; $i++)
		{
			$this->_list[$i]['price_final'] = $this->_list[$i]['price_tmp'];
			unset($this->_list[$i]['price_tmp']);
		}
	}
	public function deleteVirtualProduct()
	{
		if (!($id_product_download = ProductDownload::getIdFromIdProduct(intval(Tools::getValue('id_product')))))
			return false;
		$productDownload = new ProductDownload((int)($id_product_download));
		return $productDownload->deleteFile();
	}
	/**
	 * postProcess handle every checks before saving products information
	 *
	 * @param mixed $token
	 * @return void
	 */
	public function postProcess($token = NULL)
	{
		global $cookie, $currentIndex;
		
		/* Add a new product */
		if (Tools::isSubmit('submitAddproduct') OR Tools::isSubmit('submitAddproductAndStay') OR  Tools::isSubmit('submitAddProductAndPreview'))
		{
			if ((Tools::getValue('id_product') AND $this->tabAccess['edit'] === '1') OR ($this->tabAccess['add'] === '1' AND !Tools::isSubmit('id_product')))
				$this->submitAddproduct($token);
			else
				$this->_errors[] = Tools::displayError('You do not have permission to add here.');
		}
		/* Delete a product in the download folder */
		if (Tools::getValue('deleteVirtualProduct'))
		{
			if ($this->tabAccess['delete'] === '1')
				$this->deleteVirtualProduct();
			else
				$this->_errors[] = Tools::displayError('You do not have permission to delete here.');
		}
		/* Update attachments */
		elseif (Tools::isSubmit('submitAddAttachments'))
		{
			if ($this->tabAccess['add'] === '1')
			{
				$languages = Language::getLanguages(false);
				$is_attachment_name_valid = false;
				foreach ($languages AS $language)
				{
					$attachment_name_lang = Tools::getValue('attachment_name_'.(int)($language['id_lang']));
					if (strlen($attachment_name_lang ) > 0)
						$is_attachment_name_valid = true;
					if (!Validate::isGenericName(Tools::getValue('attachment_name_'.(int)($language['id_lang']))))
						$this->_errors[] = Tools::displayError('Invalid Name');
					elseif (Tools::strlen(Tools::getValue('attachment_name_'.(int)($language['id_lang']))) > 32)
						$this->_errors[] = Tools::displayError('Name is too long');
					if (!Validate::isCleanHtml(Tools::getValue('attachment_description_'.(int)($language['id_lang']))))
						$this->_errors[] = Tools::displayError('Invalid description');
				}
				if (!$is_attachment_name_valid)
					$this->_errors[] = Tools::displayError('Attachment Name Required');
				if (empty($this->_errors))
				{
					if (isset($_FILES['attachment_file']) AND is_uploaded_file($_FILES['attachment_file']['tmp_name']))
					{
						if ($_FILES['attachment_file']['size'] > (Configuration::get('PS_ATTACHMENT_MAXIMUM_SIZE') * 1024 * 1024))
							$this->_errors[] = $this->l('File too large, maximum size allowed:').' '.(Configuration::get('PS_ATTACHMENT_MAXIMUM_SIZE') * 1024).' '.$this->l('kb').'. '.$this->l('File size you\'re trying to upload is:').number_format(($_FILES['attachment_file']['size']/1024), 2, '.', '').$this->l('kb');
						else
						{
							do $uniqid = sha1(microtime());	while (file_exists(_PS_DOWNLOAD_DIR_.$uniqid));
							if (!copy($_FILES['attachment_file']['tmp_name'], _PS_DOWNLOAD_DIR_.$uniqid))
								$this->_errors[] = $this->l('File copy failed');
							@unlink($_FILES['attachment_file']['tmp_name']);
						}
					}
					elseif ((int)$_FILES['attachment_file']['error'] === 1)
					{
						$max_upload = (int)(ini_get('upload_max_filesize'));
						$max_post = (int)(ini_get('post_max_size'));
						$upload_mb = min($max_upload, $max_post);
						$this->_errors[] = $this->l('the File').' '.$_FILES['attachment_file']['name'].'  '.$this->l('exceeds the size allowed by the server, this limit is set to').' '.$upload_mb.$this->l('Mb').' ';
					}
					if (empty($this->_errors) && isset($uniqid))
					{
						$attachment = new Attachment();
						foreach ($languages AS $language)
						{
							if (isset($_POST['attachment_name_'.(int)($language['id_lang'])]))
								$attachment->name[(int)($language['id_lang'])] = pSQL($_POST['attachment_name_'.(int)($language['id_lang'])]);
							if (isset($_POST['attachment_description_'.(int)($language['id_lang'])]))
								$attachment->description[(int)($language['id_lang'])] = pSQL($_POST['attachment_description_'.(int)($language['id_lang'])]);
						}
						$attachment->file = $uniqid;
						$attachment->mime = $_FILES['attachment_file']['type'];
						$attachment->file_name = pSQL($_FILES['attachment_file']['name']);
						if (empty($attachment->mime) OR Tools::strlen($attachment->mime) > 128)
							$this->_errors[] = Tools::displayError('Invalid file extension');
						if (!Validate::isGenericName($attachment->file_name))
							$this->_errors[] = Tools::displayError('Invalid file name');
						if (Tools::strlen($attachment->file_name) > 128)
							$this->_errors[] = Tools::displayError('File name too long');
						if (!sizeof($this->_errors))
						{
							$attachment->add();
							Tools::redirectAdmin($currentIndex.'&id_product='.(int)(Tools::getValue($this->identifier)).'&id_category='.(int)(Tools::getValue('id_category')).'&addproduct&conf=4&tabs=6&token='.($token ? $token : $this->token));
						}
						else
							$this->_errors[] = Tools::displayError('Invalid file');
					}
				}
			}
			else
				$this->_errors[] = Tools::displayError('You do not have permission to add here.');
		}
		elseif (Tools::isSubmit('submitAttachments'))
		{
			if ($this->tabAccess['edit'] === '1')
				if ($id = (int)(Tools::getValue($this->identifier)))
					if (Attachment::attachToProduct($id, $_POST['attachments']))
						Tools::redirectAdmin($currentIndex.'&id_product='.(int)$id.(isset($_POST['id_category']) ? '&id_category='.(int)$_POST['id_category'] : '').'&conf=4&add'.$this->table.'&tabs=6&token='.($token ? $token : $this->token));
		}
		/* Product duplication */
		elseif (isset($_GET['duplicate'.$this->table]))
		{
			if ($this->tabAccess['add'] === '1')
			{
				if (Validate::isLoadedObject($product = new Product((int)(Tools::getValue('id_product')))))
				{
					$id_product_old = $product->id;
					unset($product->id);
					unset($product->id_product);
					$product->indexed = 0;
					$product->active = 0;
					if ($product->add()
					AND Category::duplicateProductCategories($id_product_old, $product->id)
					AND ($combinationImages = Product::duplicateAttributes($id_product_old, $product->id)) !== false
					AND Product::duplicateAccessories($id_product_old, $product->id)
					AND Product::duplicateFeatures($id_product_old, $product->id)
					AND Product::duplicateSpecificPrices($id_product_old, $product->id)
					AND Pack::duplicate($id_product_old, $product->id)
					AND Product::duplicateCustomizationFields($id_product_old, $product->id)
					AND Product::duplicateTags($id_product_old, $product->id)
					AND Product::duplicateDownload($id_product_old, $product->id))
					{
						if ($product->hasAttributes())
							Product::updateDefaultAttribute($product->id);
						if (!Tools::getValue('noimage') AND !Image::duplicateProductImages($id_product_old, $product->id, $combinationImages))
							$this->_errors[] = Tools::displayError('An error occurred while copying images.');
						else
						{
							Hook::addProduct($product);
							Search::indexation(false, $product->id);
							Tools::redirectAdmin($currentIndex.'&id_category='.(!empty($_REQUEST['id_category'])?$_REQUEST['id_category']:'1').'&conf=19&token='.($token ? $token : $this->token));
						}
					}
					else
						$this->_errors[] = Tools::displayError('An error occurred while creating object.');
				}
			}
			else
				$this->_errors[] = Tools::displayError('You do not have permission to add here.');
		}
		/* Change object statuts (active, inactive) */
		elseif (isset($_GET['status']) AND Tools::getValue($this->identifier))
		{
			if ($this->tabAccess['edit'] === '1')
			{
				if (Validate::isLoadedObject($object = $this->loadObject()))
				{
					if ($object->toggleStatus())
						Tools::redirectAdmin($currentIndex.'&conf=5'.((($id_category = (!empty($_REQUEST['id_category'])?$_REQUEST['id_category']:'1')) AND Tools::getValue('id_product')) ? '&id_category='.$id_category : '').'&token='.$token);
					else
						$this->_errors[] = Tools::displayError('An error occurred while updating status.');
				}
				else
					$this->_errors[] = Tools::displayError('An error occurred while updating status for object.').' '.$this->table.'  '.Tools::displayError('(cannot load object)');
			}
			else
				$this->_errors[] = Tools::displayError('You do not have permission to edit here.');
		}
		/* Delete object */
		elseif (isset($_GET['delete'.$this->table]))
		{
			if ($this->tabAccess['delete'] === '1')
			{
				if (Validate::isLoadedObject($object = $this->loadObject()) AND isset($this->fieldImageSettings))
				{
					// check if request at least one object with noZeroObject
					if (isset($object->noZeroObject) AND sizeof($taxes = call_user_func(array($this->className, $object->noZeroObject))) <= 1)
						$this->_errors[] = Tools::displayError('You need at least one object.').' '.$this->table.' '.$this->table.'  '.Tools::displayError('(cannot load object)');
			}
			else
				$this->_errors[] = Tools::displayError('You do not have permission to delete here.');
		}
		/* Delete multiple objects */
		elseif (Tools::getValue('submitDel'.$this->table))
		{
			if ($this->tabAccess['delete'] === '1')
			{
				if (isset($_POST[$this->table.'Box']))
				{
					$object = new $this->className();
					if (isset($object->noZeroObject) AND
						// Check if all object will be deleted
						(sizeof(call_user_func(array($this->className, $object->noZeroObject))) <= 1 OR sizeof($_POST[$this->table.'Box']) == sizeof(call_user_func(array($this->className, $object->noZeroObject)))))
						$this->_errors[] = Tools::displayError('You need at least one object.').' '.$this->table.' 
'.$this->table.'  '.Tools::displayError('(cannot load object)');
			if (!$object->updatePosition((int)(Tools::getValue('way')), (int)(Tools::getValue('position'))))
				$this->_errors[] = Tools::displayError('Failed to update the position.');
			else
				Tools::redirectAdmin($currentIndex.'&'.$this->table.'Orderby=position&'.$this->table.'Orderway=asc&conf=5'.(($id_category = (!empty($_REQUEST['id_category'])?$_REQUEST['id_category']:'1')) ? ('&id_category='.$id_category) : '').'&token='.Tools::getAdminTokenLite('AdminCatalog'));
		}
		else
			parent::postProcess(true);
	}
	protected function _validateSpecificPrice($id_shop, $id_currency, $id_country, $id_group, $price, $from_quantity, $reduction, $reduction_type, $from, $to)
	{
		if (!Validate::isUnsignedId($id_shop) OR !Validate::isUnsignedId($id_currency) OR !Validate::isUnsignedId($id_country) OR !Validate::isUnsignedId($id_group))
			$this->_errors[] = Tools::displayError('Wrong ID\'s');
		elseif ((empty($price) AND empty($reduction)) OR (!empty($price) AND !Validate::isPrice($price)) OR (!empty($reduction) AND !Validate::isPrice($reduction)))
			$this->_errors[] = Tools::displayError('Invalid price/reduction amount');
		elseif (!Validate::isUnsignedInt($from_quantity))
			$this->_errors[] = Tools::displayError('Invalid quantity');
		elseif ($reduction AND !Validate::isReductionType($reduction_type))
			$this->_errors[] = Tools::displayError('Please select a reduction type (amount or percentage)');
		elseif ($from AND $to AND (!Validate::isDateFormat($from) OR !Validate::isDateFormat($to)))
			$this->_errors[] = Tools::displayError('Wrong from/to date');
		else
			return true;
		return false;
	}
	// Checking customs feature
	private function checkFeatures($languages, $feature_id)
	{
		$rules = call_user_func(array('FeatureValue', 'getValidationRules'), 'FeatureValue');
		$feature = Feature::getFeature(Configuration::get('PS_LANG_DEFAULT'), $feature_id);
		$val = 0;
		foreach ($languages AS $language)
			if ($val = Tools::getValue('custom_'.$feature_id.'_'.$language['id_lang']))
			{
				$currentLanguage = new Language($language['id_lang']);
				if (Tools::strlen($val) > $rules['sizeLang']['value'])
					$this->_errors[] = Tools::displayError('name for feature').' '.$feature['name'].'  '.Tools::displayError('is too long in').' '.$currentLanguage->name;
				elseif (!call_user_func(array('Validate', $rules['validateLang']['value']), $val))
					$this->_errors[] = Tools::displayError('Valid name required for feature.').' '.$feature['name'].'  '.Tools::displayError('in').' '.$currentLanguage->name;
				if (sizeof($this->_errors))
					return (0);
				// Getting default language
				if ($language['id_lang'] == Configuration::get('PS_LANG_DEFAULT'))
					return ($val);
			}
		return (0);
	}
	/**
	 * Add or update a product image
	 *
	 * @param object $product Product object to add image
	 */
	public function addProductImage($product, $method = 'auto')
	{
		/* Updating an existing product image */
		if ($id_image = ((int)(Tools::getValue('id_image'))))
		{
			$image = new Image($id_image);
			if (!Validate::isLoadedObject($image))
				$this->_errors[] = Tools::displayError('An error occurred while loading object image.');
			else
			{
				if (($cover = Tools::getValue('cover')) == 1)
					Image::deleteCover($product->id);
				$image->cover = $cover;
				$this->validateRules('Image');
				$this->copyFromPost($image, 'image');
				if (sizeof($this->_errors) OR !$image->update())
					$this->_errors[] = Tools::displayError('An error occurred while updating image.');
				elseif (isset($_FILES['image_product']['tmp_name']) AND $_FILES['image_product']['tmp_name'] != NULL)
					$this->copyImage($product->id, $image->id, $method);
			}
		}
		/* Adding a new product image */
		elseif (isset($_FILES['image_product']['name']) && $_FILES['image_product']['name'] != NULL )
		{
			if ($error = checkImageUploadError($_FILES['image_product']))
				$this->_errors[] = $error;
			if (!sizeof($this->_errors) AND isset($_FILES['image_product']['tmp_name']) AND $_FILES['image_product']['tmp_name'] != NULL)
			{
				if (!Validate::isLoadedObject($product))
					$this->_errors[] = Tools::displayError('Cannot add image because product add failed.');
				elseif (substr($_FILES['image_product']['name'], -4) == '.zip')
					return $this->uploadImageZip($product);
				else
				{
					$image = new Image();
					$image->id_product = (int)($product->id);
					$_POST['id_product'] = $image->id_product;
					$image->position = Image::getHighestPosition($product->id) + 1;
					if (($cover = Tools::getValue('cover')) == 1)
						Image::deleteCover($product->id);
					$image->cover = !$cover ? !sizeof($product->getImages(Configuration::get('PS_LANG_DEFAULT'))) : true;
					$this->validateRules('Image', 'image');
					$this->copyFromPost($image, 'image');
					if (!sizeof($this->_errors))
					{
						if (!$image->add())
							$this->_errors[] = Tools::displayError('Error while creating additional image');
						else
							$this->copyImage($product->id, $image->id, $method);
						$id_image = $image->id;
					}
				}
			}
		}
		if (isset($image) AND Validate::isLoadedObject($image) AND !file_exists(_PS_PROD_IMG_DIR_.$image->getExistingImgPath().'.'.$image->image_format))
			$image->delete();
		if (sizeof($this->_errors))
			return false;
		@unlink(_PS_TMP_IMG_DIR_.'/product_'.$product->id.'.jpg');
		@unlink(_PS_TMP_IMG_DIR_.'/product_mini_'.$product->id.'.jpg');
		return ((isset($id_image) AND is_int($id_image) AND $id_image) ? $id_image : true);
	}
	public function uploadImageZip($product)
	{
		// Move the ZIP file to the img/tmp directory
		if (!$zipfile = tempnam(_PS_TMP_IMG_DIR_, 'PS') OR !move_uploaded_file($_FILES['image_product']['tmp_name'], $zipfile))
		{
			$this->_errors[] = Tools::displayError('An error occurred during the ZIP file upload.');
			return false;
		}
		// Unzip the file to a subdirectory
		$subdir = _PS_TMP_IMG_DIR_.uniqid().'/';
		try
		{
			if (!Tools::ZipExtract($zipfile, $subdir))
				throw new Exception(Tools::displayError('An error occurred while unzipping your file.'));
			$types = array('.gif' => 'image/gif', '.jpeg' => 'image/jpeg', '.jpg' => 'image/jpg', '.png' => 'image/png');
			$_POST['id_product'] = (int)$product->id;
			$imagesTypes = ImageType::getImagesTypes('products');
			$highestPosition = Image::getHighestPosition($product->id);
			foreach (scandir($subdir) as $file)
			{
				if ($file[0] == '.')
					continue;
				// Create image object
				$image = new Image();
				$image->id_product = (int)$product->id;
				$image->position = ++$highestPosition;
				$image->cover = ($highestPosition == 1 ? true : false);
				// Call automated copy function
				$this->validateRules('Image', 'image');
				$this->copyFromPost($image, 'image');
				if (sizeof($this->_errors))
					throw new Exception('');
				if (!$image->add())
					throw new Exception(Tools::displayError('Error while creating additional image'));
				if (filesize($subdir.$file) > $this->maxImageSize)
				{
					$image->delete();
					throw new Exception(Tools::displayError('Image is too large').' ('.(filesize($subdir.$file) / 1000).Tools::displayError('kB').'). '.Tools::displayError('Maximum allowed:').' '.($this->maxImageSize / 1000).Tools::displayError('kB'));
				}
				$ext = substr($file, -4);
				$type = (isset($types[$ext]) ? $types[$ext] : '');
				if (!isPicture(array('tmp_name' => $subdir.$file, 'type' => $type)))
				{
					$image->delete();
					throw new Exception(Tools::displayError('Image format not recognized, allowed formats are: .gif, .jpg, .png'));
				}
				
				if (!$new_path = $image->getPathForCreation())
					throw new Exception(Tools::displayError('An error occurred during new folder creation'));
				if (!imageResize($subdir.$file, $new_path.'.'.$image->image_format))
				{
					$image->delete();
					throw new Exception(Tools::displayError('An error occurred while resizing image.'));
				}
				foreach ($imagesTypes AS $k => $imageType)
					if (!imageResize($subdir.$file, _PS_PROD_IMG_DIR_.$image->getImgPath().'-'.stripslashes($imageType['name']).'.jpg', $imageType['width'], $imageType['height']))
					{
						$image->delete();
						throw new Exception(Tools::displayError('An error occurred while copying image.').' '.stripslashes($imageType['name']));
					}
				Module::hookExec('watermark', array('id_image' => $image->id, 'id_product' => $image->id_product));
			}
		}
		catch (Exception $e)
		{
			if ($error = $e->getMessage());
				$this->_errors[] = $error;
			Tools::deleteDirectory($subdir);
			return false;
		}
		Tools::deleteDirectory($subdir);
		return true;
	}
	/**
	 * Copy a product image
	 *
	 * @param integer $id_product Product Id for product image filename
	 * @param integer $id_image Image Id for product image filename
	 */
	public function copyImage($id_product, $id_image, $method = 'auto')
	{
		if (!isset($_FILES['image_product']['tmp_name']))
			return false;
		if ($error = checkImage($_FILES['image_product'], $this->maxImageSize))
			$this->_errors[] = $error;
		else
		{
			$image = new Image($id_image);
			
			if (!$new_path = $image->getPathForCreation())
				$this->_errors[] = Tools::displayError('An error occurred during new folder creation');
			if (!$tmpName = tempnam(_PS_TMP_IMG_DIR_, 'PS') OR !move_uploaded_file($_FILES['image_product']['tmp_name'], $tmpName))
				$this->_errors[] = Tools::displayError('An error occurred during the image upload');
			elseif (!imageResize($tmpName, $new_path.'.'.$image->image_format))
				$this->_errors[] = Tools::displayError('An error occurred while copying image.');
			elseif ($method == 'auto')
			{
				$imagesTypes = ImageType::getImagesTypes('products');
				foreach ($imagesTypes AS $k => $imageType)
					if (!imageResize($tmpName, $new_path.'-'.stripslashes($imageType['name']).'.'.$image->image_format, $imageType['width'], $imageType['height'], $image->image_format))
						$this->_errors[] = Tools::displayError('An error occurred while copying image:').' '.stripslashes($imageType['name']);
			}
			@unlink($tmpName);
			Module::hookExec('watermark', array('id_image' => $id_image, 'id_product' => $id_product));
		}
	}
	/**
	 * Add or update a product
	 *
	 * @global string $currentIndex Current URL in order to keep current Tab
	 */
	public function submitAddProduct($token = NULL)
	{
		global $cookie, $currentIndex, $link;
		$className = 'Product';
		$rules = call_user_func(array($this->className, 'getValidationRules'), $this->className);
		$defaultLanguage = new Language((int)(Configuration::get('PS_LANG_DEFAULT')));
		$languages = Language::getLanguages(false);
		/* Check required fields */
		foreach ($rules['required'] AS $field)
			if (($value = Tools::getValue($field)) == false AND $value != '0')
			{
				if (Tools::getValue('id_'.$this->table) AND $field == 'passwd')
					continue;
				$this->_errors[] = $this->l('the field').' '.call_user_func(array($className, 'displayFieldName'), $field, $className).'  '.$this->l('is required');
			}
		/* Check multilingual required fields */
		foreach ($rules['requiredLang'] AS $fieldLang)
			if (!Tools::getValue($fieldLang.'_'.$defaultLanguage->id))
				$this->_errors[] = $this->l('the field').' '.call_user_func(array($className, 'displayFieldName'), $fieldLang, $className).'  '.$this->l('is required at least in').' '.$defaultLanguage->name;
		/* Check fields sizes */
		foreach ($rules['size'] AS $field => $maxLength)
			if ($value = Tools::getValue($field) AND Tools::strlen($value) > $maxLength)
				$this->_errors[] = $this->l('the field').' '.call_user_func(array($className, 'displayFieldName'), $field, $className).'  '.$this->l('is too long').' ('.$maxLength.' '.$this->l('chars max').')';
		if (isset($_POST['description_short']))
		{
			$saveShort = $_POST['description_short'];
			$_POST['description_short'] = strip_tags($_POST['description_short']);
		}
		/* Check description short size without html */
		foreach ($languages AS $language)
			if ($value = Tools::getValue('description_short_'.$language['id_lang']))
				if (Tools::strlen(strip_tags($value)) > 400)
					$this->_errors[] = $this->l('the field').' '.call_user_func(array($className, 'displayFieldName'), 'description_short').' ('.$language['name'].')  '.$this->l('is too long').' : 400 '.$this->l('chars max').' ('.$this->l('count now').' '.Tools::strlen(strip_tags($value)).')';
		/* Check multilingual fields sizes */
		foreach ($rules['sizeLang'] AS $fieldLang => $maxLength)
			foreach ($languages AS $language)
				if ($value = Tools::getValue($fieldLang.'_'.$language['id_lang']) AND Tools::strlen($value) > $maxLength)
					$this->_errors[] = $this->l('the field').' '.call_user_func(array($className, 'displayFieldName'), $fieldLang, $className).' ('.$language['name'].')  '.$this->l('is too long').' ('.$maxLength.' '.$this->l('chars max').')';
		if (isset($_POST['description_short']))
			$_POST['description_short'] = $saveShort;
		/* Check fields validity */
		foreach ($rules['validate'] AS $field => $function)
			if ($value = Tools::getValue($field))
				if (!Validate::$function($value))
					$this->_errors[] = $this->l('the field').' '.call_user_func(array($className, 'displayFieldName'), $field, $className).'  '.$this->l('is invalid');
		/* Check multilingual fields validity */
		foreach ($rules['validateLang'] AS $fieldLang => $function)
			foreach ($languages AS $language)
				if ($value = Tools::getValue($fieldLang.'_'.$language['id_lang']))
					if (!Validate::$function($value))
						$this->_errors[] = $this->l('the field').' '.call_user_func(array($className, 'displayFieldName'), $fieldLang, $className).' ('.$language['name'].')  '.$this->l('is invalid');
		/* Categories */
		$productCats = '';
		if (!Tools::isSubmit('categoryBox') OR !sizeof(Tools::getValue('categoryBox')))
			$this->_errors[] = $this->l('product must be in at least one Category');
		if (!is_array(Tools::getValue('categoryBox')) OR !in_array(Tools::getValue('id_category_default'), Tools::getValue('categoryBox')))
			$this->_errors[] = $this->l('product must be in the default category');
		/* Tags */
		foreach ($languages AS $language)
			if ($value = Tools::getValue('tags_'.$language['id_lang']))
				if (!Validate::isTagsList($value))
					$this->_errors[] = $this->l('Tags list').' ('.$language['name'].') '.$this->l('is invalid');
		if (!sizeof($this->_errors))
		{
			$id = (int)(Tools::getValue('id_'.$this->table));
			$tagError = true;
			/* Update an existing product */
			if (isset($id) AND !empty($id))
			{
				$object = new $this->className($id);
				if (Validate::isLoadedObject($object))
				{
					$this->_removeTaxFromEcotax();
					$this->copyFromPost($object, $this->table);
					if ($object->update())
					{
						if ($id_reason = (int)Tools::getValue('id_mvt_reason') AND (int)Tools::getValue('mvt_quantity') > 0 AND $id_reason > 0)
						{
							$reason = new StockMvtReason((int)$id_reason);
							$qty = Tools::getValue('mvt_quantity') * $reason->sign;
							if (!$object->addStockMvt($qty, (int)$id_reason, NULL, NULL, (int)$cookie->id_employee))
								$this->_errors[] = Tools::displayError('An error occurred while updating qty.');
						}
						$this->updateAccessories($object);
						$this->updateDownloadProduct($object);
						if (!$this->updatePackItems($object))
							$this->_errors[] = Tools::displayError('An error occurred while adding products to the pack.');
						elseif (!$object->updateCategories($_POST['categoryBox'], true))
							$this->_errors[] = Tools::displayError('An error occurred while linking object.').' '.$this->table.'  '.Tools::displayError('To categories');
						elseif (!$this->updateTags($languages, $object))
							$this->_errors[] = Tools::displayError('An error occurred while adding tags.');
						elseif ($id_image = $this->addProductImage($object, Tools::getValue('resizer')))
						{
							$currentIndex .= '&image_updated='.(int)Tools::getValue('id_image');
							Hook::updateProduct($object);
							Search::indexation(false, $object->id);
							if (Tools::getValue('resizer') == 'man' && isset($id_image) AND is_int($id_image) AND $id_image)
								Tools::redirectAdmin($currentIndex.'&id_product='.$object->id.'&id_category='.(!empty($_REQUEST['id_category'])?$_REQUEST['id_category']:'1').'&edit='.strval(Tools::getValue('productCreated')).'&id_image='.$id_image.'&imageresize&toconf=4&submitAddAndStay='.((Tools::isSubmit('submitAdd'.$this->table.'AndStay') OR Tools::getValue('productCreated') == 'on') ? 'on' : 'off').'&token='.(($token ? $token : $this->token)));
							// Save and preview
							if (Tools::isSubmit('submitAddProductAndPreview'))
							{
								$preview_url = ($link->getProductLink($this->getFieldValue($object, 'id'), $this->getFieldValue($object, 'link_rewrite', (int)($cookie->id_lang)), Category::getLinkRewrite($this->getFieldValue($object, 'id_category_default'), (int)($cookie->id_lang))));
								if (!$object->active)
								{
									$admin_dir = dirname($_SERVER['PHP_SELF']);
									$admin_dir = substr($admin_dir, strrpos($admin_dir,'/') + 1);
									$token = Tools::encrypt('PreviewProduct'.$object->id);
									if (strpos($preview_url, '?') === false)
										$preview_url .= '?';
									else
										$preview_url .= '&';
									$preview_url .= 'adtoken='.$token.'&ad='.$admin_dir;
								}
								Tools::redirectAdmin($preview_url);
							} elseif (Tools::isSubmit('submitAdd'.$this->table.'AndStay') OR ($id_image AND $id_image !== true)) // Save and stay on same form
							// Save and stay on same form
							if (Tools::isSubmit('submitAdd'.$this->table.'AndStay'))
								Tools::redirectAdmin($currentIndex.'&id_product='.$object->id.'&id_category='.(!empty($_REQUEST['id_category'])?$_REQUEST['id_category']:'1').'&addproduct&conf=4&tabs='.(int)(Tools::getValue('tabs')).'&token='.($token ? $token : $this->token));
							// Default behavior (save and back)
							Tools::redirectAdmin($currentIndex.'&id_category='.(!empty($_REQUEST['id_category'])?$_REQUEST['id_category']:'1').'&conf=4&token='.($token ? $token : $this->token).'&onredirigeici');
						}
					}
					else
						$this->_errors[] = Tools::displayError('An error occurred while updating object.').' '.$this->table.'  ('.Db::getInstance()->getMsgError().')';
				}
				else
					$this->_errors[] = Tools::displayError('An error occurred while updating object.').' '.$this->table.'  ('.Tools::displayError('Cannot load object').')';
			}
			/* Add a new product */
			else
			{
				$object = new $this->className();
				$this->_removeTaxFromEcotax();
				$this->copyFromPost($object, $this->table);
				if ($object->add())
				{
					$this->updateAccessories($object);
					if (!$this->updatePackItems($object))
						$this->_errors[] = Tools::displayError('An error occurred while adding products to the pack.');
					$this->updateDownloadProduct($object);
					if (!sizeof($this->_errors))
					{
						if (!$object->updateCategories($_POST['categoryBox']))
							$this->_errors[] = Tools::displayError('An error occurred while linking object.').' '.$this->table.'  '.Tools::displayError('To categories');
						elseif (!$this->updateTags($languages, $object))
							$this->_errors[] = Tools::displayError('An error occurred while adding tags.');
						elseif ($id_image = $this->addProductImage($object))
						{
							Hook::addProduct($object);
							Search::indexation(false, $object->id);
							// Save and preview
							if (Tools::isSubmit('submitAddProductAndPreview'))
							{
								$preview_url = ($link->getProductLink($this->getFieldValue($object, 'id'), $this->getFieldValue($object, 'link_rewrite', (int)($cookie->id_lang)), Category::getLinkRewrite($this->getFieldValue($object, 'id_category_default'), (int)($cookie->id_lang))));
								if (!$object->active)
								{
									$admin_dir = dirname($_SERVER['PHP_SELF']);
									$admin_dir = substr($admin_dir, strrpos($admin_dir,'/') + 1);
									$token = Tools::encrypt('PreviewProduct'.$object->id);
									$preview_url .= '&adtoken='.$token.'&ad='.$admin_dir;
								}
								Tools::redirectAdmin($preview_url);
							}
							if (Tools::getValue('resizer') == 'man' && isset($id_image) AND is_int($id_image) AND $id_image)
								Tools::redirectAdmin($currentIndex.'&id_product='.$object->id.'&id_category='.(!empty($_REQUEST['id_category'])?$_REQUEST['id_category']:'1').'&id_image='.$id_image.'&imageresize&toconf=3&submitAddAndStay='.(Tools::isSubmit('submitAdd'.$this->table.'AndStay') ? 'on' : 'off').'&token='.(($token ? $token : $this->token)));
							// Save and stay on same form
							if (Tools::isSubmit('submitAdd'.$this->table.'AndStay'))
								Tools::redirectAdmin($currentIndex.'&id_product='.$object->id.'&id_category='.(!empty($_REQUEST['id_category'])?$_REQUEST['id_category']:'1').'&addproduct&conf=3&tabs='.(int)(Tools::getValue('tabs')).'&token='.($token ? $token : $this->token));
							// Default behavior (save and back)
							Tools::redirectAdmin($currentIndex.'&id_category='.(!empty($_REQUEST['id_category'])?$_REQUEST['id_category']:'1').'&conf=3&token='.($token ? $token : $this->token));
						}
					}
					else
						$object->delete();
				}
				else
					$this->_errors[] = Tools::displayError('An error occurred while creating object.').' '.$this->table.' ';
			}
		}
	}
	private function _removeTaxFromEcotax()
	{
		$ecotaxTaxRate = Tax::getProductEcotaxRate();
		if ($ecotax = Tools::getValue('ecotax'))
			$_POST['ecotax'] = Tools::ps_round(Tools::getValue('ecotax') / (1 + $ecotaxTaxRate / 100), 6);
	}
	private function _applyTaxToEcotax($product)
	{
		$ecotaxTaxRate = Tax::getProductEcotaxRate();
		if ($product->ecotax)
			$product->ecotax = Tools::ps_round($product->ecotax * (1 + $ecotaxTaxRate / 100), 2);
	}
	/**
	 * Update product download
	 *
	 * @param object $product Product
	 */
	public function updateDownloadProduct($product)
	{
		/* add or update a virtual product */
		if (Tools::getValue('is_virtual_good') == 'true')
		{
			if (!Tools::getValue('virtual_product_name'))
			{
				$this->_errors[] = $this->l('the field').' '.$this->l('display filename').'  '.$this->l('is required');
				return false;
			}
			if (Tools::getValue('virtual_product_nb_days') === false)
			{
				$this->_errors[] = $this->l('the field').' '.$this->l('number of days').'  '.$this->l('is required');
				return false;
			}
			if (Tools::getValue('virtual_product_expiration_date') AND !Validate::isDate(Tools::getValue('virtual_product_expiration_date')))
			{
				$this->_errors[] = $this->l('the field').' '.$this->l('expiration date').'  '.$this->l('is not valid');
				return false;
			}
			// The oos behavior MUST be "Deny orders" for virtual products
			if (Tools::getValue('out_of_stock') != 0)
			{
				$this->_errors[] = $this->l('The "when out of stock" behavior selection must be "deny order" for virtual products');
				return false;
			}
			$download = new ProductDownload(Tools::getValue('virtual_product_id'));
			$download->id_product          = $product->id;
			$download->display_filename    = Tools::getValue('virtual_product_name');
			$download->physically_filename = Tools::getValue('virtual_product_filename') ? Tools::getValue('virtual_product_filename') : ProductDownload::getNewFilename();
			$download->date_deposit        = date('Y-m-d H:i:s');
			$download->date_expiration     = Tools::getValue('virtual_product_expiration_date') ? Tools::getValue('virtual_product_expiration_date').' 23:59:59' : '';
			$download->nb_days_accessible  = Tools::getValue('virtual_product_nb_days');
			$download->nb_downloadable     = Tools::getValue('virtual_product_nb_downloable');
			$download->active              = 1;
			if ($download->save())
				return true;
		}
		else
		{
			/* unactive download product if checkbox not checked */
			if ($id_product_download = ProductDownload::getIdFromIdProduct($product->id))
			{
				$productDownload = new ProductDownload($id_product_download);
				$productDownload->date_expiration = date('Y-m-d H:i:s', time()-1);
				$productDownload->active = 0;
				return $productDownload->save();
			}
		}
		return false;
	}
	/**
	 * Update product accessories
	 *
	 * @param object $product Product
	 */
	public function updateAccessories($product)
	{
		$product->deleteAccessories();
		if ($accessories = Tools::getValue('inputAccessories'))
		{
			$accessories_id = array_unique(explode('-', $accessories));
			if (sizeof($accessories_id))
			{
				array_pop($accessories_id);
				$product->changeAccessories($accessories_id);
			}
		}
	}
	/**
	 * Update product tags
	 *
	 * @param array Languages
	 * @param object $product Product
	 * @return boolean Update result
	 */
	public function updateTags($languages, $product)
	{
		$tagError = true;
		/* Reset all tags for THIS product */
		if (!Db::getInstance()->Execute('
		DELETE FROM `'._DB_PREFIX_.'product_tag`
		WHERE `id_product` = '.(int)($product->id)))
			return false;
		/* Assign tags to this product */
		foreach ($languages AS $language)
			if ($value = Tools::getValue('tags_'.$language['id_lang']))
				$tagError &= Tag::addTags($language['id_lang'], (int)($product->id), $value);
		return $tagError;
	}
	public function display($token = NULL)
	{
		global $currentIndex, $cookie;
		if (($id_category = (int)Tools::getValue('id_category')))
			$currentIndex .= '&id_category='.$id_category;
		$this->getList((int)($cookie->id_lang), !$cookie->__get($this->table.'Orderby') ? 'position' : NULL, !$cookie->__get($this->table.'Orderway') ? 'ASC' : NULL);
		$id_category = (Tools::getValue('id_category',1));
		if (!$id_category)
			$id_category = 1;
		echo ''.(!$this->_listTotal ? ($this->l('No products found')) : ($this->_listTotal.' '.($this->_listTotal > 1 ? $this->l('products') : $this->l('product')))).' '.
		$this->l('in category').' "'.stripslashes($this->_category->getName()).'" ';
		if ($this->tabAccess['add'] === '1')
			echo '';
		$this->displayList($token);
		echo '
';
	}
	/**
	 * displayList show ordered list of current category
	 *
	 * @param mixed $token
	 * @return void
	 */
	public function displayList($token = NULL)
	{
		global $currentIndex;
		/* Display list header (filtering, pagination and column names) */
		$this->displayListHeader($token);
		if (!sizeof($this->_list))
			echo ''.$this->l('No items found').' 
			
				 
			
				'.$id_category.'
			 
			';
			for ($i = 2; $i < $level; $i++)
				echo ''.stripslashes($current['infos']['name']).'  
		 ';
		if ($level > 1)
			$has_suite[] = ($todo == $doneC ? 0 : 1);
		if (isset($categories[$id_category]))
			foreach ($categories[$id_category] AS $key => $row)
				if ($key != 'infos')
					self::recurseCategoryForInclude($id_obj, $indexedCategories, $categories, $categories[$id_category][$key], $key, $id_category_default, $has_suite);
	}
	public function displayErrors()
	{
		if ($this->includeSubTab('displayErrors'))
			;
		elseif ($nbErrors = sizeof($this->_errors))
		{
			echo '
				
				'.$nbErrors.' '.($nbErrors > 1 ? $this->l('errors') : $this->l('error')).'
				
';
			foreach ($this->_errors AS $error)
				echo ''.$error.' ';
			echo '
				 
			 ';
		}
	}
	private function _displayDraftWarning($active)
	{
		return '';
	}
	public function displayForm($isMainTab = true)
	{
		global $currentIndex, $link, $cookie;
		parent::displayForm();
		if ($id_category_back = (int)(Tools::getValue('id_category')))
			$currentIndex .= '&id_category='.$id_category_back;
		if (!($obj = $this->loadObject(true)))
			return;
		$currency = new Currency(Configuration::get('PS_CURRENCY_DEFAULT'));
		if ($obj->id)
			$currentIndex .= '&id_product='.$obj->id;
		echo '
		'.$this->l('Current product:').' '.$this->l('no name').'  
		
		
		
				 '.$this->l('You must save this product before adding specific prices').'. ';
	}
	private function _getFinalPrice($specificPrice, $productPrice, $taxRate)
	{
		$price = Tools::ps_round((float)($specificPrice['price']) ? $specificPrice['price'] : $productPrice, 2);
		if (!(float)($specificPrice['reduction']))
			return (float)($specificPrice['price']);
		return ($specificPrice['reduction_type'] == 'amount') ? ($price - $specificPrice['reduction'] / (1 + $taxRate / 100)) : ($price - $price * $specificPrice['reduction']);
	}
	protected function _displaySpecificPriceModificationForm($defaultCurrency, $shops, $currencies, $countries, $groups)
	{
		global $currentIndex;
		if (!($obj = $this->loadObject()))
			return;
		$specificPrices = SpecificPrice::getByProductId((int)($obj->id));
		$specificPricePriorities = SpecificPrice::getPriority((int)($obj->id));
		$default_country = new Country((int)Configuration::get('PS_COUNTRY_DEFAULT'));
		$taxRate = TaxRulesGroup::getTaxesRate($obj->id_tax_rules_group, Configuration::get('PS_COUNTRY_DEFAULT'), 0, 0);
		$tmp = array();
		foreach ($shops as $shop)
			$tmp[$shop['id_shop']] = $shop;
		$shops = $tmp;
		$tmp = array();
		foreach ($currencies as $currency)
			$tmp[$currency['id_currency']] = $currency;
		$currencies = $tmp;
		$tmp = array();
		foreach ($countries as $country)
			$tmp[$country['id_country']] = $country;
		$countries = $tmp;
		$tmp = array();
		foreach ($groups as $group)
			$tmp[$group['id_group']] = $group;
		$groups = $tmp;
		echo '
		'.$this->l('Current specific prices').' 
		
			
				
					'.$this->l('Currency').' 
					'.$this->l('Country').' 
					'.$this->l('Group').' 
					'.$this->l('Price').' '.($default_country->display_tax_label ? $this->l('(tax excl.)') : '').' 
					'.$this->l('Reduction').' 
					'.$this->l('Period').' 
					'.$this->l('From (quantity)').' 
					'.$this->l('Final price').' '.($default_country->display_tax_label ? $this->l('(tax excl.)') : '').' 
					'.$this->l('Action').' 
				 
			 
			';
		if (!is_array($specificPrices) OR !sizeof($specificPrices))
			echo '
				
					'.$this->l('No specific prices').' 
				 ';
		else
		{
			$i = 0;
			foreach ($specificPrices as $specificPrice)
			{
				$current_specific_currency = $currencies[($specificPrice['id_currency'] ? $specificPrice['id_currency'] : $defaultCurrency->id)];
				if ($specificPrice['reduction_type'] == 'percentage')
					$reduction = ($specificPrice['reduction'] * 100).' %';
				else
					$reduction = Tools::displayPrice(Tools::ps_round($specificPrice['reduction'], 2), $current_specific_currency);
				if ($specificPrice['from'] == '0000-00-00 00:00:00' AND $specificPrice['to'] == '0000-00-00 00:00:00')
					$period = $this->l('Unlimited');
				else
					$period = $this->l('From').' '.($specificPrice['from'] != '0000-00-00 00:00:00' ? $specificPrice['from'] : '0000-00-00 00:00:00').'
					'.($specificPrice['id_currency'] ? $currencies[$specificPrice['id_currency']]['name'] : $this->l('All currencies')).' 
					'.($specificPrice['id_country'] ? $countries[$specificPrice['id_country']]['name'] : $this->l('All countries')).' 
					'.($specificPrice['id_group'] ? $groups[$specificPrice['id_group']]['name'] : $this->l('All groups')).' 
					'.Tools::displayPrice((float)$specificPrice['price'], $current_specific_currency).' 
					'.$reduction.' 
					'.$period.' 
					'.$specificPrice['from_quantity'].'
					 '.Tools::displayPrice(Tools::ps_round((float)($this->_getFinalPrice($specificPrice, (float)($obj->price), $taxRate)), 2), $current_specific_currency).'  ';
				$i++;
			}
		}
		echo '
			 
		
';
		echo '
		
		';
		echo '
		'.$this->l('Priorities management').' 
		
				'.$this->l('Sometimes one customer could fit in multiple rules, priorities allows you to define which rule to apply.').'
		
	'.$this->l('Priorities:').' 
		
			
				'.$this->l('Currency').' 
				'.$this->l('Country').' 
				'.$this->l('Group').' 
			 
			>
			
				'.$this->l('Currency').' 
				'.$this->l('Country').' 
				'.$this->l('Group').' 
			 
			>
			
				'.$this->l('Currency').' 
				'.$this->l('Country').' 
				'.$this->l('Group').' 
			 
		
		
			'.$this->l('Apply to all products').' 
		
		
			
		';
	}
	protected function _displaySpecificPriceAdditionForm($defaultCurrency, $shops, $currencies, $countries, $groups)
	{
		if (!($product = $this->loadObject()))
			return;
		$default_country = new Country((int)Configuration::get('PS_COUNTRY_DEFAULT'));
		echo '
		';
		foreach ($languages as $language)
		{
			$fieldName = 'label_'.$type.'_'.(int)($id_customization_field).'_'.(int)($language['id_lang']);
			$text = (isset($label[(int)($language['id_lang'])])) ? $label[(int)($language['id_lang'])]['name'] : '';
			echo '
';
		}
		$required = (isset($label[(int)($language['id_lang'])])) ? $label[(int)($language['id_lang'])]['required'] : false;
		echo '
					 '.$this->l('required').' 
				
';
	}
	private function _displayLabelFields(&$obj, &$labels, $languages, $defaultLanguage, $type)
	{
		$type = (int)($type);
		$labelGenerated = array(_CUSTOMIZE_FILE_ => (isset($labels[_CUSTOMIZE_FILE_]) ? count($labels[_CUSTOMIZE_FILE_]) : 0), _CUSTOMIZE_TEXTFIELD_ => (isset($labels[_CUSTOMIZE_TEXTFIELD_]) ? count($labels[_CUSTOMIZE_TEXTFIELD_]) : 0));
		$fieldIds = $this->_getCustomizationFieldIds($labels, $labelGenerated, $obj);
		if (isset($labels[$type]))
			foreach ($labels[$type] AS $id_customization_field => $label)
				$this->_displayLabelField($label, $languages, $defaultLanguage, $type, $fieldIds, (int)($id_customization_field));
	}
	function displayFormCustomization($obj, $languages, $defaultLanguage)
	{
		parent::displayForm();
		$labels = $obj->getCustomizationFields();
		$defaultIso = Language::getIsoById($defaultLanguage);
		$hasFileLabels = (int)($this->getFieldValue($obj, 'uploadable_files'));
		$hasTextLabels = (int)($this->getFieldValue($obj, 'text_fields'));
		echo '
			
				
					'.$this->l('Add or modify customizable properties').'  
			
			'.$this->l('Filename:').'  
				
				 
				'.$this->l('Description:').'  
				
				 
				'.$this->l('File').' 
				
				 
				
					
				*  '.$this->l('Required field').'
			 
		
			
				
					'.$this->l('Attachments for this product:').'
					';
			foreach ($attach1 AS $attach)
				echo ''.$attach['name'].' ';
			echo '	 
						'.$this->l('Remove').' >>
					 
				 
				
					'.$this->l('Available attachments:').'
					';
			foreach ($attach2 AS $attach)
				echo ''.$attach['name'].' ';
			echo '	 
						<< '.$this->l('Add').'
					 
				
				 
			 
		
		 
		
			1. '.$this->l('Info.').' 
			
			'.$this->l('Product global information').'  - ';
		$preview_url = '';
		if (isset($obj->id))
		{
			$preview_url = ($link->getProductLink($this->getFieldValue($obj, 'id'), $this->getFieldValue($obj, 'link_rewrite', $this->_defaultFormLanguage), Category::getLinkRewrite($this->getFieldValue($obj, 'id_category_default'), (int)($cookie->id_lang))));
			if (!$obj->active)
			{
				$admin_dir = dirname($_SERVER['PHP_SELF']);
				$admin_dir = substr($admin_dir, strrpos($admin_dir,'/') + 1);
				$token = Tools::encrypt('PreviewProduct'.$obj->id);
				$preview_url .= $obj->active ? '' : '&adtoken='.$token.'&ad='.$admin_dir;
			}
			echo '
			
			 
			';
			if (file_exists(_PS_MODULE_DIR_.'statsproduct/statsproduct.php'))
				echo ' - 
';
		}
		echo '
			
					
						'.$this->l('Status:').' 
						
							'.$this->l('View product in shop').' )').' 
					 
					active ? 'style="display:none"' : '').'>
						'.$this->l('Options:').' 
						
							 
					 
					
						'.$this->l('Condition:').' 
						
							
								condition == 'new' ? 'selected="selected"' : '').'>'.$this->l('New').' 
								condition == 'used' ? 'selected="selected"' : '').'>'.$this->l('Used').' 
								condition == 'refurbished' ? 'selected="selected"' : '').'>'.$this->l('Refurbished').' 
							 
						 
					 
					
						'.$this->l('Manufacturer:').' 
						
							
								-- '.$this->l('Choose (optional)').' -- ';
		if ($id_manufacturer = $this->getFieldValue($obj, 'id_manufacturer'))
			echo '				'.Manufacturer::getNameById($id_manufacturer).' 
								---------- ';
		echo '
							    '.$this->l('Create').'  
					 
					
						'.$this->l('Supplier:').' 
						
							
								-- '.$this->l('Choose (optional)').' -- ';
		if ($id_supplier = $this->getFieldValue($obj, 'id_supplier'))
			echo '				'.Supplier::getNameById($id_supplier).' 
								---------- ';
		echo '
							    '.$this->l('Create').'  
					 
				
				
				
					
		
			l('Is this a downloadable product?') ?> 
			id OR !$productDownload->active) echo 'style="display:none;"' ?> >
	
		
			l('Your download repository is not writable.'); ?>
	
			id) echo '
' ?>
				
	checkFile()): ?>
				
		id): ?>
					
						l('This product is missing') ?>:
		
					l('Your server\'s maximum upload file size is') . ': ' . ini_get('upload_max_filesize') ?>
					
					l('Upload a file') ?> 
					
					
					
					
						
					l('Delete this file') ?> 
	
					
					l('This is the link').': '.$productDownload->getHtmlLink(false, true) ?>
					
l('Delete this file') ?> 
	
				
				
					l('Filename') ?> 
					l('The full filename with its extension (e.g., Book.pdf)') ?> 
				
				 
	 
	'.$this->l('Pre-tax wholesale price:').' 
						
							'.($currency->format % 2 != 0 ? $currency->sign.' ' : '').''.$this->l('The wholesale price at which you bought this product').' 
						 
					';
					echo '
					
						'.$this->l('Pre-tax retail price:').' 
						
							'.($currency->format % 2 != 0 ? $currency->sign.' ' : '').' * 
							'.$this->l('The pre-tax retail price to sell this product').' 
						 
					 ';
					$tax_rules_groups = TaxRulesGroup::getTaxRulesGroups(true);
					$taxesRatesByGroup = TaxRulesGroup::getAssociatedTaxRatesByIdCountry(Country::getDefaultCountryId());
					$ecotaxTaxRate = Tax::getProductEcotaxRate();
					echo '';
					echo '
					
						'.$this->l('Tax rule:').' 
						
					
					 
						 '.$this->l('No Tax').' ';
						foreach ($tax_rules_groups AS $tax_rules_group)
							echo 'getFieldValue($obj, 'id_tax_rules_group') == $tax_rules_group['id_tax_rules_group']) ? ' selected="selected"' : '').'>'.Tools::htmlentitiesUTF8($tax_rules_group['name']).' ';
				echo ' 
				'.$this->l('Create').'  
				';
				if (Tax::excludeTaxeOption())
				{
					echo ''.$this->l('Taxes are currently disabled').'  ('.$this->l('Tax options').'  
					 
				';
				if (Configuration::get('PS_USE_ECOTAX'))
					echo '
					
						'.$this->l('Eco-tax (tax incl.):').' 
						
							'.($currency->format % 2 != 0 ? $currency->sign.' ' : '').'('.$this->l('already included in price').') 
						 
					 ';
				if ($default_country->display_tax_label)
				{
					echo '
						
							'.$this->l('Retail price with tax:').' 
							
								'.($currency->format % 2 != 0 ? ' '.$currency->sign : '').'  
						 ';
				} else {
					echo '
						'.$this->l('Unit price without tax:').' 
						
							'.($currency->format % 2 != 0 ? ' '.$currency->sign : '').' '.$this->l('or').' '.($currency->format % 2 != 0 ? ' '.$currency->sign : '').'0.00 '.($currency->format % 2 == 0 ? ' '.$currency->sign : '').' '.$this->l('per').' '.$this->getFieldValue($obj, 'unity').'  '.$this->l('with tax') : '').' 
							'.$this->l('Eg. $15 per Lb').'
						 
					 
					
						  
						
							'.$this->l('Display "on sale" icon on product page and text on product listing').' 
						 
					 
					
						'.$this->l('Final retail price:').' 
							
							'.($currency->format % 2 != 0 ? $currency->sign.' ' : '').' ('.$this->l('tax incl.').') 
							 
							';
							if ($default_country->display_tax_label)
								echo ' / ';
							 echo ($currency->format % 2 != 0 ? $currency->sign.' ' : '').' 
						 
					 
					
						  
						
							'.$this->l('You can define many discounts and specific price rules in the Prices tab').'
						 
					 
					'.$this->l('Stock Movement:').' 
								
									
										-- ';
							$reasons = StockMvtReason::getStockMvtReasons((int)$cookie->id_lang);
							foreach ($reasons AS $reason)
								echo ''.$reason['name'].' ';
							echo ' 
									 
							
								  
								
									'.$this->l('Choose the reason and enter the quantity that you want to increase or decrease in your stock').'
								 
							 ';
						}
						else
							echo ''.$this->l('Initial stock:').' 
									
										 ';
						echo  '
								'.$this->l('Minimum quantity:').' 
									
										'.$this->l('The minimum quantity to buy this product (set to 1 to disable this feature)').'
									 
								 ';
					}
					if ($obj->id)
						echo '
							'.$this->l('Quantity in stock:').' 
								'.$qty.' 
								  
								
									'.$this->l('You used combinations, for this reason you can\'t edit your stock quantity here, but in the Combinations tab').'
								 
							 ';
				}
				else
					echo '
							'.$this->l('The stock management is disabled').' 
						 ';
						
				echo '
					
						'.$this->l('Additional shipping cost:').' 
						
							'.$this->l('Carrier tax will be applied.').'
						 
					 
					
						'.$this->l('Displayed text when in-stock:').' 
						';
		foreach ($this->_languages as $language)
			echo '		
								'.$this->l('Forbidden characters:').' <>;=#{}   
							
';
		echo '			 
					 
					
						'.$this->l('Displayed text when allowed to be back-ordered:').' 
						';
		foreach ($this->_languages as $language)
			echo '		
								'.$this->l('Forbidden characters:').' <>;=#{}   
							
';
			echo '	 
					 
					
					
						'.$this->l('When out of stock:').' 
						
							'.$this->l('Deny orders').' 
							'.$this->l('Allow orders').' 
							'.$this->l('Default:').' '.$this->l(((int)(Configuration::get('PS_ORDER_OUT_OF_STOCK')) ? 'Allow orders' : 'Deny orders')).'  ('.$this->l('as set in').' '.$this->l('Preferences').' ) 
						 
					 
					
						
							 
					 
					
						'.$this->l('Default category:').' 
						'.$this->l('Please check a category in order to select the default category.').'
						';
						if (Tools::isSubmit('categoryBox'))
						{
							$postCat = Tools::getValue('categoryBox');
							$selectedCat = Category::getSimpleCategories($this->_defaultFormLanguage, false, true, 'AND c.`id_category` IN ('.(empty($postCat) ? '1' : implode(',', $postCat)).')');
							echo '';
						}
						if ($obj->id)
							$selectedCat = Product::getProductCategoriesFull($obj->id, $this->_defaultFormLanguage);
						else if(!Tools::isSubmit('categoryBox'))
							$selectedCat[] = array('id_category' => 1, 'name' => $this->l('Home'));
						echo '';
						
							foreach($selectedCat AS $cat)
								echo 'id_category_default == $cat['id_category'] ? 'selected' : '').'>'.$cat['name'].' ';
						echo ' 
						  
					 
					
						
						';
					// Translations are not automatic for the moment ;)
					$trads = array(
						 'Home' => $this->l('Home'), 
						 'selected' => $this->l('selected'), 
						 'Collapse All' => $this->l('Collapse All'), 
						 'Expand All' => $this->l('Expand All'), 
						 'Check All' => $this->l('Check All'), 
						 'Uncheck All'  => $this->l('Uncheck All')
					);
					echo Helper::renderAdminCategorieTree($trads, $selectedCat).'
						 
					 
					
						 
						'.$this->l('Short description:').'('.$this->l('appears in search results').')  
						';
		foreach ($this->_languages as $language)
			echo '		
								
							
';
		echo '		 
					 
					
						'.$this->l('Description:').' 
						';
		foreach ($this->_languages as $language)
			echo '		
								
							
';
		echo '		 
					 ';
				echo '
					
						'.$this->l('Tags:').' 
						';
				if ($obj->id)
					$obj->tags = Tag::getProductTags((int)$obj->id);
				foreach ($this->_languages as $language)
				{
					echo '
							'.$this->l('Forbidden characters:').' !<>;?=+#"°{}_$%   
						  
';
				}
				echo '	'.$this->l('Tags separated by commas (e.g., dvd, dvd player, hifi)').'
						 
					 ';
				$accessories = Product::getAccessoriesLight((int)($cookie->id_lang), $obj->id);
				if ($postAccessories = Tools::getValue('inputAccessories'))
				{
					$postAccessoriesTab = explode('-', Tools::getValue('inputAccessories'));
					foreach ($postAccessoriesTab AS $accessoryId)
						if (!$this->haveThisAccessory($accessoryId, $accessories) AND $accessory = Product::getAccessoryById($accessoryId))
							$accessories[] = $accessory;
				}
					echo '
					
						'.$this->l('Accessories:').''.$this->l('(Do not forget to Save the product afterward)').'  
						
							';
					foreach ($accessories as $accessory)
						echo $accessory['name'].(!empty($accessory['reference']) ? ' ('.$accessory['reference'].')' : '').' 
';
					echo '
 
					 
					
						
							 
					 
				
			
			 ';
			// TinyMCE
		global $cookie;
		$iso = Language::getIsoById((int)($cookie->id_lang));
		$isoTinyMCE = (file_exists(_PS_ROOT_DIR_.'/js/tiny_mce/langs/'.$iso.'.js') ? $iso : 'en');
		$ad = dirname($_SERVER["PHP_SELF"]);
		echo '
			
			
			
			';
		$categoryBox = Tools::getValue('categoryBox', array());
		
	}
	function displayFormImages($obj, $token = NULL)
	{
		global $cookie, $currentIndex, $attributeJs, $images;
		$countImages = (int)Db::getInstance()->getValue('SELECT COUNT(*) FROM '._DB_PREFIX_.'image WHERE id_product = '.(int)$obj->id);
		echo '
		
				2. '.$this->l('Images').' ('.$countImages.') 
				
				
					'.(Tools::getValue('id_image')?$this->l('Edit this product image'):$this->l('Add a new image to this product')).'  
				
				 ';
			echo '
			
			';
	}
	public function initCombinationImagesJS()
	{
		global $cookie;
		if (!($obj = $this->loadObject(true)))
			return;
		$content = 'var combination_images = new Array();';
		if (!$allCombinationImages = $obj->getCombinationImages((int)($cookie->id_lang)))
			return $content;
		foreach ($allCombinationImages AS $id_product_attribute => $combinationImages)
		{
			$i = 0;
			$content .= 'combination_images['.(int)($id_product_attribute).'] = new Array();';
			foreach ($combinationImages AS $combinationImage)
				$content .= 'combination_images['.(int)($id_product_attribute).']['.$i++.'] = '.(int)($combinationImage['id_image']).';';
		}
		return $content;
	}
	function displayFormAttributes($obj, $languages, $defaultLanguage)
	{
		global $currentIndex, $cookie;
		$attributeJs = array();
		$attributes = Attribute::getAttributes((int)($cookie->id_lang), true);
		foreach ($attributes AS $k => $attribute)
			$attributeJs[$attribute['id_attribute_group']][$attribute['id_attribute']] = $attribute['name'];
		$currency = new Currency(Configuration::get('PS_CURRENCY_DEFAULT'));
		$attributes_groups = AttributeGroup::getAttributesGroups((int)($cookie->id_lang));
		$default_country = new Country((int)Configuration::get('PS_COUNTRY_DEFAULT'));
		$images = Image::getImages((int)($cookie->id_lang), $obj->id);
		if ($obj->id)
			{
				echo '
			
			
			
			
			  '.$this->l('Group:').' 
			  ';
				if (isset($attributes_groups))
					foreach ($attributes_groups AS $k => $attribute_group)
						if (isset($attributeJs[$attribute_group['id_attribute_group']]))
							echo '
							
							'.htmlentities(stripslashes($attribute_group['name']), ENT_COMPAT, 'UTF-8').'   ';
				echo '
				  
		  
			  '.$this->l('Attribute:').' 
			  
			  --- 
			   
			  
			   
		  
			  
			   
			  
				   
		   
		  
			  '.$this->l('Reference:').' 
			  
				'.$this->l('Special characters allowed:').' .-_#   
			   
		   
		  
			  '.$this->l('Supplier Reference:').' 
			  
				'.$this->l('Special characters allowed:').' .-_#   
			   
		   
		  
			  '.$this->l('Wholesale price:').' 
			  '.($currency->format % 2 != 0 ? $currency->sign.' ' : '').' 
		   
		  
			  '.$this->l('Impact on price:').' 
			  
				
				  '.$this->l('None').' 
				  '.$this->l('Increase').' 
				  '.$this->l('Reduction').' 
				 
				  '.$this->l('of').'  '.($currency->format % 2 != 0 ? $currency->sign.' ' : '').'
					 '.$this->l('or').' '.($currency->format % 2 != 0 ? $currency->sign.' ' : '').'
							  '.$this->l('final product price will be set to').' '.($currency->format % 2 != 0 ? $currency->sign.' ' : '').'0.00 '.($currency->format % 2 == 0 ? $currency->sign.' ' : '');
					}
			echo '
				 
			 
		   
		  
			  '.$this->l('Impact on weight:').' 
			  
			  '.$this->l('None').' 
			  '.$this->l('Increase').' 
			  '.$this->l('Reduction').' 
			   
			    '.$this->l('of').'  
				  
		  
			  '.$this->l('Impact on unit price :').' 
			  
			  '.$this->l('None').' 
			  '.$this->l('Increase').' 
			  '.$this->l('Reduction').' 
			   
			    '.$this->l('of').'  '.($currency->format % 2 != 0 ? $currency->sign.' ' : '').'
				'.$this->getFieldValue($obj, 'unity').' 
			  ';
		if (Configuration::get('PS_USE_ECOTAX'))
			echo'
				  
					  '.$this->l('Eco-tax:').' 
					  '.($currency->format % 2 != 0 ? $currency->sign.' ' : '').' 
				   ';
		echo'
		  
				'.$this->l('Initial stock:').' 
				 
		  
			
				'.$this->l('Stock movement:').' 
				
					
						-- ';
			$reasons = StockMvtReason::getStockMvtReasons((int)$cookie->id_lang);
			foreach ($reasons AS $reason)
				echo ''.$reason['name'].' ';
			echo ' 
					'.$this->l('Choose the reason and enter the quantity that you want to increase or decrease in your stock').'
				 
			 
			
			'.$this->l('Minimum quantity:').' 
				
					'.$this->l('The minimum quantity to buy this product (set to 1 to disable this feature)').'
				 
			 
		  
			  '.$this->l('Quantity in stock:').' 
			   
		  
			  '.$this->l('Image:').' 
			  
				
				 
		   
			
			  '.$this->l('Default:').' 
			  
				 
		   
		  
			    
			  
				
				    
		   
		  
			  
					
						
							'.$this->l('Attributes').' 
							'.$this->l('Impact').' 
							'.$this->l('Weight').' 
							'.$this->l('Reference').' 
							'.$this->l('EAN13').' 
							'.$this->l('UPC').' 
							'.$this->l('Quantity').' 
							'.$this->l('Actions').' 
						 ';
			if ($obj->id)
			{
				/* Build attributes combinaisons */
				$combinaisons = $obj->getAttributeCombinaisons((int)($cookie->id_lang));
				$groups = array();
				if (is_array($combinaisons))
				{
					$combinationImages = $obj->getCombinationImages((int)($cookie->id_lang));
					foreach ($combinaisons AS $k => $combinaison)
					{
						$combArray[$combinaison['id_product_attribute']]['wholesale_price'] = $combinaison['wholesale_price'];
						$combArray[$combinaison['id_product_attribute']]['price'] = $combinaison['price'];
						$combArray[$combinaison['id_product_attribute']]['weight'] = $combinaison['weight'];
						$combArray[$combinaison['id_product_attribute']]['unit_impact'] = $combinaison['unit_price_impact'];
						$combArray[$combinaison['id_product_attribute']]['reference'] = $combinaison['reference'];
						$combArray[$combinaison['id_product_attribute']]['supplier_reference'] = $combinaison['supplier_reference'];
						$combArray[$combinaison['id_product_attribute']]['ean13'] = $combinaison['ean13'];
						$combArray[$combinaison['id_product_attribute']]['upc'] = $combinaison['upc'];
						$combArray[$combinaison['id_product_attribute']]['minimal_quantity'] = $combinaison['minimal_quantity'];
						$combArray[$combinaison['id_product_attribute']]['location'] = $combinaison['location'];
						$combArray[$combinaison['id_product_attribute']]['quantity'] = $combinaison['quantity'];
						$combArray[$combinaison['id_product_attribute']]['id_image'] = isset($combinationImages[$combinaison['id_product_attribute']][0]['id_image']) ? $combinationImages[$combinaison['id_product_attribute']][0]['id_image'] : 0;
						$combArray[$combinaison['id_product_attribute']]['default_on'] = $combinaison['default_on'];
						$combArray[$combinaison['id_product_attribute']]['ecotax'] = $combinaison['ecotax'];
						$combArray[$combinaison['id_product_attribute']]['attributes'][] = array($combinaison['group_name'], $combinaison['attribute_name'], $combinaison['id_attribute']);
						if ($combinaison['is_color_group'])
							$groups[$combinaison['id_attribute_group']] = $combinaison['group_name'];
					}
				}
				$irow = 0;
				if (isset($combArray))
				{
					foreach ($combArray AS $id_product_attribute => $product_attribute)
					{
						$list = '';
						$jsList = '';
						/* In order to keep the same attributes order */
						asort($product_attribute['attributes']);
						foreach ($product_attribute['attributes'] AS $attribute)
						{
							$list .= addslashes(htmlspecialchars($attribute[0])).' - '.addslashes(htmlspecialchars($attribute[1])).', ';
							$jsList .= '\''.addslashes(htmlspecialchars($attribute[0])).' : '.addslashes(htmlspecialchars($attribute[1])).'\', \''.$attribute[2].'\', ';
						}
						$list = rtrim($list, ', ');
						$jsList = rtrim($jsList, ', ');
						$attrImage = $product_attribute['id_image'] ? new Image($product_attribute['id_image']) : false;
						echo '
						
							'.stripslashes($list).' 
							'.($currency->format % 2 != 0 ? $currency->sign.' ' : '').$product_attribute['price'].($currency->format % 2 == 0 ? ' '.$currency->sign : '').' 
							'.$product_attribute['weight'].Configuration::get('PS_WEIGHT_UNIT').' 
							'.$product_attribute['reference'].' 
							'.$product_attribute['ean13'].' 
							'.$product_attribute['upc'].' 
							'.$product_attribute['quantity'].' 
							
							
							  
							'.(!$product_attribute['default_on'] ? '
							 ' : '').'
							
							  
						 ';
					}
					echo ''.$this->l('No combination yet').'. 
						 
						 
					
					
					'.$this->l('You must save this product before adding combinations').'. ';
	}
	function displayFormFeatures($obj)
	{
		global $cookie, $currentIndex;
		parent::displayForm();
		if ($obj->id)
		{
			$feature = Feature::getFeatures((int)($cookie->id_lang));
			$ctab = '';
			foreach ($feature AS $tab)
				$ctab .= 'ccustom_'.$tab['id_feature'].'¤';
			$ctab = rtrim($ctab, '¤');
			echo '
			
				
					
						'.$this->l('Assign features to this product:').' 
							'.$this->l('You can specify a value for each relevant feature regarding this product, empty fields will not be displayed.').' 
							'.$this->l('You can either set a specific value, or select among existing pre-defined values you added previously.').' 
						 
					 
				 
			
			
				
					'.$this->l('Feature').'
					 '.$this->l('Pre-defined value').'
					 '.$this->l('or').'  '.$this->l('Customized value').'
				 ';
			if (!$nb_feature)
				echo ''.$this->l('No features defined').' 
';
			// Listing
			if ($nb_feature)
			{
				echo '
				
			'.$this->l('You must save this product before adding features').'. ';
	}
	public function haveThisAccessory($accessoryId, $accessories)
	{
		foreach ($accessories AS $accessory)
			if ((int)($accessory['id_product']) == (int)($accessoryId))
				return true;
		return false;
	}
	private function displayPack(Product $obj)
	{
		global $currentIndex, $cookie;
		$boolPack = (($obj->id AND Pack::isPack($obj->id)) OR Tools::getValue('ppack')) ? true : false;
		$packItems = $boolPack ? Pack::getItems($obj->id, $cookie->id_lang) : array();
		echo '
		
			
				'.$this->l('Pack').' 
			 
			
				 
			
		 ';
		// param multipleSeparator:'||' ajouté à cause de bug dans lib autocomplete
		echo '';
	}
	private function addPackItem()
	{
		return '
			function addPackItem()
			{
				if ($(\'#curPackItemId\').val() == \'\' || $(\'#curPackItemName\').val() == \'\')
				{
					alert(\''.$this->l('Thanks to select at least one product.').'\');
					return false;
				}
				else if ($(\'#curPackItemId\').val() == \'\' || $(\'#curPackItemQty\').val() == \'\')
				{
					alert(\''.$this->l('Thanks to set a quantity to add a product.').'\');	
					return false;
				}
	
				var lineDisplay = $(\'#curPackItemQty\').val()+ \'x \' +$(\'#curPackItemName\').val();
	
				var divContent = $(\'#divPackItems\').html();
				divContent += lineDisplay;
				divContent += \'