public function process()
 {
     parent::process();
     $hasProduct = false;
     $product_list = Tools::getValue('compare_product_list');
     $postProducts = isset($product_list) ? rtrim($product_list, '|') : '';
     if (!Configuration::get('PS_COMPARATOR_MAX_ITEM')) {
         return Tools::redirect('404.php');
     }
     if ($postProducts) {
         $ids = array_unique(explode('|', $postProducts));
         if (sizeof($ids) > 0) {
             if (sizeof($ids) > Configuration::get('PS_COMPARATOR_MAX_ITEM')) {
                 $ids = array_slice($ids, 0, Configuration::get('PS_COMPARATOR_MAX_ITEM'));
             }
             $listProducts = array();
             $listFeatures = array();
             foreach ($ids as $id) {
                 $curProduct = new Product((int) $id, true, (int) self::$cookie->id_lang);
                 if (!Validate::isLoadedObject($curProduct)) {
                     continue;
                 }
                 if (!$curProduct->active) {
                     unset($ids[$k]);
                     continue;
                 }
                 foreach ($curProduct->getFrontFeatures(self::$cookie->id_lang) as $feature) {
                     $listFeatures[$curProduct->id][$feature['id_feature']] = $feature['value'];
                 }
                 $cover = Product::getCover((int) $id);
                 $curProduct->id_image = Tools::htmlentitiesUTF8(Product::defineProductImage(array('id_image' => $cover['id_image'], 'id_product' => $id), self::$cookie->id_lang));
                 $curProduct->allow_oosp = Product::isAvailableWhenOutOfStock($curProduct->out_of_stock);
                 $listProducts[] = $curProduct;
             }
             if (sizeof($listProducts) > 0) {
                 $width = 80 / sizeof($listProducts);
                 $hasProduct = true;
                 $ordered_features = Feature::getFeaturesForComparison($ids, self::$cookie->id_lang);
                 self::$smarty->assign(array('ordered_features' => $ordered_features, 'product_features' => $listFeatures, 'products' => $listProducts, 'link' => new Link(), 'width' => $width, 'homeSize' => Image::getSize('home')));
                 self::$smarty->assign('HOOK_EXTRA_PRODUCT_COMPARISON', Module::hookExec('extraProductComparison', array('list_ids_product' => $ids)));
             }
         }
     }
     self::$smarty->assign('hasProduct', $hasProduct);
 }
 /**
  * \brief	Header hook
  * \retval 	void
  */
 public function hookHeader()
 {
     global $cookie, $cart, $smarty;
     $html = '';
     //	Check if product is a multi-dimensions product
     $multiDimensions_product = false;
     if (Tools::getIsset('id_product')) {
         $product = getProducts((int) Tools::getValue('id_product'));
         if (count($product)) {
             $multiDimensions_product = true;
         }
     }
     //	Header add only if needed
     if (strtolower(basename($_SERVER['PHP_SELF'])) == 'history.php' || Tools::getIsset('controller') && Tools::getValue('controller') == 'history' || Tools::getIsset('id_product') && $multiDimensions_product) {
         if ((double) substr(_PS_VERSION_, 0, 3) >= 1.6) {
             $this->context->controller->addJS(__PS_BASE_URI__ . 'modules/' . $this->name . '/includes/functions' . $GLOBALS['aimd_config_suffix'] . '.js');
             $this->context->controller->addCSS(__PS_BASE_URI__ . 'modules/' . $this->name . '/css/global.css');
         } else {
             if ((double) substr(_PS_VERSION_, 0, 3) == 1.5) {
                 $context = Context::getContext();
                 $context->controller->addJS(__PS_BASE_URI__ . 'modules/' . $this->name . '/includes/functions' . $GLOBALS['aimd_config_suffix'] . '.js?' . filemtime(_PS_ROOT_DIR_ . '/modules/' . $this->name . '/' . $this->name . '.php'));
                 $context->controller->addCSS(__PS_BASE_URI__ . 'modules/' . $this->name . '/css/global.css');
             } else {
                 Tools::addCSS(__PS_BASE_URI__ . 'modules/' . $this->name . '/css/global.css', 'all');
                 Tools::addJS(__PS_BASE_URI__ . 'modules/' . $this->name . '/includes/functions' . $GLOBALS['aimd_config_suffix'] . '.js?' . filemtime(_PS_ROOT_DIR_ . '/modules/' . $this->name . '/' . $this->name . '.php'));
             }
         }
         //   Header for upload
         if ((double) substr(_PS_VERSION_, 0, 3) >= 1.6) {
             //    Only if uploader activated
             if ((int) Configuration::get('AIMD_FILE_UPLOAD_TIME') != -1) {
                 $this->context->controller->addCSS(__PS_BASE_URI__ . 'modules/' . $this->name . '/css/tabs.css', 'all');
                 $this->context->controller->addJS(__PS_BASE_URI__ . 'modules/' . $this->name . '/includes/tabs.js');
                 $this->context->controller->addJS(__PS_BASE_URI__ . 'modules/' . $this->name . '/includes/mini-uploader/assets/js/jquery.knob.js');
                 $this->context->controller->addJS(__PS_BASE_URI__ . 'modules/' . $this->name . '/includes/mini-uploader/assets/js/jquery.ui.widget.js');
                 $this->context->controller->addJS(__PS_BASE_URI__ . 'modules/' . $this->name . '/includes/mini-uploader/assets/js/jquery.iframe-transport.js');
                 $this->context->controller->addJS(__PS_BASE_URI__ . 'modules/' . $this->name . '/includes/mini-uploader/assets/js/jquery.fileupload.js');
             }
         } else {
             if ((double) substr(_PS_VERSION_, 0, 3) == 1.5) {
                 //    Only if uploader activated
                 if ((int) Configuration::get('AIMD_FILE_UPLOAD_TIME') != -1) {
                     $context = Context::getContext();
                     $context->controller->addCSS(__PS_BASE_URI__ . 'modules/' . $this->name . '/includes/mini-uploader/assets/css/style.css', 'all');
                     $context->controller->addCSS(__PS_BASE_URI__ . 'modules/' . $this->name . '/css/tabs.css', 'all');
                     $context->controller->addJS(__PS_BASE_URI__ . 'modules/' . $this->name . '/includes/tabs.js');
                     $context->controller->addJS(__PS_BASE_URI__ . 'modules/' . $this->name . '/includes/mini-uploader/assets/js/jquery.knob.js');
                     $context->controller->addJS(__PS_BASE_URI__ . 'modules/' . $this->name . '/includes/mini-uploader/assets/js/jquery.ui.widget.js');
                     $context->controller->addJS(__PS_BASE_URI__ . 'modules/' . $this->name . '/includes/mini-uploader/assets/js/jquery.iframe-transport.js');
                     $context->controller->addJS(__PS_BASE_URI__ . 'modules/' . $this->name . '/includes/mini-uploader/assets/js/jquery.fileupload.js');
                 }
                 /*		    } else {
                         //    Only if uploader activated
                         if ( (int) Configuration::get('AIMD_FILE_UPLOAD_TIME') != -1 ) {
                   		        Tools::addCSS(__PS_BASE_URI__ . 'modules/' . $this->name . '/includes/mini-uploader/assets/css/style.css', 'all');
                   		        Tools::addCSS(__PS_BASE_URI__ . 'modules/' . $this->name . '/css/tabs.css', 'all');
                   		        Tools::addJS(__PS_BASE_URI__ . 'modules/' . $this->name . '/includes/tabs.js');    
                   		        Tools::addJS(__PS_BASE_URI__ . 'modules/' . $this->name . '/includes/mini-uploader/assets/js/jquery.knob.js');
                   		        Tools::addJS(__PS_BASE_URI__ . 'modules/' . $this->name . '/includes/mini-uploader/assets/js/jquery.ui.widget.js');
                   		        Tools::addJS(__PS_BASE_URI__ . 'modules/' . $this->name . '/includes/mini-uploader/assets/js/jquery.iframe-transport.js');
                   		        Tools::addJS(__PS_BASE_URI__ . 'modules/' . $this->name . '/includes/mini-uploader/assets/js/jquery.fileupload.js');
                         }*/
             }
         }
         $html .= '<script type="text/javascript">' . 'var max_files = ' . (int) Configuration::get('AIMD_FILE_NUMBER') . ';' . 'var allowed_extensions = \'' . addslashes(Configuration::get('AIMD_FILE_FORMAT')) . '\';' . 'var progressbar_label = \'' . addslashes($this->l('Upload in progress ...')) . '\';' . 'var label_extensions_error = \'' . addslashes($this->l('Extension error for file')) . '\';' . 'var label_extensions_mustBe = \'' . addslashes($this->l('must be one of')) . '\';' . '</script>';
     }
     if ($multiDimensions_product) {
         //	If magic_quotes is ON, and unactive by config, let's do it
         if (get_magic_quotes_gpc() && Configuration::get('AIMD_MAGIC_QUOTES_DISABLE')) {
             $process = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST);
             while (list($key, $val) = each($process)) {
                 foreach ($val as $k => $v) {
                     unset($process[$key][$k]);
                     if (is_array($v)) {
                         $process[$key][stripslashes($k)] = $v;
                         $process[] =& $process[$key][stripslashes($k)];
                     } else {
                         $process[$key][stripslashes($k)] = stripslashes($v);
                     }
                 }
             }
             unset($process);
         }
         //	If small dimension name is to be shows, add the cart CSS file
         if (Configuration::get('AIMD_CART_NAME') == 1) {
             if ((double) substr(_PS_VERSION_, 0, 3) >= 1.5) {
                 $context = Context::getContext();
                 $context->controller->addCSS(__PS_BASE_URI__ . 'modules/' . $this->name . '/css/cart.css');
             } else {
                 Tools::addCSS(__PS_BASE_URI__ . 'modules/' . $this->name . '/css/cart.css', 'all');
             }
         }
         //	If config is not set, exit
         if (!Configuration::get('AIMD_FIRST_DIMENSION_ACTIVE') && !Configuration::get('AIMD_SECOND_DIMENSION_ACTIVE') && !Configuration::get('AIMD_THIRD_DIMENSION_ACTIVE')) {
             return;
         }
         //	Set the base informations to calculate reductions
         $html .= '<script type="text/javascript">' . 'var default_dimensions = new Array(';
         $fdid = Configuration::get('AIMD_FIRST_DIMENSION_ID');
         $fdscale = $this->_get_scale(Configuration::get('AIMD_FIRST_DIMENSION_SCALE'));
         $fddefaultId = Db::getInstance()->ExecuteS('SELECT distinct(attribute.id_attribute) FROM ' . _DB_PREFIX_ . 'attribute as attribute LEFT JOIN ' . _DB_PREFIX_ . 'attribute_lang as lang ON attribute.id_attribute = lang.id_attribute  ' . 'WHERE attribute.id_attribute_group = ' . $fdid . ' AND lang.name = ' . $fdscale);
         $html .= 'new Array(' . $fdid . ', ' . $fdscale . ', ' . $fddefaultId[0]['id_attribute'] . '),';
         $sdid = Configuration::get('AIMD_SECOND_DIMENSION_ID');
         $sdscale = $this->_get_scale(Configuration::get('AIMD_SECOND_DIMENSION_SCALE'));
         $sddefaultId = Db::getInstance()->ExecuteS('SELECT distinct(attribute.id_attribute) FROM ' . _DB_PREFIX_ . 'attribute as attribute LEFT JOIN ' . _DB_PREFIX_ . 'attribute_lang as lang ON attribute.id_attribute = lang.id_attribute  ' . 'WHERE attribute.id_attribute_group = ' . $sdid . ' AND lang.name = ' . $sdscale);
         $html .= 'new Array(' . $sdid . ', ' . $sdscale . ', ' . $sddefaultId[0]['id_attribute'] . ')';
         $tdid = Configuration::get('AIMD_THIRD_DIMENSION_ID');
         $tdscale = $this->_get_scale(Configuration::get('AIMD_THIRD_DIMENSION_SCALE'));
         $tddefaultId = Db::getInstance()->ExecuteS('SELECT distinct(attribute.id_attribute) FROM ' . _DB_PREFIX_ . 'attribute as attribute LEFT JOIN ' . _DB_PREFIX_ . 'attribute_lang as lang ON attribute.id_attribute = lang.id_attribute  ' . 'WHERE attribute.id_attribute_group = ' . $tdid . ' AND lang.name = ' . $tdscale);
         if (Tools::getValue('id_product')) {
             if (Db::getInstance()->getValue('SELECT pa.id_product FROM ' . _DB_PREFIX_ . 'product_attribute AS pa LEFT JOIN ' . _DB_PREFIX_ . 'product_attribute_combination AS pac ON pa.id_product_attribute = pac.id_product_attribute WHERE ' . 'pa.id_product = ' . (int) Tools::getValue('id_product') . ' AND pac.id_attribute = ' . $tddefaultId[0]['id_attribute'])) {
                 $html .= ', new Array(' . $tdid . ', ' . $tdscale . ', ' . $tddefaultId[0]['id_attribute'] . ')';
             }
         } else {
             $html .= ', new Array(' . $tdid . ', ' . $tdscale . ', ' . $tddefaultId[0]['id_attribute'] . ')';
         }
         $html .= ');';
         //	Set the dimensions reductions if needed
         $dimensions = $this->l('m²');
         if (Tools::getValue('id_product')) {
             $id_product = (int) Tools::getValue('id_product');
             $html .= 'var dimensions_reductions = new Array(';
             //	Get the reductions for the product
             $first = true;
             $reductions = Db::getInstance()->ExecuteS('SELECT * FROM ' . _DB_PREFIX_ . 'aimultidimensions_reductions WHERE ar_product = ' . $id_product . ' ORDER BY ar_minimum_size');
             foreach ($reductions as $reduction) {
                 $way = '-';
                 if ($reduction['ar_way']) {
                     $way = '+';
                 }
                 if ($first) {
                     $html .= 'new Array(' . $reduction['ar_minimum_size'] . ', ' . $way . $reduction['ar_percent'] . ')';
                     $first = false;
                 } else {
                     $html .= ', new Array(' . $reduction['ar_minimum_size'] . ', ' . $way . $reduction['ar_percent'] . ')';
                 }
             }
             $html .= ');';
             //	Get the number of dimensions
             $result = Db::getInstance()->ExecuteS('SELECT attribute.id_product, group_lang.name as group_name, lang.name FROM ' . _DB_PREFIX_ . 'product_attribute_combination as combination LEFT JOIN ' . _DB_PREFIX_ . 'product_attribute as attribute ON combination.id_product_attribute = attribute.id_product_attribute LEFT JOIN ' . _DB_PREFIX_ . 'product_lang as lang ON lang.id_product = attribute.id_product ' . 'LEFT JOIN ' . _DB_PREFIX_ . 'attribute as attribute_group ON attribute_group.id_attribute = combination.id_attribute LEFT JOIN ' . _DB_PREFIX_ . 'attribute_group_lang as group_lang ON ' . 'group_lang.id_attribute_group = attribute_group.id_attribute_group WHERE lang.id_lang = ' . (int) $cookie->id_lang . ' AND lang.id_product = ' . $id_product . ' AND group_lang.id_lang = ' . (int) $cookie->id_lang . ' AND attribute_group.id_attribute IN (SELECT attrib.id_attribute FROM ' . _DB_PREFIX_ . 'attribute as attrib WHERE attrib.id_attribute_group IN (' . $fdid . ', ' . $sdid . ', ' . $tdid . ')) GROUP BY attribute.id_product, group_lang.name');
             if (count($result) == 3) {
                 $dimensions = $this->l('m3');
             }
             //	Global surface reduction
             $result = Db::getInstance()->ExecuteS('SELECT aimd_gsr FROM ' . _DB_PREFIX_ . 'product WHERE id_product = ' . $id_product);
             $html .= 'var global_surface_reduction = ' . $result[0]['aimd_gsr'] . ';';
             //	Get the default combination
             $result = Db::getInstance()->ExecuteS('SELECT id_product_attribute FROM ' . _DB_PREFIX_ . 'product_attribute WHERE id_product = ' . $id_product . ' AND default_on = 1');
             $id_product_attribute = 0;
             if (count($result)) {
                 $id_product_attribute = (int) $result[0]['id_product_attribute'];
             }
             $html .= 'var default_combination_id = ' . $id_product_attribute . ';';
             //	Limits
             $result = Db::getInstance()->ExecuteS('SELECT * FROM ' . _DB_PREFIX_ . 'aimultidimensions_limits WHERE al_product = ' . $id_product . ' AND al_dimension IN (' . (int) $fdid . ', ' . (int) $sdid . ', ' . (int) $tdid . ')');
             $html .= 'var limits = new Array(';
             $cpt = 0;
             $limits_html = '';
             foreach ($result as $row) {
                 $single_limit_id = 0;
                 //	Message to display
                 $message = '';
                 if (floatval($row['al_minimum_size']) == 0) {
                     $message = addslashes($this->l('Less than')) . ' ' . $this->_cleanSize($row['al_maximum_size']);
                 } else {
                     if (floatval($row['al_maximum_size']) == 0) {
                         $message = addslashes($this->l('More than')) . ' ' . $this->_cleanSize($row['al_minimum_size']);
                     } else {
                         $message = addslashes($this->l('From')) . ' ' . $this->_cleanSize($row['al_minimum_size']) . ' ' . addslashes($this->l('To')) . ' ' . $this->_cleanSize($row['al_maximum_size']);
                     }
                 }
                 //	Single limit id
                 if ($row['al_minimum_size'] == $row['al_maximum_size'] && $row['al_maximum_size'] != 0) {
                     $single_limit_id = Db::getInstance()->getValue('SELECT pac.id_attribute FROM ' . _DB_PREFIX_ . 'product_attribute_combination AS pac LEFT JOIN ' . _DB_PREFIX_ . 'attribute AS a ON ' . 'a.id_attribute = pac.id_attribute LEFT JOIN ' . _DB_PREFIX_ . 'attribute_lang AS al ON al.id_attribute = a.id_attribute WHERE pac.id_product_attribute = ' . $id_product_attribute . ' AND ' . 'a.id_attribute_group = ' . $row['al_dimension'] . ' AND al.name = "' . floatval($row['al_minimum_size']) . '" GROUP BY al.id_attribute');
                     if ($limits_html) {
                         $limits_html .= ', ';
                     }
                     $limits_html .= 'new Array(' . $row['al_dimension'] . ', "' . $single_limit_id . '")';
                 }
                 if ($cpt != 0) {
                     $html .= ', ';
                 }
                 $html .= 'new Array(' . $row['al_dimension'] . ', ' . $row['al_minimum_size'] . ', ' . $row['al_maximum_size'] . ', \'' . $message . '\')';
                 $cpt++;
             }
             //	Add limits from product links
             $result = Db::getInstance()->ExecuteS('SELECT COUNT(fd_attribute_group) AS number, fd_product, fd_attribute_group, fd_value FROM ' . _DB_PREFIX_ . 'aimultidimensions_fixed_dimensions WHERE ' . 'fd_product = ' . $id_product . ' GROUP BY fd_attribute_group ORDER BY number ASC');
             foreach ($result as $row) {
                 if ((int) $row['number'] == 1) {
                     $single_limit_id = Db::getInstance()->getValue('SELECT pac.id_attribute FROM ' . _DB_PREFIX_ . 'product_attribute_combination AS pac LEFT JOIN ' . _DB_PREFIX_ . 'attribute AS a ON ' . 'a.id_attribute = pac.id_attribute LEFT JOIN ' . _DB_PREFIX_ . 'attribute_lang AS al ON al.id_attribute = a.id_attribute WHERE pac.id_product_attribute = ' . $id_product_attribute . ' AND ' . 'a.id_attribute_group = ' . $row['fd_attribute_group'] . ' AND al.name = "' . floatval($row['fd_value']) . '" GROUP BY al.id_attribute');
                     if ($limits_html) {
                         $limits_html .= ', ';
                     }
                     $limits_html .= 'new Array(' . $row['fd_attribute_group'] . ', "' . $single_limit_id . '")';
                 }
             }
             $html .= ');';
             $html .= 'var limit_error_message = \'' . addslashes($this->l('Value not in the Limits range')) . '\';';
             //	Single limit id
             $html .= 'var single_limit_ids = new Array(' . $limits_html . ');';
             //	Minimum surface charged
             $minimum_surface = Db::getInstance()->getValue('SELECT aimd_msc FROM ' . _DB_PREFIX_ . 'product WHERE id_product = ' . $id_product);
             $html .= 'var minimum_surface = ' . floatval($minimum_surface) . ';';
             //	fixed dimensions
             $first_fixed_dimensions = Db::getInstance()->getValue('SELECT GROUP_CONCAT(CAST(fd_value AS CHAR) ORDER BY fd_value) FROM ' . _DB_PREFIX_ . 'aimultidimensions_fixed_dimensions WHERE fd_product = ' . $id_product . ' AND fd_attribute_group  = ' . $fdid);
             $second_fixed_dimensions = Db::getInstance()->getValue('SELECT GROUP_CONCAT(CAST(fd_value AS CHAR) ORDER BY fd_value) FROM ' . _DB_PREFIX_ . 'aimultidimensions_fixed_dimensions WHERE fd_product = ' . $id_product . ' AND fd_attribute_group  = ' . $sdid);
             $third_fixed_dimensions = Db::getInstance()->getValue('SELECT GROUP_CONCAT(CAST(fd_value AS CHAR) ORDER BY fd_value) FROM ' . _DB_PREFIX_ . 'aimultidimensions_fixed_dimensions WHERE fd_product = ' . $id_product . ' AND fd_attribute_group  = ' . $tdid);
             $html .= 'var fixed_dimensions = new Array(' . 'new Array(' . $fdid . ', "' . $first_fixed_dimensions . '"),' . 'new Array(' . $sdid . ', "' . $second_fixed_dimensions . '"),' . 'new Array(' . $tdid . ', "' . $third_fixed_dimensions . '"));' . 'var fixed_dimensions_choose_label = \'' . addslashes($this->l('Choose a dimension')) . '\';';
             //	Delivery
             $result = Db::getInstance()->getRow('SELECT ad_delivery FROM ' . _DB_PREFIX_ . 'aimultidimensions_delivery WHERE ad_product = ' . $id_product);
             if (count($result)) {
                 if ($result['ad_delivery']) {
                     $delivery = $this->_setDate((int) $result['ad_delivery']);
                     $html .= 'var delivery_text =\'' . addslashes($this->l('Delivery')) . ' ' . addslashes($this->l('about')) . ' ' . $delivery . '\';';
                 } else {
                     $html .= 'var delivery_text =\'\';';
                 }
             } else {
                 $html .= 'var delivery_text =\'\';';
             }
             //	Quantity display
             $display = (int) Db::getInstance()->getValue('SELECT aimd_dpq FROM ' . _DB_PREFIX_ . 'product WHERE id_product = ' . $id_product);
             $html .= 'var aimd_quantity_display = ' . $display . ';';
             //    Add product formula
             $format = (int) DB::getInstance()->getValue('SELECT aimd_format FROM ' . _DB_PREFIX_ . 'product WHERE id_product = ' . $id_product);
             $formula = $GLOBALS['config_format'][$format]['surface_formula'];
             $html .= 'var aimd_format_formula = \'' . $formula . '\';';
             $labels = $GLOBALS['config_format'][$format]['labels'];
             $html .= 'var aimd_format_labels = {';
             if ($labels['x'] != '') {
                 $html .= $fdid . ': \'' . addslashes($labels['x']) . '\',';
             }
             if ($labels['y'] != '') {
                 $html .= $sdid . ': \'' . addslashes($labels['y']) . '\',';
             }
             if ($labels['z'] != '') {
                 $html .= $tdid . ': \'' . addslashes($labels['z']) . '\',';
             }
             $html .= '};';
             //    Add proportionnal display
             $html .= 'var aimd_format_proportionnal_display = ' . $GLOBALS['config_format'][$format]['proportionnal display'] . ';';
         }
         //	Price display option
         $html .= 'var price_display_option = ' . (int) Configuration::get('AIMD_PRICE_DISPLAY') . ';';
         //	Surface & weight display option
         $html .= 'var surfaceWeight_display_option = ' . (int) Configuration::get('AIMD_SURFACEWEIGHT_DISPLAY') . ';';
         //	Minimum surface charged labels
         $html .= 'var minimum_surface_message = \'' . addslashes($this->l('Minimum charged surface is ')) . '\';';
         $html .= 'var minimum_surface_scale = \'' . $dimensions . '\';';
         $html .= 'var minimum_surface_on_quantity = ' . Configuration::get('AIMD_MIN_SURFACE_ON_QUANTITY') . ';';
         //	Calculate button label
         $html .= 'var calculate_button_label =\'' . $this->l('Calculate') . '\';';
         //	For availability informations
         $html .= 'var availability_informations_message = \'' . addslashes($this->l('Choose dimensions message')) . '\';';
         //	For calculating message
         $html .= 'var calculating_message = \'' . addslashes($this->l('Calculating ...')) . '\';';
         //	For choose message
         $html .= 'var choose_message = \'' . addslashes($this->l('Choose dimensions')) . '\';';
         //	Surface display
         if (Configuration::get('AIMD_SURFACE_DISPLAY') == '1') {
             $html .= 'var surface_display = true;' . 'var surface_display_message = \'' . addslashes($this->l('Surface of {value}')) . '\';';
         } else {
             $html .= 'var surface_display = false;';
         }
         //	Weight display
         if (Configuration::get('AIMD_WEIGHT_DISPLAY') == '1') {
             $html .= 'var weight_display = true;' . 'var calculated_weight_message = \'' . addslashes($this->l('Weight of')) . '\';' . 'var calculated_weight_unit = \'' . addslashes($this->l('Kgs')) . '\';';
         } else {
             $html .= 'var weight_display = false;';
         }
         //	Fixed prices
         $result = Db::getInstance()->ExecuteS('SELECT attributes.* FROM ' . _DB_PREFIX_ . 'aimultidimensions_specials_attributes AS attributes LEFT JOIN ' . _DB_PREFIX_ . 'aimultidimensions_specials AS specials ON ' . 'attributes.asa_group = specials.as_group WHERE specials.as_type = 0 ORDER BY attributes.asa_group');
         $html .= 'var fixed_prices = new Array(';
         $cpt = 0;
         foreach ($result as $row) {
             $html .= 'new Array(' . $row['asa_group'] . ', ' . $row['asa_attribute'] . ', ' . $row['asa_value'] . ')';
             $cpt++;
             if ($cpt < count($result)) {
                 $html .= ', ';
             }
         }
         $html .= ');';
         //	Percent prices
         $result = Db::getInstance()->ExecuteS('SELECT attributes.* FROM ' . _DB_PREFIX_ . 'aimultidimensions_specials_attributes AS attributes LEFT JOIN ' . _DB_PREFIX_ . 'aimultidimensions_specials AS ' . 'specials ON attributes.asa_group = specials.as_group WHERE specials.as_type = 3 ORDER BY attributes.asa_group');
         $html .= 'var percent_prices = new Array(';
         $cpt = 0;
         foreach ($result as $row) {
             $html .= 'new Array(' . $row['asa_group'] . ', ' . $row['asa_attribute'] . ', ' . $row['asa_value'] . ')';
             $cpt++;
             if ($cpt < count($result)) {
                 $html .= ', ';
             }
         }
         $html .= ');';
         //	Taxes type
         $taxesType = 0;
         if (intval($cookie->logged) == 1) {
             $result_taxesType = Db::getInstance()->ExecuteS('SELECT price_display_method FROM ' . _DB_PREFIX_ . 'group AS g LEFT JOIN ' . _DB_PREFIX_ . 'customer AS c ON g.id_group = c.id_default_group WHERE ' . 'c.id_customer = ' . $cookie->id_customer);
         } else {
             $result_taxesType = Db::getInstance()->ExecuteS('SELECT price_display_method FROM ' . _DB_PREFIX_ . 'group WHERE id_group = 1');
         }
         if (count($result_taxesType)) {
             $taxesType = 1 - $result_taxesType[0]['price_display_method'];
         }
         $html .= 'var product_taxes_type = ' . $taxesType . ';';
         //	Limit placement
         $html .= 'var limit_placement = ' . Configuration::get('AIMD_LIMIT_PLACEMENT') . ';';
         //	Single limit display
         $html .= 'var single_limit_display = ' . Configuration::get('AIMD_FIXED_DIMENSION_DISPLAY') . ';';
         //	If needed in PS 1.5 and above, add the add to cart button
         if ((double) substr(_PS_VERSION_, 0, 3) >= 1.5) {
             $html .= '$(document).ready( function () {';
             $productTmp = new Product($id_product);
             $allowOosp = Product::isAvailableWhenOutOfStock($productTmp->out_of_stock);
             if ($productTmp->available_for_order && ($allowOosp || $productTmp->quantity >= 0) && !Configuration::get('PS_CATALOG_MODE')) {
                 $html .= '$(\'form#buy_block div.content_prices span.exclusive\').after(\'<p id="add_to_cart" class="buttons_bottom_block" style="display: none"><span></span><input type="submit" name="Submit" value="' . $this->l('Add to cart') . '" class="exclusive" /></p>\');' . '$(\'form#buy_block div.content_prices span.exclusive\').remove();';
             }
             $html .= '$(\'div#ai_calculating_message\').attr(\'style\',\'display: none;\');' . '$(\'span#ai_choose_message\').attr(\'style\',\'\');' . '});';
         }
         //	Get active attributs
         $attributes = getActiveAttributes();
         //	Default values if needed
         $defaults = Db::getInstance()->ExecuteS('SELECT ag.id_attribute_group, al.name FROM ' . _DB_PREFIX_ . 'product_attribute AS pa LEFT JOIN ' . _DB_PREFIX_ . 'product_attribute_combination AS pac ON ' . 'pa.id_product_attribute = pac.id_product_attribute LEFT JOIN ' . _DB_PREFIX_ . 'attribute_lang AS al ON al.id_attribute = pac.id_attribute LEFT JOIN ' . _DB_PREFIX_ . 'attribute AS a ON ' . 'a.id_attribute = pac.id_attribute LEFT JOIN ' . _DB_PREFIX_ . 'attribute_group AS ag ON a.id_attribute_group = ag.id_attribute_group WHERE pa.id_product = ' . (int) Tools::getValue('id_product') . ' AND ' . 'pa.aimd_value = 1 AND pa.default_on = 1 AND al.id_lang = ' . (int) $cookie->id_lang . ' AND ag.id_attribute_group IN (' . implode(',', $attributes) . ') ORDER BY ag.id_attribute_group ASC');
         $proportional_value = 0;
         if (count($defaults)) {
             $add = array();
             foreach ($defaults as $default) {
                 $add[] = 'new Array(' . (int) $default['id_attribute_group'] . ', ' . $default['name'] . ')';
                 if ($default['id_attribute_group'] == Configuration::get('AIMD_PROPORTIONNAL_DIMENSION')) {
                     $proportional_value = (int) $default['name'];
                 }
             }
             $html .= 'var aimd_defaults = new Array(' . implode(',', $add) . ');';
         }
         //  Add overlay
         $html .= '$(document).ready(function () {' . '$(\'#attributes\').append(\'<div id="aimd_operations_overlay" class="wait">&nbsp;</div><div id="aimd_wait">&nbsp;</div>\');' . '});';
     }
     //	Security
     if (!isset($proportional_value)) {
         $proportional_value = 0;
     }
     //	Add Prestashop version
     if ($html == '' || (strtolower(basename($_SERVER['PHP_SELF'])) == 'history.php' || Tools::getIsset('controller') && Tools::getValue('controller') == 'history')) {
         $html .= '<script type="text/javascript">';
     }
     $html .= 'var prestashop_version = parseFloat(' . substr(_PS_VERSION_, 0, 3) . ');' . 'var prestashop_version_long = \'' . _PS_VERSION_ . '\';' . 'var multiDimensions_product = ' . (int) $multiDimensions_product . ';';
     //	Get the proportionality value
     if (Tools::getValue('id_product') && (int) $multiDimensions_product) {
         $proportionality = (int) Db::getInstance()->getValue('SELECT aimd_proportional FROM ' . _DB_PREFIX_ . 'product WHERE id_product = ' . (int) Tools::getValue('id_product'));
         $html .= 'var aimd_proportional = ' . $proportionality . ';' . 'var aimd_proportional_group = ' . (int) Configuration::get('AIMD_PROPORTIONNAL_DIMENSION') . ';' . 'var aimd_proportional_value = ' . $proportional_value . ';' . 'var proportional_message = \'' . addslashes($this->l('The dimensions are proportional, you only need to input the first one.')) . '\';';
     } else {
         $html .= 'var aimd_proportional = 0;';
     }
     //	Ending the javascript block
     $html .= '</script>';
     return $html;
 }
Example #3
0
    public function getProducts($refresh = false, $id_product = false, $id_country = null)
    {
        /* 
         * EU-Legal
         * 1) correct calculation of prices -> Problem with inaccuracy at high number of items 
         * 2) assign standard delivery times to products
         */
        if (!$this->id) {
            return array();
        }
        // Product cache must be strictly compared to NULL, or else an empty cart will add dozens of queries
        if ($this->_products !== null && !$refresh) {
            // Return product row with specified ID if it exists
            if (is_int($id_product)) {
                foreach ($this->_products as $product) {
                    if ($product['id_product'] == $id_product) {
                        return array($product);
                    }
                }
                return array();
            }
            return $this->_products;
        }
        // Build query
        $sql = new DbQuery();
        // Build SELECT
        $sql->select('cp.`id_product_attribute`, cp.`id_product`, cp.`quantity` AS cart_quantity, cp.id_shop, pl.`name`, p.`is_virtual`,
						pl.`description_short`, pl.`available_now`, pl.`available_later`, pl.`delivery_now`, pl.`delivery_later`, product_shop.`id_category_default`, p.`id_supplier`,
						p.`id_manufacturer`, product_shop.`on_sale`, product_shop.`ecotax`, product_shop.`additional_shipping_cost`,
						product_shop.`available_for_order`, product_shop.`price`, product_shop.`active`, product_shop.`unity`, product_shop.`unit_price_ratio`, 
						stock.`quantity` AS quantity_available, p.`width`, p.`height`, p.`depth`, stock.`out_of_stock`, p.`weight`,
						p.`date_add`, p.`date_upd`, IFNULL(stock.quantity, 0) as quantity, pl.`link_rewrite`, cl.`link_rewrite` AS category,
						CONCAT(LPAD(cp.`id_product`, 10, 0), LPAD(IFNULL(cp.`id_product_attribute`, 0), 10, 0), IFNULL(cp.`id_address_delivery`, 0)) AS unique_id, cp.id_address_delivery,
						product_shop.advanced_stock_management, ps.product_supplier_reference supplier_reference, IFNULL(sp.`reduction_type`, 0) AS reduction_type');
        // Build FROM
        $sql->from('cart_product', 'cp');
        // Build JOIN
        $sql->leftJoin('product', 'p', 'p.`id_product` = cp.`id_product`');
        $sql->innerJoin('product_shop', 'product_shop', '(product_shop.`id_shop` = cp.`id_shop` AND product_shop.`id_product` = p.`id_product`)');
        $sql->leftJoin('product_lang', 'pl', '
			p.`id_product` = pl.`id_product`
			AND pl.`id_lang` = ' . (int) $this->id_lang . Shop::addSqlRestrictionOnLang('pl', 'cp.id_shop'));
        $sql->leftJoin('category_lang', 'cl', '
			product_shop.`id_category_default` = cl.`id_category`
			AND cl.`id_lang` = ' . (int) $this->id_lang . Shop::addSqlRestrictionOnLang('cl', 'cp.id_shop'));
        $sql->leftJoin('product_supplier', 'ps', 'ps.`id_product` = cp.`id_product` AND ps.`id_product_attribute` = cp.`id_product_attribute` AND ps.`id_supplier` = p.`id_supplier`');
        $sql->leftJoin('specific_price', 'sp', 'sp.`id_product` = cp.`id_product`');
        // AND 'sp.`id_shop` = cp.`id_shop`
        // @todo test if everything is ok, then refactorise call of this method
        $sql->join(Product::sqlStock('cp', 'cp'));
        // Build WHERE clauses
        $sql->where('cp.`id_cart` = ' . (int) $this->id);
        if ($id_product) {
            $sql->where('cp.`id_product` = ' . (int) $id_product);
        }
        $sql->where('p.`id_product` IS NOT NULL');
        // Build GROUP BY
        $sql->groupBy('unique_id');
        // Build ORDER BY
        $sql->orderBy('cp.`date_add`, p.`id_product`, cp.`id_product_attribute` ASC');
        if (Customization::isFeatureActive()) {
            $sql->select('cu.`id_customization`, cu.`quantity` AS customization_quantity');
            $sql->leftJoin('customization', 'cu', 'p.`id_product` = cu.`id_product` AND cp.`id_product_attribute` = cu.`id_product_attribute` AND cu.`id_cart` = ' . (int) $this->id);
        } else {
            $sql->select('NULL AS customization_quantity, NULL AS id_customization');
        }
        if (Combination::isFeatureActive()) {
            $sql->select('
				product_attribute_shop.`price` AS price_attribute, product_attribute_shop.`ecotax` AS ecotax_attr,
				IF (IFNULL(pa.`reference`, \'\') = \'\', p.`reference`, pa.`reference`) AS reference,
				(p.`weight`+ pa.`weight`) weight_attribute,
				IF (IFNULL(pa.`ean13`, \'\') = \'\', p.`ean13`, pa.`ean13`) AS ean13,
				IF (IFNULL(pa.`upc`, \'\') = \'\', p.`upc`, pa.`upc`) AS upc,
				pai.`id_image` as pai_id_image, il.`legend` as pai_legend,
				IFNULL(product_attribute_shop.`minimal_quantity`, product_shop.`minimal_quantity`) as minimal_quantity,
				IF(product_attribute_shop.wholesale_price > 0,  product_attribute_shop.wholesale_price, product_shop.`wholesale_price`) wholesale_price
			');
            $sql->leftJoin('product_attribute', 'pa', 'pa.`id_product_attribute` = cp.`id_product_attribute`');
            $sql->leftJoin('product_attribute_shop', 'product_attribute_shop', '(product_attribute_shop.`id_shop` = cp.`id_shop` AND product_attribute_shop.`id_product_attribute` = pa.`id_product_attribute`)');
            $sql->leftJoin('product_attribute_image', 'pai', 'pai.`id_product_attribute` = pa.`id_product_attribute`');
            $sql->leftJoin('image_lang', 'il', 'il.`id_image` = pai.`id_image` AND il.`id_lang` = ' . (int) $this->id_lang);
        } else {
            $sql->select('p.`reference` AS reference, p.`ean13`,
				p.`upc` AS upc, product_shop.`minimal_quantity` AS minimal_quantity, product_shop.`wholesale_price` wholesale_price');
        }
        $result = Db::getInstance()->executeS($sql);
        // Reset the cache before the following return, or else an empty cart will add dozens of queries
        $products_ids = array();
        $pa_ids = array();
        if ($result) {
            foreach ($result as $row) {
                $products_ids[] = $row['id_product'];
                $pa_ids[] = $row['id_product_attribute'];
            }
        }
        // Thus you can avoid one query per product, because there will be only one query for all the products of the cart
        Product::cacheProductsFeatures($products_ids);
        Cart::cacheSomeAttributesLists($pa_ids, $this->id_lang);
        $this->_products = array();
        if (empty($result)) {
            return array();
        }
        $cart_shop_context = Context::getContext()->cloneContext();
        foreach ($result as &$row) {
            if (isset($row['ecotax_attr']) && $row['ecotax_attr'] > 0) {
                $row['ecotax'] = (double) $row['ecotax_attr'];
            }
            $row['stock_quantity'] = (int) $row['quantity'];
            // for compatibility with 1.2 themes
            $row['quantity'] = (int) $row['cart_quantity'];
            if (isset($row['id_product_attribute']) && (int) $row['id_product_attribute'] && isset($row['weight_attribute'])) {
                $row['weight'] = (double) $row['weight_attribute'];
            }
            if (Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_invoice') {
                $address_id = (int) $this->id_address_invoice;
            } else {
                $address_id = (int) $row['id_address_delivery'];
            }
            if (!Address::addressExists($address_id)) {
                $address_id = null;
            }
            if ($cart_shop_context->shop->id != $row['id_shop']) {
                $cart_shop_context->shop = new Shop((int) $row['id_shop']);
            }
            $address = Address::initialize($address_id, true);
            $id_tax_rules_group = Product::getIdTaxRulesGroupByIdProduct((int) $row['id_product'], $cart_shop_context);
            $tax_calculator = TaxManagerFactory::getManager($address, $id_tax_rules_group)->getTaxCalculator();
            $row['price'] = Product::getPriceStatic((int) $row['id_product'], false, isset($row['id_product_attribute']) ? (int) $row['id_product_attribute'] : null, 6, null, false, true, $row['cart_quantity'], false, (int) $this->id_customer ? (int) $this->id_customer : null, (int) $this->id, $address_id, $specific_price_output, false, true, $cart_shop_context);
            switch (Configuration::get('PS_ROUND_TYPE')) {
                case Order::ROUND_TOTAL:
                    $row['total'] = $row['price'] * (int) $row['cart_quantity'];
                    $row['total_wt'] = $tax_calculator->addTaxes($row['price']) * (int) $row['cart_quantity'];
                    break;
                case Order::ROUND_LINE:
                    $row['total'] = Tools::ps_round($row['price'] * (int) $row['cart_quantity'], _PS_PRICE_COMPUTE_PRECISION_);
                    $row['total_wt'] = Tools::ps_round($tax_calculator->addTaxes($row['price']) * (int) $row['cart_quantity'], _PS_PRICE_COMPUTE_PRECISION_);
                    break;
                case Order::ROUND_ITEM:
                default:
                    $row['total'] = Tools::ps_round($row['price'], _PS_PRICE_COMPUTE_PRECISION_) * (int) $row['cart_quantity'];
                    $row['total_wt'] = Tools::ps_round($tax_calculator->addTaxes($row['price']), _PS_PRICE_COMPUTE_PRECISION_) * (int) $row['cart_quantity'];
                    break;
            }
            $row['price_wt'] = $tax_calculator->addTaxes($row['price']);
            $row['description_short'] = Tools::nl2br($row['description_short']);
            if (!isset($row['pai_id_image']) || $row['pai_id_image'] == 0) {
                $cache_id = 'Cart::getProducts_' . '-pai_id_image-' . (int) $row['id_product'] . '-' . (int) $this->id_lang . '-' . (int) $row['id_shop'];
                if (!Cache::isStored($cache_id)) {
                    $row2 = Db::getInstance()->getRow('
						SELECT image_shop.`id_image` id_image, il.`legend`
						FROM `' . _DB_PREFIX_ . 'image` i
						JOIN `' . _DB_PREFIX_ . 'image_shop` image_shop ON (i.id_image = image_shop.id_image AND image_shop.cover=1 AND image_shop.id_shop=' . (int) $row['id_shop'] . ')
						LEFT JOIN `' . _DB_PREFIX_ . 'image_lang` il ON (image_shop.`id_image` = il.`id_image` AND il.`id_lang` = ' . (int) $this->id_lang . ')
						WHERE i.`id_product` = ' . (int) $row['id_product'] . ' AND image_shop.`cover` = 1');
                    Cache::store($cache_id, $row2);
                }
                $row2 = Cache::retrieve($cache_id);
                if (!$row2) {
                    $row2 = array('id_image' => false, 'legend' => false);
                } else {
                    $row = array_merge($row, $row2);
                }
            } else {
                $row['id_image'] = $row['pai_id_image'];
                $row['legend'] = $row['pai_legend'];
            }
            $row['reduction_applies'] = $specific_price_output && (double) $specific_price_output['reduction'];
            $row['quantity_discount_applies'] = $specific_price_output && $row['cart_quantity'] >= (int) $specific_price_output['from_quantity'];
            $row['id_image'] = Product::defineProductImage($row, $this->id_lang);
            $row['allow_oosp'] = Product::isAvailableWhenOutOfStock($row['out_of_stock']);
            $row['features'] = Product::getFeaturesStatic((int) $row['id_product']);
            if (array_key_exists($row['id_product_attribute'] . '-' . $this->id_lang, self::$_attributesLists)) {
                $row = array_merge($row, self::$_attributesLists[$row['id_product_attribute'] . '-' . $this->id_lang]);
            }
            /* 
             * EU-Legal
             * assign standard delivery times to products
             */
            $row['delivery_now'] = !empty($row['delivery_now']) ? $row['delivery_now'] : Configuration::get('LEGAL_DELIVERY_NOW', $this->id_lang);
            $row['delivery_later'] = !empty($row['delivery_later']) ? $row['delivery_later'] : Configuration::get('LEGAL_DELIVERY_LATER', $this->id_lang);
            $row = Product::getTaxesInformations($row, $cart_shop_context);
            $this->_products[] = $row;
        }
        return $this->_products;
    }
Example #4
0
 protected function processChangeProductInCart()
 {
     $mode = Tools::getIsset('update') && $this->id_product ? 'update' : 'add';
     if (!$this->id_product) {
         $this->errors[] = Tools::displayError('Product not found', !Tools::getValue('ajax'));
     }
     $product = new Product($this->id_product, true, $this->context->language->id);
     if (!$product->id || !$product->active || !$product->checkAccess($this->context->cart->id_customer)) {
         $this->errors[] = Tools::displayError('This product is no longer available.', !Tools::getValue('ajax'));
         return;
     }
     $qty_factor = 1;
     $ext_qty_factor = 1;
     $ext_prop_quantities = null;
     $id_cart_product = 0;
     $qty_behavior = 0;
     $icp = (int) Tools::getValue('icp');
     $properties = $product->productProperties();
     if ($icp && $this->context->cart->id) {
         $cart_products = $this->context->cart->getProducts();
         if (count($cart_products)) {
             foreach ($cart_products as $cart_product) {
                 if ($icp == (int) $cart_product['id_cart_product']) {
                     $id_cart_product = $icp;
                     if ($mode == 'add') {
                         if (Tools::getValue('qty') != 'default') {
                             $qty_factor = (int) Tools::getValue('qty');
                         }
                         $_POST['qty'] = (double) $cart_product['cart_quantity_fractional'] > 0 ? (double) $cart_product['cart_quantity_fractional'] : ($product->qtyStep() > 0 ? $product->qtyStep() : 1);
                     } elseif ($mode == 'update') {
                         $qty_behavior = PP::qtyBehavior($product, $cart_product['cart_quantity']);
                     }
                     break;
                 }
             }
         }
     } else {
         if ($properties['pp_ext'] == 1 && in_array($properties['pp_ext_policy'], array(0, 2))) {
             $ext_prop_quantities = array();
             $ext_prop_qty_ratio = array();
             if ($properties['pp_ext_policy'] == 2) {
                 $prop = $product->productProp();
                 if ($this->id_product_attribute) {
                     $id_product_attribute = $this->id_product_attribute;
                 } else {
                     if ($product->hasAttributes()) {
                         $id_product_attribute = Product::getDefaultAttribute($product->id);
                     } else {
                         $id_product_attribute = 0;
                     }
                 }
             }
             $positions = count($properties['pp_ext_prop']);
             for ($position = 1; $position <= $positions; $position++) {
                 $pp_ext_prop = $properties['pp_ext_prop'][$position];
                 if ($properties['pp_ext_policy'] == 2) {
                     $q = PP::productProp($prop, $id_product_attribute, $position, 'quantity');
                     if ($q === false) {
                         $q = (double) $pp_ext_prop['default_quantity'];
                     }
                     if ($q <= 0) {
                         $q = 1;
                     }
                 } else {
                     $q = PP::resolveInputQty(Tools::getValue('pp_ext_prop_quantity_' . $position, 'default'), $properties['pp_qty_policy'], $pp_ext_prop['qty_step'], $pp_ext_prop['default_quantity'] > 0 ? $pp_ext_prop['default_quantity'] : 1);
                 }
                 $ext_prop_quantities[$position] = $q;
                 $ext_prop_qty_ratio[$position] = $properties['pp_ext_prop'][$position]['qty_ratio'];
                 if ($q <= 0) {
                     $this->errors[] = Tools::displayError('Quantity not specified.', !Tools::getValue('ajax'));
                 }
                 $min_qty = (double) $pp_ext_prop['minimum_quantity'];
                 if ($min_qty > 0 && $q < $min_qty) {
                     $this->errors[] = Tools::displayError(sprintf('Please specify at least %s for %s', (string) PP::formatQty($min_qty), (string) $pp_ext_prop['property']), !Tools::getValue('ajax'));
                 }
                 $max_qty = (double) $pp_ext_prop['maximum_quantity'];
                 if ($max_qty > 0 && $q > $max_qty) {
                     $this->errors[] = Tools::displayError(sprintf('Please specify no more than %s for %s', (string) PP::formatQty($max_qty), (string) $pp_ext_prop['property']), !Tools::getValue('ajax'));
                 }
             }
             if (!$this->errors) {
                 $ext_qty_factor = $properties['pp_ext_method'] == 1 ? 1 : 0;
                 $positions = count($ext_prop_quantities);
                 for ($position = 1; $position <= $positions; $position++) {
                     $value = $ext_prop_quantities[$position];
                     $qty_ratio = $ext_prop_qty_ratio[$position];
                     if ($properties['pp_ext_method'] == 1) {
                         $ext_qty_factor *= $qty_ratio > 0 ? $value / $qty_ratio : $value;
                     } elseif ($properties['pp_ext_method'] == 2) {
                         $ext_qty_factor += $qty_ratio > 0 ? $value / $qty_ratio : $value;
                     }
                 }
             }
         }
     }
     if (!$this->errors) {
         if ($this->id_product_attribute) {
             $default_quantity = $product->attributeDefaultQty($this->id_product_attribute);
             $this->qty = $qty_factor * $this->resolveInputQty($properties, $default_quantity);
             if ($this->qty == 0) {
                 $this->errors[] = Tools::displayError('Quantity not specified.', !Tools::getValue('ajax'));
             } else {
                 if (!Product::isAvailableWhenOutOfStock($product->out_of_stock) && !Attribute::checkAttributeQty($this->id_product_attribute, $ext_qty_factor * $this->qty)) {
                     $this->errors[] = Tools::displayError('There isn\'t enough product in stock.', !Tools::getValue('ajax'));
                 }
             }
         } else {
             if ($product->hasAttributes()) {
                 $min_quantity = $product->out_of_stock == 2 ? !Configuration::get('PS_ORDER_OUT_OF_STOCK') : !$product->out_of_stock;
                 $this->id_product_attribute = Product::getDefaultAttribute($product->id, $min_quantity);
                 if (!$this->id_product_attribute) {
                     Tools::redirectAdmin($this->context->link->getProductLink($product));
                 } else {
                     $default_quantity = $product->attributeDefaultQty($this->id_product_attribute);
                     $this->qty = $qty_factor * $this->resolveInputQty($properties, $default_quantity);
                     if ($this->qty == 0) {
                         $this->errors[] = Tools::displayError('Quantity not specified.', !Tools::getValue('ajax'));
                     } else {
                         if (!Product::isAvailableWhenOutOfStock($product->out_of_stock) && !Attribute::checkAttributeQty($this->id_product_attribute, $ext_qty_factor * $this->qty)) {
                             $this->errors[] = Tools::displayError('There isn\'t enough product in stock.', !Tools::getValue('ajax'));
                         }
                     }
                 }
             } else {
                 $default_quantity = $product->defaultQty();
                 $this->qty = $qty_factor * $this->resolveInputQty($properties, $default_quantity);
                 if ($this->qty == 0) {
                     $this->errors[] = Tools::displayError('Quantity not specified.', !Tools::getValue('ajax'));
                 } else {
                     if (!$product->checkQty($ext_qty_factor * $this->qty)) {
                         $this->errors[] = Tools::displayError('There isn\'t enough product in stock.', !Tools::getValue('ajax'));
                     }
                 }
             }
         }
     }
     if (!$this->errors && ($mode == 'add' || $mode == 'update' && $qty_behavior)) {
         if ($mode == 'add' && !$this->context->cart->id) {
             if (Context::getContext()->cookie->id_guest) {
                 $guest = new Guest(Context::getContext()->cookie->id_guest);
                 $this->context->cart->mobile_theme = $guest->mobile_theme;
             }
             $this->context->cart->add();
             if ($this->context->cart->id) {
                 $this->context->cookie->id_cart = (int) $this->context->cart->id;
             }
         }
         if (!$product->hasAllRequiredCustomizableFields() && !$this->customization_id) {
             $this->errors[] = Tools::displayError('Please fill in all of the required fields, and then save your customizations.', !Tools::getValue('ajax'));
         }
         if (!$this->errors) {
             $cart_rules = $this->context->cart->getCartRules();
             $update_quantity = $this->context->cart->updateQty($id_cart_product ? $mode == 'add' ? $qty_factor : $this->qty : ($ext_prop_quantities !== null ? $ext_qty_factor : $this->qty), $this->id_product, $this->id_product_attribute, $this->customization_id, $mode == 'update' ? 'update' : Tools::getValue('op', 'up'), $this->id_address_delivery, null, true, $id_cart_product, $ext_prop_quantities, $this->qty);
             if ($update_quantity < 0) {
                 $minimal_quantity = $this->id_product_attribute ? $product->attributeMinQty($this->id_product_attribute) : $product->minQty();
                 $this->errors[] = Tools::displayError(sprintf('You must add %s minimum quantity', $minimal_quantity), !Tools::getValue('ajax'));
             } elseif (!$update_quantity) {
                 $this->errors[] = Tools::displayError('You already have the maximum quantity available for this product.', !Tools::getValue('ajax'));
             } elseif ((int) Tools::getValue('allow_refresh')) {
                 $cart_rules2 = $this->context->cart->getCartRules();
                 if (count($cart_rules2) != count($cart_rules)) {
                     $this->ajax_refresh = true;
                 } else {
                     $rule_list = array();
                     foreach ($cart_rules2 as $rule) {
                         $rule_list[] = $rule['id_cart_rule'];
                     }
                     foreach ($cart_rules as $rule) {
                         if (!in_array($rule['id_cart_rule'], $rule_list)) {
                             $this->ajax_refresh = true;
                             break;
                         }
                     }
                 }
             }
         }
     }
     $removed = CartRule::autoRemoveFromCart();
     CartRule::autoAddToCart();
     if (count($removed) && (int) Tools::getValue('allow_refresh')) {
         $this->ajax_refresh = true;
     }
 }
 /**
  * @param \Product $product
  *
  * @return bool
  * @author Panagiotis Vagenas <*****@*****.**>
  * @since 150213
  */
 protected function backOrdersAllowed(\Product $product)
 {
     return \Product::isAvailableWhenOutOfStock($product->out_of_stock) == 1;
 }
 /**
  * This process add or update a product in the cart
  */
 protected function processChangeProductInCart()
 {
     $mode = Tools::getIsset('update') && $this->id_product ? 'update' : 'add';
     if ($this->qty == 0) {
         $this->errors[] = Tools::displayError('Null quantity.', !Tools::getValue('ajax'));
     } elseif (!$this->id_product) {
         $this->errors[] = Tools::displayError('Product not found', !Tools::getValue('ajax'));
     }
     $product = new Product($this->id_product, true, $this->context->language->id);
     if (!$product->id || !$product->active || !$product->checkAccess($this->context->cart->id_customer)) {
         $this->errors[] = Tools::displayError('This product is no longer available.', !Tools::getValue('ajax'));
         return;
     }
     $qty_to_check = $this->qty;
     $cart_products = $this->context->cart->getProducts();
     if (is_array($cart_products)) {
         foreach ($cart_products as $cart_product) {
             if ((!isset($this->id_product_attribute) || $cart_product['id_product_attribute'] == $this->id_product_attribute) && (isset($this->id_product) && $cart_product['id_product'] == $this->id_product)) {
                 $qty_to_check = $cart_product['cart_quantity'];
                 if (Tools::getValue('op', 'up') == 'down') {
                     $qty_to_check -= $this->qty;
                 } else {
                     $qty_to_check += $this->qty;
                 }
                 break;
             }
         }
     }
     // Check product quantity availability
     if ($this->id_product_attribute) {
         if (!Product::isAvailableWhenOutOfStock($product->out_of_stock) && !Attribute::checkAttributeQty($this->id_product_attribute, $qty_to_check)) {
             $this->errors[] = Tools::displayError('There isn\'t enough product in stock.', !Tools::getValue('ajax'));
         }
     } elseif ($product->hasAttributes()) {
         $minimumQuantity = $product->out_of_stock == 2 ? !Configuration::get('PS_ORDER_OUT_OF_STOCK') : !$product->out_of_stock;
         $this->id_product_attribute = Product::getDefaultAttribute($product->id, $minimumQuantity);
         // @todo do something better than a redirect admin !!
         if (!$this->id_product_attribute) {
             Tools::redirectAdmin($this->context->link->getProductLink($product));
         } elseif (!Product::isAvailableWhenOutOfStock($product->out_of_stock) && !Attribute::checkAttributeQty($this->id_product_attribute, $qty_to_check)) {
             $this->errors[] = Tools::displayError('There isn\'t enough product in stock.', !Tools::getValue('ajax'));
         }
     } elseif (!$product->checkQty($qty_to_check)) {
         $this->errors[] = Tools::displayError('There isn\'t enough product in stock.', !Tools::getValue('ajax'));
     }
     // If no errors, process product addition
     if (!$this->errors && $mode == 'add') {
         // Add cart if no cart found
         if (!$this->context->cart->id) {
             if (Context::getContext()->cookie->id_guest) {
                 $guest = new Guest(Context::getContext()->cookie->id_guest);
                 $this->context->cart->mobile_theme = $guest->mobile_theme;
             }
             $this->context->cart->add();
             if ($this->context->cart->id) {
                 $this->context->cookie->id_cart = (int) $this->context->cart->id;
             }
         }
         // Check customizable fields
         if (!$product->hasAllRequiredCustomizableFields() && !$this->customization_id) {
             $this->errors[] = Tools::displayError('Please fill in all of the required fields, and then save your customizations.', !Tools::getValue('ajax'));
         }
         if (!$this->errors) {
             $cart_rules = $this->context->cart->getCartRules();
             $available_cart_rules = CartRule::getCustomerCartRules($this->context->language->id, isset($this->context->customer->id) ? $this->context->customer->id : 0, true, true, true, $this->context->cart, false, true);
             $update_quantity = $this->context->cart->updateQty($this->qty, $this->id_product, $this->id_product_attribute, $this->customization_id, Tools::getValue('op', 'up'), $this->id_address_delivery);
             if ($update_quantity < 0) {
                 // If product has attribute, minimal quantity is set with minimal quantity of attribute
                 $minimal_quantity = $this->id_product_attribute ? Attribute::getAttributeMinimalQty($this->id_product_attribute) : $product->minimal_quantity;
                 $this->errors[] = sprintf(Tools::displayError('You must add %d minimum quantity', !Tools::getValue('ajax')), $minimal_quantity);
             } elseif (!$update_quantity) {
                 $this->errors[] = Tools::displayError('You already have the maximum quantity available for this product.', !Tools::getValue('ajax'));
             } elseif ((int) Tools::getValue('allow_refresh')) {
                 // If the cart rules has changed, we need to refresh the whole cart
                 $cart_rules2 = $this->context->cart->getCartRules();
                 if (count($cart_rules2) != count($cart_rules)) {
                     $this->ajax_refresh = true;
                 } elseif (count($cart_rules2)) {
                     $rule_list = array();
                     foreach ($cart_rules2 as $rule) {
                         $rule_list[] = $rule['id_cart_rule'];
                     }
                     foreach ($cart_rules as $rule) {
                         if (!in_array($rule['id_cart_rule'], $rule_list)) {
                             $this->ajax_refresh = true;
                             break;
                         }
                     }
                 } else {
                     $available_cart_rules2 = CartRule::getCustomerCartRules($this->context->language->id, isset($this->context->customer->id) ? $this->context->customer->id : 0, true, true, true, $this->context->cart, false, true);
                     if (count($available_cart_rules2) != count($available_cart_rules)) {
                         $this->ajax_refresh = true;
                     } elseif (count($available_cart_rules2)) {
                         $rule_list = array();
                         foreach ($available_cart_rules2 as $rule) {
                             $rule_list[] = $rule['id_cart_rule'];
                         }
                         foreach ($cart_rules2 as $rule) {
                             if (!in_array($rule['id_cart_rule'], $rule_list)) {
                                 $this->ajax_refresh = true;
                                 break;
                             }
                         }
                     }
                 }
             }
         }
     }
     $removed = CartRule::autoRemoveFromCart();
     CartRule::autoAddToCart();
     if (count($removed) && (int) Tools::getValue('allow_refresh')) {
         $this->ajax_refresh = true;
     }
 }
 public function process()
 {
     global $cart, $currency;
     parent::process();
     if (!($id_product = (int) Tools::getValue('id_product')) or !Validate::isUnsignedId($id_product)) {
         $this->errors[] = Tools::displayError('Product not found');
     } else {
         if (!Validate::isLoadedObject($this->product) or !$this->product->active and Tools::getValue('adtoken') != Tools::encrypt('PreviewProduct' . $this->product->id) || !file_exists(dirname(__FILE__) . '/../' . Tools::getValue('ad') . '/ajax.php')) {
             header('HTTP/1.1 404 page not found');
             $this->errors[] = Tools::displayError('Product is no longer available.');
         } elseif (!$this->product->checkAccess((int) self::$cookie->id_customer)) {
             $this->errors[] = Tools::displayError('You do not have access to this product.');
         } else {
             self::$smarty->assign('virtual', ProductDownload::getIdFromIdProduct((int) $this->product->id));
             if (!$this->product->active) {
                 self::$smarty->assign('adminActionDisplay', true);
             }
             /* rewrited url set */
             $rewrited_url = self::$link->getProductLink($this->product->id, $this->product->link_rewrite);
             /* Product pictures management */
             require_once 'images.inc.php';
             self::$smarty->assign('customizationFormTarget', Tools::safeOutput(urldecode($_SERVER['REQUEST_URI'])));
             if (Tools::isSubmit('submitCustomizedDatas')) {
                 $this->pictureUpload($this->product, $cart);
                 $this->textRecord($this->product, $cart);
                 $this->formTargetFormat();
             } elseif (isset($_GET['deletePicture']) and !$cart->deletePictureToProduct((int) $this->product->id, (int) Tools::getValue('deletePicture'))) {
                 $this->errors[] = Tools::displayError('An error occurred while deleting the selected picture');
             }
             $files = self::$cookie->getFamily('pictures_' . (int) $this->product->id);
             $textFields = self::$cookie->getFamily('textFields_' . (int) $this->product->id);
             foreach ($textFields as $key => $textField) {
                 $textFields[$key] = str_replace('<br />', "\n", $textField);
             }
             self::$smarty->assign(array('pictures' => $files, 'textFields' => $textFields));
             if ((int) Tools::getValue('pp') == 1) {
                 echo 'here1';
             }
             $productPriceWithTax = Product::getPriceStatic($id_product, true, NULL, 6);
             if (Product::$_taxCalculationMethod == PS_TAX_INC) {
                 $productPriceWithTax = Tools::ps_round($productPriceWithTax, 2);
             }
             if ((int) Tools::getValue('pp') == 1) {
                 $time2 = time();
                 echo 'time2: ' . $time2;
             }
             $productPriceWithoutEcoTax = (double) ($productPriceWithTax - $this->product->ecotax);
             $configs = Configuration::getMultiple(array('PS_ORDER_OUT_OF_STOCK', 'PS_LAST_QTIES'));
             /* Features / Values */
             $features = $this->product->getFrontFeatures((int) self::$cookie->id_lang);
             $attachments = $this->product->getAttachments((int) self::$cookie->id_lang);
             /* Category */
             $category = false;
             if (isset($_SERVER['HTTP_REFERER']) and preg_match('!^(.*)\\/([0-9]+)\\-(.*[^\\.])|(.*)id_category=([0-9]+)(.*)$!', $_SERVER['HTTP_REFERER'], $regs) and !strstr($_SERVER['HTTP_REFERER'], '.html')) {
                 if (isset($regs[2]) and is_numeric($regs[2])) {
                     if (Product::idIsOnCategoryId((int) $this->product->id, array('0' => array('id_category' => (int) $regs[2])))) {
                         $category = new Category((int) $regs[2], (int) self::$cookie->id_lang);
                     }
                 } elseif (isset($regs[5]) and is_numeric($regs[5])) {
                     if (Product::idIsOnCategoryId((int) $this->product->id, array('0' => array('id_category' => (int) $regs[5])))) {
                         $category = new Category((int) $regs[5], (int) self::$cookie->id_lang);
                     }
                 }
             }
             if (!$category) {
                 $category = new Category($this->product->id_category_default, (int) self::$cookie->id_lang);
             }
             if (isset($category) and Validate::isLoadedObject($category)) {
                 self::$smarty->assign(array('path' => Tools::getPath((int) $category->id, $this->product->name, true), 'category' => $category, 'subCategories' => $category->getSubCategories((int) self::$cookie->id_lang, true), 'id_category_current' => (int) $category->id, 'id_category_parent' => (int) $category->id_parent, 'return_category_name' => Tools::safeOutput($category->name)));
             } else {
                 self::$smarty->assign('path', Tools::getPath((int) $this->product->id_category_default, $this->product->name));
             }
             self::$smarty->assign('return_link', (isset($category->id) and $category->id) ? Tools::safeOutput(self::$link->getCategoryLink($category)) : 'javascript: history.back();');
             $lang = Configuration::get('PS_LANG_DEFAULT');
             if (Pack::isPack((int) $this->product->id, (int) $lang) and !Pack::isInStock((int) $this->product->id, (int) $lang)) {
                 $this->product->quantity = 0;
             }
             $group_reduction = (100 - Group::getReduction((int) self::$cookie->id_customer)) / 100;
             $id_customer = (isset(self::$cookie->id_customer) and self::$cookie->id_customer) ? (int) self::$cookie->id_customer : 0;
             $id_group = $id_customer ? (int) Customer::getDefaultGroupId($id_customer) : _PS_DEFAULT_CUSTOMER_GROUP_;
             $id_country = (int) ($id_customer ? Customer::getCurrentCountry($id_customer) : Configuration::get('PS_COUNTRY_DEFAULT'));
             if ((int) Tools::getValue('pp') == 1) {
                 $time3 = time();
                 echo 'time3: ' . $time3;
             }
             // Tax
             $tax = (double) Tax::getProductTaxRate((int) $this->product->id, $cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')});
             self::$smarty->assign('tax_rate', $tax);
             $ecotax_rate = (double) Tax::getProductEcotaxRate($cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')});
             $ecotaxTaxAmount = Tools::ps_round($this->product->ecotax, 2);
             if (Product::$_taxCalculationMethod == PS_TAX_INC && (int) Configuration::get('PS_TAX')) {
                 $ecotaxTaxAmount = Tools::ps_round($ecotaxTaxAmount * (1 + $ecotax_rate / 100), 2);
             }
             $manufacturer = new Manufacturer((int) $this->product->id_manufacturer, 1);
             $sizechart = new Sizechart((int) $this->product->id_sizechart, 1);
             //see if the product is already in the wishlist
             if ($id_customer) {
                 $sql = "select id from ps_wishlist where id_customer = " . $id_customer . " and id_product = " . $this->product->id;
                 $res = Db::getInstance()->ExecuteS($sql);
                 if ($res) {
                     self::$smarty->assign("in_wishlist", true);
                 } else {
                     self::$smarty->assign("in_wishlist", false);
                 }
             } else {
                 self::$smarty->assign("in_wishlist", false);
             }
             self::$smarty->assign(array('quantity_discounts' => $this->formatQuantityDiscounts(SpecificPrice::getQuantityDiscounts((int) $this->product->id, (int) Shop::getCurrentShop(), (int) self::$cookie->id_currency, $id_country, $id_group), $this->product->getPrice(Product::$_taxCalculationMethod == PS_TAX_INC, false), (double) $tax), 'product' => $this->product, 'ecotax_tax_inc' => $ecotaxTaxAmount, 'ecotax_tax_exc' => Tools::ps_round($this->product->ecotax, 2), 'ecotaxTax_rate' => $ecotax_rate, 'homeSize' => Image::getSize('home'), 'product_manufacturer' => $manufacturer, 'token' => Tools::getToken(false), 'productPriceWithoutEcoTax' => (double) $productPriceWithoutEcoTax, 'features' => $features, 'attachments' => $attachments, 'allow_oosp' => $this->product->isAvailableWhenOutOfStock((int) $this->product->out_of_stock), 'last_qties' => (int) $configs['PS_LAST_QTIES'], 'group_reduction' => $group_reduction, 'col_img_dir' => _PS_COL_IMG_DIR_, 'sizechart' => $sizechart->sizechart, 'sizechart_data' => $sizechart->sizechart_data));
             self::$smarty->assign(array('HOOK_EXTRA_LEFT' => Module::hookExec('extraLeft'), 'HOOK_EXTRA_RIGHT' => Module::hookExec('extraRight'), 'HOOK_PRODUCT_OOS' => Hook::productOutOfStock($this->product), 'HOOK_PRODUCT_FOOTER' => Hook::productFooter($this->product, $category), 'HOOK_PRODUCT_ACTIONS' => Module::hookExec('productActions'), 'HOOK_PRODUCT_TAB' => Module::hookExec('productTab'), 'HOOK_PRODUCT_TAB_CONTENT' => Module::hookExec('productTabContent')));
             if ((int) Tools::getValue('pp') == 1) {
                 $time4 = time();
                 echo 'time4: ' . $time4;
             }
             $images = $this->product->getImages((int) self::$cookie->id_lang);
             $productImages = array();
             foreach ($images as $k => $image) {
                 if ($image['cover']) {
                     self::$smarty->assign('mainImage', $images[0]);
                     $cover = $image;
                     $cover['id_image'] = Configuration::get('PS_LEGACY_IMAGES') ? $this->product->id . '-' . $image['id_image'] : $image['id_image'];
                     $cover['id_image_only'] = (int) $image['id_image'];
                 }
                 $productImages[(int) $image['id_image']] = $image;
             }
             if (!isset($cover)) {
                 $cover = array('id_image' => Language::getIsoById(self::$cookie->id_lang) . '-default', 'legend' => 'No picture', 'title' => 'No picture');
             }
             $size = Image::getSize('large');
             self::$smarty->assign(array('cover' => $cover, 'imgWidth' => (int) $size['width'], 'mediumSize' => Image::getSize('medium'), 'largeSize' => Image::getSize('large'), 'accessories' => $this->product->getAccessories((int) self::$cookie->id_lang)));
             if (sizeof($productImages)) {
                 self::$smarty->assign('images', $productImages);
             }
             if ((int) Tools::getValue('pp') == 1) {
                 $time5 = time();
                 echo 'time5: ' . $time5;
             }
             /* Attributes / Groups & colors */
             $colors = array();
             //see if the product has shades
             if ($this->product->id_group && $this->product->id_group > 0) {
                 global $link;
                 $related_productIds = $this->product->getRelatedProducts();
                 $related_products = array();
                 foreach ($related_productIds as &$productId) {
                     $relProduct = new Product((int) $productId['id_product'], true, self::$cookie->id_lang);
                     $idImage = $relProduct->getCoverWs();
                     if ($idImage) {
                         $idImage = $relProduct->id . '-' . $idImage;
                     } else {
                         $idImage = Language::getIsoById(1) . '-default';
                     }
                     $relProduct->image_link = $link->getImageLink($relProduct->link_rewrite, $idImage, 'small');
                     $relProduct->link = $relProduct->getLink();
                     $related_products[] = $relProduct;
                 }
                 self::$smarty->assign('relatedProducts', $related_products);
             }
             if ((int) Tools::getValue('pp') == 1) {
                 $time6 = time();
                 echo 'time6: ' . $time6;
             }
             $attributesGroups = $this->product->getAttributesGroups((int) self::$cookie->id_lang);
             // @todo (RM) should only get groups and not all declination ?
             if (is_array($attributesGroups) and $attributesGroups) {
                 $groups = array();
                 $combinationImages = $this->product->getCombinationImages((int) self::$cookie->id_lang);
                 foreach ($attributesGroups as $k => $row) {
                     /* Color management */
                     if ((isset($row['attribute_color']) and $row['attribute_color'] or file_exists(_PS_COL_IMG_DIR_ . $row['id_attribute'] . '.jpg')) and $row['id_attribute_group'] == $this->product->id_color_default) {
                         $colors[$row['id_attribute']]['value'] = $row['attribute_color'];
                         $colors[$row['id_attribute']]['name'] = $row['attribute_name'];
                         if (!isset($colors[$row['id_attribute']]['attributes_quantity'])) {
                             $colors[$row['id_attribute']]['attributes_quantity'] = 0;
                         }
                         $colors[$row['id_attribute']]['attributes_quantity'] += (int) $row['quantity'];
                     }
                     if (!isset($groups[$row['id_attribute_group']])) {
                         $groups[$row['id_attribute_group']] = array('name' => $row['public_group_name'], 'is_color_group' => $row['is_color_group'], 'default' => -1);
                     }
                     $groups[$row['id_attribute_group']]['attributes'][$row['id_attribute']] = $row['attribute_name'];
                     if ($row['default_on'] && $groups[$row['id_attribute_group']]['default'] == -1) {
                         $groups[$row['id_attribute_group']]['default'] = (int) $row['id_attribute'];
                     }
                     if (!isset($groups[$row['id_attribute_group']]['attributes_quantity'][$row['id_attribute']])) {
                         $groups[$row['id_attribute_group']]['attributes_quantity'][$row['id_attribute']] = 0;
                     }
                     $groups[$row['id_attribute_group']]['attributes_quantity'][$row['id_attribute']] += (int) $row['quantity'];
                     $combinations[$row['id_product_attribute']]['attributes_values'][$row['id_attribute_group']] = $row['attribute_name'];
                     $combinations[$row['id_product_attribute']]['attributes'][] = (int) $row['id_attribute'];
                     $combinations[$row['id_product_attribute']]['price'] = (double) $row['price'];
                     $combinations[$row['id_product_attribute']]['ecotax'] = (double) $row['ecotax'];
                     $combinations[$row['id_product_attribute']]['weight'] = (double) $row['weight'];
                     $combinations[$row['id_product_attribute']]['quantity'] = (int) $row['quantity'];
                     $combinations[$row['id_product_attribute']]['reference'] = $row['reference'];
                     $combinations[$row['id_product_attribute']]['unit_impact'] = $row['unit_price_impact'];
                     $combinations[$row['id_product_attribute']]['minimal_quantity'] = $row['minimal_quantity'];
                     $combinations[$row['id_product_attribute']]['id_image'] = isset($combinationImages[$row['id_product_attribute']][0]['id_image']) ? $combinationImages[$row['id_product_attribute']][0]['id_image'] : -1;
                 }
                 if ((int) Tools::getValue('pp') == 1) {
                     $time7 = time();
                     echo 'time7: ' . $time7;
                 }
                 //wash attributes list (if some attributes are unavailables and if allowed to wash it)
                 if (!Product::isAvailableWhenOutOfStock($this->product->out_of_stock) && Configuration::get('PS_DISP_UNAVAILABLE_ATTR') == 0) {
                     foreach ($groups as &$group) {
                         foreach ($group['attributes_quantity'] as $key => &$quantity) {
                             if (!$quantity) {
                                 unset($group['attributes'][$key]);
                             }
                         }
                     }
                     foreach ($colors as $key => $color) {
                         if (!$color['attributes_quantity']) {
                             unset($colors[$key]);
                         }
                     }
                 }
                 if ((int) Tools::getValue('pp') == 1) {
                     $time71 = time();
                     echo 'time71: ' . $time71;
                 }
                 foreach ($groups as &$group) {
                     natcasesort($group['attributes']);
                 }
                 foreach ($combinations as $id_product_attribute => $comb) {
                     $attributeList = '';
                     foreach ($comb['attributes'] as $id_attribute) {
                         $attributeList .= '\'' . (int) $id_attribute . '\',';
                     }
                     $attributeList = rtrim($attributeList, ',');
                     $combinations[$id_product_attribute]['list'] = $attributeList;
                 }
                 self::$smarty->assign(array('groups' => $groups, 'combinaisons' => $combinations, 'combinations' => $combinations, 'colors' => (sizeof($colors) and $this->product->id_color_default) ? $colors : false, 'combinationImages' => $combinationImages));
             }
             if ((int) Tools::getValue('pp') == 1) {
                 $time72 = time();
                 echo 'time72: ' . $time72;
             }
             //$newProducts = Product::getNewProducts((int)(self::$cookie->id_lang), 0, 10, false, 'date_add', 'desc');
             /*$categoryProducts = $this->getRandomCatProducts();
               self::$smarty->assign('cat_products', $categoryProducts);*/
             //$brandProducts = $this->getRandomBrandProducts();
             //self::$smarty->assign('brand_products', $brandProducts);
             if ((int) Tools::getValue('pp') == 1) {
                 $time73 = time();
                 echo ' time73: ' . $time73;
             }
             self::$smarty->assign(array('no_tax' => Tax::excludeTaxeOption() or !Tax::getProductTaxRate((int) $this->product->id, $cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}), 'customizationFields' => $this->product->getCustomizationFields((int) self::$cookie->id_lang)));
             if ((int) Tools::getValue('pp') == 1) {
                 $time74 = time();
                 echo 'time74: ' . $time74;
             }
             // Pack management
             self::$smarty->assign('packItems', $this->product->cache_is_pack ? Pack::getItemTable($this->product->id, (int) self::$cookie->id_lang, true) : array());
             self::$smarty->assign('packs', Pack::getPacksTable($this->product->id, (int) self::$cookie->id_lang, true, 1));
             if ((int) Tools::getValue('pp') == 1) {
                 print_r('pack done');
             }
         }
     }
     if ((int) Tools::getValue('pp') == 1) {
         $time8 = time();
         echo 'time8: ' . $time8;
     }
     if ($this->is_saree || $this->is_lehenga) {
         if ($this->is_lehenga) {
             self::$smarty->assign('is_lehenga', $this->is_lehenga);
         }
         self::$smarty->assign('as_shown', (bool) $this->product->as_shown);
         /*if($blouse_measurements = $this->getCustomerMeasurements(self::$cookie->id_customer, 1))
               self::$smarty->assign('measurement_info', $blouse_measurements);
           if($skirt_measurements = $this->getCustomerMeasurements(self::$cookie->id_customer, 2))
               self::$smarty->assign('skirt_measurement_info', $skirt_measurements);*/
         if ((int) Tools::getValue('pp') == 1) {
             $time81 = time();
             echo 'time81: ' . $time81;
         }
         if ($this->is_saree) {
             //count of all styles mapped to this product
             $res = Db::getInstance()->getRow("select count(s.id_style) as style_count from ps_styles s inner join ps_product_style ps on ps.id_style = s.id_style and ps.id_product = {$id_product} and s.style_type = 1");
             $style_count = (int) $res['style_count'];
             if ($style_count === 0) {
                 // show the default style for sarees
                 $style = array('id_style' => 1, 'style_image_small' => '1-small.png', 'style_name' => 'Round');
             } else {
                 $res = Db::getInstance()->getRow("select s.id_style, s.style_name, s.style_image_small  from ps_styles s inner join ps_product_style ps on ps.id_style = s.id_style and ps.id_product = {$id_product} and s.style_type = 1 and ps.is_default = 1");
                 if (!empty($res)) {
                     //show the default style for this product
                     $style = array('id_style' => $res['id_style'], 'style_image_small' => $res['style_image_small'], 'style_name' => $res['style_name']);
                 }
             }
             if ((int) Tools::getValue('pp') == 1) {
                 $time82 = time();
                 echo 'time82: ' . $time82;
             }
             self::$smarty->assign('blouse_style_count', $style_count);
             self::$smarty->assign('blouse_style', $style);
         }
     } else {
         if ($this->is_skd || $this->is_skd_rts) {
             self::$smarty->assign('is_anarkali', $this->is_anarkali);
             if ($this->is_anarkali) {
                 if ($kurta_measurements = $this->getCustomerMeasurements(self::$cookie->id_customer, 5)) {
                     self::$smarty->assign('kurta_measurement_info', $kurta_measurements);
                 }
             } else {
                 if ($kurta_measurements = $this->getCustomerMeasurements(self::$cookie->id_customer, 3)) {
                     self::$smarty->assign('kurta_measurement_info', $kurta_measurements);
                 }
             }
             if ($salwar_measurements = $this->getCustomerMeasurements(self::$cookie->id_customer, 4)) {
                 self::$smarty->assign('salwar_measurement_info', $salwar_measurements);
             }
             //get default styles for this product (RTS)
             if ($this->is_skd_rts) {
                 $res = Db::getInstance()->ExecuteS("select count(s.id_style) as style_count, s.style_type, ps.id_product from ps_styles s inner join ps_product_style ps on ps.id_style = s.id_style and ps.id_product = {$id_product} group by ps.id_product,s.style_type");
                 foreach ($res as $s) {
                     $style_count = (int) $s['style_count'];
                     if ((int) $s['style_type'] === 4) {
                         self::$smarty->assign('kurta_style_count', $style_count);
                     } else {
                         if ((int) $s['style_type'] === 5) {
                             self::$smarty->assign('salwar_style_count', $style_count);
                         }
                     }
                 }
                 $res = Db::getInstance()->ExecuteS("select s.id_style, s.style_type, s.style_image_small, s.style_name from ps_styles s inner join ps_product_style ps on ps.id_style = s.id_style and ps.id_product = {$id_product} and ps.is_default = 1");
                 foreach ($res as $s) {
                     $style = array('id_style' => $s['id_style'], 'style_image_small' => $s['style_image_small'], 'style_name' => $s['style_name']);
                     if ((int) $s['style_type'] === 4) {
                         self::$smarty->assign('kurta_style', $style);
                     } else {
                         if ((int) $s['style_type'] === 5) {
                             self::$smarty->assign('salwar_style', $style);
                         }
                     }
                 }
             }
         }
     }
     self::$smarty->assign('is_bottoms', $this->is_bottoms);
     self::$smarty->assign('is_abaya', $this->is_abaya);
     self::$smarty->assign('is_wristwear', $this->is_wristwear);
     self::$smarty->assign('is_pakistani_rts', $this->is_pakistani_rts);
     if ((int) Tools::getValue('pp') == 1) {
         $time85 = time();
         echo 'time85: ' . $time85;
     }
     self::$smarty->assign(array('ENT_NOQUOTES' => ENT_NOQUOTES, 'outOfStockAllowed' => (int) Configuration::get('PS_ORDER_OUT_OF_STOCK'), 'errors' => $this->errors, 'categories' => Category::getHomeCategories((int) self::$cookie->id_lang), 'have_image' => Product::getCover((int) Tools::getValue('id_product')), 'tax_enabled' => Configuration::get('PS_TAX'), 'display_qties' => (int) Configuration::get('PS_DISPLAY_QTIES'), 'display_ht' => !Tax::excludeTaxeOption(), 'ecotax' => !sizeof($this->errors) and $this->product->ecotax > 0 ? Tools::convertPrice((double) $this->product->ecotax) : 0, 'currencySign' => $currency->sign, 'currencyRate' => $currency->conversion_rate, 'currencyFormat' => $currency->format, 'currencyBlank' => $currency->blank, 'jqZoomEnabled' => Configuration::get('PS_DISPLAY_JQZOOM')));
     if ((int) Tools::getValue('pp') == 1) {
         $time9 = time();
         echo 'time9: ' . $time9;
     }
     //add this to product stats
     //Tools::captureActivity(PSTAT_VIEWS,$id_product);
     if ((int) Tools::getValue('pp') == 1) {
         $time1 = time();
         echo 'process end: ' . $time1;
     }
 }
Example #8
0
    public function getProducts($refresh = false, $id_product = false, $id_country = null)
    {
        if (!$this->id) {
            return array();
        }
        // Product cache must be strictly compared to NULL, or else an empty cart will add dozens of queries
        if ($this->_products !== null && !$refresh) {
            // Return product row with specified ID if it exists
            if (is_int($id_product)) {
                foreach ($this->_products as $product) {
                    if ($product['id_product'] == $id_product) {
                        return array($product);
                    }
                }
                return array();
            }
            return $this->_products;
        }
        // Build query
        $sql = new DbQuery();
        // Build SELECT
        $sql->select('cp.`id_product_attribute`, cp.`id_product`, cp.`quantity` AS cart_quantity, cp.id_shop, pl.`name`, p.`is_virtual`,
						pl.`description_short`, pl.`available_now`, pl.`available_later`, product_shop.`id_category_default`, p.`id_supplier`,
						p.`id_manufacturer`, product_shop.`on_sale`, product_shop.`ecotax`, product_shop.`additional_shipping_cost`,
						product_shop.`available_for_order`, product_shop.`price`, product_shop.`active`, product_shop.`unity`, product_shop.`unit_price_ratio`, 
						stock.`quantity` AS quantity_available, p.`width`, p.`height`, p.`depth`, stock.`out_of_stock`, p.`weight`,
						p.`date_add`, p.`date_upd`, IFNULL(stock.quantity, 0) as quantity, pl.`link_rewrite`, cl.`link_rewrite` AS category,
						CONCAT(LPAD(cp.`id_product`, 10, 0), LPAD(IFNULL(cp.`id_product_attribute`, 0), 10, 0), IFNULL(cp.`id_address_delivery`, 0)) AS unique_id, cp.id_address_delivery,
						product_shop.`wholesale_price`, product_shop.advanced_stock_management, ps.product_supplier_reference supplier_reference');
        // Build FROM
        $sql->from('cart_product', 'cp');
        // Build JOIN
        $sql->leftJoin('product', 'p', 'p.`id_product` = cp.`id_product`');
        $sql->innerJoin('product_shop', 'product_shop', '(product_shop.`id_shop` = cp.`id_shop` AND product_shop.`id_product` = p.`id_product`)');
        $sql->leftJoin('product_lang', 'pl', '
			p.`id_product` = pl.`id_product`
			AND pl.`id_lang` = ' . (int) $this->id_lang . Shop::addSqlRestrictionOnLang('pl', 'cp.id_shop'));
        $sql->leftJoin('category_lang', 'cl', '
			product_shop.`id_category_default` = cl.`id_category`
			AND cl.`id_lang` = ' . (int) $this->id_lang . Shop::addSqlRestrictionOnLang('cl', 'cp.id_shop'));
        $sql->leftJoin('product_supplier', 'ps', 'ps.`id_product` = cp.`id_product` AND ps.`id_product_attribute` = cp.`id_product_attribute` AND ps.`id_supplier` = p.`id_supplier`');
        // @todo test if everything is ok, then refactorise call of this method
        $sql->join(Product::sqlStock('cp', 'cp'));
        // Build WHERE clauses
        $sql->where('cp.`id_cart` = ' . (int) $this->id);
        if ($id_product) {
            $sql->where('cp.`id_product` = ' . (int) $id_product);
        }
        $sql->where('p.`id_product` IS NOT NULL');
        // Build GROUP BY
        $sql->groupBy('unique_id');
        // Build ORDER BY
        $sql->orderBy('p.`id_product`, cp.`id_product_attribute`, cp.`date_add` ASC');
        if (Customization::isFeatureActive()) {
            $sql->select('cu.`id_customization`, cu.`quantity` AS customization_quantity');
            $sql->leftJoin('customization', 'cu', 'p.`id_product` = cu.`id_product` AND cp.`id_product_attribute` = cu.`id_product_attribute` AND cu.`id_cart` = ' . (int) $this->id);
        } else {
            $sql->select('NULL AS customization_quantity, NULL AS id_customization');
        }
        if (Combination::isFeatureActive()) {
            $sql->select('
				product_attribute_shop.`price` AS price_attribute, product_attribute_shop.`ecotax` AS ecotax_attr,
				IF (IFNULL(pa.`reference`, \'\') = \'\', p.`reference`, pa.`reference`) AS reference,
				(p.`weight`+ pa.`weight`) weight_attribute,
				IF (IFNULL(pa.`ean13`, \'\') = \'\', p.`ean13`, pa.`ean13`) AS ean13,
				IF (IFNULL(pa.`upc`, \'\') = \'\', p.`upc`, pa.`upc`) AS upc,
				pai.`id_image` as pai_id_image, il.`legend` as pai_legend,
				IFNULL(product_attribute_shop.`minimal_quantity`, product_shop.`minimal_quantity`) as minimal_quantity
			');
            $sql->leftJoin('product_attribute', 'pa', 'pa.`id_product_attribute` = cp.`id_product_attribute`');
            $sql->leftJoin('product_attribute_shop', 'product_attribute_shop', '(product_attribute_shop.`id_shop` = cp.`id_shop` AND product_attribute_shop.`id_product_attribute` = pa.`id_product_attribute`)');
            $sql->leftJoin('product_attribute_image', 'pai', 'pai.`id_product_attribute` = pa.`id_product_attribute`');
            $sql->leftJoin('image_lang', 'il', 'il.`id_image` = pai.`id_image` AND il.`id_lang` = ' . (int) $this->id_lang);
        } else {
            $sql->select('p.`reference` AS reference, p.`ean13`,
				p.`upc` AS upc, product_shop.`minimal_quantity` AS minimal_quantity');
        }
        $result = Db::getInstance()->executeS($sql);
        // Reset the cache before the following return, or else an empty cart will add dozens of queries
        $products_ids = array();
        $pa_ids = array();
        if ($result) {
            foreach ($result as $row) {
                $products_ids[] = $row['id_product'];
                $pa_ids[] = $row['id_product_attribute'];
            }
        }
        // Thus you can avoid one query per product, because there will be only one query for all the products of the cart
        Product::cacheProductsFeatures($products_ids);
        Cart::cacheSomeAttributesLists($pa_ids, $this->id_lang);
        $this->_products = array();
        if (empty($result)) {
            return array();
        }
        $cart_shop_context = Context::getContext()->cloneContext();
        foreach ($result as &$row) {
            //                        $quantityDiscount = SpecificPrice::getQuantityDiscount((int)$row['id_product'], $row['id_shop'],
            //			(int)$cart->id_currency, (int)$this->vat_address->id_country,
            //			(int)$this->customer->id_default_group, (int)$row['cart_quantity'], false, null, null, $null, true, true, $this->context);
            //
            //                        echo '<pre>';
            //                        print_r($quantityDiscount);
            //                        echo '</pre>';
            if (isset($row['ecotax_attr']) && $row['ecotax_attr'] > 0) {
                $row['ecotax'] = (double) $row['ecotax_attr'];
            }
            $row['stock_quantity'] = (int) $row['quantity'];
            // for compatibility with 1.2 themes
            $row['quantity'] = (int) $row['cart_quantity'];
            if (isset($row['id_product_attribute']) && (int) $row['id_product_attribute'] && isset($row['weight_attribute'])) {
                $row['weight'] = (double) $row['weight_attribute'];
            }
            if (Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_invoice') {
                $address_id = (int) $this->id_address_invoice;
            } else {
                $address_id = (int) $row['id_address_delivery'];
            }
            if (!Address::addressExists($address_id)) {
                $address_id = null;
            }
            if ($cart_shop_context->shop->id != $row['id_shop']) {
                $cart_shop_context->shop = new Shop((int) $row['id_shop']);
            }
            if ($this->_taxCalculationMethod == PS_TAX_EXC) {
                $row['price'] = Product::getPriceStatic((int) $row['id_product'], false, isset($row['id_product_attribute']) ? (int) $row['id_product_attribute'] : null, 2, null, false, true, (int) $row['cart_quantity'], false, (int) $this->id_customer ? (int) $this->id_customer : null, (int) $this->id, (int) $address_id ? (int) $address_id : null, $specific_price_output, true, true, $cart_shop_context);
                // Here taxes are computed only once the quantity has been applied to the product price
                $row['price_wt'] = Product::getPriceStatic((int) $row['id_product'], true, isset($row['id_product_attribute']) ? (int) $row['id_product_attribute'] : null, 2, null, false, true, (int) $row['cart_quantity'], false, (int) $this->id_customer ? (int) $this->id_customer : null, (int) $this->id, (int) $address_id ? (int) $address_id : null, $null, true, true, $cart_shop_context);
                $tax_rate = Tax::getProductTaxRate((int) $row['id_product'], (int) $address_id);
                $row['total_wt'] = Tools::ps_round($row['price'] * (double) $row['cart_quantity'] * (1 + (double) $tax_rate / 100), 2);
                $row['total'] = $row['price'] * (int) $row['cart_quantity'];
            } else {
                $row['price'] = Product::getPriceStatic((int) $row['id_product'], false, (int) $row['id_product_attribute'], 2, null, false, true, $row['cart_quantity'], false, (int) $this->id_customer ? (int) $this->id_customer : null, (int) $this->id, (int) $address_id ? (int) $address_id : null, $specific_price_output, true, true, $cart_shop_context);
                $row['price_wt'] = Product::getPriceStatic((int) $row['id_product'], true, (int) $row['id_product_attribute'], 2, null, false, true, $row['cart_quantity'], false, (int) $this->id_customer ? (int) $this->id_customer : null, (int) $this->id, (int) $address_id ? (int) $address_id : null, $null, true, true, $cart_shop_context);
                // In case when you use QuantityDiscount, getPriceStatic() can be return more of 2 decimals
                $row['price_wt'] = Tools::ps_round($row['price_wt'], 2);
                $row['total_wt'] = $row['price_wt'] * (int) $row['cart_quantity'];
                $row['total'] = Tools::ps_round($row['price'] * (int) $row['cart_quantity'], 2);
                $row['description_short'] = Tools::nl2br($row['description_short']);
            }
            if (!isset($row['pai_id_image']) || $row['pai_id_image'] == 0) {
                $cache_id = 'Cart::getProducts_' . '-pai_id_image-' . (int) $row['id_product'] . '-' . (int) $this->id_lang . '-' . (int) $row['id_shop'];
                if (!Cache::isStored($cache_id)) {
                    $row2 = Db::getInstance()->getRow('
						SELECT image_shop.`id_image` id_image, il.`legend`
						FROM `' . _DB_PREFIX_ . 'image` i
						JOIN `' . _DB_PREFIX_ . 'image_shop` image_shop ON (i.id_image = image_shop.id_image AND image_shop.cover=1 AND image_shop.id_shop=' . (int) $row['id_shop'] . ')
						LEFT JOIN `' . _DB_PREFIX_ . 'image_lang` il ON (image_shop.`id_image` = il.`id_image` AND il.`id_lang` = ' . (int) $this->id_lang . ')
						WHERE i.`id_product` = ' . (int) $row['id_product'] . ' AND image_shop.`cover` = 1');
                    Cache::store($cache_id, $row2);
                }
                $row2 = Cache::retrieve($cache_id);
                if (!$row2) {
                    $row2 = array('id_image' => false, 'legend' => false);
                } else {
                    $row = array_merge($row, $row2);
                }
            } else {
                $row['id_image'] = $row['pai_id_image'];
                $row['legend'] = $row['pai_legend'];
            }
            $row['reduction_applies'] = $specific_price_output && (double) $specific_price_output['reduction'];
            $row['quantity_discount_applies'] = $specific_price_output && $row['cart_quantity'] >= (int) $specific_price_output['from_quantity'];
            $row['id_image'] = Product::defineProductImage($row, $this->id_lang);
            $row['allow_oosp'] = Product::isAvailableWhenOutOfStock($row['out_of_stock']);
            $row['features'] = Product::getFeaturesStatic((int) $row['id_product']);
            if (array_key_exists($row['id_product_attribute'] . '-' . $this->id_lang, self::$_attributesLists)) {
                $row = array_merge($row, self::$_attributesLists[$row['id_product_attribute'] . '-' . $this->id_lang]);
            }
            if (Context::getContext()->language->id != 1) {
                $row['name'] = Tools::rus2translit($row['name']);
            }
            $row = Product::getTaxesInformations($row, $cart_shop_context);
            $this->_products[] = $row;
        }
        return $this->_products;
    }
 private static function isAllowOOSP($product)
 {
     return Product::isAvailableWhenOutOfStock($product->out_of_stock);
 }
Example #10
0
 $idProduct = intval(Tools::getValue('id_product', NULL));
 $idProductAttribute = intval(Tools::getValue('id_product_attribute', Tools::getValue('ipa')));
 $customizationId = intval(Tools::getValue('id_customization', 0));
 $qty = intval(abs(Tools::getValue('qty', 1)));
 if ($qty == 0) {
     $errors[] = Tools::displayError('null quantity');
 } elseif (!$idProduct) {
     $errors[] = Tools::displayError('product not found');
 } else {
     $producToAdd = new Product(intval($idProduct), false, intval($cookie->id_lang));
     if ((!$producToAdd->id or !$producToAdd->active) and !$delete) {
         $errors[] = Tools::displayError('product is no longer available');
     } else {
         /* Check the quantity availability */
         if ($idProductAttribute and is_numeric($idProductAttribute)) {
             if (!$delete and !$producToAdd->isAvailableWhenOutOfStock($producToAdd->out_of_stock) and !Attribute::checkAttributeQty(intval($idProductAttribute), intval($qty))) {
                 $errors[] = Tools::displayError('product is no longer available');
             }
         } elseif ($producToAdd->hasAttributes() and !$delete) {
             $idProductAttribute = Product::getDefaultAttribute(intval($producToAdd->id), intval($producToAdd->out_of_stock) == 2 ? !intval(Configuration::get('PS_ORDER_OUT_OF_STOCK')) : !intval($producToAdd->out_of_stock));
             if (!$idProductAttribute) {
                 Tools::redirectAdmin($link->getProductLink($producToAdd));
             } elseif (!$delete and !$producToAdd->isAvailableWhenOutOfStock($producToAdd->out_of_stock) and !Attribute::checkAttributeQty(intval($idProductAttribute), intval($qty))) {
                 $errors[] = Tools::displayError('product is no longer available');
             }
         } elseif (!$delete and !$producToAdd->checkQty(intval($qty))) {
             $errors[] = Tools::displayError('product is no longer available');
         }
         /* Check vouchers compatibility */
         if ($add and (intval($producToAdd->reduction_price) or intval($producToAdd->reduction_percent) or $producToAdd->on_sale)) {
             $discounts = $cart->getDiscounts();
Example #11
0
 public function hookActionProductOutOfStock($params)
 {
     if (!$this->customer_qty || !Configuration::get('PS_STOCK_MANAGEMENT') || Product::isAvailableWhenOutOfStock($params['product']->out_of_stock)) {
         return;
     }
     $context = Context::getContext();
     $id_product = (int) $params['product']->id;
     $id_product_attribute = 0;
     $id_customer = (int) $context->customer->id;
     if ((int) $context->customer->id <= 0) {
         $this->context->smarty->assign('email', 1);
     } elseif (MailAlert::customerHasNotification($id_customer, $id_product, $id_product_attribute, (int) $context->shop->id)) {
         return;
     }
     $this->context->smarty->assign(array('id_product' => $id_product, 'id_product_attribute' => $id_product_attribute));
     return $this->display(__FILE__, 'product.tpl');
 }
Example #12
0
 public static function getProductProperties($id_lang, $row, Context $context = null)
 {
     Hook::exec('actionGetProductPropertiesBefore', ['id_lang' => $id_lang, 'product' => $row, 'context' => $context]);
     if (!$row['id_product']) {
         return false;
     }
     if ($context == null) {
         $context = Context::getContext();
     }
     $id_product_attribute = $row['id_product_attribute'] = !empty($row['id_product_attribute']) ? (int) $row['id_product_attribute'] : null;
     // Product::getDefaultAttribute is only called if id_product_attribute is missing from the SQL query at the origin of it:
     // consider adding it in order to avoid unnecessary queries
     $row['allow_oosp'] = Product::isAvailableWhenOutOfStock($row['out_of_stock']);
     if (Combination::isFeatureActive() && $id_product_attribute === null && (isset($row['cache_default_attribute']) && ($ipa_default = $row['cache_default_attribute']) !== null || ($ipa_default = Product::getDefaultAttribute($row['id_product'], !$row['allow_oosp'])))) {
         $id_product_attribute = $row['id_product_attribute'] = $ipa_default;
     }
     if (!Combination::isFeatureActive() || !isset($row['id_product_attribute'])) {
         $id_product_attribute = $row['id_product_attribute'] = 0;
     }
     // Tax
     $usetax = !Tax::excludeTaxeOption();
     $cache_key = $row['id_product'] . '-' . $id_product_attribute . '-' . $id_lang . '-' . (int) $usetax;
     if (isset($row['id_product_pack'])) {
         $cache_key .= '-pack' . $row['id_product_pack'];
     }
     if (isset(self::$producPropertiesCache[$cache_key])) {
         return array_merge($row, self::$producPropertiesCache[$cache_key]);
     }
     // Datas
     $row['category'] = Category::getLinkRewrite((int) $row['id_category_default'], (int) $id_lang);
     $row['category_name'] = Db::getInstance()->getValue('SELECT name FROM ' . _DB_PREFIX_ . 'category_lang WHERE id_shop = ' . (int) $context->shop->id . ' AND id_lang = ' . (int) $id_lang . ' AND id_category = ' . (int) $row['id_category_default']);
     $row['link'] = $context->link->getProductLink((int) $row['id_product'], $row['link_rewrite'], $row['category'], $row['ean13']);
     $row['attribute_price'] = 0;
     if ($id_product_attribute) {
         $row['attribute_price'] = (double) Combination::getPrice($id_product_attribute);
     }
     if (isset($row['quantity_wanted'])) {
         // 'quantity_wanted' may very well be zero even if set
         $quantity = max((int) $row['minimal_quantity'], (int) $row['quantity_wanted']);
     } else {
         $quantity = (int) $row['minimal_quantity'];
     }
     $row['price_tax_exc'] = Product::getPriceStatic((int) $row['id_product'], false, $id_product_attribute, self::$_taxCalculationMethod == PS_TAX_EXC ? 2 : 6, null, false, true, $quantity);
     if (self::$_taxCalculationMethod == PS_TAX_EXC) {
         $row['price_tax_exc'] = Tools::ps_round($row['price_tax_exc'], 2);
         $row['price'] = Product::getPriceStatic((int) $row['id_product'], true, $id_product_attribute, 6, null, false, true, $quantity);
         $row['price_without_reduction'] = Product::getPriceStatic((int) $row['id_product'], false, $id_product_attribute, 2, null, false, false, $quantity);
     } else {
         $row['price'] = Tools::ps_round(Product::getPriceStatic((int) $row['id_product'], true, $id_product_attribute, 6, null, false, true, $quantity), (int) Configuration::get('PS_PRICE_DISPLAY_PRECISION'));
         $row['price_without_reduction'] = Product::getPriceStatic((int) $row['id_product'], true, $id_product_attribute, 6, null, false, false, $quantity);
     }
     $row['reduction'] = Product::getPriceStatic((int) $row['id_product'], (bool) $usetax, $id_product_attribute, 6, null, true, true, $quantity, true, null, null, null, $specific_prices);
     $row['specific_prices'] = $specific_prices;
     $row['quantity'] = Product::getQuantity((int) $row['id_product'], 0, isset($row['cache_is_pack']) ? $row['cache_is_pack'] : null);
     $row['quantity_all_versions'] = $row['quantity'];
     if ($row['id_product_attribute']) {
         $row['quantity'] = Product::getQuantity((int) $row['id_product'], $id_product_attribute, isset($row['cache_is_pack']) ? $row['cache_is_pack'] : null);
         $row['available_date'] = Product::getAvailableDate((int) $row['id_product'], $id_product_attribute);
     }
     $row['id_image'] = Product::defineProductImage($row, $id_lang);
     $row['features'] = Product::getFrontFeaturesStatic((int) $id_lang, $row['id_product']);
     $row['attachments'] = array();
     if (!isset($row['cache_has_attachments']) || $row['cache_has_attachments']) {
         $row['attachments'] = Product::getAttachmentsStatic((int) $id_lang, $row['id_product']);
     }
     $row['virtual'] = !isset($row['is_virtual']) || $row['is_virtual'] ? 1 : 0;
     // Pack management
     $row['pack'] = !isset($row['cache_is_pack']) ? Pack::isPack($row['id_product']) : (int) $row['cache_is_pack'];
     $row['packItems'] = $row['pack'] ? Pack::getItemTable($row['id_product'], $id_lang) : array();
     $row['nopackprice'] = $row['pack'] ? Pack::noPackPrice($row['id_product']) : 0;
     if ($row['pack'] && !Pack::isInStock($row['id_product'])) {
         $row['quantity'] = 0;
     }
     $row['customization_required'] = false;
     if (isset($row['customizable']) && $row['customizable'] && Customization::isFeatureActive()) {
         if (count(Product::getRequiredCustomizableFieldsStatic((int) $row['id_product']))) {
             $row['customization_required'] = true;
         }
     }
     $attributes = Product::getAttributesParams($row['id_product'], $row['id_product_attribute']);
     foreach ($attributes as $attribute) {
         $row['attributes'][$attribute['id_attribute_group']] = $attribute;
     }
     $row = Product::getTaxesInformations($row, $context);
     $row['ecotax_rate'] = (double) Tax::getProductEcotaxRate($context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')});
     Hook::exec('actionGetProductPropertiesAfter', ['id_lang' => $id_lang, 'product' => $row, 'context' => $context]);
     $combination = new Combination($id_product_attribute);
     if (0 != $combination->unit_price_impact && 0 != $row['unit_price_ratio']) {
         $unitPrice = $row['price_tax_exc'] / $row['unit_price_ratio'] + $combination->unit_price_impact;
         $row['unit_price_ratio'] = $row['price_tax_exc'] / $unitPrice;
     }
     $row['unit_price'] = $row['unit_price_ratio'] != 0 ? $row['price'] / $row['unit_price_ratio'] : 0;
     self::$producPropertiesCache[$cache_key] = $row;
     return self::$producPropertiesCache[$cache_key];
 }
Example #13
0
 public static function getProductProperties($id_lang, $row)
 {
     if (!$row['id_product']) {
         return false;
     }
     $row['allow_oosp'] = Product::isAvailableWhenOutOfStock($row['out_of_stock']);
     if ((!isset($row['id_product_attribute']) or !$row['id_product_attribute']) and $ipa_default = Product::getDefaultAttribute($row['id_product'], !$row['allow_oosp'])) {
         $row['id_product_attribute'] = $ipa_default;
     }
     if (!isset($row['id_product_attribute'])) {
         $row['id_product_attribute'] = 0;
     }
     // Tax
     $usetax = true;
     $tax = floatval(Tax::getApplicableTax(intval($row['id_tax']), floatval($row['rate'])));
     if (Tax::excludeTaxeOption() or !$tax) {
         $usetax = false;
     }
     $cacheKey = $row['id_product'] . '-' . $row['id_product_attribute'] . '-' . $id_lang . '-' . intval($usetax);
     if (array_key_exists($cacheKey, self::$producPropertiesCache)) {
         return self::$producPropertiesCache[$cacheKey];
     }
     // Datas
     $link = new Link();
     $row['category'] = Category::getLinkRewrite($row['id_category_default'], intval($id_lang));
     $row['link'] = $link->getProductLink($row['id_product'], $row['link_rewrite'], $row['category'], $row['ean13']);
     $row['attribute_price'] = (isset($row['id_product_attribute']) and $row['id_product_attribute']) ? floatval(Product::getProductAttributePrice($row['id_product_attribute'])) : 0;
     $row['price_tax_exc'] = Product::getPriceStatic($row['id_product'], false, (isset($row['id_product_attribute']) and !empty($row['id_product_attribute'])) ? intval($row['id_product_attribute']) : NULL, 6);
     if (self::$_taxCalculationMethod == PS_TAX_EXC) {
         $row['price_tax_exc'] = Tools::ps_round($row['price_tax_exc'], 2);
         $row['price'] = Product::getPriceStatic($row['id_product'], true, (isset($row['id_product_attribute']) and !empty($row['id_product_attribute'])) ? intval($row['id_product_attribute']) : NULL, 6);
     } else {
         $row['price'] = Tools::ps_round(Product::getPriceStatic($row['id_product'], true, (isset($row['id_product_attribute']) and !empty($row['id_product_attribute'])) ? intval($row['id_product_attribute']) : NULL, 6), 2);
     }
     $row['reduction'] = self::getReductionValue($row['reduction_price'], $row['reduction_percent'], $row['reduction_from'], $row['reduction_to'], $row['price'], $usetax, floatval($row['rate']));
     $row['price_without_reduction'] = Product::getPriceStatic($row['id_product'], true, (isset($row['id_product_attribute']) and !empty($row['id_product_attribute'])) ? intval($row['id_product_attribute']) : NULL, 6, NULL, false, false);
     $row['quantity'] = Product::getQuantity($row['id_product']);
     $row['id_image'] = Product::defineProductImage($row);
     $row['features'] = Product::getFrontFeaturesStatic(intval($id_lang), $row['id_product']);
     $row['attachments'] = Product::getAttachmentsStatic(intval($id_lang), $row['id_product']);
     $row['pack'] = Pack::isPack($row['id_product']);
     $row['packItems'] = $row['pack'] ? Pack::getItemTable($row['id_product'], $id_lang) : array();
     $row['nopackprice'] = $row['pack'] ? Pack::noPackPrice($row['id_product']) : 0;
     self::$producPropertiesCache[$cacheKey] = $row;
     return self::$producPropertiesCache[$cacheKey];
 }
 protected function restoreOrderToCart(Cart $cart)
 {
     if (!$cart || !ValidateCore::isLoadedObject($cart)) {
         return null;
     }
     Db::getInstance()->execute('BEGIN');
     $new_cart = null;
     try {
         /** @var CartCore $new_cart */
         /** @noinspection PhpUndefinedClassInspection */
         $new_cart = new Cart();
         /** @noinspection PhpUndefinedFieldInspection */
         $new_cart->id_customer = (int) $cart->id_customer;
         /** @noinspection PhpUndefinedFieldInspection */
         $new_cart->id_address_delivery = (int) $cart->id_address_delivery;
         /** @noinspection PhpUndefinedFieldInspection */
         $new_cart->id_address_invoice = (int) $cart->id_address_invoice;
         /** @noinspection PhpUndefinedFieldInspection */
         $new_cart->id_lang = (int) $cart->id_lang;
         /** @noinspection PhpUndefinedFieldInspection */
         $new_cart->id_currency = (int) $cart->id_currency;
         /** @noinspection PhpUndefinedFieldInspection */
         $new_cart->id_carrier = (int) $cart->id_carrier;
         /** @noinspection PhpUndefinedFieldInspection */
         $new_cart->recyclable = (int) $cart->recyclable;
         /** @noinspection PhpUndefinedFieldInspection */
         $new_cart->gift = (int) $cart->gift;
         $new_cart->add();
         /** @noinspection PhpUndefinedMethodInspection */
         $products = $cart->getProducts();
         if ($products) {
             foreach ($products as $p) {
                 $idProduct = $p['id_product'];
                 $idProductAttribute = $p['id_product_attribute'];
                 $qty = $p['cart_quantity'];
                 /** @noinspection PhpUndefinedClassInspection */
                 /** @noinspection PhpUndefinedFieldInspection */
                 $producToAdd = new Product((int) $idProduct, true, (int) $cart->id_lang);
                 /** @noinspection PhpUndefinedFieldInspection */
                 if (!$producToAdd->id || !$producToAdd->active) {
                     continue;
                 }
                 /* Check the quantity availability  */
                 if ($idProductAttribute > 0 and is_numeric($idProductAttribute)) {
                     /** @noinspection PhpUndefinedClassInspection */
                     /** @noinspection PhpUndefinedMethodInspection */
                     /** @noinspection PhpUndefinedFieldInspection */
                     if (!$producToAdd->isAvailableWhenOutOfStock($producToAdd->out_of_stock) and !Attribute::checkAttributeQty((int) $idProductAttribute, (int) $qty)) {
                         /* There is not enough product attribute in stock - set customer qty to current stock on hand */
                         /** @noinspection PhpUndefinedFunctionInspection */
                         $qty = getAttributeQty($idProductAttribute);
                     }
                 } elseif (!$producToAdd->checkQty((int) $qty)) {
                     /* There is not enough product in stock - set customer qty to current stock on hand */
                     /** @noinspection PhpUndefinedMethodInspection */
                     $qty = $producToAdd->getQuantity($idProduct);
                 }
                 $new_cart->updateQty((int) $qty, (int) $idProduct, (int) $idProductAttribute, NULL, 'up');
                 unset($p);
             }
         }
         $new_cart->update();
         Db::getInstance()->execute('COMMIT');
     } catch (Exception $e) {
         Db::getInstance()->execute('ROLLBACK');
         throw $e;
     }
     /** @noinspection PhpUndefinedFieldInspection */
     $this->context->cookie->id_cart = (int) $new_cart->id;
     return $new_cart;
 }
Example #15
0
    /**
     * Returns module content for left column
     */
    public function hookProductFooter($params)
    {
        $cache_id = 'crossselling_mod|productfooter|' . (int) $params['product']->id;
        if (!$this->isCached('crossselling_mod.tpl', $this->getCacheId($cache_id))) {
            $orders = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT o.id_order
			FROM ' . _DB_PREFIX_ . 'orders o
			LEFT JOIN ' . _DB_PREFIX_ . 'order_detail od ON (od.id_order = o.id_order)
			WHERE o.valid = 1 AND od.product_id = ' . (int) $params['product']->id);
            if (count($orders)) {
                $list = '';
                foreach ($orders as $order) {
                    $list .= (int) $order['id_order'] . ',';
                }
                $list = rtrim($list, ',');
                if (Group::isFeatureActive()) {
                    $sql_groups_join = '
					LEFT JOIN `' . _DB_PREFIX_ . 'category_product` cp ON (cp.`id_category` = product_shop.id_category_default AND cp.id_product = product_shop.id_product)
					LEFT JOIN `' . _DB_PREFIX_ . 'category_group` cg ON (cp.`id_category` = cg.`id_category`)';
                    $groups = FrontController::getCurrentCustomerGroups();
                    $sql_groups_where = 'AND cg.`id_group` ' . (count($groups) ? 'IN (' . implode(',', $groups) . ')' : '=' . (int) Group::getCurrent()->id);
                }
                $order_products = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT DISTINCT od.product_id, pl.name, pl.link_rewrite, p.reference, i.id_image, product_shop.show_price, product_shop.id_category_default, p.available_for_order, p.customizable, cl.link_rewrite category, p.ean13, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity
					FROM ' . _DB_PREFIX_ . 'order_detail od
					LEFT JOIN ' . _DB_PREFIX_ . 'product p ON (p.id_product = od.product_id)
					' . Shop::addSqlAssociation('product', 'p') . (Combination::isFeatureActive() ? 'LEFT JOIN `' . _DB_PREFIX_ . 'product_attribute` pa
					ON (p.`id_product` = pa.`id_product`)
					' . Shop::addSqlAssociation('product_attribute', 'pa', false, 'product_attribute_shop.`default_on` = 1') . '
					' . Product::sqlStock('p', 'product_attribute_shop', false, $this->context->shop) : Product::sqlStock('p', 'product', false, $this->context->shop)) . '
					LEFT JOIN ' . _DB_PREFIX_ . 'product_lang pl ON (pl.id_product = od.product_id' . Shop::addSqlRestrictionOnLang('pl') . ')
					LEFT JOIN ' . _DB_PREFIX_ . 'category_lang cl ON (cl.id_category = product_shop.id_category_default' . Shop::addSqlRestrictionOnLang('cl') . ')
					LEFT JOIN ' . _DB_PREFIX_ . 'image i ON (i.id_product = od.product_id)
					' . (Group::isFeatureActive() ? $sql_groups_join : '') . '
					WHERE od.id_order IN (' . $list . ')
					AND pl.id_lang = ' . (int) $this->context->language->id . '
					AND cl.id_lang = ' . (int) $this->context->language->id . '
					AND od.product_id != ' . (int) $params['product']->id . '
					AND i.cover = 1
					AND product_shop.active = 1
					' . (Group::isFeatureActive() ? $sql_groups_where : '') . '
					ORDER BY RAND()
					LIMIT ' . (int) Configuration::get('CROSSSELLING_NBR_M'));
                $tax_calc = Product::getTaxCalculationMethod();
                foreach ($order_products as &$order_product) {
                    $order_product['id_product'] = (int) $order_product['product_id'];
                    $order_product['image'] = $this->context->link->getImageLink($order_product['link_rewrite'], (int) $order_product['product_id'] . '-' . (int) $order_product['id_image'], ImageType::getFormatedName('home'));
                    $order_product['link'] = $this->context->link->getProductLink((int) $order_product['product_id'], $order_product['link_rewrite'], $order_product['category'], $order_product['ean13']);
                    if ($tax_calc == 0 || $tax_calc == 2) {
                        $order_product['price'] = Product::getPriceStatic((int) $order_product['product_id'], true, null);
                    } elseif ($tax_calc == 1) {
                        $order_product['price'] = Product::getPriceStatic((int) $order_product['product_id'], false, null);
                    }
                    $order_product['allow_oosp'] = Product::isAvailableWhenOutOfStock((int) $order_product['out_of_stock']);
                }
                $order_products = Product::getProductsProperties((int) $this->context->language->id, $order_products);
                $this->smarty->assign(array('order' => false, 'orderProducts' => $order_products, 'homeSize' => Image::getSize(ImageType::getFormatedName('home')), 'middlePosition_crossselling' => round(count($order_products) / 2, 0), 'crossDisplayPrice' => Configuration::get('CROSSSELLING_DISPLAY_PRICE_M')));
            }
        }
        return $this->display(__FILE__, 'crossselling_mod.tpl', $this->getCacheId($cache_id));
    }
 public function process()
 {
     global $cart, $currency;
     parent::process();
     if (!Validate::isLoadedObject($this->product)) {
         $this->errors[] = Tools::displayError('Product not found');
     } else {
         if (!$this->product->active and Tools::getValue('adtoken') != Tools::encrypt('PreviewProduct' . $this->product->id) || !file_exists(dirname(__FILE__) . '/../' . Tools::getValue('ad') . '/ajax.php')) {
             header('HTTP/1.1 404 page not found');
             $this->errors[] = Tools::displayError('Product is no longer available.');
         } elseif (!$this->product->checkAccess((int) self::$cookie->id_customer)) {
             $this->errors[] = Tools::displayError('You do not have access to this product.');
         } else {
             self::$smarty->assign('virtual', ProductDownload::getIdFromIdProduct((int) $this->product->id));
             if (!$this->product->active) {
                 self::$smarty->assign('adminActionDisplay', true);
             }
             /* Product pictures management */
             require_once 'images.inc.php';
             if ($this->product->customizable) {
                 self::$smarty->assign('customizationFormTarget', Tools::safeOutput(urldecode($_SERVER['REQUEST_URI'])));
                 if (Tools::isSubmit('submitCustomizedDatas')) {
                     $this->pictureUpload($this->product, $cart);
                     $this->textRecord($this->product, $cart);
                     $this->formTargetFormat();
                 } elseif (isset($_GET['deletePicture']) and !$cart->deletePictureToProduct((int) $this->product->id, (int) Tools::getValue('deletePicture'))) {
                     $this->errors[] = Tools::displayError('An error occurred while deleting the selected picture');
                 }
                 $files = self::$cookie->getFamily('pictures_' . (int) $this->product->id);
                 $textFields = self::$cookie->getFamily('textFields_' . (int) $this->product->id);
                 foreach ($textFields as $key => $textField) {
                     $textFields[$key] = str_replace('<br />', "\n", $textField);
                 }
                 self::$smarty->assign(array('pictures' => $files, 'textFields' => $textFields));
             }
             /* Features / Values */
             $features = $this->product->getFrontFeatures((int) self::$cookie->id_lang);
             $attachments = $this->product->cache_has_attachments ? $this->product->getAttachments((int) self::$cookie->id_lang) : array();
             /* Category */
             $category = false;
             if (isset($_SERVER['HTTP_REFERER']) and preg_match('!^(.*)\\/([0-9]+)\\-(.*[^\\.])|(.*)id_category=([0-9]+)(.*)$!', $_SERVER['HTTP_REFERER'], $regs) and !strstr($_SERVER['HTTP_REFERER'], '.html')) {
                 if (isset($regs[2]) and is_numeric($regs[2])) {
                     if (Product::idIsOnCategoryId((int) $this->product->id, array('0' => array('id_category' => (int) $regs[2])))) {
                         $category = new Category((int) $regs[2], (int) self::$cookie->id_lang);
                     }
                 } elseif (isset($regs[5]) and is_numeric($regs[5])) {
                     if (Product::idIsOnCategoryId((int) $this->product->id, array('0' => array('id_category' => (int) $regs[5])))) {
                         $category = new Category((int) $regs[5], (int) self::$cookie->id_lang);
                     }
                 }
             }
             if (!$category) {
                 $category = new Category($this->product->id_category_default, (int) self::$cookie->id_lang);
             }
             if (isset($category) and Validate::isLoadedObject($category)) {
                 self::$smarty->assign(array('path' => Tools::getPath((int) $category->id, $this->product->name, true), 'category' => $category, 'subCategories' => $category->getSubCategories((int) self::$cookie->id_lang, true), 'id_category_current' => (int) $category->id, 'id_category_parent' => (int) $category->id_parent, 'return_category_name' => Tools::safeOutput($category->name)));
             } else {
                 self::$smarty->assign('path', Tools::getPath((int) $this->product->id_category_default, $this->product->name));
             }
             self::$smarty->assign('return_link', (isset($category->id) and $category->id) ? Tools::safeOutput(self::$link->getCategoryLink($category)) : 'javascript: history.back();');
             if (Pack::isPack((int) $this->product->id) and !Pack::isInStock((int) $this->product->id)) {
                 $this->product->quantity = 0;
             }
             $group_reduction = (100 - Group::getReduction((int) self::$cookie->id_customer)) / 100;
             $id_customer = (isset(self::$cookie->id_customer) and self::$cookie->id_customer) ? (int) self::$cookie->id_customer : 0;
             $id_group = $id_customer ? (int) Customer::getDefaultGroupId($id_customer) : _PS_DEFAULT_CUSTOMER_GROUP_;
             $id_country = (int) ($id_customer ? Customer::getCurrentCountry($id_customer) : Configuration::get('PS_COUNTRY_DEFAULT'));
             // Tax
             $tax = (double) Tax::getProductTaxRate((int) $this->product->id, $cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')});
             self::$smarty->assign('tax_rate', $tax);
             $productPriceWithTax = Product::getPriceStatic($this->product->id, true, NULL, 6);
             if (Product::$_taxCalculationMethod == PS_TAX_INC) {
                 $productPriceWithTax = Tools::ps_round($productPriceWithTax, 2);
             }
             $productPriceWithoutEcoTax = (double) ($productPriceWithTax - $this->product->ecotax);
             $ecotax_rate = (double) Tax::getProductEcotaxRate($cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')});
             $ecotaxTaxAmount = Tools::ps_round($this->product->ecotax, 2);
             if (Product::$_taxCalculationMethod == PS_TAX_INC && (int) Configuration::get('PS_TAX')) {
                 $ecotaxTaxAmount = Tools::ps_round($ecotaxTaxAmount * (1 + $ecotax_rate / 100), 2);
             }
             self::$smarty->assign(array('quantity_discounts' => $this->formatQuantityDiscounts(SpecificPrice::getQuantityDiscounts((int) $this->product->id, (int) Shop::getCurrentShop(), (int) self::$cookie->id_currency, $id_country, $id_group), $this->product->getPrice(Product::$_taxCalculationMethod == PS_TAX_INC, false), (double) $tax), 'product' => $this->product, 'ecotax_tax_inc' => $ecotaxTaxAmount, 'ecotax_tax_exc' => Tools::ps_round($this->product->ecotax, 2), 'ecotaxTax_rate' => $ecotax_rate, 'homeSize' => Image::getSize('home'), 'product_manufacturer' => new Manufacturer((int) $this->product->id_manufacturer, self::$cookie->id_lang), 'token' => Tools::getToken(false), 'productPriceWithoutEcoTax' => (double) $productPriceWithoutEcoTax, 'features' => $features, 'attachments' => $attachments, 'allow_oosp' => $this->product->isAvailableWhenOutOfStock((int) $this->product->out_of_stock), 'last_qties' => (int) Configuration::get('PS_LAST_QTIES'), 'group_reduction' => $group_reduction, 'col_img_dir' => _PS_COL_IMG_DIR_));
             self::$smarty->assign(array('HOOK_EXTRA_LEFT' => Module::hookExec('extraLeft'), 'HOOK_EXTRA_RIGHT' => Module::hookExec('extraRight'), 'HOOK_PRODUCT_OOS' => Hook::productOutOfStock($this->product), 'HOOK_PRODUCT_FOOTER' => Hook::productFooter($this->product, $category), 'HOOK_PRODUCT_ACTIONS' => Module::hookExec('productActions'), 'HOOK_PRODUCT_TAB' => Module::hookExec('productTab'), 'HOOK_PRODUCT_TAB_CONTENT' => Module::hookExec('productTabContent')));
             $images = $this->product->getImages((int) self::$cookie->id_lang);
             $productImages = array();
             foreach ($images as $k => $image) {
                 if ($image['cover']) {
                     self::$smarty->assign('mainImage', $images[0]);
                     $cover = $image;
                     $cover['id_image'] = Configuration::get('PS_LEGACY_IMAGES') ? $this->product->id . '-' . $image['id_image'] : $image['id_image'];
                     $cover['id_image_only'] = (int) $image['id_image'];
                 }
                 $productImages[(int) $image['id_image']] = $image;
             }
             if (!isset($cover)) {
                 $cover = array('id_image' => Language::getIsoById(self::$cookie->id_lang) . '-default', 'legend' => 'No picture', 'title' => 'No picture');
             }
             $size = Image::getSize('large');
             self::$smarty->assign(array('cover' => $cover, 'imgWidth' => (int) $size['width'], 'mediumSize' => Image::getSize('medium'), 'largeSize' => Image::getSize('large'), 'accessories' => $this->product->getAccessories((int) self::$cookie->id_lang)));
             if (count($productImages)) {
                 self::$smarty->assign('images', $productImages);
             }
             /* Attributes / Groups & colors */
             $colors = array();
             $attributesGroups = $this->product->getAttributesGroups((int) self::$cookie->id_lang);
             // @todo (RM) should only get groups and not all declination ?
             if (is_array($attributesGroups) and $attributesGroups) {
                 $groups = array();
                 $combinationImages = $this->product->getCombinationImages((int) self::$cookie->id_lang);
                 foreach ($attributesGroups as $k => $row) {
                     /* Color management */
                     if ((isset($row['attribute_color']) and $row['attribute_color'] or file_exists(_PS_COL_IMG_DIR_ . $row['id_attribute'] . '.jpg')) and $row['id_attribute_group'] == $this->product->id_color_default) {
                         $colors[$row['id_attribute']]['value'] = $row['attribute_color'];
                         $colors[$row['id_attribute']]['name'] = $row['attribute_name'];
                         if (!isset($colors[$row['id_attribute']]['attributes_quantity'])) {
                             $colors[$row['id_attribute']]['attributes_quantity'] = 0;
                         }
                         $colors[$row['id_attribute']]['attributes_quantity'] += (int) $row['quantity'];
                     }
                     if (!isset($groups[$row['id_attribute_group']])) {
                         $groups[$row['id_attribute_group']] = array('name' => $row['public_group_name'], 'is_color_group' => $row['is_color_group'], 'default' => -1);
                     }
                     $groups[$row['id_attribute_group']]['attributes'][$row['id_attribute']] = $row['attribute_name'];
                     if ($row['default_on'] && $groups[$row['id_attribute_group']]['default'] == -1) {
                         $groups[$row['id_attribute_group']]['default'] = (int) $row['id_attribute'];
                     }
                     if (!isset($groups[$row['id_attribute_group']]['attributes_quantity'][$row['id_attribute']])) {
                         $groups[$row['id_attribute_group']]['attributes_quantity'][$row['id_attribute']] = 0;
                     }
                     $groups[$row['id_attribute_group']]['attributes_quantity'][$row['id_attribute']] += (int) $row['quantity'];
                     $combinations[$row['id_product_attribute']]['attributes_values'][$row['id_attribute_group']] = $row['attribute_name'];
                     $combinations[$row['id_product_attribute']]['attributes'][] = (int) $row['id_attribute'];
                     $combinations[$row['id_product_attribute']]['price'] = (double) $row['price'];
                     $combinations[$row['id_product_attribute']]['ecotax'] = (double) $row['ecotax'];
                     $combinations[$row['id_product_attribute']]['weight'] = (double) $row['weight'];
                     $combinations[$row['id_product_attribute']]['quantity'] = (int) $row['quantity'];
                     $combinations[$row['id_product_attribute']]['reference'] = $row['reference'];
                     $combinations[$row['id_product_attribute']]['unit_impact'] = $row['unit_price_impact'];
                     $combinations[$row['id_product_attribute']]['minimal_quantity'] = $row['minimal_quantity'];
                     $combinations[$row['id_product_attribute']]['id_image'] = isset($combinationImages[$row['id_product_attribute']][0]['id_image']) ? $combinationImages[$row['id_product_attribute']][0]['id_image'] : -1;
                 }
                 //wash attributes list (if some attributes are unavailables and if allowed to wash it)
                 if (!Product::isAvailableWhenOutOfStock($this->product->out_of_stock) && Configuration::get('PS_DISP_UNAVAILABLE_ATTR') == 0) {
                     foreach ($groups as &$group) {
                         foreach ($group['attributes_quantity'] as $key => &$quantity) {
                             if (!$quantity) {
                                 unset($group['attributes'][$key]);
                             }
                         }
                     }
                     foreach ($colors as $key => $color) {
                         if (!$color['attributes_quantity']) {
                             unset($colors[$key]);
                         }
                     }
                 }
                 foreach ($groups as &$group) {
                     natcasesort($group['attributes']);
                 }
                 foreach ($combinations as $id_product_attribute => $comb) {
                     $attributeList = '';
                     foreach ($comb['attributes'] as $id_attribute) {
                         $attributeList .= '\'' . (int) $id_attribute . '\',';
                     }
                     $attributeList = rtrim($attributeList, ',');
                     $combinations[$id_product_attribute]['list'] = $attributeList;
                 }
                 self::$smarty->assign(array('groups' => $groups, 'combinaisons' => $combinations, 'combinations' => $combinations, 'colors' => (sizeof($colors) and $this->product->id_color_default) ? $colors : false, 'combinationImages' => $combinationImages));
             }
             self::$smarty->assign(array('no_tax' => Tax::excludeTaxeOption() or !Tax::getProductTaxRate((int) $this->product->id, $cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}), 'customizationFields' => $this->product->customizable ? $this->product->getCustomizationFields((int) self::$cookie->id_lang) : false));
             // Pack management
             self::$smarty->assign('packItems', $this->product->cache_is_pack ? Pack::getItemTable($this->product->id, (int) self::$cookie->id_lang, true) : array());
             self::$smarty->assign('packs', Pack::getPacksTable($this->product->id, (int) self::$cookie->id_lang, true, 1));
         }
     }
     self::$smarty->assign(array('ENT_NOQUOTES' => ENT_NOQUOTES, 'outOfStockAllowed' => (int) Configuration::get('PS_ORDER_OUT_OF_STOCK'), 'errors' => $this->errors, 'categories' => Category::getHomeCategories((int) self::$cookie->id_lang), 'have_image' => isset($cover) ? (int) $cover['id_image'] : false, 'tax_enabled' => Configuration::get('PS_TAX'), 'display_qties' => (int) Configuration::get('PS_DISPLAY_QTIES'), 'display_ht' => !Tax::excludeTaxeOption(), 'ecotax' => !sizeof($this->errors) and $this->product->ecotax > 0 ? Tools::convertPrice((double) $this->product->ecotax) : 0, 'currencySign' => $currency->sign, 'currencyRate' => $currency->conversion_rate, 'currencyFormat' => $currency->format, 'currencyBlank' => $currency->blank, 'jqZoomEnabled' => Configuration::get('PS_DISPLAY_JQZOOM')));
 }
Example #17
0
    public function getFilterBlock($selected_filters = array())
    {
        global $cookie;
        static $cache = null;
        $id_lang = Context::getContext()->language->id;
        $currency = Context::getContext()->currency;
        $id_shop = (int) Context::getContext()->shop->id;
        $alias = 'product_shop';
        if (is_array($cache)) {
            return $cache;
        }
        $home_category = Configuration::get('PS_HOME_CATEGORY');
        $id_parent = (int) Tools::getValue('id_category', Tools::getValue('id_category_layered', $home_category));
        if ($id_parent == $home_category) {
            return;
        }
        $parent = new Category((int) $id_parent, $id_lang);
        /* Get the filters for the current category */
        $filters = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('
			SELECT * FROM ' . _DB_PREFIX_ . 'layered_category
			WHERE id_category = ' . (int) $id_parent . '
				AND id_shop = ' . $id_shop . '
			GROUP BY `type`, id_value ORDER BY position ASC');
        // Remove all empty selected filters
        foreach ($selected_filters as $key => $value) {
            switch ($key) {
                case 'price':
                case 'weight':
                    if ($value[0] === '' && $value[1] === '') {
                        unset($selected_filters[$key]);
                    }
                    break;
                default:
                    if ($value == '') {
                        unset($selected_filters[$key]);
                    }
                    break;
            }
        }
        $filter_blocks = array();
        foreach ($filters as $filter) {
            $sql_query = array('select' => '', 'from' => '', 'join' => '', 'where' => '', 'group' => '', 'second_query' => '');
            switch ($filter['type']) {
                // conditions + quantities + weight + price
                case 'price':
                case 'weight':
                case 'condition':
                case 'quantity':
                    $sql_query['select'] = 'SELECT p.`id_product`, product_shop.`condition`, p.`id_manufacturer`, sa.`quantity`, p.`weight` ';
                    $sql_query['from'] = '
					FROM ' . _DB_PREFIX_ . 'product p ';
                    $sql_query['join'] = '
					INNER JOIN ' . _DB_PREFIX_ . 'category_product cp ON (cp.id_product = p.id_product)
					INNER JOIN ' . _DB_PREFIX_ . 'category c ON (c.id_category = cp.id_category AND
					' . (Configuration::get('PS_LAYERED_FULL_TREE') ? 'c.nleft >= ' . (int) $parent->nleft . '
					AND c.nright <= ' . (int) $parent->nright : 'c.id_category = ' . (int) $id_parent) . '
					AND c.active = 1) ';
                    $sql_query['join'] .= 'LEFT JOIN `' . _DB_PREFIX_ . 'stock_available` sa
						ON (sa.id_product = p.id_product AND sa.id_shop = ' . (int) $this->context->shop->id . ') ';
                    $sql_query['where'] = 'WHERE product_shop.`active` = 1 AND product_shop.`visibility` IN ("both", "catalog") ';
                    $sql_query['group'] = ' GROUP BY p.id_product ';
                    break;
                case 'manufacturer':
                    $sql_query['select'] = 'SELECT m.name, COUNT(DISTINCT p.id_product) nbr, m.id_manufacturer ';
                    $sql_query['from'] = '
					FROM `' . _DB_PREFIX_ . 'category_product` cp
					INNER JOIN  `' . _DB_PREFIX_ . 'category` c ON (c.id_category = cp.id_category)
					INNER JOIN ' . _DB_PREFIX_ . 'product p ON (p.id_product = cp.id_product)
					INNER JOIN ' . _DB_PREFIX_ . 'manufacturer m ON (m.id_manufacturer = p.id_manufacturer) ';
                    $sql_query['where'] = 'WHERE
					' . (Configuration::get('PS_LAYERED_FULL_TREE') ? 'c.nleft >= ' . (int) $parent->nleft . '
					AND c.nright <= ' . (int) $parent->nright : 'c.id_category = ' . (int) $id_parent) . '
					AND c.active = 1
					AND ' . $alias . '.active = 1 AND ' . $alias . '.`visibility` IN ("both", "catalog")';
                    $sql_query['group'] = ' GROUP BY p.id_manufacturer ORDER BY m.name';
                    if (!Configuration::get('PS_LAYERED_HIDE_0_VALUES')) {
                        $sql_query['second_query'] = '
							SELECT m.name, 0 nbr, m.id_manufacturer

							FROM `' . _DB_PREFIX_ . 'category_product` cp' . Shop::addSqlAssociation('product', 'cp') . '
							INNER JOIN  `' . _DB_PREFIX_ . 'category` c ON (c.id_category = cp.id_category)
							INNER JOIN ' . _DB_PREFIX_ . 'product p ON (p.id_product = cp.id_product)
							INNER JOIN ' . _DB_PREFIX_ . 'manufacturer m ON (m.id_manufacturer = p.id_manufacturer)

							WHERE ' . (Configuration::get('PS_LAYERED_FULL_TREE') ? 'c.nleft >= ' . (int) $parent->nleft . '
							AND c.nright <= ' . (int) $parent->nright : 'c.id_category = ' . (int) $id_parent) . '
							AND c.active = 1
							AND ' . $alias . '.active = 1 AND ' . $alias . '.`visibility` IN ("both", "catalog")
							GROUP BY p.id_manufacturer ORDER BY m.name';
                    }
                    break;
                case 'id_attribute_group':
                    // attribute group
                    $sql_query['select'] = '
					SELECT COUNT(DISTINCT p.id_product) nbr, lpa.id_attribute_group,
					a.color, al.name attribute_name, agl.public_name attribute_group_name , lpa.id_attribute, ag.is_color_group,
					liagl.url_name name_url_name, liagl.meta_title name_meta_title, lial.url_name value_url_name, lial.meta_title value_meta_title';
                    $sql_query['from'] = '
					FROM ' . _DB_PREFIX_ . 'layered_product_attribute lpa
					INNER JOIN ' . _DB_PREFIX_ . 'attribute a
					ON a.id_attribute = lpa.id_attribute
					INNER JOIN ' . _DB_PREFIX_ . 'attribute_lang al
					ON al.id_attribute = a.id_attribute
					AND al.id_lang = ' . (int) $id_lang . '
					INNER JOIN ' . _DB_PREFIX_ . 'product as p
					ON p.id_product = lpa.id_product
					INNER JOIN ' . _DB_PREFIX_ . 'attribute_group ag
					ON ag.id_attribute_group = lpa.id_attribute_group
					INNER JOIN ' . _DB_PREFIX_ . 'attribute_group_lang agl
					ON agl.id_attribute_group = lpa.id_attribute_group
					AND agl.id_lang = ' . (int) $id_lang . '
					LEFT JOIN ' . _DB_PREFIX_ . 'layered_indexable_attribute_group_lang_value liagl
					ON (liagl.id_attribute_group = lpa.id_attribute_group AND liagl.id_lang = ' . (int) $id_lang . ')
					LEFT JOIN ' . _DB_PREFIX_ . 'layered_indexable_attribute_lang_value lial
					ON (lial.id_attribute = lpa.id_attribute AND lial.id_lang = ' . (int) $id_lang . ') ';
                    $sql_query['where'] = 'WHERE a.id_attribute_group = ' . (int) $filter['id_value'];
                    $sql_query['where'] .= ' AND lpa.`id_shop` = ' . (int) Context::getContext()->shop->id;
                    $sql_query['where'] .= ' AND ' . $alias . '.active = 1 AND ' . $alias . '.`visibility` IN ("both", "catalog")
					AND p.id_product IN (
						SELECT id_product
						FROM ' . _DB_PREFIX_ . 'category_product cp
						INNER JOIN ' . _DB_PREFIX_ . 'category c ON (c.id_category = cp.id_category AND
						' . (Configuration::get('PS_LAYERED_FULL_TREE') ? 'c.nleft >= ' . (int) $parent->nleft . '
						AND c.nright <= ' . (int) $parent->nright : 'c.id_category = ' . (int) $id_parent) . '
						AND c.active = 1)
					) ';
                    $sql_query['group'] = '
					GROUP BY lpa.id_attribute
					ORDER BY ag.`position` ASC, a.`position` ASC';
                    if (!Configuration::get('PS_LAYERED_HIDE_0_VALUES')) {
                        $sql_query['second_query'] = '
							SELECT 0 nbr, lpa.id_attribute_group,
								a.color, al.name attribute_name, agl.public_name attribute_group_name , lpa.id_attribute, ag.is_color_group,
								liagl.url_name name_url_name, liagl.meta_title name_meta_title, lial.url_name value_url_name, lial.meta_title value_meta_title
							FROM ' . _DB_PREFIX_ . 'layered_product_attribute lpa' . Shop::addSqlAssociation('product', 'lpa') . '
							INNER JOIN ' . _DB_PREFIX_ . 'attribute a
								ON a.id_attribute = lpa.id_attribute
							INNER JOIN ' . _DB_PREFIX_ . 'attribute_lang al
								ON al.id_attribute = a.id_attribute AND al.id_lang = ' . (int) $id_lang . '
							INNER JOIN ' . _DB_PREFIX_ . 'product as p
								ON p.id_product = lpa.id_product
							INNER JOIN ' . _DB_PREFIX_ . 'attribute_group ag
								ON ag.id_attribute_group = lpa.id_attribute_group
							INNER JOIN ' . _DB_PREFIX_ . 'attribute_group_lang agl
								ON agl.id_attribute_group = lpa.id_attribute_group
							AND agl.id_lang = ' . (int) $id_lang . '
							LEFT JOIN ' . _DB_PREFIX_ . 'layered_indexable_attribute_group_lang_value liagl
								ON (liagl.id_attribute_group = lpa.id_attribute_group AND liagl.id_lang = ' . (int) $id_lang . ')
							LEFT JOIN ' . _DB_PREFIX_ . 'layered_indexable_attribute_lang_value lial
								ON (lial.id_attribute = lpa.id_attribute AND lial.id_lang = ' . (int) $id_lang . ')
							WHERE ' . $alias . '.active = 1 AND ' . $alias . '.`visibility` IN ("both", "catalog")
							AND a.id_attribute_group = ' . (int) $filter['id_value'] . '
							AND lpa.`id_shop` = ' . (int) Context::getContext()->shop->id . '
							GROUP BY lpa.id_attribute
							ORDER BY id_attribute_group, id_attribute';
                    }
                    break;
                case 'id_feature':
                    $sql_query['select'] = 'SELECT fl.name feature_name, fp.id_feature, fv.id_feature_value, fvl.value,
					COUNT(DISTINCT p.id_product) nbr,
					lifl.url_name name_url_name, lifl.meta_title name_meta_title, lifvl.url_name value_url_name, lifvl.meta_title value_meta_title ';
                    $sql_query['from'] = '
					FROM ' . _DB_PREFIX_ . 'feature_product fp
					INNER JOIN ' . _DB_PREFIX_ . 'product p ON (p.id_product = fp.id_product)
					LEFT JOIN ' . _DB_PREFIX_ . 'feature_lang fl ON (fl.id_feature = fp.id_feature AND fl.id_lang = ' . $id_lang . ')
					INNER JOIN ' . _DB_PREFIX_ . 'feature_value fv ON (fv.id_feature_value = fp.id_feature_value AND (fv.custom IS NULL OR fv.custom = 0))
					LEFT JOIN ' . _DB_PREFIX_ . 'feature_value_lang fvl ON (fvl.id_feature_value = fp.id_feature_value AND fvl.id_lang = ' . $id_lang . ')
					LEFT JOIN ' . _DB_PREFIX_ . 'layered_indexable_feature_lang_value lifl
					ON (lifl.id_feature = fp.id_feature AND lifl.id_lang = ' . $id_lang . ')
					LEFT JOIN ' . _DB_PREFIX_ . 'layered_indexable_feature_value_lang_value lifvl
					ON (lifvl.id_feature_value = fp.id_feature_value AND lifvl.id_lang = ' . $id_lang . ') ';
                    $sql_query['where'] = 'WHERE ' . $alias . '.`active` = 1 AND ' . $alias . '.`visibility` IN ("both", "catalog")
					AND fp.id_feature = ' . (int) $filter['id_value'] . '
					AND p.id_product IN (
					SELECT id_product
					FROM ' . _DB_PREFIX_ . 'category_product cp
					INNER JOIN ' . _DB_PREFIX_ . 'category c ON (c.id_category = cp.id_category AND
					' . (Configuration::get('PS_LAYERED_FULL_TREE') ? 'c.nleft >= ' . (int) $parent->nleft . '
					AND c.nright <= ' . (int) $parent->nright : 'c.id_category = ' . (int) $id_parent) . '
					AND c.active = 1)) ';
                    $sql_query['group'] = 'GROUP BY fv.id_feature_value';
                    if (!Configuration::get('PS_LAYERED_HIDE_0_VALUES')) {
                        $sql_query['second_query'] = '
							SELECT fl.name feature_name, fp.id_feature, fv.id_feature_value, fvl.value,
							0 nbr,
							lifl.url_name name_url_name, lifl.meta_title name_meta_title, lifvl.url_name value_url_name, lifvl.meta_title value_meta_title

							FROM ' . _DB_PREFIX_ . 'feature_product fp' . Shop::addSqlAssociation('product', 'fp') . '
							INNER JOIN ' . _DB_PREFIX_ . 'product p ON (p.id_product = fp.id_product)
							LEFT JOIN ' . _DB_PREFIX_ . 'feature_lang fl ON (fl.id_feature = fp.id_feature AND fl.id_lang = ' . (int) $id_lang . ')
							INNER JOIN ' . _DB_PREFIX_ . 'feature_value fv ON (fv.id_feature_value = fp.id_feature_value AND (fv.custom IS NULL OR fv.custom = 0))
							LEFT JOIN ' . _DB_PREFIX_ . 'feature_value_lang fvl ON (fvl.id_feature_value = fp.id_feature_value AND fvl.id_lang = ' . (int) $id_lang . ')
							LEFT JOIN ' . _DB_PREFIX_ . 'layered_indexable_feature_lang_value lifl
								ON (lifl.id_feature = fp.id_feature AND lifl.id_lang = ' . (int) $id_lang . ')
							LEFT JOIN ' . _DB_PREFIX_ . 'layered_indexable_feature_value_lang_value lifvl
								ON (lifvl.id_feature_value = fp.id_feature_value AND lifvl.id_lang = ' . (int) $id_lang . ')
							WHERE ' . $alias . '.`active` = 1 AND ' . $alias . '.`visibility` IN ("both", "catalog")
							AND fp.id_feature = ' . (int) $filter['id_value'] . '
							GROUP BY fv.id_feature_value';
                    }
                    break;
                case 'category':
                    if (Group::isFeatureActive()) {
                        $this->user_groups = $this->context->customer->isLogged() ? $this->context->customer->getGroups() : array(Configuration::get('PS_UNIDENTIFIED_GROUP'));
                    }
                    $depth = Configuration::get('PS_LAYERED_FILTER_CATEGORY_DEPTH');
                    if ($depth === false) {
                        $depth = 1;
                    }
                    $sql_query['select'] = '
					SELECT c.id_category, c.id_parent, cl.name, (SELECT count(DISTINCT p.id_product) # ';
                    $sql_query['from'] = '
					FROM ' . _DB_PREFIX_ . 'category_product cp
					LEFT JOIN ' . _DB_PREFIX_ . 'product p ON (p.id_product = cp.id_product) ';
                    $sql_query['where'] = '
					WHERE cp.id_category = c.id_category
					AND ' . $alias . '.active = 1 AND ' . $alias . '.`visibility` IN ("both", "catalog")';
                    $sql_query['group'] = ') count_products
					FROM ' . _DB_PREFIX_ . 'category c
					LEFT JOIN ' . _DB_PREFIX_ . 'category_lang cl ON (cl.id_category = c.id_category AND cl.`id_shop` = ' . (int) Context::getContext()->shop->id . ' and cl.id_lang = ' . (int) $id_lang . ') ';
                    if (Group::isFeatureActive()) {
                        $sql_query['group'] .= 'RIGHT JOIN ' . _DB_PREFIX_ . 'category_group cg ON (cg.id_category = c.id_category AND cg.`id_group` IN (' . implode(', ', $this->user_groups) . ')) ';
                    }
                    $sql_query['group'] .= 'WHERE c.nleft > ' . (int) $parent->nleft . '
					AND c.nright < ' . (int) $parent->nright . '
					' . ($depth ? 'AND c.level_depth <= ' . ($parent->level_depth + (int) $depth) : '') . '
					AND c.active = 1
					GROUP BY c.id_category ORDER BY c.nleft, c.position';
            }
            foreach ($filters as $filter_tmp) {
                $method_name = 'get' . ucfirst($filter_tmp['type']) . 'FilterSubQuery';
                if (method_exists('BlockLayered', $method_name) && (!in_array($filter['type'], array('price', 'weight')) && $filter['type'] != $filter_tmp['type'] || $filter['type'] == $filter_tmp['type'])) {
                    if ($filter['type'] == $filter_tmp['type'] && $filter['id_value'] == $filter_tmp['id_value']) {
                        $sub_query_filter = self::$method_name(array(), true);
                    } else {
                        if (!is_null($filter_tmp['id_value'])) {
                            $selected_filters_cleaned = $this->cleanFilterByIdValue(@$selected_filters[$filter_tmp['type']], $filter_tmp['id_value']);
                        } else {
                            $selected_filters_cleaned = @$selected_filters[$filter_tmp['type']];
                        }
                        $sub_query_filter = self::$method_name($selected_filters_cleaned, $filter['type'] == $filter_tmp['type']);
                    }
                    foreach ($sub_query_filter as $key => $value) {
                        $sql_query[$key] .= $value;
                    }
                }
            }
            $products = false;
            if (!empty($sql_query['from'])) {
                $sql_query['from'] .= Shop::addSqlAssociation('product', 'p');
                $products = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql_query['select'] . "\n" . $sql_query['from'] . "\n" . $sql_query['join'] . "\n" . $sql_query['where'] . "\n" . $sql_query['group']);
            }
            foreach ($filters as $filter_tmp) {
                $method_name = 'filterProductsBy' . ucfirst($filter_tmp['type']);
                if (method_exists('BlockLayered', $method_name) && (!in_array($filter['type'], array('price', 'weight')) && $filter['type'] != $filter_tmp['type'] || $filter['type'] == $filter_tmp['type'])) {
                    if ($filter['type'] == $filter_tmp['type']) {
                        $products = self::$method_name(array(), $products);
                    } else {
                        $products = self::$method_name(@$selected_filters[$filter_tmp['type']], $products);
                    }
                }
            }
            if (!empty($sql_query['second_query'])) {
                $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql_query['second_query']);
                if ($res) {
                    $products = array_merge($products, $res);
                }
            }
            switch ($filter['type']) {
                case 'price':
                    if ($this->showPriceFilter()) {
                        $price_array = array('type_lite' => 'price', 'type' => 'price', 'id_key' => 0, 'name' => $this->l('Price'), 'slider' => true, 'max' => '0', 'min' => null, 'values' => array('1' => 0), 'unit' => $currency->sign, 'format' => $currency->format, 'filter_show_limit' => $filter['filter_show_limit'], 'filter_type' => $filter['filter_type']);
                        if (isset($products) && $products) {
                            foreach ($products as $product) {
                                if (is_null($price_array['min'])) {
                                    $price_array['min'] = $product['price_min'];
                                    $price_array['values'][0] = $product['price_min'];
                                } else {
                                    if ($price_array['min'] > $product['price_min']) {
                                        $price_array['min'] = $product['price_min'];
                                        $price_array['values'][0] = $product['price_min'];
                                    }
                                }
                                if ($price_array['max'] < $product['price_max']) {
                                    $price_array['max'] = $product['price_max'];
                                    $price_array['values'][1] = $product['price_max'];
                                }
                            }
                        }
                        if ($price_array['max'] != $price_array['min'] && $price_array['min'] != null) {
                            if ($filter['filter_type'] == 2) {
                                $price_array['list_of_values'] = array();
                                $nbr_of_value = $filter['filter_show_limit'];
                                if ($nbr_of_value < 2) {
                                    $nbr_of_value = 4;
                                }
                                $delta = ($price_array['max'] - $price_array['min']) / $nbr_of_value;
                                $current_step = $price_array['min'];
                                for ($i = 0; $i < $nbr_of_value; $i++) {
                                    $price_array['list_of_values'][] = array((int) ($price_array['min'] + $i * $delta), (int) ($price_array['min'] + ($i + 1) * $delta));
                                }
                            }
                            if (isset($selected_filters['price']) && isset($selected_filters['price'][0]) && isset($selected_filters['price'][1])) {
                                $price_array['values'][0] = $selected_filters['price'][0];
                                $price_array['values'][1] = $selected_filters['price'][1];
                            }
                            $filter_blocks[] = $price_array;
                        }
                    }
                    break;
                case 'weight':
                    $weight_array = array('type_lite' => 'weight', 'type' => 'weight', 'id_key' => 0, 'name' => $this->l('Weight'), 'slider' => true, 'max' => '0', 'min' => null, 'values' => array('1' => 0), 'unit' => Configuration::get('PS_WEIGHT_UNIT'), 'format' => 5, 'filter_show_limit' => $filter['filter_show_limit'], 'filter_type' => $filter['filter_type']);
                    if (isset($products) && $products) {
                        foreach ($products as $product) {
                            if (is_null($weight_array['min'])) {
                                $weight_array['min'] = $product['weight'];
                                $weight_array['values'][0] = $product['weight'];
                            } else {
                                if ($weight_array['min'] > $product['weight']) {
                                    $weight_array['min'] = $product['weight'];
                                    $weight_array['values'][0] = $product['weight'];
                                }
                            }
                            if ($weight_array['max'] < $product['weight']) {
                                $weight_array['max'] = $product['weight'];
                                $weight_array['values'][1] = $product['weight'];
                            }
                        }
                    }
                    if ($weight_array['max'] != $weight_array['min'] && $weight_array['min'] != null) {
                        if (isset($selected_filters['weight']) && isset($selected_filters['weight'][0]) && isset($selected_filters['weight'][1])) {
                            $weight_array['values'][0] = $selected_filters['weight'][0];
                            $weight_array['values'][1] = $selected_filters['weight'][1];
                        }
                        $filter_blocks[] = $weight_array;
                    }
                    break;
                case 'condition':
                    $condition_array = array('new' => array('name' => $this->l('New'), 'nbr' => 0), 'used' => array('name' => $this->l('Used'), 'nbr' => 0), 'refurbished' => array('name' => $this->l('Refurbished'), 'nbr' => 0));
                    if (isset($products) && $products) {
                        foreach ($products as $product) {
                            if (isset($selected_filters['condition']) && in_array($product['condition'], $selected_filters['condition'])) {
                                $condition_array[$product['condition']]['checked'] = true;
                            }
                        }
                    }
                    foreach ($condition_array as $key => $condition) {
                        if (isset($selected_filters['condition']) && in_array($key, $selected_filters['condition'])) {
                            $condition_array[$key]['checked'] = true;
                        }
                    }
                    if (isset($products) && $products) {
                        foreach ($products as $product) {
                            if (isset($condition_array[$product['condition']])) {
                                $condition_array[$product['condition']]['nbr']++;
                            }
                        }
                    }
                    $filter_blocks[] = array('type_lite' => 'condition', 'type' => 'condition', 'id_key' => 0, 'name' => $this->l('Condition'), 'values' => $condition_array, 'filter_show_limit' => $filter['filter_show_limit'], 'filter_type' => $filter['filter_type']);
                    break;
                case 'quantity':
                    $quantity_array = array(0 => array('name' => $this->l('Not available'), 'nbr' => 0), 1 => array('name' => $this->l('In stock'), 'nbr' => 0));
                    foreach ($quantity_array as $key => $quantity) {
                        if (isset($selected_filters['quantity']) && in_array($key, $selected_filters['quantity'])) {
                            $quantity_array[$key]['checked'] = true;
                        }
                    }
                    if (isset($products) && $products) {
                        foreach ($products as $product) {
                            //If oosp move all not available quantity to available quantity
                            if ((int) $product['quantity'] > 0 || Product::isAvailableWhenOutOfStock(StockAvailable::outOfStock($product['id_product']))) {
                                $quantity_array[1]['nbr']++;
                            } else {
                                $quantity_array[0]['nbr']++;
                            }
                        }
                    }
                    $filter_blocks[] = array('type_lite' => 'quantity', 'type' => 'quantity', 'id_key' => 0, 'name' => $this->l('Availability'), 'values' => $quantity_array, 'filter_show_limit' => $filter['filter_show_limit'], 'filter_type' => $filter['filter_type']);
                    break;
                case 'manufacturer':
                    if (isset($products) && $products) {
                        $manufaturers_array = array();
                        foreach ($products as $manufacturer) {
                            if (!isset($manufaturers_array[$manufacturer['id_manufacturer']])) {
                                $manufaturers_array[$manufacturer['id_manufacturer']] = array('name' => $manufacturer['name'], 'nbr' => $manufacturer['nbr']);
                            }
                            if (isset($selected_filters['manufacturer']) && in_array((int) $manufacturer['id_manufacturer'], $selected_filters['manufacturer'])) {
                                $manufaturers_array[$manufacturer['id_manufacturer']]['checked'] = true;
                            }
                        }
                        $filter_blocks[] = array('type_lite' => 'manufacturer', 'type' => 'manufacturer', 'id_key' => 0, 'name' => $this->l('Manufacturer'), 'values' => $manufaturers_array, 'filter_show_limit' => $filter['filter_show_limit'], 'filter_type' => $filter['filter_type']);
                    }
                    break;
                case 'id_attribute_group':
                    $attributes_array = array();
                    if (isset($products) && $products) {
                        foreach ($products as $attributes) {
                            if (!isset($attributes_array[$attributes['id_attribute_group']])) {
                                $attributes_array[$attributes['id_attribute_group']] = array('type_lite' => 'id_attribute_group', 'type' => 'id_attribute_group', 'id_key' => (int) $attributes['id_attribute_group'], 'name' => $attributes['attribute_group_name'], 'is_color_group' => (bool) $attributes['is_color_group'], 'values' => array(), 'url_name' => $attributes['name_url_name'], 'meta_title' => $attributes['name_meta_title'], 'filter_show_limit' => $filter['filter_show_limit'], 'filter_type' => $filter['filter_type']);
                            }
                            if (!isset($attributes_array[$attributes['id_attribute_group']]['values'][$attributes['id_attribute']])) {
                                $attributes_array[$attributes['id_attribute_group']]['values'][$attributes['id_attribute']] = array('color' => $attributes['color'], 'name' => $attributes['attribute_name'], 'nbr' => (int) $attributes['nbr'], 'url_name' => $attributes['value_url_name'], 'meta_title' => $attributes['value_meta_title']);
                            }
                            if (isset($selected_filters['id_attribute_group'][$attributes['id_attribute']])) {
                                $attributes_array[$attributes['id_attribute_group']]['values'][$attributes['id_attribute']]['checked'] = true;
                            }
                        }
                        $filter_blocks = array_merge($filter_blocks, $attributes_array);
                    }
                    break;
                case 'id_feature':
                    $feature_array = array();
                    if (isset($products) && $products) {
                        foreach ($products as $feature) {
                            if (!isset($feature_array[$feature['id_feature']])) {
                                $feature_array[$feature['id_feature']] = array('type_lite' => 'id_feature', 'type' => 'id_feature', 'id_key' => (int) $feature['id_feature'], 'values' => array(), 'name' => $feature['feature_name'], 'url_name' => $feature['name_url_name'], 'meta_title' => $feature['name_meta_title'], 'filter_show_limit' => $filter['filter_show_limit'], 'filter_type' => $filter['filter_type']);
                            }
                            if (!isset($feature_array[$feature['id_feature']]['values'][$feature['id_feature_value']])) {
                                $feature_array[$feature['id_feature']]['values'][$feature['id_feature_value']] = array('nbr' => (int) $feature['nbr'], 'name' => $feature['value'], 'url_name' => $feature['value_url_name'], 'meta_title' => $feature['value_meta_title']);
                            }
                            if (isset($selected_filters['id_feature'][$feature['id_feature_value']])) {
                                $feature_array[$feature['id_feature']]['values'][$feature['id_feature_value']]['checked'] = true;
                            }
                        }
                        //Natural sort
                        foreach ($feature_array as $key => $value) {
                            $temp = array();
                            foreach ($feature_array[$key]['values'] as $keyint => $valueint) {
                                $temp[$keyint] = $valueint['name'];
                            }
                            natcasesort($temp);
                            $temp2 = array();
                            foreach ($temp as $keytemp => $valuetemp) {
                                $temp2[$keytemp] = $feature_array[$key]['values'][$keytemp];
                            }
                            $feature_array[$key]['values'] = $temp2;
                        }
                        $filter_blocks = array_merge($filter_blocks, $feature_array);
                    }
                    break;
                case 'category':
                    $tmp_array = array();
                    if (isset($products) && $products) {
                        $categories_with_products_count = 0;
                        foreach ($products as $category) {
                            $tmp_array[$category['id_category']] = array('name' => $category['name'], 'nbr' => (int) $category['count_products']);
                            if ((int) $category['count_products']) {
                                $categories_with_products_count++;
                            }
                            if (isset($selected_filters['category']) && in_array($category['id_category'], $selected_filters['category'])) {
                                $tmp_array[$category['id_category']]['checked'] = true;
                            }
                        }
                        if ($categories_with_products_count || !Configuration::get('PS_LAYERED_HIDE_0_VALUES')) {
                            $filter_blocks[] = array('type_lite' => 'category', 'type' => 'category', 'id_key' => 0, 'name' => $this->l('Categories'), 'values' => $tmp_array, 'filter_show_limit' => $filter['filter_show_limit'], 'filter_type' => $filter['filter_type']);
                        }
                    }
                    break;
            }
        }
        // All non indexable attribute and feature
        $non_indexable = array();
        // Get all non indexable attribute groups
        foreach (Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('
		SELECT public_name
		FROM `' . _DB_PREFIX_ . 'attribute_group_lang` agl
		LEFT JOIN `' . _DB_PREFIX_ . 'layered_indexable_attribute_group` liag
		ON liag.id_attribute_group = agl.id_attribute_group
		WHERE indexable IS NULL OR indexable = 0
		AND id_lang = ' . (int) $id_lang) as $attribute) {
            $non_indexable[] = Tools::link_rewrite($attribute['public_name']);
        }
        // Get all non indexable features
        foreach (Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('
		SELECT name
		FROM `' . _DB_PREFIX_ . 'feature_lang` fl
		LEFT JOIN  `' . _DB_PREFIX_ . 'layered_indexable_feature` lif
		ON lif.id_feature = fl.id_feature
		WHERE indexable IS NULL OR indexable = 0
		AND id_lang = ' . (int) $id_lang) as $attribute) {
            $non_indexable[] = Tools::link_rewrite($attribute['name']);
        }
        //generate SEO link
        $param_selected = '';
        $param_product_url = '';
        $option_checked_array = array();
        $param_group_selected_array = array();
        $title_values = array();
        $meta_values = array();
        //get filters checked by group
        foreach ($filter_blocks as $type_filter) {
            $filter_name = !empty($type_filter['url_name']) ? $type_filter['url_name'] : $type_filter['name'];
            $filter_meta = !empty($type_filter['meta_title']) ? $type_filter['meta_title'] : $type_filter['name'];
            $attr_key = $type_filter['type'] . '_' . $type_filter['id_key'];
            $param_group_selected = '';
            if (in_array(strtolower($type_filter['type']), array('price', 'weight')) && (double) $type_filter['values'][0] > (double) $type_filter['min'] && (double) $type_filter['values'][1] > (double) $type_filter['max']) {
                $param_group_selected .= $this->getAnchor() . str_replace($this->getAnchor(), '_', $type_filter['values'][0]) . $this->getAnchor() . str_replace($this->getAnchor(), '_', $type_filter['values'][1]);
                $param_group_selected_array[Tools::link_rewrite($filter_name)][] = Tools::link_rewrite($filter_name);
                if (!isset($title_values[$filter_meta])) {
                    $title_values[$filter_meta] = array();
                }
                $title_values[$filter_meta][] = $filter_meta;
                if (!isset($meta_values[$attr_key])) {
                    $meta_values[$attr_key] = array('title' => $filter_meta, 'values' => array());
                }
                $meta_values[$attr_key]['values'][] = $filter_meta;
            } else {
                foreach ($type_filter['values'] as $key => $value) {
                    if (is_array($value) && array_key_exists('checked', $value)) {
                        $value_name = !empty($value['url_name']) ? $value['url_name'] : $value['name'];
                        $value_meta = !empty($value['meta_title']) ? $value['meta_title'] : $value['name'];
                        $param_group_selected .= $this->getAnchor() . str_replace($this->getAnchor(), '_', Tools::link_rewrite($value_name));
                        $param_group_selected_array[Tools::link_rewrite($filter_name)][] = Tools::link_rewrite($value_name);
                        if (!isset($title_values[$filter_meta])) {
                            $title_values[$filter_meta] = array();
                        }
                        $title_values[$filter_meta][] = $value_name;
                        if (!isset($meta_values[$attr_key])) {
                            $meta_values[$attr_key] = array('title' => $filter_meta, 'values' => array());
                        }
                        $meta_values[$attr_key]['values'][] = $value_meta;
                    } else {
                        $param_group_selected_array[Tools::link_rewrite($filter_name)][] = array();
                    }
                }
            }
            if (!empty($param_group_selected)) {
                $param_selected .= '/' . str_replace($this->getAnchor(), '_', Tools::link_rewrite($filter_name)) . $param_group_selected;
                $option_checked_array[Tools::link_rewrite($filter_name)] = $param_group_selected;
            }
            // select only attribute and group attribute to display an unique product combination link
            if (!empty($param_group_selected) && $type_filter['type'] == 'id_attribute_group') {
                $param_product_url .= '/' . str_replace($this->getAnchor(), '_', Tools::link_rewrite($filter_name)) . $param_group_selected;
            }
        }
        if ($this->page > 1) {
            $param_selected .= '/page-' . $this->page;
        }
        $blacklist = array('weight', 'price');
        if (!Configuration::get('PS_LAYERED_FILTER_INDEX_CDT')) {
            $blacklist[] = 'condition';
        }
        if (!Configuration::get('PS_LAYERED_FILTER_INDEX_QTY')) {
            $blacklist[] = 'quantity';
        }
        if (!Configuration::get('PS_LAYERED_FILTER_INDEX_MNF')) {
            $blacklist[] = 'manufacturer';
        }
        if (!Configuration::get('PS_LAYERED_FILTER_INDEX_CAT')) {
            $blacklist[] = 'category';
        }
        $global_nofollow = false;
        foreach ($filter_blocks as &$type_filter) {
            $filter_name = !empty($type_filter['url_name']) ? $type_filter['url_name'] : $type_filter['name'];
            if (count($type_filter) > 0 && !isset($type_filter['slider'])) {
                foreach ($type_filter['values'] as $key => $values) {
                    $nofollow = false;
                    if (!empty($values['checked']) && in_array($type_filter['type'], $blacklist)) {
                        $global_nofollow = true;
                    }
                    $option_checked_clone_array = $option_checked_array;
                    // If not filters checked, add parameter
                    $value_name = !empty($values['url_name']) ? $values['url_name'] : $values['name'];
                    if (!in_array(Tools::link_rewrite($value_name), $param_group_selected_array[Tools::link_rewrite($filter_name)])) {
                        // Update parameter filter checked before
                        if (array_key_exists(Tools::link_rewrite($filter_name), $option_checked_array)) {
                            $option_checked_clone_array[Tools::link_rewrite($filter_name)] = $option_checked_clone_array[Tools::link_rewrite($filter_name)] . $this->getAnchor() . str_replace($this->getAnchor(), '_', Tools::link_rewrite($value_name));
                            if (in_array($type_filter['type'], $blacklist)) {
                                $nofollow = true;
                            }
                        } else {
                            $option_checked_clone_array[Tools::link_rewrite($filter_name)] = $this->getAnchor() . str_replace($this->getAnchor(), '_', Tools::link_rewrite($value_name));
                        }
                    } else {
                        // Remove selected parameters
                        $option_checked_clone_array[Tools::link_rewrite($filter_name)] = str_replace($this->getAnchor() . str_replace($this->getAnchor(), '_', Tools::link_rewrite($value_name)), '', $option_checked_clone_array[Tools::link_rewrite($filter_name)]);
                        if (empty($option_checked_clone_array[Tools::link_rewrite($filter_name)])) {
                            unset($option_checked_clone_array[Tools::link_rewrite($filter_name)]);
                        }
                    }
                    $parameters = '';
                    ksort($option_checked_clone_array);
                    // Order parameters
                    foreach ($option_checked_clone_array as $key_group => $value_group) {
                        $parameters .= '/' . str_replace($this->getAnchor(), '_', $key_group) . $value_group;
                    }
                    // Add nofollow if any blacklisted filters ins in parameters
                    foreach ($filter_blocks as $filter) {
                        $name = Tools::link_rewrite(!empty($filter['url_name']) ? $filter['url_name'] : $filter['name']);
                        if (in_array($filter['type'], $blacklist) && strpos($parameters, $name . '-') !== false) {
                            $nofollow = true;
                        }
                    }
                    // Check if there is an non indexable attribute or feature in the url
                    foreach ($non_indexable as $value) {
                        if (strpos($parameters, '/' . $value) !== false) {
                            $nofollow = true;
                        }
                    }
                    $type_filter['values'][$key]['link'] = Context::getContext()->link->getCategoryLink($parent, null, null) . '#' . ltrim($parameters, '/');
                    $type_filter['values'][$key]['rel'] = $nofollow ? 'nofollow' : '';
                }
            }
        }
        $n_filters = 0;
        if (isset($selected_filters['price'])) {
            if ($price_array['min'] == $selected_filters['price'][0] && $price_array['max'] == $selected_filters['price'][1]) {
                unset($selected_filters['price']);
            }
        }
        if (isset($selected_filters['weight'])) {
            if ($weight_array['min'] == $selected_filters['weight'][0] && $weight_array['max'] == $selected_filters['weight'][1]) {
                unset($selected_filters['weight']);
            }
        }
        foreach ($selected_filters as $filters) {
            $n_filters += count($filters);
        }
        $cache = array('layered_show_qties' => (int) Configuration::get('PS_LAYERED_SHOW_QTIES'), 'id_category_layered' => (int) $id_parent, 'selected_filters' => $selected_filters, 'n_filters' => (int) $n_filters, 'nbr_filterBlocks' => count($filter_blocks), 'filters' => $filter_blocks, 'title_values' => $title_values, 'meta_values' => $meta_values, 'current_friendly_url' => $param_selected, 'param_product_url' => $param_product_url, 'no_follow' => !empty($param_selected) || $global_nofollow);
        return $cache;
    }
 public function preProcess()
 {
     parent::preProcess();
     $orderTotal = self::$cart->getOrderTotal(true, Cart::ONLY_PRODUCTS);
     $this->cartDiscounts = self::$cart->getDiscounts();
     foreach ($this->cartDiscounts as $k => $this->cartDiscount) {
         if ($error = self::$cart->checkDiscountValidity(new Discount((int) $this->cartDiscount['id_discount']), $this->cartDiscounts, $orderTotal, self::$cart->getProducts())) {
             self::$cart->deleteDiscount((int) $this->cartDiscount['id_discount']);
         }
     }
     $add = Tools::getIsset('add') ? 1 : 0;
     $delete = Tools::getIsset('delete') ? 1 : 0;
     if (Configuration::get('PS_TOKEN_ENABLE') == 1 && strcasecmp(Tools::getToken(false), strval(Tools::getValue('token'))) && self::$cookie->isLogged() === true) {
         $this->errors[] = Tools::displayError('Invalid token');
     }
     // Update the cart ONLY if $this->cookies are available, in order to avoid ghost carts created by bots
     if (($add or Tools::getIsset('update') or $delete) and isset(self::$cookie->date_add)) {
         //get the values
         $idProduct = (int) Tools::getValue('id_product', NULL);
         $idProductAttribute = (int) Tools::getValue('id_product_attribute', Tools::getValue('ipa'));
         $customizationId = (int) Tools::getValue('id_customization', 0);
         $qty = (int) abs(Tools::getValue('qty', 1));
         if ($qty == 0) {
             $this->errors[] = Tools::displayError('Null quantity');
         } elseif (!$idProduct) {
             $this->errors[] = Tools::displayError('Product not found');
         } else {
             $producToAdd = new Product((int) $idProduct, true, (int) self::$cookie->id_lang);
             if ((!$producToAdd->id or !$producToAdd->active) and !$delete) {
                 if (Tools::getValue('ajax') == 'true') {
                     die('{"hasError" : true, "errors" : ["' . Tools::displayError('Pproduct is no longer available.', false) . '"]}');
                 } else {
                     $this->errors[] = Tools::displayError('Pproduct is no longer available.', false);
                 }
             } else {
                 /* Check the quantity availability */
                 if ($idProductAttribute and is_numeric($idProductAttribute)) {
                     if (!$delete and !$producToAdd->isAvailableWhenOutOfStock($producToAdd->out_of_stock) and !Attribute::checkAttributeQty((int) $idProductAttribute, (int) $qty)) {
                         if (Tools::getValue('ajax') == 'true') {
                             die('{"hasError" : true, "errors" : ["' . Tools::displayError('There is not enough product in stock.', false) . '"]}');
                         } else {
                             $this->errors[] = Tools::displayError('There is not enough product in stock.');
                         }
                     }
                 } elseif ($producToAdd->hasAttributes() and !$delete) {
                     $idProductAttribute = Product::getDefaultAttribute((int) $producToAdd->id, (int) $producToAdd->out_of_stock == 2 ? !(int) Configuration::get('PS_ORDER_OUT_OF_STOCK') : !(int) $producToAdd->out_of_stock);
                     if (!$idProductAttribute) {
                         Tools::redirectAdmin($link->getProductLink($producToAdd));
                     } elseif (!$delete and !$producToAdd->isAvailableWhenOutOfStock($producToAdd->out_of_stock) and !Attribute::checkAttributeQty((int) $idProductAttribute, (int) $qty)) {
                         if (Tools::getValue('ajax') == 'true') {
                             die('{"hasError" : true, "errors" : ["' . Tools::displayError('There is not enough product in stock.', false) . '"]}');
                         } else {
                             $this->errors[] = Tools::displayError('There is not enough product in stock.');
                         }
                     }
                 } elseif (!$delete and !$producToAdd->checkQty((int) $qty)) {
                     if (Tools::getValue('ajax') == 'true') {
                         die('{"hasError" : true, "errors" : ["' . Tools::displayError('There is not enough product in stock.') . '"]}');
                     } else {
                         $this->errors[] = Tools::displayError('There is not enough product in stock.');
                     }
                 }
                 /* Check vouchers compatibility */
                 if ($add and ($producToAdd->specificPrice and (double) $producToAdd->specificPrice['reduction'] or $producToAdd->on_sale)) {
                     $discounts = self::$cart->getDiscounts();
                     foreach ($discounts as $discount) {
                         if (!$discount['cumulable_reduction']) {
                             $this->errors[] = Tools::displayError('Cannot add this product because current voucher does not allow additional discounts.');
                         }
                     }
                 }
                 if (!sizeof($this->errors)) {
                     if ($add and $qty >= 0) {
                         /* Product addition to the cart */
                         if (!isset(self::$cart->id) or !self::$cart->id) {
                             self::$cart->add();
                             if (self::$cart->id) {
                                 self::$cookie->id_cart = (int) self::$cart->id;
                             }
                         }
                         if ($add and !$producToAdd->hasAllRequiredCustomizableFields() and !$customizationId) {
                             $this->errors[] = Tools::displayError('Please fill in all required fields, then save the customization.');
                         }
                         if (!sizeof($this->errors)) {
                             $updateQuantity = self::$cart->updateQty((int) $qty, (int) $idProduct, (int) $idProductAttribute, $customizationId, Tools::getValue('op', 'up'));
                             if ($updateQuantity < 0) {
                                 /* if product has attribute, minimal quantity is set with minimal quantity of attribute*/
                                 if ((int) $idProductAttribute) {
                                     $minimal_quantity = Attribute::getAttributeMinimalQty((int) $idProductAttribute);
                                 } else {
                                     $minimal_quantity = $producToAdd->minimal_quantity;
                                 }
                                 if (Tools::getValue('ajax') == 'true') {
                                     die('{"hasError" : true, "errors" : ["' . Tools::displayError('You must add', false) . ' ' . $minimal_quantity . ' ' . Tools::displayError('Minimum quantity', false) . '"]}');
                                 } else {
                                     $this->errors[] = Tools::displayError('You must add') . ' ' . $minimal_quantity . ' ' . Tools::displayError('Minimum quantity') . ((isset($_SERVER['HTTP_REFERER']) and basename($_SERVER['HTTP_REFERER']) == 'order.php' or !Tools::isSubmit('ajax') and substr(basename($_SERVER['REQUEST_URI']), 0, strlen('cart.php')) == 'cart.php') ? '<script language="javascript">setTimeout("history.back()",5000);</script><br />- ' . Tools::displayError('You will be redirected to your cart in a few seconds.') : '');
                                 }
                             } elseif (!$updateQuantity) {
                                 if (Tools::getValue('ajax') == 'true') {
                                     die('{"hasError" : true, "errors" : ["' . Tools::displayError('You already have the maximum quantity available for this product.', false) . '"]}');
                                 } else {
                                     $this->errors[] = Tools::displayError('You already have the maximum quantity available for this product.') . ((isset($_SERVER['HTTP_REFERER']) and basename($_SERVER['HTTP_REFERER']) == 'order.php' or !Tools::isSubmit('ajax') and substr(basename($_SERVER['REQUEST_URI']), 0, strlen('cart.php')) == 'cart.php') ? '<script language="javascript">setTimeout("history.back()",5000);</script><br />- ' . Tools::displayError('You will be redirected to your cart in a few seconds.') : '');
                                 }
                             }
                         }
                     } elseif ($delete) {
                         if (self::$cart->deleteProduct((int) $idProduct, (int) $idProductAttribute, (int) $customizationId)) {
                             if (!Cart::getNbProducts((int) self::$cart->id)) {
                                 self::$cart->id_carrier = 0;
                                 self::$cart->gift = 0;
                                 self::$cart->gift_message = '';
                                 self::$cart->update();
                             }
                         }
                     }
                 }
                 $discounts = self::$cart->getDiscounts();
                 foreach ($discounts as $discount) {
                     $discountObj = new Discount((int) $discount['id_discount'], (int) self::$cookie->id_lang);
                     if ($error = self::$cart->checkDiscountValidity($discountObj, $discounts, self::$cart->getOrderTotal(true, Cart::ONLY_PRODUCTS), self::$cart->getProducts())) {
                         self::$cart->deleteDiscount((int) $discount['id_discount']);
                         self::$cart->update();
                         $errors[] = $error;
                     }
                 }
                 if (!sizeof($this->errors)) {
                     $queryString = Tools::safeOutput(Tools::getValue('query', NULL));
                     if ($queryString and !Configuration::get('PS_CART_REDIRECT')) {
                         Tools::redirect('search.php?search=' . $queryString);
                     }
                     if (isset($_SERVER['HTTP_REFERER'])) {
                         // Redirect to previous page
                         preg_match('!http(s?)://(.*)/(.*)!', $_SERVER['HTTP_REFERER'], $regs);
                         if (isset($regs[3]) and !Configuration::get('PS_CART_REDIRECT') and Tools::getValue('ajax') != 'true') {
                             Tools::redirect($regs[3]);
                         }
                     }
                 }
             }
             if (Tools::getValue('ajax') != 'true' and !sizeof($this->errors)) {
                 Tools::redirect('order.php?' . (isset($idProduct) ? 'ipa=' . (int) $idProduct : ''));
             }
         }
     }
 }
Example #19
0
    /**
     * Update product quantity
     *
     * @param integer $quantity Quantity to add (or substract)
     * @param integer $id_product Product ID
     * @param integer $id_product_attribute Attribute ID if needed
     * @param string $operator Indicate if quantity must be increased or decreased
     */
    public function updateQty($quantity, $id_product, $id_product_attribute = NULL, $id_customization = false, $operator = 'up')
    {
        $product = new Product((int) $id_product, false, (int) Configuration::get('PS_LANG_DEFAULT'));
        /* If we have a product combination, the minimal quantity is set with the one of this combination */
        if (!empty($id_product_attribute)) {
            $minimalQuantity = (int) Attribute::getAttributeMinimalQty((int) $id_product_attribute);
        } else {
            $minimalQuantity = (int) $product->minimal_quantity;
        }
        if (!Validate::isLoadedObject($product)) {
            die(Tools::displayError());
        }
        if (isset(self::$_nbProducts[$this->id])) {
            unset(self::$_nbProducts[$this->id]);
        }
        if (isset(self::$_totalWeight[$this->id])) {
            unset(self::$_totalWeight[$this->id]);
        }
        if ((int) $quantity <= 0) {
            return $this->deleteProduct((int) $id_product, (int) $id_product_attribute, (int) $id_customization);
        } else {
            if (!$product->available_for_order or Configuration::get('PS_CATALOG_MODE')) {
                return false;
            } else {
                /* Check if the product is already in the cart */
                $result = $this->containsProduct((int) $id_product, (int) $id_product_attribute, (int) $id_customization);
                /* Update quantity if product already exist */
                if ($result) {
                    if ($operator == 'up') {
                        $result2 = Db::getInstance()->getRow('
						SELECT ' . (!empty($id_product_attribute) ? 'pa' : 'p') . '.`quantity`, p.`out_of_stock`
						FROM `' . _DB_PREFIX_ . 'product` p
						' . (!empty($id_product_attribute) ? 'LEFT JOIN `' . _DB_PREFIX_ . 'product_attribute` pa ON p.`id_product` = pa.`id_product`' : '') . '
						WHERE p.`id_product` = ' . (int) $id_product . (!empty($id_product_attribute) ? ' AND `id_product_attribute` = ' . (int) $id_product_attribute : ''));
                        $productQty = (int) $result2['quantity'];
                        $newQty = (int) $result['quantity'] + (int) $quantity;
                        $qty = '+ ' . (int) $quantity;
                        if (!Product::isAvailableWhenOutOfStock((int) $result2['out_of_stock'])) {
                            if ($newQty > $productQty) {
                                return false;
                            }
                        }
                    } elseif ($operator == 'down') {
                        $qty = '- ' . (int) $quantity;
                        $newQty = (int) $result['quantity'] - (int) $quantity;
                        if ($newQty < $minimalQuantity and $minimalQuantity > 1) {
                            return -1;
                        }
                    } else {
                        return false;
                    }
                    /* Delete product from cart */
                    if ($newQty <= 0) {
                        return $this->deleteProduct((int) $id_product, (int) $id_product_attribute, (int) $id_customization);
                    } else {
                        if ($newQty < $minimalQuantity) {
                            return -1;
                        } else {
                            Db::getInstance()->Execute('
					UPDATE `' . _DB_PREFIX_ . 'cart_product`
					SET `quantity` = `quantity` ' . $qty . ', `date_add` = NOW()
					WHERE `id_product` = ' . (int) $id_product . (!empty($id_product_attribute) ? ' AND `id_product_attribute` = ' . (int) $id_product_attribute : '') . '
					AND `id_cart` = ' . (int) $this->id . '
					LIMIT 1');
                        }
                    }
                } else {
                    $result2 = Db::getInstance()->getRow('
				SELECT ' . (!empty($id_product_attribute) ? 'pa' : 'p') . '.`quantity`, p.`out_of_stock`
				FROM `' . _DB_PREFIX_ . 'product` p
				' . (!empty($id_product_attribute) ? 'LEFT JOIN `' . _DB_PREFIX_ . 'product_attribute` pa ON p.`id_product` = pa.`id_product`' : '') . '
				WHERE p.`id_product` = ' . (int) $id_product . (!empty($id_product_attribute) ? ' AND `id_product_attribute` = ' . (int) $id_product_attribute : ''));
                    if (!Product::isAvailableWhenOutOfStock((int) $result2['out_of_stock'])) {
                        if ((int) $quantity > $result2['quantity']) {
                            return false;
                        }
                    }
                    if ((int) $quantity < $minimalQuantity) {
                        return -1;
                    }
                    if (!Db::getInstance()->AutoExecute(_DB_PREFIX_ . 'cart_product', array('id_product' => (int) $id_product, 'id_product_attribute' => (int) $id_product_attribute, 'id_cart' => (int) $this->id, 'quantity' => (int) $quantity, 'date_add' => date('Y-m-d H:i:s')), 'INSERT')) {
                        return false;
                    }
                }
            }
        }
        // refresh cache of self::_products
        $this->_products = $this->getProducts(true);
        $this->update(true);
        if ($product->customizable) {
            return $this->_updateCustomizationQuantity((int) $quantity, (int) $id_customization, (int) $id_product, (int) $id_product_attribute, $operator);
        } else {
            return true;
        }
    }
Example #20
0
 /**
  * @param array $products_id an array of product ids
  * @return array
  */
 protected function getOrderProducts(array $products_id)
 {
     $q_orders = 'SELECT o.id_order
     FROM ' . _DB_PREFIX_ . 'orders o
     LEFT JOIN ' . _DB_PREFIX_ . 'order_detail od ON (od.id_order = o.id_order)
     WHERE o.valid = 1 AND od.product_id IN (' . implode(',', $products_id) . ')';
     $orders = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($q_orders);
     $final_products_list = array();
     if (count($orders) > 0) {
         $list = '';
         foreach ($orders as $order) {
             $list .= (int) $order['id_order'] . ',';
         }
         $list = rtrim($list, ',');
         $list_product_ids = join(',', $products_id);
         if (Group::isFeatureActive()) {
             $sql_groups_join = '
             LEFT JOIN `' . _DB_PREFIX_ . 'category_product` cp ON (cp.`id_category` = product_shop.id_category_default
                 AND cp.id_product = product_shop.id_product)
             LEFT JOIN `' . _DB_PREFIX_ . 'category_group` cg ON (cp.`id_category` = cg.`id_category`)';
             $groups = FrontController::getCurrentCustomerGroups();
             $sql_groups_where = 'AND cg.`id_group` ' . (count($groups) ? 'IN (' . implode(',', $groups) . ')' : '=' . (int) Group::getCurrent()->id);
         }
         $order_products = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('
             SELECT DISTINCT od.product_id, pl.name, pl.description_short, pl.link_rewrite, p.reference, i.id_image, product_shop.show_price,
                 cl.link_rewrite category, p.ean13, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity
             FROM ' . _DB_PREFIX_ . 'order_detail od
             LEFT JOIN ' . _DB_PREFIX_ . 'product p ON (p.id_product = od.product_id)
             ' . Shop::addSqlAssociation('product', 'p') . (Combination::isFeatureActive() ? 'LEFT JOIN `' . _DB_PREFIX_ . 'product_attribute` pa
             ON (p.`id_product` = pa.`id_product`)
             ' . Shop::addSqlAssociation('product_attribute', 'pa', false, 'product_attribute_shop.`default_on` = 1') . '
             ' . Product::sqlStock('p', 'product_attribute_shop', false, $this->context->shop) : Product::sqlStock('p', 'product', false, $this->context->shop)) . '
             LEFT JOIN ' . _DB_PREFIX_ . 'product_lang pl ON (pl.id_product = od.product_id' . Shop::addSqlRestrictionOnLang('pl') . ')
             LEFT JOIN ' . _DB_PREFIX_ . 'category_lang cl ON (cl.id_category = product_shop.id_category_default' . Shop::addSqlRestrictionOnLang('cl') . ')
             LEFT JOIN ' . _DB_PREFIX_ . 'image i ON (i.id_product = od.product_id)
             ' . (Group::isFeatureActive() ? $sql_groups_join : '') . '
             WHERE od.id_order IN (' . $list . ')
             AND pl.id_lang = ' . (int) $this->context->language->id . '
             AND cl.id_lang = ' . (int) $this->context->language->id . '
             AND od.product_id NOT IN (' . $list_product_ids . ')
             AND i.cover = 1
             AND product_shop.active = 1
             ' . (Group::isFeatureActive() ? $sql_groups_where : '') . '
             ORDER BY RAND()
             LIMIT ' . (int) Configuration::get('CROSSSELLING_NBR'));
         $tax_calc = Product::getTaxCalculationMethod();
         foreach ($order_products as &$order_product) {
             $order_product['id_product'] = (int) $order_product['product_id'];
             $order_product['image'] = $this->context->link->getImageLink($order_product['link_rewrite'], (int) $order_product['product_id'] . '-' . (int) $order_product['id_image'], ImageType::getFormatedName('home'));
             $order_product['link'] = $this->context->link->getProductLink((int) $order_product['product_id'], $order_product['link_rewrite'], $order_product['category'], $order_product['ean13']);
             if (Configuration::get('CROSSSELLING_DISPLAY_PRICE') && ($tax_calc == 0 || $tax_calc == 2)) {
                 $order_product['displayed_price'] = Product::getPriceStatic((int) $order_product['product_id'], true, null);
             } elseif (Configuration::get('CROSSSELLING_DISPLAY_PRICE') && $tax_calc == 1) {
                 $order_product['displayed_price'] = Product::getPriceStatic((int) $order_product['product_id'], false, null);
             }
             $order_product['allow_oosp'] = Product::isAvailableWhenOutOfStock((int) $order_product['out_of_stock']);
             if (!isset($final_products_list[$order_product['product_id'] . '-' . $order_product['id_image']])) {
                 $final_products_list[$order_product['product_id'] . '-' . $order_product['id_image']] = $order_product;
             }
         }
     }
     return $final_products_list;
 }
Example #21
0
 /**
  * Assign template vars related to page content
  * @see FrontController::initContent()
  */
 public function initContent()
 {
     parent::initContent();
     //Clean compare product table
     CompareProduct::cleanCompareProducts('week');
     $hasProduct = false;
     if (!Configuration::get('PS_COMPARATOR_MAX_ITEM')) {
         return Tools::redirect('index.php?controller=404');
     }
     if (($product_list = Tools::getValue('compare_product_list')) && ($postProducts = isset($product_list) ? rtrim($product_list, '|') : '')) {
         $ids = array_unique(explode('|', $postProducts));
     } else {
         if (isset($this->context->cookie->id_compare)) {
             $ids = CompareProduct::getCompareProducts($this->context->cookie->id_compare);
         } else {
             $ids = null;
         }
     }
     if ($ids) {
         if (count($ids) > 0) {
             if (count($ids) > Configuration::get('PS_COMPARATOR_MAX_ITEM')) {
                 $ids = array_slice($ids, 0, Configuration::get('PS_COMPARATOR_MAX_ITEM'));
             }
             $listProducts = array();
             $listFeatures = array();
             foreach ($ids as $k => &$id) {
                 $curProduct = new Product((int) $id, true, $this->context->language->id);
                 if (!Validate::isLoadedObject($curProduct) || !$curProduct->active || !$curProduct->isAssociatedToShop()) {
                     if (isset($this->context->cookie->id_compare)) {
                         CompareProduct::removeCompareProduct($this->context->cookie->id_compare, $id);
                     }
                     unset($ids[$k]);
                     continue;
                 }
                 foreach ($curProduct->getFrontFeatures($this->context->language->id) as $feature) {
                     $listFeatures[$curProduct->id][$feature['id_feature']] = $feature['value'];
                 }
                 $cover = Product::getCover((int) $id);
                 $curProduct->id_image = Tools::htmlentitiesUTF8(Product::defineProductImage(array('id_image' => $cover['id_image'], 'id_product' => $id), $this->context->language->id));
                 $curProduct->allow_oosp = Product::isAvailableWhenOutOfStock($curProduct->out_of_stock);
                 $listProducts[] = $curProduct;
             }
             if (count($listProducts) > 0) {
                 $width = 80 / count($listProducts);
                 $hasProduct = true;
                 $ordered_features = Feature::getFeaturesForComparison($ids, $this->context->language->id);
                 $this->context->smarty->assign(array('ordered_features' => $ordered_features, 'product_features' => $listFeatures, 'products' => $listProducts, 'width' => $width, 'homeSize' => Image::getSize(ImageType::getFormatedName('home'))));
                 $this->context->smarty->assign('HOOK_EXTRA_PRODUCT_COMPARISON', Hook::exec('displayProductComparison', array('list_ids_product' => $ids)));
             } else {
                 if (isset($this->context->cookie->id_compare)) {
                     $object = new CompareProduct((int) $this->context->cookie->id_compare);
                     if (Validate::isLoadedObject($object)) {
                         $object->delete();
                     }
                 }
             }
         }
     }
     $this->context->smarty->assign('hasProduct', $hasProduct);
     $this->setTemplate(_PS_THEME_DIR_ . 'products-comparison.tpl');
 }
Example #22
0
 public static function getProductProperties($id_lang, $row, Context $context = null)
 {
     if (!$row['id_product']) {
         return false;
     }
     if ($context == null) {
         $context = Context::getContext();
     }
     // Product::getDefaultAttribute is only called if id_product_attribute is missing from the SQL query at the origin of it:
     // consider adding it in order to avoid unnecessary queries
     $row['allow_oosp'] = Product::isAvailableWhenOutOfStock($row['out_of_stock']);
     if (Combination::isFeatureActive() && (!isset($row['id_product_attribute']) || !$row['id_product_attribute']) && (isset($row['cache_default_attribute']) && ($ipa_default = $row['cache_default_attribute']) !== null || ($ipa_default = Product::getDefaultAttribute($row['id_product'], !$row['allow_oosp'])))) {
         $row['id_product_attribute'] = $ipa_default;
     }
     if (!Combination::isFeatureActive() || !isset($row['id_product_attribute'])) {
         $row['id_product_attribute'] = 0;
     }
     // Tax
     $usetax = Tax::excludeTaxeOption();
     $cache_key = $row['id_product'] . '-' . $row['id_product_attribute'] . '-' . $id_lang . '-' . (int) $usetax;
     if (isset($row['id_product_pack'])) {
         $cache_key .= '-pack' . $row['id_product_pack'];
     }
     if (isset(self::$producPropertiesCache[$cache_key])) {
         return self::$producPropertiesCache[$cache_key];
     }
     // Datas
     $row['category'] = Category::getLinkRewrite((int) $row['id_category_default'], (int) $id_lang);
     $row['link'] = $context->link->getProductLink((int) $row['id_product'], $row['link_rewrite'], $row['category'], $row['ean13']);
     $row['attribute_price'] = 0;
     if (isset($row['id_product_attribute']) && $row['id_product_attribute']) {
         $row['attribute_price'] = (double) Product::getProductAttributePrice($row['id_product_attribute']);
     }
     $row['price_tax_exc'] = Product::getPriceStatic((int) $row['id_product'], false, isset($row['id_product_attribute']) && !empty($row['id_product_attribute']) ? (int) $row['id_product_attribute'] : null, self::$_taxCalculationMethod == PS_TAX_EXC ? 2 : 6);
     if (self::$_taxCalculationMethod == PS_TAX_EXC) {
         $row['price_tax_exc'] = Tools::ps_round($row['price_tax_exc'], 2);
         $row['price'] = Product::getPriceStatic((int) $row['id_product'], true, isset($row['id_product_attribute']) && !empty($row['id_product_attribute']) ? (int) $row['id_product_attribute'] : null, 6);
         $row['price_without_reduction'] = Product::getPriceStatic((int) $row['id_product'], false, isset($row['id_product_attribute']) && !empty($row['id_product_attribute']) ? (int) $row['id_product_attribute'] : null, 2, null, false, false);
     } else {
         $row['price'] = Tools::ps_round(Product::getPriceStatic((int) $row['id_product'], true, isset($row['id_product_attribute']) && !empty($row['id_product_attribute']) ? (int) $row['id_product_attribute'] : null, 2), 2);
         $row['price_without_reduction'] = Product::getPriceStatic((int) $row['id_product'], true, isset($row['id_product_attribute']) && !empty($row['id_product_attribute']) ? (int) $row['id_product_attribute'] : null, 6, null, false, false);
     }
     $row['reduction'] = Product::getPriceStatic((int) $row['id_product'], (bool) $usetax, (int) $row['id_product_attribute'], 6, null, true, true, 1, true, null, null, null, $specific_prices);
     $row['specific_prices'] = $specific_prices;
     if ($row['id_product_attribute']) {
         $row['quantity_all_versions'] = $row['quantity'];
         $row['quantity'] = Product::getQuantity((int) $row['id_product'], $row['id_product_attribute'], isset($row['cache_is_pack']) ? $row['cache_is_pack'] : null);
     } else {
         $row['quantity'] = Product::getQuantity((int) $row['id_product']);
     }
     $row['id_image'] = Product::defineProductImage($row, $id_lang);
     $row['features'] = Product::getFrontFeaturesStatic((int) $id_lang, $row['id_product']);
     $row['attachments'] = array();
     if (!isset($row['cache_has_attachments']) || $row['cache_has_attachments']) {
         $row['attachments'] = Product::getAttachmentsStatic((int) $id_lang, $row['id_product']);
     }
     $row['virtual'] = !isset($row['is_virtual']) || $row['is_virtual'] ? 1 : 0;
     // Pack management
     $row['pack'] = !isset($row['cache_is_pack']) ? Pack::isPack($row['id_product']) : (int) $row['cache_is_pack'];
     $row['packItems'] = $row['pack'] ? Pack::getItemTable($row['id_product'], $id_lang) : array();
     $row['nopackprice'] = $row['pack'] ? Pack::noPackPrice($row['id_product']) : 0;
     if ($row['pack'] && !Pack::isInStock($row['id_product'])) {
         $row['quantity'] = 0;
     }
     self::$producPropertiesCache[$cache_key] = $row;
     return self::$producPropertiesCache[$cache_key];
 }
 protected function insertOrderItems(ShopgateOrder $order)
 {
     $this->log('start insertOrderItems()', ShopgateLogger::LOGTYPE_DEBUG);
     $products = array();
     //Check product quantitys
     $settings = Configuration::getMultiple(array('SHOPGATE_MIN_QUANTITY_CHECK', 'SHOPGATE_OUT_OF_STOCK_CHECK'));
     // complete weight of the order
     foreach ($order->getItems() as $i) {
         list($id_product, $id_product_attribute) = $this->getProductIdentifiers($i);
         if ($id_product == 0) {
             continue;
         }
         $wantedQty = (int) $i->getQuantity();
         $product = new Product($id_product, true, (int) Configuration::get('PS_LANG_DEFAULT'));
         $minQty = 1;
         if ((int) $id_product_attribute) {
             $stockQty = (int) Product::getQuantity((int) $id_product, (int) $id_product_attribute);
             if (version_compare(_PS_VERSION_, '1.4.0.7', '>=')) {
                 // this attribute doesn't exist before 1.4.0.7
                 $minQty = Attribute::getAttributeMinimalQty((int) $id_product_attribute);
             }
         } else {
             $stockQty = (int) Product::getQuantity((int) $id_product, NULL);
             if (version_compare(_PS_VERSION_, '1.4.0.2', '>=')) {
                 // this attribute doesn't exist before 1.4.0.2
                 $minQty = (int) $product->minimal_quantity;
             }
         }
         $oos_available = Product::isAvailableWhenOutOfStock($product->out_of_stock);
         $qtyDifference = 0;
         if (!$oos_available && $wantedQty > $stockQty) {
             $qtyDifference = $wantedQty - $stockQty;
         }
         $p = array();
         $p['id_product'] = (int) $id_product;
         $p['id_product_attribute'] = (int) $id_product_attribute;
         $p['name'] = $product->name;
         $p['quantity'] = $wantedQty;
         $p['quantity_in_stock'] = $stockQty;
         $p['quantity_difference'] = $qtyDifference;
         if (empty($p['name'])) {
             $p['name'] = $i->getName();
         }
         if ($oos_available) {
             $stockQty = $wantedQty;
         }
         if ((bool) $settings['SHOPGATE_MIN_QUANTITY_CHECK'] && $wantedQty < $minQty) {
             throw new ShopgateLibraryException(ShopgateLibraryException::PLUGIN_DATABASE_ERROR, 'Minimum quantity required', true);
         }
         if ((bool) $settings['SHOPGATE_OUT_OF_STOCK_CHECK'] && $wantedQty > $stockQty) {
             throw new ShopgateLibraryException(ShopgateLibraryException::PLUGIN_DATABASE_ERROR, 'Out of stock', true);
         }
         array_push($products, $p);
     }
     $this->log('end insertOrderItems()', ShopgateLogger::LOGTYPE_DEBUG);
     return $products;
 }
Example #24
0
    /**
     * Return cart products
     *
     * @result array Products
     */
    public function getProducts($refresh = false, $id_product = false)
    {
        if (!$this->id) {
            return array();
        }
        if ($this->_products and !$refresh) {
            return $this->_products;
        }
        $sql = '
		SELECT cp.`id_product_attribute`, cp.`id_product`, cp.`quantity` AS cart_quantity, pl.`name`,
		pl.`description_short`, pl.`available_now`, pl.`available_later`, p.`id_product`, p.`id_category_default`, p.`id_supplier`, p.`id_manufacturer`, p.`id_tax`, p.`on_sale`, p.`ecotax`,
		p.`quantity`, p.`price`, p.`reduction_price`, p.`reduction_percent`, p.`reduction_from`, p.`reduction_to`, p.`weight`, p.`out_of_stock`, p.`active`, p.`date_add`, p.`date_upd`,
		t.`id_tax`, tl.`name` AS tax, t.`rate`, pa.`price` AS price_attribute, pa.`quantity` AS quantity_attribute, 
        pa.`ecotax` AS ecotax_attr, i.`id_image`, il.`legend`, pl.`link_rewrite`, cl.`link_rewrite` AS category, CONCAT(cp.`id_product`, cp.`id_product_attribute`) AS unique_id,
        IF (IFNULL(pa.`reference`, \'\') = \'\', p.`reference`, pa.`reference`) AS reference, 
        IF (IFNULL(pa.`supplier_reference`, \'\') = \'\', p.`supplier_reference`, pa.`supplier_reference`) AS supplier_reference, 
        IF (IFNULL(pa.`weight`, 0) = \'\', p.`weight`, pa.`weight`) AS weight_attribute,
        IF (IFNULL(pa.`ean13`, \'\') = \'\', p.`ean13`, pa.`ean13`) AS ean13
		FROM `' . _DB_PREFIX_ . 'cart_product` cp
		LEFT JOIN `' . _DB_PREFIX_ . 'product` p ON p.`id_product` = cp.`id_product`
		LEFT JOIN `' . _DB_PREFIX_ . 'product_lang` pl ON (p.`id_product` = pl.`id_product` AND pl.`id_lang` = ' . intval($this->id_lang) . ')
		LEFT JOIN `' . _DB_PREFIX_ . 'product_attribute` pa ON (pa.`id_product_attribute` = cp.`id_product_attribute`)
		LEFT JOIN `' . _DB_PREFIX_ . 'tax` t ON (t.`id_tax` = p.`id_tax`)
		LEFT JOIN `' . _DB_PREFIX_ . 'tax_lang` tl ON (t.`id_tax` = tl.`id_tax` AND tl.`id_lang` = ' . intval($this->id_lang) . ')
		LEFT JOIN `' . _DB_PREFIX_ . 'product_attribute_image` pai ON (pai.`id_product_attribute` = cp.`id_product_attribute`)
		LEFT JOIN `' . _DB_PREFIX_ . 'image` i ON (i.`id_product` = cp.`id_product` AND (IF(pai.`id_image`, pai.`id_image` = i.`id_image`, i.`cover` = 1)))
		LEFT JOIN `' . _DB_PREFIX_ . 'image_lang` il ON (i.`id_image` = il.`id_image` AND il.`id_lang` = ' . intval($this->id_lang) . ')
		LEFT JOIN `' . _DB_PREFIX_ . 'category_lang` cl ON (p.`id_category_default` = cl.`id_category` AND cl.`id_lang` = ' . intval($this->id_lang) . ')
		WHERE `id_cart` = ' . intval($this->id) . '
		' . ($id_product ? ' AND cp.`id_product` = ' . intval($id_product) : '') . '
		AND p.`id_product` IS NOT NULL
		GROUP BY unique_id
		ORDER BY cp.date_add ASC';
        $result = Db::getInstance()->ExecuteS($sql);
        /* Modify SQL results */
        $products = array();
        if (empty($result)) {
            return array();
        }
        foreach ($result as $k => $row) {
            if (isset($row['ecotax_attr']) and $row['ecotax_attr'] > 0) {
                $row['ecotax'] = floatval($row['ecotax_attr']);
            }
            $row['stock_quantity'] = intval($row['quantity']);
            $row['weight'] = $row['weight_attribute'];
            $row['quantity'] = intval($row['cart_quantity']);
            $row['price'] = Product::getPriceStatic(intval($row['id_product']), false, isset($row['id_product_attribute']) ? intval($row['id_product_attribute']) : NULL, 6, NULL, false, true, intval($row['quantity']));
            $row['price_wt'] = Product::getPriceStatic(intval($row['id_product']), true, isset($row['id_product_attribute']) ? intval($row['id_product_attribute']) : NULL, 6, NULL, false, true, intval($row['quantity']));
            $row['total'] = $row['price'] * intval($row['quantity']);
            $row['total_wt'] = $row['price_wt'] * intval($row['quantity']);
            $row['id_image'] = Product::defineProductImage($row);
            $row['allow_oosp'] = Product::isAvailableWhenOutOfStock($row['out_of_stock']);
            $row['features'] = Product::getFeaturesStatic(intval($row['id_product']));
            /* Add attributes to the SQL result if needed */
            if (isset($row['id_product_attribute']) and intval($row['id_product_attribute'])) {
                $result2 = Db::getInstance()->ExecuteS('
				SELECT agl.`public_name` AS public_group_name, al.`name` AS attribute_name
				FROM `' . _DB_PREFIX_ . 'product_attribute_combination` pac
				LEFT JOIN `' . _DB_PREFIX_ . 'attribute` a ON a.`id_attribute` = pac.`id_attribute`
				LEFT JOIN `' . _DB_PREFIX_ . 'attribute_group` ag ON ag.`id_attribute_group` = a.`id_attribute_group`
				LEFT JOIN `' . _DB_PREFIX_ . 'attribute_lang` al ON (a.`id_attribute` = al.`id_attribute` AND al.`id_lang` = ' . intval($this->id_lang) . ')
				LEFT JOIN `' . _DB_PREFIX_ . 'attribute_group_lang` agl ON (ag.`id_attribute_group` = agl.`id_attribute_group` AND agl.`id_lang` = ' . intval($this->id_lang) . ')
				WHERE pac.`id_product_attribute` = ' . intval($row['id_product_attribute']));
                $attributesList = '';
                $attributesListSmall = '';
                if ($result2) {
                    foreach ($result2 as $k2 => $row2) {
                        $attributesList .= $row2['public_group_name'] . ' : ' . $row2['attribute_name'] . ', ';
                        $attributesListSmall .= $row2['attribute_name'] . ', ';
                    }
                }
                $attributesList = rtrim($attributesList, ', ');
                $attributesListSmall = rtrim($attributesListSmall, ', ');
                $row['attributes'] = $attributesList;
                $row['attributes_small'] = $attributesListSmall;
                $row['stock_quantity'] = $row['quantity_attribute'];
            }
            $products[] = $row;
        }
        $this->_products = $products;
        return $this->_products;
    }
Example #25
0
 public function ajaxProcessUpdateQty()
 {
     if ($this->tabAccess['edit'] === '1') {
         $errors = array();
         if (!$this->context->cart->id) {
             return;
         }
         if ($this->context->cart->OrderExists()) {
             $errors[] = Tools::displayError('An order has already been placed with this cart.');
         } elseif (!($id_product = (int) Tools::getValue('id_product')) || !($product = new Product((int) $id_product, true, $this->context->language->id))) {
             $errors[] = Tools::displayError('Invalid product');
         } elseif (!($qty = Tools::getValue('qty')) || $qty == 0) {
             $errors[] = Tools::displayError('Invalid quantity');
         }
         // Don't try to use a product if not instanciated before due to errors
         if (isset($product) && $product->id) {
             if (($id_product_attribute = Tools::getValue('id_product_attribute')) != 0) {
                 if (!Product::isAvailableWhenOutOfStock($product->out_of_stock) && !Attribute::checkAttributeQty((int) $id_product_attribute, (int) $qty)) {
                     $errors[] = Tools::displayError('There is not enough product in stock.');
                 }
             } else {
                 if (!$product->checkQty((int) $qty)) {
                     $errors[] = Tools::displayError('There is not enough product in stock.');
                 }
             }
             if (!($id_customization = (int) Tools::getValue('id_customization', 0)) && !$product->hasAllRequiredCustomizableFields()) {
                 $errors[] = Tools::displayError('Please fill in all the required fields.');
             }
             $this->context->cart->save();
         } else {
             $errors[] = Tools::displayError('This product cannot be added to the cart.');
         }
         if (!count($errors)) {
             if ((int) $qty < 0) {
                 $qty = str_replace('-', '', $qty);
                 $operator = 'down';
             } else {
                 $operator = 'up';
             }
             if (!($qty_upd = $this->context->cart->updateQty($qty, $id_product, (int) $id_product_attribute, (int) $id_customization, $operator))) {
                 $errors[] = Tools::displayError('You already have the maximum quantity available for this product.');
             } elseif ($qty_upd < 0) {
                 $minimal_qty = $id_product_attribute ? Attribute::getAttributeMinimalQty((int) $id_product_attribute) : $product->minimal_quantity;
                 $errors[] = sprintf(Tools::displayError('You must add a minimum quantity of %d', false), $minimal_qty);
             }
         }
         echo Tools::jsonEncode(array_merge($this->ajaxReturnVars(), array('errors' => $errors)));
     }
 }
Example #26
0
     }
     if (!isset($groups[$row['id_attribute_group']]['attributes_quantity'][$row['id_attribute']])) {
         $groups[$row['id_attribute_group']]['attributes_quantity'][$row['id_attribute']] = 0;
     }
     $groups[$row['id_attribute_group']]['attributes_quantity'][$row['id_attribute']] += intval($row['quantity']);
     $combinations[$row['id_product_attribute']]['attributes_values'][$row['id_attribute_group']] = $row['attribute_name'];
     $combinations[$row['id_product_attribute']]['attributes'][] = intval($row['id_attribute']);
     $combinations[$row['id_product_attribute']]['price'] = floatval($row['price']);
     $combinations[$row['id_product_attribute']]['ecotax'] = floatval($row['ecotax']);
     $combinations[$row['id_product_attribute']]['weight'] = floatval($row['weight']);
     $combinations[$row['id_product_attribute']]['quantity'] = intval($row['quantity']);
     $combinations[$row['id_product_attribute']]['reference'] = $row['reference'];
     $combinations[$row['id_product_attribute']]['id_image'] = isset($combinationImages[$row['id_product_attribute']][0]['id_image']) ? $combinationImages[$row['id_product_attribute']][0]['id_image'] : -1;
 }
 //wash attributes list (if some attributes are unavailables and if allowed to wash it)
 if (!Product::isAvailableWhenOutOfStock($product->out_of_stock) && Configuration::get('PS_DISP_UNAVAILABLE_ATTR') == 0) {
     foreach ($groups as &$group) {
         foreach ($group['attributes_quantity'] as $key => &$quantity) {
             if (!$quantity) {
                 unset($group['attributes'][$key]);
             }
         }
     }
 }
 foreach ($groups as &$group) {
     natcasesort($group['attributes']);
 }
 foreach ($combinations as $id_product_attribute => $comb) {
     $attributeList = '';
     foreach ($comb['attributes'] as $id_attribute) {
         $attributeList .= '\'' . intval($id_attribute) . '\',';
Example #27
0
    /**
     * Update product quantity
     *
     * @param integer $quantity Quantity to add (or substract)
     * @param integer $id_product Product ID
     * @param integer $id_product_attribute Attribute ID if needed
     * @param string $operator Indicate if quantity must be increased or decreased
     */
    public function updateQty($quantity, $id_product, $id_product_attribute = null, $id_customization = false, $operator = 'up', $id_address_delivery = 0, Shop $shop = null, $auto_add_cart_rule = true)
    {
        if (!$shop) {
            $shop = Context::getContext()->shop;
        }
        if (Context::getContext()->customer->id) {
            if ($id_address_delivery == 0 && (int) $this->id_address_delivery) {
                // The $id_address_delivery is null, use the cart delivery address
                $id_address_delivery = $this->id_address_delivery;
            } elseif ($id_address_delivery == 0) {
                // The $id_address_delivery is null, get the default customer address
                $id_address_delivery = (int) Address::getFirstCustomerAddressId((int) Context::getContext()->customer->id);
            } elseif (!Customer::customerHasAddress(Context::getContext()->customer->id, $id_address_delivery)) {
                // The $id_address_delivery must be linked with customer
                $id_address_delivery = 0;
            }
        }
        $quantity = (int) $quantity;
        $id_product = (int) $id_product;
        $id_product_attribute = (int) $id_product_attribute;
        $product = new Product($id_product, false, Configuration::get('PS_LANG_DEFAULT'), $shop->id);
        if ($id_product_attribute) {
            $combination = new Combination((int) $id_product_attribute);
            if ($combination->id_product != $id_product) {
                return false;
            }
        }
        /* If we have a product combination, the minimal quantity is set with the one of this combination */
        if (!empty($id_product_attribute)) {
            $minimal_quantity = (int) Attribute::getAttributeMinimalQty($id_product_attribute);
        } else {
            $minimal_quantity = (int) $product->minimal_quantity;
        }
        if (!Validate::isLoadedObject($product)) {
            die(Tools::displayError());
        }
        if (isset(self::$_nbProducts[$this->id])) {
            unset(self::$_nbProducts[$this->id]);
        }
        if (isset(self::$_totalWeight[$this->id])) {
            unset(self::$_totalWeight[$this->id]);
        }
        if ((int) $quantity <= 0) {
            return $this->deleteProduct($id_product, $id_product_attribute, (int) $id_customization);
        } elseif (!$product->available_for_order || Configuration::get('PS_CATALOG_MODE')) {
            return false;
        } else {
            /* Check if the product is already in the cart */
            $result = $this->containsProduct($id_product, $id_product_attribute, (int) $id_customization, (int) $id_address_delivery);
            /* Update quantity if product already exist */
            if ($result) {
                if ($operator == 'up') {
                    $sql = 'SELECT stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity
							FROM ' . _DB_PREFIX_ . 'product p
							' . Product::sqlStock('p', $id_product_attribute, true, $shop) . '
							WHERE p.id_product = ' . $id_product;
                    $result2 = Db::getInstance()->getRow($sql);
                    $product_qty = (int) $result2['quantity'];
                    // Quantity for product pack
                    if (Pack::isPack($id_product)) {
                        $product_qty = Pack::getQuantity($id_product, $id_product_attribute);
                    }
                    $new_qty = (int) $result['quantity'] + (int) $quantity;
                    $qty = '+ ' . (int) $quantity;
                    if (!Product::isAvailableWhenOutOfStock((int) $result2['out_of_stock'])) {
                        if ($new_qty > $product_qty) {
                            return false;
                        }
                    }
                } else {
                    if ($operator == 'down') {
                        $qty = '- ' . (int) $quantity;
                        $new_qty = (int) $result['quantity'] - (int) $quantity;
                        if ($new_qty < $minimal_quantity && $minimal_quantity > 1) {
                            return -1;
                        }
                    } else {
                        return false;
                    }
                }
                /* Delete product from cart */
                if ($new_qty <= 0) {
                    return $this->deleteProduct((int) $id_product, (int) $id_product_attribute, (int) $id_customization);
                } else {
                    if ($new_qty < $minimal_quantity) {
                        return -1;
                    } else {
                        Db::getInstance()->execute('
						UPDATE `' . _DB_PREFIX_ . 'cart_product`
						SET `quantity` = `quantity` ' . $qty . ', `date_add` = NOW()
						WHERE `id_product` = ' . (int) $id_product . (!empty($id_product_attribute) ? ' AND `id_product_attribute` = ' . (int) $id_product_attribute : '') . '
						AND `id_cart` = ' . (int) $this->id . (Configuration::get('PS_ALLOW_MULTISHIPPING') && $this->isMultiAddressDelivery() ? ' AND `id_address_delivery` = ' . (int) $id_address_delivery : '') . '
						LIMIT 1');
                    }
                }
            } elseif ($operator == 'up') {
                $sql = 'SELECT stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity
						FROM ' . _DB_PREFIX_ . 'product p
						' . Product::sqlStock('p', $id_product_attribute, true, $shop) . '
						WHERE p.id_product = ' . $id_product;
                $result2 = Db::getInstance()->getRow($sql);
                // Quantity for product pack
                if (Pack::isPack($id_product)) {
                    $result2['quantity'] = Pack::getQuantity($id_product, $id_product_attribute);
                }
                if (!Product::isAvailableWhenOutOfStock((int) $result2['out_of_stock'])) {
                    if ((int) $quantity > $result2['quantity']) {
                        return false;
                    }
                }
                if ((int) $quantity < $minimal_quantity) {
                    return -1;
                }
                $result_add = Db::getInstance()->insert('cart_product', array('id_product' => (int) $id_product, 'id_product_attribute' => (int) $id_product_attribute, 'id_cart' => (int) $this->id, 'id_address_delivery' => (int) $id_address_delivery, 'id_shop' => $shop->id, 'quantity' => (int) $quantity, 'date_add' => date('Y-m-d H:i:s')));
                if (!$result_add) {
                    return false;
                }
            }
        }
        // refresh cache of self::_products
        $this->_products = $this->getProducts(true);
        $this->update(true);
        $context = Context::getContext()->cloneContext();
        $context->cart = $this;
        Cache::clean('getContextualValue_*');
        if ($auto_add_cart_rule) {
            CartRule::autoAddToCart($context);
        }
        if ($product->customizable) {
            return $this->_updateCustomizationQuantity((int) $quantity, (int) $id_customization, (int) $id_product, (int) $id_product_attribute, (int) $id_address_delivery, $operator);
        } else {
            return true;
        }
    }
Example #28
0
 public static function getProductProperties($id_lang, $row)
 {
     if (!$row['id_product']) {
         return false;
     }
     // Product::getDefaultAttribute is only called if id_product_attribute is missing from the SQL query at the origin of it: consider adding it in order to avoid unnecessary queries
     $row['allow_oosp'] = Product::isAvailableWhenOutOfStock($row['out_of_stock']);
     if ((!isset($row['id_product_attribute']) or !$row['id_product_attribute']) and (isset($row['cache_default_attribute']) and ($ipa_default = $row['cache_default_attribute']) !== NULL or $ipa_default = Product::getDefaultAttribute($row['id_product'], !$row['allow_oosp']))) {
         $row['id_product_attribute'] = $ipa_default;
     }
     if (!isset($row['id_product_attribute'])) {
         $row['id_product_attribute'] = 0;
     }
     // Tax
     $usetax = Tax::excludeTaxeOption();
     $cacheKey = $row['id_product'] . '-' . $row['id_product_attribute'] . '-' . $id_lang . '-' . (int) $usetax;
     if (array_key_exists($cacheKey, self::$producPropertiesCache)) {
         return self::$producPropertiesCache[$cacheKey];
     }
     // Datas
     $link = new Link();
     $row['category'] = Category::getLinkRewrite((int) $row['id_category_default'], (int) $id_lang);
     $row['link'] = $link->getProductLink((int) $row['id_product'], $row['link_rewrite'], $row['category'], $row['ean13']);
     $row['attribute_price'] = (isset($row['id_product_attribute']) and $row['id_product_attribute']) ? (double) Product::getProductAttributePrice($row['id_product_attribute']) : 0;
     $row['price_tax_exc'] = Product::getPriceStatic((int) $row['id_product'], false, (isset($row['id_product_attribute']) and !empty($row['id_product_attribute'])) ? (int) $row['id_product_attribute'] : NULL, self::$_taxCalculationMethod == PS_TAX_EXC ? 2 : 6);
     if (self::$_taxCalculationMethod == PS_TAX_EXC) {
         $row['price_tax_exc'] = Tools::ps_round($row['price_tax_exc'], 2);
         $row['price'] = Product::getPriceStatic((int) $row['id_product'], true, (isset($row['id_product_attribute']) and !empty($row['id_product_attribute'])) ? (int) $row['id_product_attribute'] : NULL, 6);
         $row['price_without_reduction'] = Product::getPriceStatic((int) $row['id_product'], false, (isset($row['id_product_attribute']) and !empty($row['id_product_attribute'])) ? (int) $row['id_product_attribute'] : NULL, 2, NULL, false, false);
     } else {
         $row['price'] = Tools::ps_round(Product::getPriceStatic((int) $row['id_product'], true, (isset($row['id_product_attribute']) and !empty($row['id_product_attribute'])) ? (int) $row['id_product_attribute'] : NULL, 2), 2);
         $row['price_without_reduction'] = Product::getPriceStatic((int) $row['id_product'], true, (isset($row['id_product_attribute']) and !empty($row['id_product_attribute'])) ? (int) $row['id_product_attribute'] : NULL, 6, NULL, false, false);
     }
     $row['reduction'] = Product::getPriceStatic((int) $row['id_product'], (bool) $usetax, (int) $row['id_product_attribute'], 6, NULL, true, true, 1, true, NULL, NULL, NULL, $specific_prices);
     $row['specific_prices'] = $specific_prices;
     if ($row['id_product_attribute']) {
         $row['quantity_all_versions'] = $row['quantity'];
         $row['quantity'] = Product::getQuantity((int) $row['id_product'], $row['id_product_attribute'], isset($row['cache_is_pack']) ? $row['cache_is_pack'] : NULL);
     }
     $row['id_image'] = Product::defineProductImage($row, $id_lang);
     $row['features'] = Product::getFrontFeaturesStatic((int) $id_lang, $row['id_product']);
     $row['attachments'] = (!isset($row['cache_has_attachments']) or $row['cache_has_attachments']) ? Product::getAttachmentsStatic((int) $id_lang, $row['id_product']) : array();
     // Pack management
     $row['pack'] = !isset($row['cache_is_pack']) ? Pack::isPack($row['id_product']) : (int) $row['cache_is_pack'];
     $row['packItems'] = $row['pack'] ? Pack::getItemTable($row['id_product'], $id_lang) : array();
     $row['nopackprice'] = $row['pack'] ? Pack::noPackPrice($row['id_product']) : 0;
     if ($row['pack'] and !Pack::isInStock($row['id_product'])) {
         $row['quantity'] = 0;
     }
     self::$producPropertiesCache[$cacheKey] = $row;
     return self::$producPropertiesCache[$cacheKey];
 }
 /**
  * Assign template vars related to attribute groups and colors
  */
 protected function assignAttributesGroups()
 {
     $colors = array();
     $groups = array();
     // @todo (RM) should only get groups and not all declination ?
     $attributes_groups = $this->product->getAttributesGroups($this->context->language->id);
     if (is_array($attributes_groups) && $attributes_groups) {
         $combination_images = $this->product->getCombinationImages($this->context->language->id);
         $combination_prices_set = array();
         foreach ($attributes_groups as $k => $row) {
             // Color management
             if (isset($row['attribute_color']) && $row['attribute_color'] || file_exists(_PS_COL_IMG_DIR_ . $row['id_attribute'] . '.jpg')) {
                 $colors[$row['id_attribute']]['value'] = $row['attribute_color'];
                 $colors[$row['id_attribute']]['name'] = $row['attribute_name'];
                 if (!isset($colors[$row['id_attribute']]['attributes_quantity'])) {
                     $colors[$row['id_attribute']]['attributes_quantity'] = 0;
                 }
                 $colors[$row['id_attribute']]['attributes_quantity'] += (int) $row['quantity'];
             }
             if (!isset($groups[$row['id_attribute_group']])) {
                 $groups[$row['id_attribute_group']] = array('name' => $row['public_group_name'], 'group_type' => $row['group_type'], 'default' => -1);
             }
             $groups[$row['id_attribute_group']]['attributes'][$row['id_attribute']] = $row['attribute_name'];
             if ($row['default_on'] && $groups[$row['id_attribute_group']]['default'] == -1) {
                 $groups[$row['id_attribute_group']]['default'] = (int) $row['id_attribute'];
             }
             if (!isset($groups[$row['id_attribute_group']]['attributes_quantity'][$row['id_attribute']])) {
                 $groups[$row['id_attribute_group']]['attributes_quantity'][$row['id_attribute']] = 0;
             }
             $groups[$row['id_attribute_group']]['attributes_quantity'][$row['id_attribute']] += (int) $row['quantity'];
             if ($row['available_date'] != '0000-00-00 00:00:00' && $row['available_date'] != '0000-00-00') {
                 $available_date = Tools::displayDate($row['available_date'], $this->context->language->id);
             } else {
                 $available_date = $row['available_date'];
             }
             $combinations[$row['id_product_attribute']]['attributes_values'][$row['id_attribute_group']] = $row['attribute_name'];
             $combinations[$row['id_product_attribute']]['attributes'][] = (int) $row['id_attribute'];
             $combinations[$row['id_product_attribute']]['price'] = (double) $row['price'];
             // Call getPriceStatic in order to set $combination_specific_price
             if (!isset($combination_prices_set[(int) $row['id_product_attribute']])) {
                 Product::getPriceStatic((int) $this->product->id, false, $row['id_product_attribute'], 6, null, false, true, 1, false, null, null, null, $combination_specific_price);
                 $combination_prices_set[(int) $row['id_product_attribute']] = true;
                 $combinations[$row['id_product_attribute']]['specific_price'] = $combination_specific_price;
             }
             $combinations[$row['id_product_attribute']]['ecotax'] = (double) $row['ecotax'];
             $combinations[$row['id_product_attribute']]['weight'] = (double) $row['weight'];
             $combinations[$row['id_product_attribute']]['quantity'] = (int) $row['quantity'];
             $combinations[$row['id_product_attribute']]['reference'] = $row['reference'];
             $combinations[$row['id_product_attribute']]['unit_impact'] = $row['unit_price_impact'];
             $combinations[$row['id_product_attribute']]['minimal_quantity'] = $row['minimal_quantity'];
             $combinations[$row['id_product_attribute']]['available_date'] = $available_date;
             if (isset($combination_images[$row['id_product_attribute']][0]['id_image'])) {
                 $combinations[$row['id_product_attribute']]['id_image'] = $combination_images[$row['id_product_attribute']][0]['id_image'];
             } else {
                 $combinations[$row['id_product_attribute']]['id_image'] = -1;
             }
         }
         // wash attributes list (if some attributes are unavailables and if allowed to wash it)
         if (!Product::isAvailableWhenOutOfStock($this->product->out_of_stock) && Configuration::get('PS_DISP_UNAVAILABLE_ATTR') == 0) {
             foreach ($groups as &$group) {
                 foreach ($group['attributes_quantity'] as $key => &$quantity) {
                     if (!$quantity) {
                         unset($group['attributes'][$key]);
                     }
                 }
             }
             foreach ($colors as $key => $color) {
                 if (!$color['attributes_quantity']) {
                     unset($colors[$key]);
                 }
             }
         }
         foreach ($combinations as $id_product_attribute => $comb) {
             $attribute_list = '';
             foreach ($comb['attributes'] as $id_attribute) {
                 $attribute_list .= '\'' . (int) $id_attribute . '\',';
             }
             $attribute_list = rtrim($attribute_list, ',');
             $combinations[$id_product_attribute]['list'] = $attribute_list;
         }
         $this->context->smarty->assign(array('groups' => $groups, 'combinations' => $combinations, 'colors' => count($colors) ? $colors : false, 'combinationImages' => $combination_images));
     }
 }
Example #30
0
 public static function getProductProperties($id_lang, $row)
 {
     if (!$row['id_product']) {
         return false;
     }
     // Product::getDefaultAttribute is only called if id_product_attribute is missing from the SQL query at the origin of it: consider adding it in order to avoid unnecessary queries
     $row['allow_oosp'] = Product::isAvailableWhenOutOfStock($row['out_of_stock']);
     if ((!isset($row['id_product_attribute']) or !$row['id_product_attribute']) and (isset($row['cache_default_attribute']) and ($ipa_default = $row['cache_default_attribute']) !== NULL or $ipa_default = Product::getDefaultAttribute($row['id_product'], !$row['allow_oosp']))) {
         $row['id_product_attribute'] = $ipa_default;
     }
     if (!isset($row['id_product_attribute'])) {
         $row['id_product_attribute'] = 0;
     }
     // Tax
     $usetax = Tax::excludeTaxeOption();
     $cacheKey = $row['id_product'] . '-' . $row['id_product_attribute'] . '-' . $id_lang . '-' . (int) $usetax;
     if (array_key_exists($cacheKey, self::$producPropertiesCache)) {
         return self::$producPropertiesCache[$cacheKey];
     }
     // Datas
     $row['category'] = Category::getLinkRewrite((int) $row['id_category_default'], (int) $id_lang);
     if (!preg_match("/^1.3.*/", _PS_VERSION_)) {
         // Not available in Prestashop 1.3.x
         $row['reduction'] = Product::getPriceStatic((int) $row['id_product'], (bool) $usetax, (int) $row['id_product_attribute'], 6, NULL, true, true, 1, true, NULL, NULL, NULL, $specific_prices);
         $row['specific_prices'] = $specific_prices;
     }
     if ($row['id_product_attribute']) {
         $row['quantity_all_versions'] = $row['quantity'];
         $row['quantity'] = Product::getQuantity((int) $row['id_product'], $row['id_product_attribute'], isset($row['cache_is_pack']) ? $row['cache_is_pack'] : NULL);
     }
     $row['id_image'] = Product::defineProductImage($row, $id_lang);
     $row['features'] = Product::getFrontFeaturesStatic((int) $id_lang, $row['id_product']);
     // Pack management
     $row['pack'] = !isset($row['cache_is_pack']) ? Pack::isPack($row['id_product']) : (int) $row['cache_is_pack'];
     $row['packItems'] = $row['pack'] ? Pack::getItemTable($row['id_product'], $id_lang) : array();
     $row['nopackprice'] = $row['pack'] ? Pack::noPackPrice($row['id_product']) : 0;
     if ($row['pack'] and !Pack::isInStock($row['id_product'])) {
         $row['quantity'] = 0;
     }
     $sql_combination = '
   SELECT pa.id_product_attribute, pa.price, pa.quantity, pa.id_product
   FROM `' . _DB_PREFIX_ . 'product` p
   LEFT JOIN `' . _DB_PREFIX_ . 'product_attribute` pa ON (p.`id_product` = pa.`id_product`)
   WHERE p.`id_product` =' . $row['id_product'];
     $result_combination = ProductExtended::getDbInstance()->ExecuteS($sql_combination);
     $row['combinations'] = array();
     if ($result_combination) {
         foreach ($result_combination as $combination) {
             $combination['attributes'] = array();
             /* New combinations system Prestashop 1.5.x */
             if (!preg_match("/^1.(3|4).*/", _PS_VERSION_)) {
                 $combination['quantity'] = StockAvailable::getQuantityAvailableByProduct($row['id_product'], $combination['id_product_attribute']);
             }
             if (isset($combination['id_product_attribute'])) {
                 $sql_attribute = '
         SELECT pa.id_product_attribute, agl.id_attribute_group, al.name as name_value, agl.name as name_option
         FROM `' . _DB_PREFIX_ . 'product_attribute` pa
         LEFT JOIN `' . _DB_PREFIX_ . 'product_attribute_combination` pac ON (pac.`id_product_attribute` = pa.`id_product_attribute`)
         LEFT JOIN `' . _DB_PREFIX_ . 'attribute` a ON (a.`id_attribute` = pac.`id_attribute`)
         LEFT JOIN `' . _DB_PREFIX_ . 'attribute_lang` al ON (al.`id_attribute` = a.`id_attribute` AND al.`id_lang` = ' . $id_lang . ')
         LEFT JOIN `' . _DB_PREFIX_ . 'attribute_group` ag ON (ag.`id_attribute_group` = a.`id_attribute_group`)
         LEFT JOIN `' . _DB_PREFIX_ . 'attribute_group_lang` agl ON (agl.`id_attribute_group` = ag.`id_attribute_group` AND agl.`id_lang` = ' . $id_lang . ')
         WHERE pa.`id_product_attribute` =' . $combination['id_product_attribute'];
                 $result_attribute = ProductExtended::getDbInstance()->ExecuteS($sql_attribute);
                 if ($result_attribute) {
                     foreach ($result_attribute as $attribute) {
                         array_push($combination['attributes'], $attribute);
                     }
                 }
                 array_push($row['combinations'], $combination);
             }
         }
     }
     $sql_image = '
   SELECT DISTINCT i.*, pl.link_rewrite
   FROM `' . _DB_PREFIX_ . 'product` p
   LEFT JOIN `' . _DB_PREFIX_ . 'image` i ON (p.`id_product` = i.`id_product`)
   LEFT JOIN `' . _DB_PREFIX_ . 'product_lang` pl ON (p.`id_product` = pl.`id_product`)
   WHERE p.`id_product` =' . $row['id_product'];
     $result_image = ProductExtended::getDbInstance()->ExecuteS($sql_image);
     $row['images'] = array();
     $lang = new Language($id_lang);
     $row['url_locale'] = $lang->iso_code;
     if ($result_image) {
         $link = preg_match("/^1.(3|4).*/", _PS_VERSION_) ? new Link() : Context::getContext()->link;
         foreach ($result_image as $image) {
             if (!preg_match("/^1.3.*/", _PS_VERSION_)) {
                 // Image URL gives relative version using 1.3.x-
                 $image['image_url'] = $link->getImageLink($image['link_rewrite'], $image['id_product'] . '-' . $image['id_image']);
             }
             array_push($row['images'], $image);
         }
     }
     self::$producPropertiesCache[$cacheKey] = $row;
     return self::$producPropertiesCache[$cacheKey];
 }