diff --git a/classes/Dispatcher.php b/classes/Dispatcher.php index a56e20192..9886bbed1 100644 --- a/classes/Dispatcher.php +++ b/classes/Dispatcher.php @@ -381,8 +381,9 @@ class DispatcherCore * @param string $route_id Name the route * @param array $params * @param bool $use_routes If false, don't use to create this url + * @param string $anchor Optional anchor to add at the end of this url */ - public function createUrl($route_id, $params = array(), $use_routes = true) + public function createUrl($route_id, $params = array(), $use_routes = true, $anchor = '') { if (!is_array($params)) die('Dispatcher::createUrl() $params must be an array'); @@ -390,7 +391,7 @@ class DispatcherCore if (!isset($this->routes[$route_id])) { $query = http_build_query($params); - return ($route_id == 'index') ? 'index.php'.(($query) ? '?'.$query : '') : 'index.php?controller='.$route_id.(($query) ? '&'.$query : ''); + return ($route_id == 'index') ? 'index.php'.(($query) ? '?'.$query : '') : 'index.php?controller='.$route_id.(($query) ? '&'.$query : '').$anchor; } $route = $this->routes[$route_id]; @@ -427,7 +428,7 @@ class DispatcherCore else $url = 'index.php?controller='.$route['controller'].(($query_params) ? '&'.http_build_query($query_params) : ''); - return $url; + return $url.$anchor; } /** diff --git a/classes/Link.php b/classes/Link.php index 9827e479a..24b8384d0 100644 --- a/classes/Link.php +++ b/classes/Link.php @@ -68,9 +68,10 @@ class LinkCore * @param string $ean13 * @param int $id_lang * @param int $id_shop (since 1.5.0) ID shop need to be used when we generate a product link for a product in a cart + * @param int $ipa ID product attribute * @return string */ - public function getProductLink($product, $alias = null, $category = null, $ean13 = null, $id_lang = null, $id_shop = null) + public function getProductLink($product, $alias = null, $category = null, $ean13 = null, $id_lang = null, $id_shop = null, $ipa = 0) { $dispatcher = Dispatcher::getInstance(); $url = _PS_BASE_URL_.__PS_BASE_URI__; @@ -107,7 +108,12 @@ class LinkCore if ($dispatcher->hasKeyword('product_rule', 'tags')) $params['tags'] = Tools::str2url($product->getTags($id_lang)); - return $url.$dispatcher->createUrl('product_rule', $params, $this->allow); + if ($ipa) + $anchor = $product->getAnchor($ipa); + else + $anchor = ''; + + return $url.$dispatcher->createUrl('product_rule', $params, $this->allow, $anchor); } /** diff --git a/classes/Product.php b/classes/Product.php index c7e4f7ff1..e976352c2 100644 --- a/classes/Product.php +++ b/classes/Product.php @@ -3641,44 +3641,224 @@ class ProductCore extends ObjectModel /** * Get label by lang and value by lang too + * @todo Remove existing module condition * @param int $id_product * @param int $product_attribute_id + * @return array */ public static function getAttributesParams($id_product, $id_product_attribute) { - return Db::getInstance()->executeS(' - SELECT al.`name`, agl.`name` as `group` - FROM `'._DB_PREFIX_.'attribute` a - LEFT JOIN `'._DB_PREFIX_.'attribute_lang` al - ON (al.`id_attribute` = a.`id_attribute` AND al.`id_lang` = '.(int)Context::getContext()->language->id.') - LEFT JOIN `'._DB_PREFIX_.'product_attribute_combination` pac - ON (pac.`id_attribute` = a.`id_attribute`) - LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa - ON (pa.`id_product_attribute` = pac.`id_product_attribute`) - LEFT JOIN `'._DB_PREFIX_.'attribute_group_lang` agl - ON (a.`id_attribute_group` = agl.`id_attribute_group` AND agl.`id_lang` = '.(int)Context::getContext()->language->id.') - WHERE pa.`id_product` = '.(int)$id_product.' - AND pac.`id_product_attribute` = '.(int)$id_product_attribute.' - AND agl.`id_lang` = '.(int)Context::getContext()->language->id); + // if blocklayered module is installed we check if user has set custom attribute name + if (Module::isInstalled('blocklayered')) + { + $nb_custom_values = Db::getInstance()->executeS(' + SELECT DISTINCT la.`id_attribute`, la.`url_name` as `name` + FROM `'._DB_PREFIX_.'attribute` a + LEFT JOIN `'._DB_PREFIX_.'product_attribute_combination` pac + ON (a.`id_attribute` = pac.`id_attribute`) + LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa + ON (pac.`id_product_attribute` = pa.`id_product_attribute`) + LEFT JOIN `'._DB_PREFIX_.'layered_indexable_attribute_lang_value` la + ON (la.`id_attribute` = a.`id_attribute` AND la.`id_lang` = '.(int)Context::getContext()->language->id.') + WHERE la.`url_name` IS NOT NULL + AND pa.`id_product` = '.(int)$id_product); + + if (!empty($nb_custom_values)) + { + $tab_id_attribute = array(); + foreach ($nb_custom_values as $attribute) + { + $tab_id_attribute[] = $attribute['id_attribute']; + + $group = Db::getInstance()->executeS(' + SELECT g.`id_attribute_group`, g.`url_name` as `group` + FROM `'._DB_PREFIX_.'layered_indexable_attribute_group_lang_value` g + LEFT JOIN `'._DB_PREFIX_.'attribute` a + ON (a.`id_attribute_group` = g.`id_attribute_group`) + WHERE a.`id_attribute` = '.(int)$attribute['id_attribute'].' + AND g.`id_lang` = '.(int)Context::getContext()->language->id.' + AND g.`url_name` IS NOT NULL'); + if (empty($group)) + { + $group = Db::getInstance()->executeS(' + SELECT g.`id_attribute_group`, g.`name` as `group` + FROM `'._DB_PREFIX_.'attribute_group_lang` g + LEFT JOIN `'._DB_PREFIX_.'attribute` a + ON (a.`id_attribute_group` = g.`id_attribute_group`) + WHERE a.`id_attribute` = '.(int)$attribute['id_attribute'].' + AND g.`id_lang` = '.(int)Context::getContext()->language->id.' + AND g.`name` IS NOT NULL'); + } + $result[] = array_merge($attribute, $group[0]); + } + $values_not_custom = Db::getInstance()->executeS(' + SELECT DISTINCT a.`id_attribute_group`, al.`name`, agl.`name` as `group` + FROM `'._DB_PREFIX_.'attribute` a + LEFT JOIN `'._DB_PREFIX_.'attribute_lang` al + ON (a.`id_attribute` = al.`id_attribute` AND al.`id_lang` = '.(int)Context::getContext()->language->id.') + LEFT JOIN `'._DB_PREFIX_.'attribute_group_lang` agl + ON (a.`id_attribute_group` = agl.`id_attribute_group` AND agl.`id_lang` = '.(int)Context::getContext()->language->id.') + LEFT JOIN `'._DB_PREFIX_.'product_attribute_combination` pac + ON (a.`id_attribute` = pac.`id_attribute`) + LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa + ON (pac.`id_product_attribute` = pa.`id_product_attribute`) + WHERE pa.`id_product` = '.(int)$id_product.' + AND a.`id_attribute` NOT IN('.implode(', ', $tab_id_attribute).')'); + $result = array_merge($values_not_custom, $result); + } + else + { + $result = Db::getInstance()->executeS(' + SELECT al.`name`, agl.`name` as `group` + FROM `'._DB_PREFIX_.'attribute` a + LEFT JOIN `'._DB_PREFIX_.'attribute_lang` al + ON (al.`id_attribute` = a.`id_attribute` AND al.`id_lang` = '.(int)Context::getContext()->language->id.') + LEFT JOIN `'._DB_PREFIX_.'product_attribute_combination` pac + ON (pac.`id_attribute` = a.`id_attribute`) + LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa + ON (pa.`id_product_attribute` = pac.`id_product_attribute`) + LEFT JOIN `'._DB_PREFIX_.'attribute_group_lang` agl + ON (a.`id_attribute_group` = agl.`id_attribute_group` AND agl.`id_lang` = '.(int)Context::getContext()->language->id.') + WHERE pa.`id_product` = '.(int)$id_product.' + AND pac.`id_product_attribute` = '.(int)$id_product_attribute.' + AND agl.`id_lang` = '.(int)Context::getContext()->language->id); + } + } + else + { + $result = Db::getInstance()->executeS(' + SELECT al.`name`, agl.`name` as `group` + FROM `'._DB_PREFIX_.'attribute` a + LEFT JOIN `'._DB_PREFIX_.'attribute_lang` al + ON (al.`id_attribute` = a.`id_attribute` AND al.`id_lang` = '.(int)Context::getContext()->language->id.') + LEFT JOIN `'._DB_PREFIX_.'product_attribute_combination` pac + ON (pac.`id_attribute` = a.`id_attribute`) + LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa + ON (pa.`id_product_attribute` = pac.`id_product_attribute`) + LEFT JOIN `'._DB_PREFIX_.'attribute_group_lang` agl + ON (a.`id_attribute_group` = agl.`id_attribute_group` AND agl.`id_lang` = '.(int)Context::getContext()->language->id.') + WHERE pa.`id_product` = '.(int)$id_product.' + AND pac.`id_product_attribute` = '.(int)$id_product_attribute.' + AND agl.`id_lang` = '.(int)Context::getContext()->language->id); + } + return $result; } /** + * @todo Remove existing module condition * @param int $id_product */ public static function getAttributesInformationsByProduct($id_product) { - return Db::getInstance()->executeS(' - SELECT DISTINCT a.`id_attribute`, a.`id_attribute_group`, al.`name` as `attribute`, agl.`name` as `group` - FROM `'._DB_PREFIX_.'attribute` a - LEFT JOIN `'._DB_PREFIX_.'attribute_lang` al - ON (a.`id_attribute` = al.`id_attribute` AND al.`id_lang` = '.(int)Context::getContext()->language->id.') - LEFT JOIN `'._DB_PREFIX_.'attribute_group_lang` agl - ON (a.`id_attribute_group` = agl.`id_attribute_group` AND agl.`id_lang` = '.(int)Context::getContext()->language->id.') - LEFT JOIN `'._DB_PREFIX_.'product_attribute_combination` pac - ON (a.`id_attribute` = pac.`id_attribute`) - LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa - ON (pac.`id_product_attribute` = pa.`id_product_attribute`) - WHERE pa.`id_product` = '.(int)$id_product); + // if blocklayered module is installed we check if user has set custom attribute name + if (Module::isInstalled('blocklayered')) + { + $nb_custom_values = Db::getInstance()->executeS(' + SELECT DISTINCT la.`id_attribute`, la.`url_name` as `attribute` + FROM `'._DB_PREFIX_.'attribute` a + LEFT JOIN `'._DB_PREFIX_.'product_attribute_combination` pac + ON (a.`id_attribute` = pac.`id_attribute`) + LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa + ON (pac.`id_product_attribute` = pa.`id_product_attribute`) + LEFT JOIN `'._DB_PREFIX_.'layered_indexable_attribute_lang_value` la + ON (la.`id_attribute` = a.`id_attribute` AND la.`id_lang` = '.(int)Context::getContext()->language->id.') + WHERE la.`url_name` IS NOT NULL + AND pa.`id_product` = '.(int)$id_product); + + if (!empty($nb_custom_values)) + { + $tab_id_attribute = array(); + foreach ($nb_custom_values as $attribute) + { + $tab_id_attribute[] = $attribute['id_attribute']; + + $group = Db::getInstance()->executeS(' + SELECT g.`id_attribute_group`, g.`url_name` as `group` + FROM `'._DB_PREFIX_.'layered_indexable_attribute_group_lang_value` g + LEFT JOIN `'._DB_PREFIX_.'attribute` a + ON (a.`id_attribute_group` = g.`id_attribute_group`) + WHERE a.`id_attribute` = '.(int)$attribute['id_attribute'].' + AND g.`id_lang` = '.(int)Context::getContext()->language->id.' + AND g.`url_name` IS NOT NULL'); + if (empty($group)) + { + $group = Db::getInstance()->executeS(' + SELECT g.`id_attribute_group`, g.`name` as `group` + FROM `'._DB_PREFIX_.'attribute_group_lang` g + LEFT JOIN `'._DB_PREFIX_.'attribute` a + ON (a.`id_attribute_group` = g.`id_attribute_group`) + WHERE a.`id_attribute` = '.(int)$attribute['id_attribute'].' + AND g.`id_lang` = '.(int)Context::getContext()->language->id.' + AND g.`name` IS NOT NULL'); + } + $result[] = array_merge($attribute, $group[0]); + } + $values_not_custom = Db::getInstance()->executeS(' + SELECT DISTINCT a.`id_attribute`, a.`id_attribute_group`, a.`id_attribute_group`, al.`name` as `attribute`, agl.`name` as `group` + FROM `'._DB_PREFIX_.'attribute` a + LEFT JOIN `'._DB_PREFIX_.'attribute_lang` al + ON (a.`id_attribute` = al.`id_attribute` AND al.`id_lang` = '.(int)Context::getContext()->language->id.') + LEFT JOIN `'._DB_PREFIX_.'attribute_group_lang` agl + ON (a.`id_attribute_group` = agl.`id_attribute_group` AND agl.`id_lang` = '.(int)Context::getContext()->language->id.') + LEFT JOIN `'._DB_PREFIX_.'product_attribute_combination` pac + ON (a.`id_attribute` = pac.`id_attribute`) + LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa + ON (pac.`id_product_attribute` = pa.`id_product_attribute`) + WHERE pa.`id_product` = '.(int)$id_product.' + AND a.`id_attribute` NOT IN('.implode(', ', $tab_id_attribute).')'); + $result = array_merge($values_not_custom, $result); + } + else + { + $result = Db::getInstance()->executeS(' + SELECT DISTINCT a.`id_attribute`, a.`id_attribute_group`, al.`name` as `attribute`, agl.`name` as `group` + FROM `'._DB_PREFIX_.'attribute` a + LEFT JOIN `'._DB_PREFIX_.'attribute_lang` al + ON (a.`id_attribute` = al.`id_attribute` AND al.`id_lang` = '.(int)Context::getContext()->language->id.') + LEFT JOIN `'._DB_PREFIX_.'attribute_group_lang` agl + ON (a.`id_attribute_group` = agl.`id_attribute_group` AND agl.`id_lang` = '.(int)Context::getContext()->language->id.') + LEFT JOIN `'._DB_PREFIX_.'product_attribute_combination` pac + ON (a.`id_attribute` = pac.`id_attribute`) + LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa + ON (pac.`id_product_attribute` = pa.`id_product_attribute`) + WHERE pa.`id_product` = '.(int)$id_product); + } + } + else + { + $result = Db::getInstance()->executeS(' + SELECT DISTINCT a.`id_attribute`, a.`id_attribute_group`, al.`name` as `attribute`, agl.`name` as `group` + FROM `'._DB_PREFIX_.'attribute` a + LEFT JOIN `'._DB_PREFIX_.'attribute_lang` al + ON (a.`id_attribute` = al.`id_attribute` AND al.`id_lang` = '.(int)Context::getContext()->language->id.') + LEFT JOIN `'._DB_PREFIX_.'attribute_group_lang` agl + ON (a.`id_attribute_group` = agl.`id_attribute_group` AND agl.`id_lang` = '.(int)Context::getContext()->language->id.') + LEFT JOIN `'._DB_PREFIX_.'product_attribute_combination` pac + ON (a.`id_attribute` = pac.`id_attribute`) + LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa + ON (pac.`id_product_attribute` = pa.`id_product_attribute`) + WHERE pa.`id_product` = '.(int)$id_product); + } + return $result; + } + + /** + * Get the combination url anchor of the product + * + * @param integer $id_product_attribute + * @return string + */ + public function getAnchor($id_product_attribute) + { + $attributes = Product::getAttributesParams($this->id, $id_product_attribute); + $anchor = '#'; + foreach ($attributes as &$a) + { + foreach ($a as &$b) + $b = str_replace('-', '_', Tools::link_rewrite($b)); + $anchor .= '/'.$a['group'].'-'.$a['name']; + } + return $anchor; } } diff --git a/controllers/front/ProductController.php b/controllers/front/ProductController.php index 97806d849..0b191850b 100644 --- a/controllers/front/ProductController.php +++ b/controllers/front/ProductController.php @@ -375,7 +375,8 @@ class ProductControllerCore extends FrontController { $attributes_combinations = Product::getAttributesInformationsByProduct($this->product->id); foreach ($attributes_combinations as &$ac) - $ac = array_map('Tools::str2url', $ac); + foreach ($ac as &$val) + $val = str_replace('-', '_', Tools::link_rewrite($val)); $this->context->smarty->assign('attributesCombinations', $attributes_combinations); } diff --git a/modules/blockcart/blockcart-json.tpl b/modules/blockcart/blockcart-json.tpl index 8dcce7536..792642e42 100644 --- a/modules/blockcart/blockcart-json.tpl +++ b/modules/blockcart/blockcart-json.tpl @@ -32,7 +32,7 @@ {assign var='productAttributeId' value=$product.id_product_attribute} {ldelim} "id": {$product.id_product}, - "link": "{$link->getProductLink($product.id_product, $product.link_rewrite, $product.category, null, null, $product.id_shop)|addslashes|replace:'\\\'':'\''}", + "link": "{$link->getProductLink($product.id_product, $product.link_rewrite, $product.category, null, null, $product.id_shop, $product.id_product_attribute)|addslashes|replace:'\\\'':'\''}", "quantity": {$product.cart_quantity}, "priceByLine": "{if $priceDisplay == $smarty.const.PS_TAX_EXC}{displayWtPrice|html_entity_decode:2:'UTF-8' p=$product.total}{else}{displayWtPrice|html_entity_decode:2:'UTF-8' p=$product.total_wt}{/if}", "name": "{$product.name|html_entity_decode:2:'UTF-8'|escape|truncate:15:'...':true}", diff --git a/modules/blockcart/blockcart.tpl b/modules/blockcart/blockcart.tpl index cde0abeca..eb780f2b1 100644 --- a/modules/blockcart/blockcart.tpl +++ b/modules/blockcart/blockcart.tpl @@ -62,14 +62,14 @@ var removingLinkText = '{l s='remove this product from my cart' mod='blockcart' {assign var='productAttributeId' value=$product.id_product_attribute}