* @copyright PrestaShop * @license http://www.opensource.org/licenses/osl-3.0.php Open-source licence 3.0 * @version 1.2 */ include_once(PS_ADMIN_DIR.'/../classes/AdminTab.php'); 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), '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'), 'active' => array('title' => $this->l('Displayed'), 'active' => 'status', '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` t ON (t.`id_tax` = a.`id_tax`)'; $this->_filter = 'AND cp.`id_category` = '.intval($this->_category->id); $this->_select = 'cp.`position`, i.`id_image`, (a.`price` * ((100 + (t.`rate`))/100) - IF((DATEDIFF(a.`reduction_from`, CURDATE()) <= 0 AND DATEDIFF(a.`reduction_to`, CURDATE()) >=0) OR a.`reduction_from` = a.`reduction_to`, IF(a.`reduction_price` > 0, a.`reduction_price`, (a.`price` * ((100 + (t.`rate`))/100) * a.`reduction_percent` / 100)),0)) AS price_final'; parent::__construct(); } protected function copyFromPost(&$object, $table) { parent::copyFromPost($object, $table); if (get_class($object) != 'Product') return; /* Additional fields */ $languages = Language::getLanguages(); foreach ($languages as $language) if (isset($_POST['meta_keywords_'.$language['id_lang']])) $_POST['meta_keywords_'.$language['id_lang']] = preg_replace('/ *,? +,*/', ',', strtolower($_POST['meta_keywords_'.$language['id_lang']])); $_POST['weight'] = empty($_POST['weight']) ? '0' : str_replace(',', '.', $_POST['weight']); if ($_POST['reduction_price'] != NULL) $object->reduction_price = str_replace(',', '.', $_POST['reduction_price']); if ($_POST['reduction_percent'] != NULL) $object->reduction_percent = str_replace(',', '.', $_POST['reduction_percent']); if ($_POST['ecotax'] != NULL) $object->ecotax = str_replace(',', '.', $_POST['ecotax']); $object->active = (!isset($_POST['active']) OR $_POST['active']) ? true : false; $object->on_sale = (!isset($_POST['on_sale']) ? false : true); } 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(Tools::getValue('id_product')))) return false; $productDownload = new ProductDownload(intval($id_product_download)); return $productDownload->deleteFile(); } public function postProcess($token = NULL) { global $currentIndex; /* Add a new product */ if (Tools::isSubmit('submitAddproduct') OR Tools::isSubmit('submitAddproductAndStay')) { if (Tools::getValue('id_product') AND $this->tabAccess['edit'] === '1') $this->submitAddproduct($token); elseif ($this->tabAccess['add'] === '1' AND !Tools::isSubmit('id_product')) $this->submitAddproduct($token); else $this->_errors[] = Tools::displayError('You do not have permission to add anything 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 anything here.'); } /* Update attachments */ elseif (Tools::isSubmit('submitAttachments')) { if ($this->tabAccess['edit'] === '1') if ($id = intval(Tools::getValue($this->identifier))) if (Attachment::attachToProduct($id, $_POST['attachments'])) Tools::redirectAdmin($currentIndex.'&id_product='.$id.'&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(intval(Tools::getValue('id_product'))))) { $id_product_old = $product->id; unset($product->id); unset($product->id_product); $product->indexed = 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::duplicateQuantityDiscount($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 (!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); Tools::redirectAdmin($currentIndex.'&id_category='.intval(Tools::getValue('id_category')).'&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 anything 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 = intval(Tools::getValue('id_category'))) 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 anything 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.''.Tools::displayError(', you cannot delete all of them'); else { $this->deleteImage($object->id); if ($this->deleted) { $object->deleted = 1; if ($object->update()) Tools::redirectAdmin($currentIndex.'&conf=1&token='.($token ? $token : $this->token)); } elseif ($object->delete()) Tools::redirectAdmin($currentIndex.'&conf=1&token='.($token ? $token : $this->token)); $this->_errors[] = Tools::displayError('an error occurred during deletion'); } } else $this->_errors[] = Tools::displayError('an error occurred while deleting object').' '.$this->table.' '.Tools::displayError('(cannot load object)'); } else $this->_errors[] = Tools::displayError('You do not have permission to delete here.'); } /* Product images management */ elseif (($id_image = intval(Tools::getValue('id_image'))) AND Validate::isUnsignedId($id_image) AND Validate::isLoadedObject($image = new Image($id_image))) { if ($this->tabAccess['edit'] === '1') { /* Delete product image */ if (isset($_GET['deleteImage'])) { $image->delete(); deleteImage($image->id_product, $image->id); if (!Image::getCover($image->id_product)) { $first_img = Db::getInstance()->getRow(' SELECT `id_image` FROM `'._DB_PREFIX_.'image` WHERE `id_product` = '.intval($image->id_product)); Db::getInstance()->Execute(' UPDATE `'._DB_PREFIX_.'image` SET `cover` = 1 WHERE `id_image` = '.intval($first_img['id_image'])); } @unlink(dirname(__FILE__).'/../../img/tmp/product_'.$image->id_product.'.jpg'); @unlink(dirname(__FILE__).'/../../img/tmp/product_mini_'.$image->id_product.'.jpg'); Tools::redirectAdmin($currentIndex.'&id_product='.$image->id_product.'&id_category='.intval(Tools::getValue('id_category')).'&add'.$this->table.'&tabs=1'.'&token='.($token ? $token : $this->token)); } /* Update product image/legend */ elseif (isset($_GET['editImage'])) { if ($image->cover) $_POST['cover'] = 1; $languages = Language::getLanguages(); foreach ($languages as $language) if (isset($image->legend[$language['id_lang']])) $_POST['legend_'.$language['id_lang']] = $image->legend[$language['id_lang']]; $_POST['id_image'] = $image->id; $this->displayForm(); } /* Choose product cover image */ elseif (isset($_GET['coverImage'])) { Image::deleteCover($image->id_product); $image->cover = 1; if (!$image->update()) $this->_errors[] = Tools::displayError('Impossible to change the product cover'); else { $productId = intval(Tools::getValue('id_product')); @unlink(dirname(__FILE__).'/../../img/tmp/product_'.$productId.'.jpg'); @unlink(dirname(__FILE__).'/../../img/tmp/product_mini_'.$productId.'.jpg'); Tools::redirectAdmin($currentIndex.'&id_product='.$image->id_product.'&id_category='.intval(Tools::getValue('id_category')).'&addproduct&tabs=1'.'&token='.($token ? $token : $this->token)); } } /* Choose product image position */ elseif (isset($_GET['imgPosition']) AND isset($_GET['imgDirection'])) { $image->positionImage(intval(Tools::getValue('imgPosition')), intval(Tools::getValue('imgDirection'))); Tools::redirectAdmin($currentIndex.'&id_product='.$image->id_product.'&id_category='.intval(Tools::getValue('id_category')).'&add'.$this->table.'&tabs=1&token='.($token ? $token : $this->token)); } } else $this->_errors[] = Tools::displayError('You do not have permission to edit anything here.'); } /* Product attributes management */ elseif (Tools::isSubmit('submitProductAttribute')) { if (Validate::isLoadedObject($product = new Product(intval(Tools::getValue('id_product'))))) { if (!isset($_POST['attribute_quantity']) OR $_POST['attribute_quantity'] == NULL) $this->_errors[] = Tools::displayError('attribute quantity is required'); if (!isset($_POST['attribute_price']) OR $_POST['attribute_price'] == NULL) $this->_errors[] = Tools::displayError('attribute price is required'); if (!isset($_POST['attribute_combinaison_list']) OR !sizeof($_POST['attribute_combinaison_list'])) $this->_errors[] = Tools::displayError('you must add at least one attribute'); if (!sizeof($this->_errors)) { if (!isset($_POST['attribute_wholesale_price'])) $_POST['attribute_wholesale_price'] = 0; if (!isset($_POST['attribute_price_impact'])) $_POST['attribute_price_impact'] = 0; if (!isset($_POST['attribute_weight_impact'])) $_POST['attribute_weight_impact'] = 0; if (!isset($_POST['attribute_ecotax'])) $_POST['attribute_ecotax'] = 0; if (Tools::getValue('attribute_default')) $product->deleteDefaultAttributes(); // Change existing one if ($id_product_attribute = intval(Tools::getValue('id_product_attribute'))) { if ($this->tabAccess['edit'] === '1') { if ($product->productAttributeExists($_POST['attribute_combinaison_list'], $id_product_attribute)) $this->_errors[] = Tools::displayError('This attribute already exists.'); else $product->updateProductAttribute($id_product_attribute, Tools::getValue('attribute_wholesale_price'), Tools::getValue('attribute_price') * Tools::getValue('attribute_price_impact'), Tools::getValue('attribute_weight') * Tools::getValue('attribute_weight_impact'), Tools::getValue('attribute_ecotax'), Tools::getValue('attribute_quantity'), Tools::getValue('id_image_attr'), Tools::getValue('attribute_reference'), Tools::getValue('attribute_supplier_reference'), Tools::getValue('attribute_ean13'), Tools::getValue('attribute_default'), Tools::getValue('attribute_location')); } else $this->_errors[] = Tools::displayError('You do not have permission to add anything here.'); } // Add new else { if ($this->tabAccess['add'] === '1') { if ($product->productAttributeExists($_POST['attribute_combinaison_list'])) $this->_errors[] = Tools::displayError('This combination already exists.'); else $id_product_attribute = $product->addCombinationEntity(Tools::getValue('attribute_wholesale_price'), Tools::getValue('attribute_price') * Tools::getValue('attribute_price_impact'), Tools::getValue('attribute_weight') * Tools::getValue('attribute_weight_impact'), Tools::getValue('attribute_ecotax'), Tools::getValue('attribute_quantity'), Tools::getValue('id_image_attr'), Tools::getValue('attribute_reference'), Tools::getValue('attribute_supplier_reference'), Tools::getValue('attribute_ean13'), Tools::getValue('attribute_default'), Tools::getValue('attribute_location')); } else $this->_errors[] = Tools::displayError('You do not have permission to').'
'.Tools::displayError('edit something here.'); } if (!sizeof($this->_errors)) { $product->addAttributeCombinaison($id_product_attribute, Tools::getValue('attribute_combinaison_list')); $product->checkDefaultAttributes(); } if (!sizeof($this->_errors)) Tools::redirectAdmin($currentIndex.'&id_product='.$product->id.'&id_category='.intval(Tools::getValue('id_category')).'&add'.$this->table.'&tabs=2&token='.($token ? $token : $this->token)); } } } elseif (Tools::isSubmit('deleteProductAttribute')) { if ($this->tabAccess['delete'] === '1') { if (($id_product = intval(Tools::getValue('id_product'))) AND Validate::isUnsignedId($id_product) AND Validate::isLoadedObject($product = new Product($id_product))) { $product->deleteAttributeCombinaison(intval(Tools::getValue('id_product_attribute'))); $product->checkDefaultAttributes(); Tools::redirectAdmin($currentIndex.'&add'.$this->table.'&id_category='.intval(Tools::getValue('id_category')).'&tabs=2&id_product='.$product->id.'&token='.($token ? $token : $this->token)); } else $this->_errors[] = Tools::displayError('impossible to delete attribute'); } else $this->_errors[] = Tools::displayError('You do not have permission to delete here.'); } elseif (Tools::isSubmit('deleteAllProductAttributes')) { if ($this->tabAccess['delete'] === '1') { if (($id_product = intval(Tools::getValue('id_product'))) AND Validate::isUnsignedId($id_product) AND Validate::isLoadedObject($product = new Product($id_product))) { $product->deleteProductAttributes(); Tools::redirectAdmin($currentIndex.'&add'.$this->table.'&id_category='.intval(Tools::getValue('id_category')).'&tabs=2&id_product='.$product->id.'&token='.($token ? $token : $this->token)); } else $this->_errors[] = Tools::displayError('impossible to delete attributes'); } else $this->_errors[] = Tools::displayError('You do not have permission to delete here.'); } /* Product features management */ elseif (Tools::isSubmit('submitProductFeature')) { if ($this->tabAccess['edit'] === '1') { if (Validate::isLoadedObject($product = new Product(intval(Tools::getValue('id_product'))))) { // delete all objects $product->deleteFeatures(); // add new objects $languages = Language::getLanguages(); foreach ($_POST AS $key => $val) { if (preg_match("/^feature_([0-9]+)_value/i", $key, $match)) { if ($val) $product->addFeaturesToDB($match[1], $val); else { if ($default_value = $this->checkFeatures($languages, $match[1])) { $id_value = $product->addFeaturesToDB($match[1], 0, 1, $language['id_lang']); foreach ($languages AS $language) { if ($cust = Tools::getValue('custom_'.$match[1].'_'.$language['id_lang'])) $product->addFeaturesCustomToDB($id_value, $language['id_lang'], $cust); else $product->addFeaturesCustomToDB($id_value, $language['id_lang'], $default_value); } } } } } if (!sizeof($this->_errors)) Tools::redirectAdmin($currentIndex.'&id_product='.$product->id.'&id_category='.intval(Tools::getValue('id_category')).'&add'.$this->table.'&tabs=3&token='.($token ? $token : $this->token)); } else $this->_errors[] = Tools::displayError('product must be created before adding features'); } $this->_errors[] = Tools::displayError('You do not have permission to edit anything here.'); } /* Product quantity discount management */ elseif (Tools::isSubmit('submitQuantityDiscount')) { $_POST['tabs'] = 5; if ($this->tabAccess['add'] === '1') { if (Validate::isLoadedObject($product = new Product(intval(Tools::getValue('id_product'))))) { if (!($id_discount_type = intval(Tools::getValue('id_discount_type')))) $this->_errors[] = Tools::displayError('discount type not selected'); elseif (!($quantity_discount = intval(Tools::getValue('quantity_discount'))) OR $quantity_discount <= 1) $this->_errors[] = Tools::displayError('quantity is required and must be superior of 1'); elseif (!($value_discount = floatval(Tools::getValue('value_discount')))) $this->_errors[] = Tools::displayError('value is required'); elseif ($value_discount > 100 AND $id_discount_type == 1) $this->_errors[] = Tools::displayError('value is incorrect'); else { $qD = new QuantityDiscount(); $qD->id_product = $product->id; $qD->id_discount_type = $id_discount_type; $qD->quantity = $quantity_discount; $qD->value = $value_discount; if ($qD->add() AND !sizeof($this->_errors) AND $qD->validateFields()) Tools::redirectAdmin($currentIndex.'&id_product='.$product->id.'&id_category='.intval(Tools::getValue('id_category')).'&add'.$this->table.'&tabs=5&conf=3&token='.($token ? $token : $this->token)); $this->_errors[] = Tools::displayError('an error occurred while creating object'); } } else $this->_errors[] = Tools::displayError('product must be created before adding quantity discounts'); } else $this->_errors[] = Tools::displayError('You do not have permission to add anything here.'); } elseif (isset($_GET['deleteQuantityDiscount'])) { if ($this->tabAccess['delete'] === '1') { if (Validate::isLoadedObject($product = new Product(intval(Tools::getValue('id_product'))))) { if (Validate::isLoadedObject($qD = new QuantityDiscount(intval(Tools::getValue('id_quantity_discount'))))) { $qD->delete(); if (!sizeof($this->_errors)) Tools::redirectAdmin($currentIndex.'&id_product='.$product->id.'&id_category='.intval(Tools::getValue('id_category')).'&add'.$this->table.'&tabs=5&conf=1&token='.($token ? $token : $this->token)); } else $this->_errors[] = Tools::displayError('not a valid quantity discount'); } else $this->_errors[] = Tools::displayError('product must be created before delete quantity discounts'); $qD = new QuantityDiscount(); } else $this->_errors[] = Tools::displayError('You do not have permission to delete here.'); } /* Customization management */ elseif (Tools::isSubmit('submitCustomizationConfiguration')) { if ($this->tabAccess['edit'] === '1') { if (Validate::isLoadedObject($product = new Product(intval(Tools::getValue('id_product'))))) { if (!$product->createLabels(intval($_POST['uploadable_files']) - intval($product->uploadable_files), intval($_POST['text_fields']) - intval($product->text_fields))) $this->_errors[] = Tools::displayError('an error occured while creating customization fields'); if (!sizeof($this->_errors) AND !$product->updateLabels()) $this->_errors[] = Tools::displayError('an error occured while updating customization'); $product->uploadable_files = intval($_POST['uploadable_files']); $product->text_fields = intval($_POST['text_fields']); $product->customizable = (intval($_POST['uploadable_files']) > 0 OR intval($_POST['text_fields']) > 0) ? 1 : 0; if (!sizeof($this->_errors) AND !$product->update()) $this->_errors[] = Tools::displayError('an error occured while updating customization configuration'); if (!sizeof($this->_errors)) Tools::redirectAdmin($currentIndex.'&id_product='.$product->id.'&id_category='.intval(Tools::getValue('id_category')).'&add'.$this->table.'&tabs=4&token='.($token ? $token : $this->token)); } else $this->_errors[] = Tools::displayError('product must be created before adding customization possibilities'); } else $this->_errors[] = Tools::displayError('You do not have permission to edit anything here.'); } elseif (Tools::isSubmit('submitProductCustomization')) { if ($this->tabAccess['edit'] === '1') { if (Validate::isLoadedObject($product = new Product(intval(Tools::getValue('id_product'))))) { foreach ($_POST AS $field => $value) if (strncmp($field, 'label_', 6) == 0 AND !Validate::isLabel($value)) $this->_errors[] = Tools::displayError('label fields are invalid'); if (!sizeof($this->_errors) AND !$product->updateLabels()) $this->_errors[] = Tools::displayError('an error occured while updating customization'); if (!sizeof($this->_errors)) Tools::redirectAdmin($currentIndex.'&id_product='.$product->id.'&id_category='.intval(Tools::getValue('id_category')).'&add'.$this->table.'&tabs=4&token='.($token ? $token : $this->token)); } else $this->_errors[] = Tools::displayError('product must be created before adding customization possibilities'); } else $this->_errors[] = Tools::displayError('You do not have permission to edit anything here.'); } else parent::postProcess(true); } // 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 = (intval(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']['tmp_name']) AND $_FILES['image_product']['tmp_name'] != NULL) { if (!Validate::isLoadedObject($product)) $this->_errors[] = Tools::displayError('cannot add image because product add failed'); else { $image = new Image(); $image->id_product = intval($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_IMG_DIR_.'p/'.$image->id_product.'-'.$image->id.'.jpg')) $image->delete(); if (sizeof($this->_errors)) return false; @unlink(dirname(__FILE__).'/../../img/tmp/product_'.$product->id.'.jpg'); @unlink(dirname(__FILE__).'/../../img/tmp/product_mini_'.$product->id.'.jpg'); return ((isset($id_image) AND is_int($id_image) AND $id_image) ? $id_image : 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']) OR !file_exists($_FILES['image_product']['tmp_name'])) return false; if ($error = checkImage($_FILES['image_product'], $this->maxImageSize)) $this->_errors[] = $error; else { if (!$tmpName = tempnam(_PS_TMP_IMG_DIR_, 'PS') OR !move_uploaded_file($_FILES['image_product']['tmp_name'], $tmpName)) $this->_errors[] = Tools::displayError('An error occured during the image upload'); elseif (!imageResize($tmpName, _PS_IMG_DIR_.'p/'.$id_product.'-'.$id_image.'.jpg')) $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, _PS_IMG_DIR_.'p/'.$id_product.'-'.$id_image.'-'.stripslashes($imageType['name']).'.jpg', $imageType['width'], $imageType['height'])) $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 $currentIndex; $className = 'Product'; $rules = call_user_func(array($this->className, 'getValidationRules'), $this->className); $defaultLanguage = new Language(intval(Configuration::get('PS_LANG_DEFAULT'))); $languages = Language::getLanguages(); /* 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'); $productCats = ''; if (!isset($_POST['categoryBox']) OR !sizeof($_POST['categoryBox'])) $this->_errors[] = $this->l('product must be in at least one Category'); 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 = intval(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->copyFromPost($object, $this->table); if ($object->update()) { $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='.intval(Tools::getValue('id_image')); Hook::updateProduct($object); Search::indexation(false); 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='.intval(Tools::getValue('id_category')).'&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 stay on same form if (Tools::isSubmit('submitAdd'.$this->table.'AndStay') OR ($id_image AND $id_image !== true)) Tools::redirectAdmin($currentIndex.'&id_product='.$object->id.'&id_category='.intval(Tools::getValue('id_category')).'&addproduct&conf=4&tabs='.intval(Tools::getValue('tabs')).'&token='.($token ? $token : $this->token)); // Default behavior (save and back) Tools::redirectAdmin($currentIndex.'&id_category='.intval(Tools::getValue('id_category')).'&conf=4&token='.($token ? $token : $this->token)); } } 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->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'); else if (!$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); 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='.intval(Tools::getValue('id_category')).'&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='.intval(Tools::getValue('id_category')).'&addproduct&conf=3&tabs='.intval(Tools::getValue('tabs')).'&token='.($token ? $token : $this->token)); // Default behavior (save and back) Tools::redirectAdmin($currentIndex.'&id_category='.intval(Tools::getValue('id_category')).'&conf=3&token='.($token ? $token : $this->token)); } } else $object->delete(); } else $this->_errors[] = Tools::displayError('an error occurred while creating object').' '.$this->table.''; } } } /** * 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')) { $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` = '.intval($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'], intval($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(intval($cookie->id_lang), !$cookie->__get($this->table.'Orderby') ? 'position' : NULL, !$cookie->__get($this->table.'Orderway') ? 'ASC' : NULL); $id_category = intval(Tools::getValue('id_category')); 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(Category::hideCategoryPosition($this->_category->getName())).'"

'; echo ' '.$this->l('Add a new product').'
'; $this->displayList($token); echo '
'; } 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').''; /* Show the content of the table */ $this->displayListContent($token); /* Close list table and submit button */ $this->displayListFooter($token); } /** * Build a categories tree * * @param array $indexedCategories Array with categories where product is indexed (in order to check checkbox) * @param array $categories Categories to list * @param array $current Current category * @param integer $id_category Current category id */ function recurseCategoryForInclude($indexedCategories, $categories, $current, $id_category = 1, $id_category_default = NULL) { global $done; static $irow; $id_obj = intval(Tools::getValue($this->identifier)); if (!isset($done[$current['infos']['id_parent']])) $done[$current['infos']['id_parent']] = 0; $done[$current['infos']['id_parent']] += 1; $todo = sizeof($categories[$current['infos']['id_parent']]); $doneC = $done[$current['infos']['id_parent']]; $level = $current['infos']['level_depth'] + 1; $img = $level == 1 ? 'lv1.gif' : 'lv'.$level.'_'.($todo == $doneC ? 'f' : 'b').'.gif'; echo ' '.$id_category.'   '; if (isset($categories[$id_category])) foreach ($categories[$id_category] AS $key => $row) if ($key != 'infos') $this->recurseCategoryForInclude($indexedCategories, $categories, $categories[$id_category][$key], $key); } 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 '
  1. '.$error.'
  2. '; echo '
'; } } public function displayForm($isMainTab = true) { global $currentIndex, $link, $cookie; parent::displayForm(); if ($id_category_back = intval(Tools::getValue('id_category'))) $currentIndex .= '&id_category='.$id_category_back; $obj = $this->loadObject(true); $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').'

'; /* Tabs */ $this->displayFormInformations($obj, $currency); $this->displayFormImages($obj, $this->token); if ($obj->id) echo '

3. '.$this->l('Combinations').'

4. '.$this->l('Features').'

5. '.$this->l('Customization').'

6. '.$this->l('Discounts').'

7. '.$this->l('Attachments').'

'; echo '
'; if (Tools::getValue('id_category') > 1) { $productIndex = preg_replace('/(&id_product=[0-9]*)/', '', $currentIndex); echo '

'.$this->l('Back to the category').'
'; } } function displayFormQuantityDiscount($obj, $languages, $defaultLanguage) { global $cookie, $currentIndex; if ($obj->id) { $quantityDiscounts = QuantityDiscount::getQuantityDiscounts($obj->id, false); $defaultCurrency = new Currency(Configuration::get('PS_CURRENCY_DEFAULT')); echo '
'.$this->l('Add quantity discount to this product').'


'.$this->l('Product quantity:').'

'.$this->l('Minimum product quantity for discount').'

'.$this->l('Discount value:').'

'.$this->l('The discount value (% or amount)').'

'.$this->l('Discount type:').'

'.$this->l('Will be applied on final product price').'


'; // Listing $irow = 0; if (is_array($quantityDiscounts) AND sizeof($quantityDiscounts)) { foreach ($quantityDiscounts as $qD) echo ' '; } else echo ' '; echo '
'.$this->l('ID').' '.$this->l('# products').' '.$this->l('Discount').' '.$this->l('Action').'
'.$qD['id_discount_quantity'].'  '.$qD['quantity'].' '.($qD['id_discount_type'] == 1 ? $qD['value'].'%' : Tools::displayPrice($qD['value'], $defaultCurrency)).' '.$this->l('Delete this discount').'
'.$this->l('No quantity discount defined').'
'; } else echo ''.$this->l('You must save this product before adding quantity discounts').'.'; } private function _getCustomizationFieldIds($labels, $alreadyGenerated, $obj) { $customizableFieldIds = array(); if (isset($labels[_CUSTOMIZE_FILE_])) foreach ($labels[_CUSTOMIZE_FILE_] AS $id_customization_field => $label) $customizableFieldIds[] = 'label_'._CUSTOMIZE_FILE_.'_'.intval($id_customization_field); if (isset($labels[_CUSTOMIZE_TEXTFIELD_])) foreach ($labels[_CUSTOMIZE_TEXTFIELD_] AS $id_customization_field => $label) $customizableFieldIds[] = 'label_'._CUSTOMIZE_TEXTFIELD_.'_'.intval($id_customization_field); $j = 0; for ($i = $alreadyGenerated[_CUSTOMIZE_FILE_]; $i < intval($this->getFieldValue($obj, 'uploadable_files')); $i++) $customizableFieldIds[] = 'newLabel_'._CUSTOMIZE_FILE_.'_'.$j++; $j = 0; for ($i = $alreadyGenerated[_CUSTOMIZE_TEXTFIELD_]; $i < intval($this->getFieldValue($obj, 'text_fields')); $i++) $customizableFieldIds[] = 'newLabel_'._CUSTOMIZE_TEXTFIELD_.'_'.$j++; return implode('¤', $customizableFieldIds); } private function _displayLabelField(&$label, $languages, $defaultLanguage, $type, $fieldIds, $id_customization_field) { $fieldsName = 'label_'.$type.'_'.intval($id_customization_field); $fieldsContainerName = 'labelContainer_'.$type.'_'.intval($id_customization_field); echo '
'; foreach ($languages as $language) { $fieldName = 'label_'.$type.'_'.intval($id_customization_field).'_'.intval($language['id_lang']); echo '
#'.intval($id_customization_field).'
'; } echo '
'; } private function _displayLabelFields(&$obj, &$labels, $languages, $defaultLanguage, $type) { $type = intval($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, intval($id_customization_field)); } function displayFormCustomization($obj, $languages, $defaultLanguage) { parent::displayForm(false); $labels = $obj->getCustomizationFields(); $defaultIso = Language::getIsoById($defaultLanguage); $hasFileLabels = intval($this->getFieldValue($obj, 'uploadable_files')); $hasTextLabels = intval($this->getFieldValue($obj, 'text_fields')); echo '
'.$this->l('Add or modify customizable properties').'


'; if ($hasFileLabels) { echo ' '; } if ($hasTextLabels) { echo ' '; } echo '
'.$this->l('File fields:').'

'.$this->l('Number of upload file fields displayed').'

'.$this->l('Text fields:').'

'.$this->l('Number of text fields displayed').'


'.$this->l('Files fields:').' '; $this->_displayLabelFields($obj, $labels, $languages, $defaultLanguage, _CUSTOMIZE_FILE_); echo '

'.$this->l('Text fields:').' '; $this->_displayLabelFields($obj, $labels, $languages, $defaultLanguage, _CUSTOMIZE_TEXTFIELD_); echo '
'; if ($hasFileLabels OR $hasTextLabels) echo ''; echo '
'; } function displayFormAttachments($obj, $languages, $defaultLanguage) { global $currentIndex, $cookie; $obj = $this->loadObject(true); $languages = Language::getLanguages(); $attach1 = Attachment::getAttachments($cookie->id_lang, $obj->id, true); $attach2 = Attachment::getAttachments($cookie->id_lang, $obj->id, false); echo ' new '.$this->l('Upload new attachment').'
 


'.$this->l('Remove').' >>


<< '.$this->l('Add').'
 
'; } function displayFormInformations($obj, $currency) { parent::displayForm(); global $currentIndex, $cookie; $iso = Language::getIsoById(intval($cookie->id_lang)); $qty_state = 'readonly'; $qty = Attribute::getAttributeQty($this->getFieldValue($obj, 'id_product')); if ($qty === false) { if (Validate::isLoadedObject($obj)) $qty = $this->getFieldValue($obj, 'quantity'); else $qty = 1; $qty_state = ''; } $cover = Product::getCover($obj->id); $link = new Link(); //includeDatepicker(array('reduction_from', 'reduction_to')); echo '

1. '.$this->l('Info.').'

'.$this->l('Product global informations').' - '; if (isset($obj->id)) { echo ' '.$this->l('View product in shop').' '.$this->l('View product in shop').''; if (file_exists(_PS_MODULE_DIR_.'statsproduct/statsproduct.php')) echo ' -  '.$this->l('View product sales').' '.$this->l('View product sales').''; } echo '

'; $this->displayPack($obj); echo ' '; /* * Form for add a virtual product like software, mp3, etc... */ $productDownload = new ProductDownload(); if ($id_product_download = $productDownload->getIdFromIdProduct($this->getFieldValue($obj, 'id'))) $productDownload = new ProductDownload($id_product_download); ?> var newLabel = \''.$this->l('New label').'\'; var choose_language = \''.$this->l('Choose language:').'\'; var required = \''.$this->l('required').'\'; var customizationUploadableFileNumber = '.intval($this->getFieldValue($obj, 'uploadable_files')).'; var customizationTextFieldNumber = '.intval($this->getFieldValue($obj, 'text_fields')).'; var uploadableFileLabel = 0; var textFieldLabel = 0; '; ?> '; echo ' '; $taxes = Tax::getTaxes(intval($cookie->id_lang)); echo ''; echo ' '; echo ' '; $accessories = Product::getAccessoriesLight(intval($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('Name:').' '; foreach ($this->_languages as $language) echo '
id) ? ' onkeyup="copy2friendlyURL();"' : '').' onkeyup="updateCurrentText();" onchange="updateCurrentText();" /> * '.$this->l('Invalid characters:').' <>;=#{} 
'; echo '
'.$this->l('Status:').' getFieldValue($obj, 'active') ? 'checked="checked" ' : '').'/>
getFieldValue($obj, 'active') ? 'checked="checked" ' : '').'/>
'.$this->l('Manufacturer:').'    '.$this->l('Create').' '.$this->l('Create').'
'.$this->l('Supplier:').'    '.$this->l('Create').' '.$this->l('Create').'
'.$this->l('Reference:').' '.$this->l('EAN13:').' '.$this->l('Special characters allowed:').' .-_#\ 
'.$this->l('Supplier Reference:').' '.$this->l('Location:').' '.$this->l('Special characters allowed:').' .-_#\ 
'.$this->l('Weight:').' '.Configuration::get('PS_WEIGHT_UNIT').'


id OR Tools::getValue('is_virtual_good')=='true') AND $productDownload->active) echo 'checked="checked"' ?> />
id OR !$productDownload->active) echo 'style="display:none;"' ?> >

l('Your download repository is not writable.'); ?>

id) echo '' ?>

checkFile()): ?> id): ?>

l('This product is missing') ?>:
physically_filename ?>

l('Your server\'s maximum upload file size is') . ': ' . ini_get('upload_max_filesize') ?>

l('This is the link').': '.$productDownload->getHtmlLink(false, true) ?> l('Delete this file') ?>

l('Format: YYYY-MM-DD'); ?>

*


'.$this->l('Pre-tax wholesale price:').' '.($currency->format == 1 ? $currency->sign.' ' : '').''.($currency->format == 2 ? ' '.$currency->sign : '').' '.$this->l('The wholesale price at which you bought this product').'
'.$this->l('Pre-tax retail price:').' '.($currency->format == 1 ? $currency->sign.' ' : '').''.($currency->format == 2 ? ' '.$currency->sign : '').' * '.$this->l('The pre-tax retail price to sell this product').'
'.$this->l('Tax:').' '; if (Tax::excludeTaxeOption()) { echo ''.$this->l('Taxes are currently disabled').' ('.$this->l('Tax options').')'; echo ''; } echo '
'.$this->l('Retail price with tax:').' '.($currency->format == 1 ? ' '.$currency->sign : '').' '.($currency->format == 2 ? ' '.$currency->sign : '').'
'.$this->l('Eco-tax:').' '.($currency->format == 1 ? $currency->sign.' ' : '').''.($currency->format == 2 ? ' '.$currency->sign : '').' ('.$this->l('already included in price').')
'.$this->l('Reduction amount:').' '.($currency->format == 1 ? ' '.$currency->sign.' ' : '').' '.($currency->format == 2 ? ' '.$currency->sign : '').' '.$this->l('OR').' %
  '.$this->l('available from').' '.$this->l('to').'

'.$this->l('Leave same dates for undefined duration').'

  getFieldValue($obj, 'on_sale') ? 'checked="checked"' : '').'value="1" /> 
'.$this->l('Final retail price:').' '.($currency->format == 1 ? $currency->sign.' ' : '').''.($currency->format == 2 ? ' '.$currency->sign : '').'

'.$this->l('Quantity:').' * ('.$this->l('If you use combinations, you can\'t edit this information').')
'.$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:').' getFieldValue($obj, 'out_of_stock')) == 0 ? 'checked="checked"' : '').'/>
getFieldValue($obj, 'out_of_stock') == 1 ? 'checked="checked"' : '').'/>
getFieldValue($obj, 'out_of_stock') == 2 ? 'checked="checked"' : '').'/>

'.$this->l('Catalog:').'
'; $done = array(); $index = array(); $indexedCategories = isset($_POST['categoryBox']) ? $_POST['categoryBox'] : ($obj->id ? Product::getIndexedCategories($obj->id) : array()); foreach ($indexedCategories AS $k => $row) $index[] = $row['id_category']; $this->recurseCategoryForInclude($index, $categories, $categories[0][1], 1, $obj->id_category_default); echo '
'.$this->l('ID').' '.$this->l('Name').'

'.$this->l('Mark all checkbox(es) of categories in which product is to appear').' *


'.$this->l('SEO').''.$this->l('Click here to improve product\'s rank in search engines (SEO)').'

'.$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 '
'.$this->l('Tags:').' '; foreach ($this->_languages as $language) { echo '
'.$this->l('Forbidden characters:').' !<>;?=+#"°{}_$% 
'; } echo '

'.$this->l('Tags separated by commas (e.g., dvd, dvd player, hifi)').'

'.$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 '

'.$this->l('Begin typing the first letters of the product name, then select the product from the drop-down list:').'

'.$this->l('Add an accessory').'

 
'; } function displayFormImages($obj, $token = NULL) { global $cookie, $currentIndex, $attributeJs, $images; echo '

2. '.$this->l('Images').'

'.$this->l('Add a new image to this product').'


'; if (!sizeof($images) OR !isset($obj->id)) echo ''; else { echo '
'.$this->l('File:').'

'.$this->l('Format:').' JPG, GIF, PNG
'.$this->l('Filesize:').' '.($this->maxImageSize / 1000).''.$this->l('Kb max.').'

'.$this->l('Caption:').' '; foreach ($this->_languages as $language) { if (!Tools::getValue('legend_'.$language['id_lang'])) $legend = $this->getFieldValue($obj, 'name', $language['id_lang']); else $legend = Tools::getValue('legend_'.$language['id_lang']); echo '
* '.$this->l('Forbidden characters:').' <>;=#{}
'.$this->l('Forbidden characters will be automatically erased.').' 
'; } echo '

'.$this->l('Short description of the image').'

'.$this->l('Cover:').'

'.$this->l('If you want to select this image as a product cover').'

'.$this->l('Thumbnails resize method:').'

'.$this->l('Method you want to use to generate resized thumbnails').'

'; $images = Image::getImages(intval($cookie->id_lang), $obj->id); $imagesTotal = Image::getImagesTotal($obj->id); if (isset($obj->id) AND sizeof($images)) { echo ''; echo '

'; } echo (Tools::getValue('id_image') ? '' : '').'

'.(Tools::isSubmit('id_category') ? '' : '').'  
'; foreach ($images AS $k => $image) { echo ' '; } } echo '
'.$this->l('Image').'   '.$this->l('Position').' '.$this->l('Cover').' '.$this->l('Action').'
'.htmlentities(stripslashes($image['legend']), ENT_COMPAT, 'UTF-8').' '.intval($image['position']).' '; if ($image['position'] == 1) { echo '[ ]'; if ($image['position'] == $imagesTotal) echo '[ ]'; else echo '[ ]'; } elseif ($image['position'] == $imagesTotal) echo ' [ ] [ ]'; else echo ' [ ] [ ]'; echo ' '.$this->l('Modify this image').' '.$this->l('Delete this image').'
'; echo ' '; } public function initCombinationImagesJS() { global $cookie; $content = 'var combination_images = new Array();'; if (!$allCombinationImages = $this->loadObject(true)->getCombinationImages(intval($cookie->id_lang))) return $content; foreach ($allCombinationImages AS $id_product_attribute => $combinationImages) { $i = 0; $content .= 'combination_images['.intval($id_product_attribute).'] = new Array();'; foreach ($combinationImages AS $combinationImage) $content .= 'combination_images['.intval($id_product_attribute).']['.$i++.'] = '.intval($combinationImage['id_image']).';'; } return $content; } function displayFormAttributes($obj, $languages, $defaultLanguage) { global $currentIndex, $cookie; $attributeJs = array(); $attributes = Attribute::getAttributes(intval($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(intval($cookie->id_lang)); $images = Image::getImages(intval($cookie->id_lang), $obj->id); if ($obj->id) { echo '
'.$this->l('Add or modify combinations for this product').' -  combinations_generator '.$this->l('Product combinations generator').'


'.$this->l('Group:').'
'.$this->l('Attribute:').'


'.$this->l('Reference:').' '.$this->l('EAN13:').' '.$this->l('Special characters allowed:').' .-_# 
'.$this->l('Supplier Reference:').' '.$this->l('Location:').' '.$this->l('Special characters allowed:').' .-_# 

'.$this->l('Wholesale price:').' '.($currency->format == 1 ? $currency->sign.' ' : '').''.($currency->format == 2 ? ' '.$currency->sign : '').' ('.$this->l('overrides Wholesale price on Information tab').')
'.$this->l('Impact on price:').' *   '.$this->l('of').'  '.($currency->format == 1 ? $currency->sign.' ' : '').' '.($currency->format == 2 ? ' '.$currency->sign : '').'
'.$this->l('Impact on weight:').'   '.$this->l('of').'   '.Configuration::get('PS_WEIGHT_UNIT').'
'.$this->l('Eco-tax:').' '.($currency->format == 1 ? $currency->sign.' ' : '').''.($currency->format == 2 ? ' '.$currency->sign : '').' ('.$this->l('overrides Eco-tax on Information tab').')
'.$this->l('Quantity:').' ('.$this->l('overrides Quantity on Information tab').')
* '.$this->l('included tax').'

'.$this->l('Image:').'
    '; $i = 0; $imageType = ImageType::getByNameNType('small', 'products'); $imageWidth = (isset($imageType['width']) ? intval($imageType['width']) : 64) + 25; foreach ($images AS $image) { echo '
  • '; ++$i; } echo '
'.$this->l('Default:').'

 '.$this->l('Make the default combination for this product').'

 


'; if ($obj->id) { /* Build attributes combinaisons */ $combinaisons = $obj->getAttributeCombinaisons(intval($cookie->id_lang)); $groups = array(); if (is_array($combinaisons)) { $combinationImages = $obj->getCombinationImages(intval($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']]['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']]['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 = ''; 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 ' '; } echo ''; } else echo ''; } echo '
'.$this->l('Attributes').' '.$this->l('Impact').' '.$this->l('Weight').' '.$this->l('Reference').' '.$this->l('EAN13').' '.$this->l('Quantity').' '.$this->l('Actions').'
'.stripslashes($list).' '.($currency->format == 1 ? $currency->sign.' ' : '').$product_attribute['price'].($currency->format == 2 ? ' '.$currency->sign : '').' '.$product_attribute['weight'].Configuration::get('PS_WEIGHT_UNIT').' '.$product_attribute['reference'].' '.$product_attribute['ean13'].' '.$product_attribute['quantity'].' '.$this->l('Modify this combination').'  '.$this->l('Delete this combination').'
'.$this->l('Delete this combination').' '.$this->l('Delete all combinations').'
'.$this->l('No combination yet').'.

'.$this->l('The row in blue is the default combination.').'
'.$this->l('A default combination must be designated for each product.').'

'.$this->l('Color picker:').'         '.$this->l('Color attribute management').'

'.$this->l('Active the color choice by selecting a color attribute group.').'

'; } else echo ''.$this->l('You must save this product before adding combinations').'.'; } function displayFormFeatures($obj) { global $cookie, $currentIndex; parent::displayForm(false); if ($obj->id) { $feature = Feature::getFeatures(intval($cookie->id_lang)); $ctab = ''; foreach ($feature AS $tab) $ctab .= 'ccustom_'.$tab['id_feature'].'¤'; $ctab = rtrim($ctab, '¤'); echo '
'.$this->l('Assign features to this product').'


'; // Header $nb_feature = Feature::nbFeatures(intval($cookie->id_lang)); echo ' '; if (!$nb_feature) echo ''; echo '
'.$this->l('Features').' '.$this->l('Value').' '.$this->l('Customized').'
'.$this->l('No features defined').'
'; // Listing if ($nb_feature) { echo ''; foreach ($feature AS $tab_features) { $current_item = false; $custom = true; foreach ($obj->getFeatures() as $tab_products) if ($tab_products['id_feature'] == $tab_features['id_feature']) $current_item = $tab_products['id_feature_value']; echo ' '; } echo ' '; } echo '
'.$tab_features['name'].' '; $tab_customs = ($custom ? FeatureValue::getFeatureValueLang($current_item) : array()); foreach ($this->_languages as $language) echo '
'; echo '
 

new_features '.$this->l('Create new features').'
'; } else echo ''.$this->l('You must save this product before adding features').'.'; } public function haveThisAccessory($accessoryId, $accessories) { foreach ($accessories AS $accessory) if (intval($accessory['id_product']) == intval($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 ' '; } private function fillPackItems($obj) { global $currentIndex, $cookie; return ' function fillPackItems() { $.getJSON("'.dirname($currentIndex).'/ajax.php",{ajaxProductPackItems:1,id_lang:'.intval($cookie->id_lang).',id_product:'.($obj->id ? intval($obj->id) : 0).'}, function(result) { for (var i = 0; i < result.length; i++) packItems[i] = new Array(result[i].value, result[i].text); formProduct = document.layers ? document.forms.product : document.product; formProduct.selectPackItems.length = packItems.length + 1; for (i = 0, j = 1; i < packItems.length; i++) { if (formProduct.filterPack.value) if (packItems[i][1].toLowerCase().indexOf(formProduct.filterPack.value.toLowerCase()) == -1) continue; formProduct.selectPackItems.options[j].value = packItems[i][0]; formProduct.selectPackItems.options[j].text = packItems[i][1]; j++; } if (j == 1) { formProduct.selectPackItems.length = 2; formProduct.selectPackItems.options[1].value = -1; formProduct.selectPackItems.options[1].text = \''.$this->l('No match found').'\'; formProduct.selectPackItems.options.selectedIndex = 1; } else { formProduct.selectPackItems.length = j; formProduct.selectPackItems.options.selectedIndex = (formProduct.filterPack.value == \'\' ? 0 : 1); } } ); }'; } private function packItemJsInit() { return ' var reg = new RegExp(\'-\', \'g\'); var regx = new RegExp(\'x\', \'g\'); var div = getE(\'divPackItems\'); var input = getE(\'inputPackItems\'); var name = getE(\'namePackItems\'); var select = getE(\'selectPackItems\'); var select_quantity = getE(\'quantityPackItems\');'; } private function addPackItem() { return ' function addPackItem() { '.$this->packItemJsInit().' if (select.value == \'0\') return; var cut = select.value.split(reg); var inputCut = input.value.split(reg); for (var i = 0; i < inputCut.length; ++i) if (inputCut[i]) { var inputQty = inputCut[i].split(regx); if (inputQty[1] == cut[0]) return false; } for (i = 0; i < select.length; ++i) if (select.options[i].selected == true) select.options[i] = null; select.selectedIndex = 0; var nameStr = \'\'; for (i = 1; i < cut.length; ++i) nameStr += select_quantity.value + \' x \' + cut[i]; input.value += select_quantity.value + \'x\' + cut[0] + \'-\'; name.value += nameStr + \'¤\'; div.innerHTML += nameStr + \'
\'; }'; } private function delPackItem() { return ' function delPackItem(id) { '.$this->packItemJsInit().' var inputCut = input.value.split(reg); var nameCut = name.value.split(new RegExp(\'¤\', \'g\')); input.value = \'\'; name.value = \'\'; div.innerHTML = \'\'; for (var i = 0; i < inputCut.length; ++i) if (inputCut[i]) { var inputQty = inputCut[i].split(regx); if (inputQty[1] != id) { input.value += inputCut[i] + \'-\'; name.value += nameCut[i] + \'¤\'; div.innerHTML += nameCut[i] + \'
\'; } } }'; } public function updatePackItems($product) { Pack::deleteItems($product->id); if (Tools::getValue('ppack') AND $items = Tools::getValue('inputPackItems') AND sizeof($ids = array_unique(explode('-', $items)))) if (!Pack::addItems($product->id, $ids)) return false; return true; } } ?>