John77 Posted November 27, 2014 Share Posted November 27, 2014 Bonjour à tous, Je souhaiterais faire des association de produits sur mes fiches produits mais je suis face à un mur... J'explique rapidement : J'ai une boutique qui vend des roues de voitures. Ces roues sont rangées dans des categories comme ceci : Marque véhicule > Modèle véhicule > taille de roue jusque la pas de souci... Mais maintenant je souhaite associer des pneus à ces roues et c'est là que sa ce corse ! Une roue peut recevoir différentes tailles de pneus en fonction du modèle de véhicule et de la taille de roue. Si j'associe un pneu à une roue, cette association ce retrouve sur tout les modèles de véhicule alors que dans mon cas les tailles de pneus varient d'un véhicule à un autre. N'ayant pas trouver de moyen de gérer cette problématique j'ai donc créé dans mes catégories : --> Roues --> Marque véhicule --> Modèle véhicule --> Taille roue --> Pneus --> Marque véhicule --> Modèle véhicule --> Taille roue Maintenant je me dis que je peux afficher sur ma fiche produit les produits contenu dans pneus sur ma fiche produit roues mais je sèche totalement sur ce coup la... Je pense que je cherche trop compliqué peut être et qu'il y a plus simple... Quelqu'un aurait une idée ou une piste ? Link to comment Share on other sites More sharing options...
John77 Posted November 27, 2014 Author Share Posted November 27, 2014 Voila un exemple de ce que j'aimerais un peu obtenir : http://www.ldprestige.com/jante/ld085-2 Link to comment Share on other sites More sharing options...
Alexandre Carette Posted November 27, 2014 Share Posted November 27, 2014 (edited) Je n'ai pas trop compris mais pourquoi ne pas utiliser "accessoires" dans la fiche produit de la jante ? Edited November 27, 2014 by alexandre-km (see edit history) Link to comment Share on other sites More sharing options...
John77 Posted November 27, 2014 Author Share Posted November 27, 2014 Le problème en utilisant accessoires c'est que les pneus associés comme accessoires s'affiche pour la jantes quelque soit le modele de véhicule hors les pneus ne sont pas pareil selon le vehicule choisi Link to comment Share on other sites More sharing options...
John77 Posted November 27, 2014 Author Share Posted November 27, 2014 L'idéal serait d'attribuer des pneus entant qu'accessoires selon la catégorie dans laquelle se trouve la jante Link to comment Share on other sites More sharing options...
Alexandre Carette Posted November 27, 2014 Share Posted November 27, 2014 (edited) a mon avis il faut developper un module spécifique pour l'affichage des produits associés... sinon en mode bricolage, tu dupliques le module homefeatured que tu modifies pour obtenir les produits de ta catégorie, tu le hook dans la fiche produit, ca peut être une piste... Edited November 27, 2014 by alexandre-km (see edit history) Link to comment Share on other sites More sharing options...
John77 Posted November 27, 2014 Author Share Posted November 27, 2014 Oui je pense que je vais faire comme ca car je ne trouve pas d'autre solution et a vrai dire j'en vois pas pour le moment... J'avais pensais filtrer l'affichage des produits en accessoires en récupérant les nom de marque modele etc sont identiques dans ma categorie jante et dans ma categorie pneus. C'est exactement la meme arborescence à l'interieure de ces deux categories, seul les id changes donc en utilisant les noms plutot que les id dans le filtre je pense que ca peut fonctionner... Link to comment Share on other sites More sharing options...
Alexandre Carette Posted November 27, 2014 Share Posted November 27, 2014 (edited) A tester, donne nous la suite car c'est un post interéssant ! Edited November 27, 2014 by alexandre-km (see edit history) Link to comment Share on other sites More sharing options...
Broceliande Posted November 27, 2014 Share Posted November 27, 2014 Malheureusement pour ce genre de problématique il faut déplier au max les sous-catégories quitte à avoir une redondance. En fait je pense qu'il manque un niveau de catégorie à la base , au minimum dans les roues : --> Roues --> Marque véhicule --> Modèle véhicule --> Taille roue --> Pneus ! A ce stade il est facile de glisser dans l'arbo les pneus dispos puisqu'on est au bout de cette arbo (on a donc bien le modèle voulu et la taille de roue). Bien sûr on aura pris soin de laisser le produit dans la catégorie Taille roue (et par défaut) Il devient alors facile de récup l'id de la sous catégorie fille de la catégorie par défaut de la roue, de l'instancier et d'en lister les produits (voir Category->getProducts() dans la classe Category). Link to comment Share on other sites More sharing options...
John77 Posted November 27, 2014 Author Share Posted November 27, 2014 (edited) j'essais de modifier la class accessory mais je ne ne trouve pour le moment, je souhaite essayer de modifier cette class en ajoutant une condition WHERE afin que les catégories correspondent Categorie Jante Catalogue Pneu Marque = Marque Modele = Modele Taille = Taille et ce afin d'afficher uniquement les pneus qui correspondent Je pense qu'il faut modifier dans Product.php entre la ligne 3201et 3270 public static function getAccessoriesLight($id_lang, $id_product, Context $context = null) { if (!$context) $context = Context::getContext(); $sql = 'SELECT p.`id_product`, p.`reference`, pl.`name` FROM `'._DB_PREFIX_.'accessory` LEFT JOIN `'._DB_PREFIX_.'product` p ON (p.`id_product`= `id_product_2`) '.Shop::addSqlAssociation('product', 'p').' LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON ( p.`id_product` = pl.`id_product` AND pl.`id_lang` = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('pl').' ) WHERE `id_product_1` = '.(int)$id_product; return Db::getInstance()->executeS($sql); } /** * Get product accessories * * @param integer $id_lang Language id * @return array Product accessories */ public function getAccessories($id_lang, $active = true, Context $context = null) { if (!$context) $context = Context::getContext(); $sql = 'SELECT p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity, pl.`description`, pl.`description_short`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, pl.`available_now`, pl.`available_later`, MAX(image_shop.`id_image`) id_image, il.`legend`, m.`name` as manufacturer_name, cl.`name` AS category_default, DATEDIFF( p.`date_add`, DATE_SUB( NOW(), INTERVAL '.(Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY ) ) > 0 AS new FROM `'._DB_PREFIX_.'accessory` LEFT JOIN `'._DB_PREFIX_.'product` p ON p.`id_product` = `id_product_2` '.Shop::addSqlAssociation('product', 'p').' LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON ( p.`id_product` = pl.`id_product` AND pl.`id_lang` = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('pl').' ) LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON ( product_shop.`id_category_default` = cl.`id_category` AND cl.`id_lang` = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('cl').' ) LEFT JOIN `'._DB_PREFIX_.'image` i ON (i.`id_product` = p.`id_product`)'. Shop::addSqlAssociation('image', 'i', false, 'image_shop.cover=1').' LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (i.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$id_lang.') LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON (p.`id_manufacturer`= m.`id_manufacturer`) '.Product::sqlStock('p', 0).' WHERE `id_product_1` = '.(int)$this->id. ($active ? ' AND product_shop.`active` = 1 AND product_shop.`visibility` != \'none\'' : '').' GROUP BY product_shop.id_product'; if (!$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql)) return false; foreach ($result as &$row) $row['id_product_attribute'] = Product::getDefaultAttribute((int)$row['id_product']); return $this->getProductsProperties($id_lang, $result); } public static function getAccessoryById($accessory_id) { return Db::getInstance()->getRow('SELECT `id_product`, `name` FROM `'._DB_PREFIX_.'product_lang` WHERE `id_product` = '.(int)$accessory_id); } Edited November 27, 2014 by John77 (see edit history) Link to comment Share on other sites More sharing options...
John77 Posted November 28, 2014 Author Share Posted November 28, 2014 Je fais suite au sujet. Donc après plusieurs tentatives non concluante par rapport au dernier post j'ai donc changé totalement de direction et cédé à la facilité ! J'ai créer un bouton en dessous du bouton ajouter au panier de la fiche produit comme ceci : <div class="box-cart-bottom"> <p id="add_to_cart" class="buttons_bottom_block no-print"> <button type="submit" name="Submit" class="exclusive"> <span>Pack jantes + Pneus</span></button> </p> </div> En cliquant sur ce bouton le produit s'ajoute directement au panier. Il faut maintenant que je génère un lien qui redirige vers la sous catégorie dans laquelle le visiteur ce trouve (C'est dans cette sous-catégorie que sont stocké les pneus correspondant à afficher) En gros : Clique sur ajouter au panier = Ajouter au panier + redirection catégorie enfant de celle dans laquelle on se trouve. Ce qui devrait donner quelque chose qui ressemble à cela : <a href="{$link->getCategoryLink($child.id_category, $child.link_rewrite)|escape:'htmlall':'UTF-8'}" id="{$child.id_category}"> </a> Mais bien évidement ca ne fonctionne pas... Link to comment Share on other sites More sharing options...
John77 Posted December 1, 2014 Author Share Posted December 1, 2014 (edited) Bon après un weekend à chercher, je ne parviens toujours pas à générer un lien vers la sous catégorie dans laquelle on se trouve lorsque que l'on est sur la fiche produit... Je parviens toujours à ce résultat : <a href="../fr/-" id=""> Ce qui indique qu'aucune info n'est récupérer... D'autre part, j'utilise un systeme de recherche rapide en ajax selon 3 criteres (marque, modele, taille) ce qui permet d'afficher la liste des produits de la catégorie choisi. Lorsque je suis sur la fiche produit dans le code source de la page ce module affiche : <div class="block_content" style="float:left; width:50%;margin:30px 10px 21px 17px;"> <div class="categoriesnc_container" style="float:left;width:169px;margin:12px 7px;"> <div class="categoriesnc_select" > <select id="lev1" class="lev form-control" style="float:left;width: 169px;" onchange="var lev = parseInt(this.id.substring(3)); deleteCats(lev); if (this.value.indexOf('|catID=') != -1) loadCat(parseInt(this.value.substring(this.value.indexOf('|catID=') + 7)), lev); else if (this.value != 0) window.location = this.value;"> <option value="0">Marque</option> <option value="../fr/17-marque|catID=17" selected="selected">Marque</option> ....... ....... ....... ....... </select> </div></div> <div class="categoriesnc_container" style="float:left;width:169px;margin:12px 7px;"> <div class="categoriesnc_select""> <select id="lev2" class="lev form-control" style="float:left;width: 169px;" onchange="var lev = parseInt(this.id.substring(3)); deleteCats(lev); if (this.value.indexOf('catID=') != -1) loadCat(parseInt(this.value.substring(6)), lev); else if (this.value != 0) window.location = this.value;" onclick="deleteCats(2); loadCat(parseInt($('#lev1').val().substring($('#lev1').val().indexOf('|catID=')+7)), 1); this.onclick = null"> <option value="0">Choisir catégorie</option> <option value="../fr/36-Modele|catID=36" selected="selected">Modele</option> </select> </div> </div> <div class="categoriesnc_container" style="float:left;width:169px;margin:12px 7px;"> <div class="categoriesnc_select""> <select id="lev3" class="lev form-control" style="float:left;width: 169px;" onchange="var lev = parseInt(this.id.substring(3)); deleteCats(lev); if (this.value.indexOf('catID=') != -1) loadCat(parseInt(this.value.substring(6)), lev); else if (this.value != 0) window.location = this.value;" onclick="deleteCats(3); loadCat(parseInt($('#lev2').val().substring($('#lev2').val().indexOf('|catID=')+7)), 2); this.onclick = null"> <option value="0">Choisir catégorie</option> <option value="../fr/953-Taille|catID=953" selected="selected">Taille</option> </select> </div> </div> </div> Dans le fichier PHP de ce module j'ai le code suivant : <?php if (!defined('_PS_VERSION_')) exit; class CategoriesNC extends Module { public function __construct() { $this->name = 'categoriesnc'; $this->tab = 'front_office_features'; $this->parents = array(); $this->bootstrap = true; parent::__construct(); $this->displayName = $this->l('AJAX Dropdown Categories'); $this->description = $this->l('Dynamically loads product categories and presents them in dropdowns'); // Check whether to enable retrocompability $this->retro = Tools::version_compare(_PS_VERSION_, '1.6.0.0'); // Copy the appropriate CSS for the PrestaShop version $file_exists = file_exists(_PS_ROOT_DIR_.'/modules/'.$this->name.'/css/'.$this->name.'.css'); if (!$file_exists && file_exists(_PS_ROOT_DIR_.'/modules/'.$this->name.'/css/original'.($this->retro ? '' : '16').'.css')) copy(_PS_ROOT_DIR_.'/modules/'.$this->name.'/css/original'.($this->retro ? '' : '16'). '.css', _PS_ROOT_DIR_.'/modules/'.$this->name.'/css/'.$this->name.'.css'); // Display a warning if there are no category levels $depth = $this->getNumberOfLevels(Tools::getValue('fromCategory', (int)Configuration::get('CATEG_NC_START_FROM_CATEG'))); if (Configuration::get('CATEG_NC_NUM_PRODUCTS') > 0 || Configuration::get('CATEG_NC_HIDE_EMPTY_CATEG') || $depth == 0) $this->warning = ''; // Display a warning if the override is missing $has_override = false; if (Configuration::get('CATEG_NC_NUM_PRODUCTS') > 0 || Configuration::get('CATEG_NC_HIDE_EMPTY_CATEG')) { $file_exists = file_exists(_PS_ROOT_DIR_.'/override/controllers/front/CategoryController.php'); if ($file_exists) { $fname = _PS_ROOT_DIR_.'/override/controllers/front/CategoryController.php'; $fhandle = fopen($fname, 'r'); $content = (filesize($fname) > 0 ? fread($fhandle, filesize($fname)) : ''); fclose($fhandle); $has_override = (strpos($content, '$this->context->smarty->assign(\'subcategories\', count($modifiedSubcategories) > 0 ? $modifiedSubcategories : null);')); } if (!$has_override) $this->warning .= $this->l('To display product numbers and hide empty categories on the category pages, you must').' '. (!$file_exists ? $this->l('copy') : $this->l('merge')).' modules/'.$this->name.'/override/controllers/front/CategoryController.php '. (!$file_exists ? $this->l('to') : $this->l('with')).' override/controllers/front/CategoryController.php'; } else $has_override = true; if ($depth == 0) $this->warning .= (!$has_override ? '<br /><br />' : ''). $this->l('There are no category levels - please add more levels or increase the maximum depth'); if ($this->warning && Tools::getValue('configure') == $this->name) $this->adminDisplayWarning($this->warning); } public function install() { $sort = Configuration::get('BLOCK_CATEG_SORT'); $sort_way = Configuration::get('BLOCK_CATEG_SORT_WAY'); $footer_columns = Configuration::get('BLOCK_CATEG_NBR_COLUMN_FOOTER'); if (!parent::install() || !$this->registerHook('displayLeftColumn') || !$this->registerHook('displayFooter') || !$this->registerHook('displayHeader') // Temporary hooks. Do NOT hook any module on it. Some CRUD hook will replace them as soon as possible. || !$this->registerHook('categoryAddition') || !$this->registerHook('categoryUpdate') || !$this->registerHook('categoryDeletion') || !$this->registerHook('actionAdminMetaControllerUpdate_optionsBefore') || !$this->registerHook('actionAdminLanguagesControllerStatusBefore') || !$this->registerHook('addproduct') || !$this->registerHook('deleteproduct') /* || !$this->registerHook('updateproduct')*/ || !Configuration::updateValue('CATEG_NC_SECURE_KEY', Tools::strtoupper(Tools::passwdGen(16))) || !Configuration::updateValue('CATEG_NC_MAX_DEPTH', 3) || !Configuration::updateValue('CATEG_NC_SORT', $sort != false ? $sort : 0) || !Configuration::updateValue('CATEG_NC_SORT_WAY', $sort_way != false ? $sort_way : 0) || !Configuration::updateValue('CATEG_NC_NBR_COLUMN_FOOTER', $footer_columns != false ? $footer_columns : 1) || !Configuration::updateValue('CATEG_NC_FOOTER_MAX_DEPTH', 2) || !Configuration::updateValue('CATEG_NC_SHOW_GO_BUTTONS', 0) || !Configuration::updateValue('CATEG_NC_SHOW_ALL_DROPDOWNS', 0) || !Configuration::updateValue('CATEG_NC_FIX_IE_SELECT_WIDTH', 0) || !Configuration::updateValue('CATEG_NC_NUM_PRODUCTS', 0) || !Configuration::updateValue('CATEG_NC_HIDE_ZERO_COUNTS', 0) || !Configuration::updateValue('CATEG_NC_HIDE_EMPTY_CATEG', 0) || !Configuration::updateValue('CATEG_NC_SHOW_PRODUCTS', 0) || !Configuration::updateValue('CATEG_NC_SAVE', 1) || !Configuration::updateValue('CATEG_NC_RELOAD', 0) || !Configuration::updateValue('CATEG_NC_START_FROM_CATEG', $this->context->shop->getCategory()) || !Configuration::updateValue('CATEG_NC_LABEL_POSITION', 0) || !Configuration::updateValue('CATEG_NC_MAX_CATEGORIES', 500)) return false; $depth = 0; $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT MAX(`level_depth`) as `max_depth` FROM `'._DB_PREFIX_.'category`'); if (is_array($result) && count($result) > 0) $depth = $result[0]['max_depth']; $max_depth = Configuration::get('CATEG_NC_MAX_DEPTH'); $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT `level_depth` FROM `'._DB_PREFIX_.'category` WHERE `id_category` = '. Configuration::get('CATEG_NC_START_FROM_CATEG')); if ($result != null && count($result) > 0) $depth -= $result[0]['level_depth']; if (Configuration::get('CATEG_NC_SHOW_PRODUCTS')) $depth++; if ($max_depth > 0 && $depth > $max_depth) $depth = $max_depth; $languages = Language::getLanguages(false); $default_language = (int)Configuration::get('PS_LANG_DEFAULT'); $default_language_iso = 'en'; foreach ($languages as $language) if ($language['id_lang'] == $default_language) $default_language_iso = $language['iso_code']; $translations = array(); foreach ($languages as $language) $translations[$language['id_lang']] = array_key_exists($language['iso_code'], $this->default_labels) ? $this->default_labels[$language['iso_code']] : (array_key_exists($default_language_iso, $this->default_labels) ? $this->default_labels[$default_language_iso] : $this->default_labels['en']); for ($i = 1; $i <= $depth; $i++) if (!Configuration::updateValue('CATEG_NC_LABEL_'.$i, $translations)) return false; return true; } public function uninstall() { if (!Configuration::deleteByName('CATEG_NC_SECURE_KEY') || !Configuration::deleteByName('CATEG_NC_MAX_DEPTH') || !Configuration::deleteByName('CATEG_NC_SORT') || !Configuration::deleteByName('CATEG_NC_SORT_WAY') || !Configuration::deleteByName('CATEG_NC_NBR_COLUMN_FOOTER') || !Configuration::deleteByName('CATEG_NC_FOOTER_MAX_DEPTH') || !Configuration::deleteByName('CATEG_NC_SHOW_GO_BUTTONS') || !Configuration::deleteByName('CATEG_NC_SHOW_ALL_DROPDOWNS') || !Configuration::deleteByName('CATEG_NC_FIX_IE_SELECT_WIDTH') || !Configuration::deleteByName('CATEG_NC_NUM_PRODUCTS') || !Configuration::deleteByName('CATEG_NC_HIDE_ZERO_COUNTS') || !Configuration::deleteByName('CATEG_NC_HIDE_EMPTY_CATEG') || !Configuration::deleteByName('CATEG_NC_SHOW_PRODUCTS') || !Configuration::deleteByName('CATEG_NC_SAVE') || !Configuration::deleteByName('CATEG_NC_RELOAD') || !Configuration::deleteByName('CATEG_NC_START_FROM_CATEG') || !Configuration::deleteByName('CATEG_NC_LABEL_POSITION') || !Configuration::deleteByName('CATEG_NC_MAX_CATEGORIES') || !parent::uninstall()) return false; Db::getInstance(_PS_USE_SQL_SLAVE_)->Execute(' DELETE FROM `'._DB_PREFIX_.'configuration_lang` WHERE `id_configuration` IN ( SELECT `id_configuration` FROM `'._DB_PREFIX_.'configuration` WHERE `name` LIKE "CATEG_NC_LABEL_%")'); Db::getInstance(_PS_USE_SQL_SLAVE_)->Execute(' DELETE FROM `'._DB_PREFIX_.'configuration` WHERE `name` LIKE "CATEG_NC_LABEL_%"'); Db::getInstance(_PS_USE_SQL_SLAVE_)->Execute('DROP TABLE IF EXISTS `'._DB_PREFIX_.'blockcategoriesnc_numproducts`'); return true; } protected function getNumberOfLevels($from_category) { $depth = 0; $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT MAX(`level_depth`) as `max_depth` FROM `'._DB_PREFIX_.'category`'); if (is_array($result) && count($result) > 0) $depth = $result[0]['max_depth']; $max_depth = Configuration::get('CATEG_NC_MAX_DEPTH'); $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT `level_depth` FROM `'._DB_PREFIX_.'category` WHERE `id_category` = '.$from_category); if (Configuration::get('CATEG_NC_SHOW_PRODUCTS')) $depth++; if ($max_depth > 0 && $depth > $max_depth) $depth = $max_depth; return $depth - ($result != null && count($result) > 0 ? $result[0]['level_depth'] : 0); } public function headerHTML() { if (Tools::getValue('controller') != 'AdminModules' && Tools::getValue('configure') != $this->name) return; $this->context->controller->addJqueryUI('ui.sortable'); /* Style & js for fieldset 'messages configuration' */ $html = '<style type="text/css"> @media (min-width: 768px) { #nc_panel {margin:40px 20px;} #left_panel {float: left; padding-right: 20px; margin-right: 20px; border-right: 1px solid #ccced7;} #right_panel {padding-left: 20px;} } </style> <div id="nc_panel"> <div id="left_panel"> <a href="http://www.nethercottconstructions.com" target="_blank"><img src="'. $this->_path.'img/logo.png" alt="'.$this->author.'" width="195" height="93" /></a> </div> <div id="right_panel"> <h2>'.$this->displayName.' <span style="font-size:13px;">v'.$this->version.'</span></h2> <p><strong>'.$this->description.'</strong></p> <p>'.$this->l('For any technical questions or problems with this module, please'). ' <a href="http://www.nethercottconstructions.com/contact-us" target="_blank">'.$this->l('contact us').'</a></p> </div> <div class="clearfix"></div> </div>'.($this->retro ? '<br />' : ''); return $html; } public function getContent() { $output = $this->headerHTML(); $this->_errors = array(); $allow_employee_form_lang = Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG') ? Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG') : 0; if ($allow_employee_form_lang && !$this->context->cookie->employee_form_lang) $this->context->cookie->employee_form_lang = (int)Configuration::get('PS_LANG_DEFAULT'); $use_lang_from_cookie = false; $this->_languages = Language::getLanguages(); if ($allow_employee_form_lang) foreach ($this->_languages as $lang) if ($this->context->cookie->employee_form_lang == $lang['id_lang']) $use_lang_from_cookie = true; if (!$use_lang_from_cookie) $default_language = (int)Configuration::get('PS_LANG_DEFAULT'); else $default_language = (int)$this->context->cookie->employee_form_lang; $languages = Language::getLanguages(); $default_language_iso = 'en'; foreach ($languages as $language) if ($language['id_lang'] == $default_language) $default_language_iso = $language['iso_code']; if (Tools::getValue('submitRestore')) { if (file_exists(_PS_MODULE_DIR_.$this->name.'/css/original'.($this->retro ? '' : '16').'.css')) { if (file_exists(_PS_MODULE_DIR_.$this->name.'/css/'.$this->name.'.css')) unlink(_PS_MODULE_DIR_.$this->name.'/css/'.$this->name.'.css'); copy(_PS_MODULE_DIR_.$this->name.'/css/original'.($this->retro ? '' : '16').'.css', _PS_MODULE_DIR_.$this->name.'/css/'.$this->name.'.css'); $output .= $this->displayConfirmation($this->l('Successfully restored CSS')); } else $this->_errors[] = $this->l('Could not find file').' original'. ($this->retro ? '' : '16').'.css - '.$this->l('please restore the file from the module archive'); } elseif (Tools::isSubmit('submitProductNumber')) { $num_products = (int)Tools::getValue('CATEG_NC_NUM_PRODUCTS'); $hide_empty_categories = (int)Tools::getValue('CATEG_NC_HIDE_EMPTY_CATEG'); $hide_zero_counts = (int)Tools::getValue('CATEG_NC_HIDE_ZERO_COUNTS'); if ($num_products != 0 && $num_products != 1 && $num_products != 2) $this->_errors[] = $this->l('Product numbers: Invalid choice'); if ($hide_zero_counts != 0 && $hide_zero_counts != 1) $this->_errors[] = $this->l('Hide zero counts: Invalid choice'); if (count($this->_errors) == 0) { $current_num_products = Configuration::get('CATEG_NC_NUM_PRODUCTS'); $current_hide_empty_categories = Configuration::get('CATEG_NC_HIDE_EMPTY_CATEGORIES'); // Create cache for product numbers if necessary if ((int)$num_products == 2 && $current_num_products != 2 && $current_hide_empty_categories == 0) { Db::getInstance(_PS_USE_SQL_SLAVE_)->Execute(' CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.'blockcategoriesnc_numproducts` ( `id_category` int(10) unsigned NOT NULL, `num_products` int(10) unsigned NOT NULL, PRIMARY KEY (`id_category`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;'); $this->createCache(); } // Delete the cache if it is no longer necessary elseif ($current_num_products == 2 && (int)$num_products != 2 && $current_hide_empty_categories == 0) Db::getInstance(_PS_USE_SQL_SLAVE_)->Execute('DROP TABLE IF EXISTS `'._DB_PREFIX_.'blockcategoriesnc_numproducts`'); Configuration::updateValue('CATEG_NC_NUM_PRODUCTS', (int)$num_products); Configuration::updateValue('CATEG_NC_HIDE_ZERO_COUNTS', (int)$hide_zero_counts); $output .= $this->displayConfirmation($this->l('Settings updated')); } else { $error_messages = '<ul>'; foreach ($this->_errors as $error_message) $error_messages .= '<li>'.$error_message.'</li>'; $error_messages .= '</ul>'; $output .= $this->displayError($error_messages); } } elseif (Tools::isSubmit('submitCSS')) { $custom_css = Tools::getValue('CATEG_NC_CUSTOM_CSS'); $previous_custom_css = ''; $fname = _PS_MODULE_DIR_.$this->name.'/css/'.$this->name.'.css'; if (file_exists($fname)) { $fhandle = fopen($fname, 'r'); $previous_custom_css = (filesize($fname) > 0 ? fread($fhandle, filesize($fname)) : ''); fclose($fhandle); if (trim($custom_css) != trim($previous_custom_css)) { unlink($fname); $fhandle = fopen($fname, 'w'); fwrite($fhandle, $custom_css); fclose($fhandle); } } $output .= $this->displayConfirmation($this->l('Settings updated')); } elseif (Tools::isSubmit('submitTroubleshooting')) { $max_categories = (int)Tools::getValue('CATEG_NC_MAX_CATEGORIES'); if (!is_numeric($max_categories) || (int)$max_categories < 0) $this->_errors[] = $this->l('Maximum categories per query: Must be a positive integer'); if (count($this->_errors) == 0) { Configuration::updateValue('CATEG_NC_MAX_CATEGORIES', (int)$max_categories); $output .= $this->displayConfirmation($this->l('Settings updated')); } else { $error_messages = '<ul>'; foreach ($this->_errors as $error_message) $error_messages .= '<li>'.$error_message.'</li>'; $error_messages .= '</ul>'; $output .= $this->displayError($error_messages); } } elseif (Tools::isSubmit('submitSettings')) { $max_depth = Tools::getValue('CATEG_NC_MAX_DEPTH'); $num_products = (int)Tools::getValue('CATEG_NC_NUM_PRODUCTS'); $show_go_buttons = (int)Tools::getValue('CATEG_NC_SHOW_GO_BUTTONS'); $show_all_dropdowns = (int)Tools::getValue('CATEG_NC_SHOW_ALL_DROPDOWNS'); $ie_fix = (int)Tools::getValue('CATEG_NC_FIX_IE_SELECT_WIDTH'); $hide_empty_categories = (int)Tools::getValue('CATEG_NC_HIDE_EMPTY_CATEG'); $show_products = (int)Tools::getValue('CATEG_NC_SHOW_PRODUCTS'); $save = (int)Tools::getValue('CATEG_NC_SAVE'); $reload = (int)Tools::getValue('CATEG_NC_RELOAD'); $start_from_category = (int)Tools::getValue('from_category'); $label_position = (int)Tools::getValue('CATEG_NC_LABEL_POSITION'); $nbr_columns = (int)Tools::getValue('CATEG_NC_NBR_COLUMN_FOOTER', 4); $footer_max_depth = Tools::getValue('CATEG_NC_FOOTER_MAX_DEPTH'); if (!is_numeric($max_depth) || (is_numeric($max_depth) && (int)$max_depth < 0)) $this->_errors[] = $this->l('Maximum depth: Invalid number'); if ($show_go_buttons != 0 && $show_go_buttons != 1) $this->_errors[] = $this->l('Show go buttons: Invalid choice'); if ($show_all_dropdowns != 0 && $show_all_dropdowns != 1) $this->_errors[] = $this->l('Show all dropdowns: Invalid choice'); if ($ie_fix != 0 && $ie_fix != 1) $this->_errors[] = $this->l('Fix IE select width: Invalid choice'); if ($hide_empty_categories != 0 && $hide_empty_categories != 1) $this->_errors[] = $this->l('Hide empty categories: Invalid choice'); if ($show_products != 0 && $show_products != 1) $this->_errors[] = $this->l('Show products: Invalid choice'); if ($save != 0 && $save != 1) $this->_errors[] = $this->l('Save state: Invalid choice'); if ($reload != 0 && $reload != 1) $this->_errors[] = $this->l('Reload categories: Invalid choice'); if ($start_from_category <= 0) $this->_errors[] = $this->l('Start from: Invalid choice'); if ($label_position != 0 && $label_position != 1) $this->_errors[] = $this->l('Dropdown label position: Invalid choice'); if (!is_numeric($footer_max_depth) || (is_numeric($footer_max_depth) && (int)$footer_max_depth < 0)) $this->_errors[] = $this->l('Footer maximum depth: Invalid number'); if (count($this->_errors) == 0) { $current_num_products = Configuration::get('CATEG_NC_NUM_PRODUCTS'); $current_hide_empty_categories = Configuration::get('CATEG_NC_HIDE_EMPTY_CATEGORIES'); // Create cache for product numbers if necessary if ($hide_empty_categories == 1 && $current_hide_empty_categories == 0 && $current_num_products != 2) { Db::getInstance(_PS_USE_SQL_SLAVE_)->Execute(' CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.'blockcategoriesnc_numproducts` ( `id_category` int(10) unsigned NOT NULL, `num_products` int(10) unsigned NOT NULL, PRIMARY KEY (`id_category`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;'); $this->createCache(); } // Delete the cache if it is no longer necessary elseif ($hide_empty_categories == 0 && $current_hide_empty_categories == 1 && $current_num_products != 2) Db::getInstance(_PS_USE_SQL_SLAVE_)->Execute('DROP TABLE IF EXISTS `'._DB_PREFIX_.'blockcategoriesnc_numproducts`'); Configuration::updateValue('CATEG_NC_MAX_DEPTH', (int)$max_depth); Configuration::updateValue('CATEG_NC_SHOW_GO_BUTTONS', (int)$show_go_buttons); Configuration::updateValue('CATEG_NC_SHOW_ALL_DROPDOWNS', (int)$show_all_dropdowns); Configuration::updateValue('CATEG_NC_FIX_IE_SELECT_WIDTH', (int)$ie_fix); Configuration::updateValue('CATEG_NC_HIDE_EMPTY_CATEG', (int)$hide_empty_categories); Configuration::updateValue('CATEG_NC_SAVE', (int)$save); Configuration::updateValue('CATEG_NC_RELOAD', (int)$reload); Configuration::updateValue('CATEG_NC_SHOW_PRODUCTS', (int)$show_products); Configuration::updateValue('CATEG_NC_START_FROM_CATEG', (int)$start_from_category); Configuration::updateValue('CATEG_NC_LABEL_POSITION', (int)$label_position); Configuration::updateValue('CATEG_NC_NBR_COLUMN_FOOTER', $nbr_columns); Configuration::updateValue('CATEG_NC_FOOTER_MAX_DEPTH', (int)$footer_max_depth); Configuration::updateValue('CATEG_NC_SORT_WAY', (int)Tools::getValue('CATEG_NC_SORT_WAY')); Configuration::updateValue('CATEG_NC_SORT', (int)Tools::getValue('CATEG_NC_SORT')); $depth = $this->getNumberOfLevels($start_from_category); for ($i = 1; $i <= $depth; $i++) { $translations = array(); foreach ($languages as $language) $translations[$language['id_lang']] = (trim(Tools::getValue('CATEG_NC_LABEL_'.$i.'_'.$language['id_lang'])) == '' ? (trim(Tools::getValue('CATEG_NC_LABEL_'.$i.'_'.$language['id_lang'])) == '' ? (array_key_exists($language['iso_code'], $this->default_labels) ? $this->default_labels[$language['iso_code']] : (array_key_exists($default_language_iso, $this->default_labels) ? $this->default_labels[$default_language_iso] : $this->default_labels['en'])) : Tools::getValue('CATEG_NC_LABEL_'.$i.'_'.$languages[$default_language]['id_lang'])) : Tools::getValue('CATEG_NC_LABEL_'.$i.'_'.$language['id_lang'])); Configuration::updateValue('CATEG_NC_LABEL_'.$i, $translations); } $output .= $this->displayConfirmation($this->l('Settings updated')); } else { $error_messages = '<ul>'; foreach ($this->_errors as $error_message) $error_messages .= '<li>'.$error_message.'</li>'; $error_messages .= '</ul>'; $output .= $this->displayError($error_messages); } } elseif (Tools::isSubmit('submitRegenerateCache')) { if ((int)Configuration::get('CATEG_NC_NUM_PRODUCTS') == 2 || (int)Configuration::get('CATEG_NC_HIDE_EMPTY_CATEG') == 1) $this->createCache(); $output .= $this->displayConfirmation($this->l('Cache regeneration successful')); } elseif (Tools::isSubmit('submitRepairTree')) { $this->repairTree(); $output .= $this->displayConfirmation($this->l('Tree repair successful')); } return $output.$this->renderForm(); } public function renderForm() { $root_category = Category::getRootCategory(); $root_category = array('id_category' => $root_category->id, 'name' => $root_category->name); $settings_form = array( 'form' => array( 'legend' => array( 'title' => $this->l('Settings'), 'icon' => 'icon-cogs', 'image' => $this->retro ? $this->_path.'logo.gif' : null ), 'input' => array( array( 'type' => 'text', 'label' => $this->l('Maximum depth'), 'name' => 'CATEG_NC_MAX_DEPTH', $this->retro ? 'desc' : 'hint' => $this->l('Set the maximum depth of sublevels displayed in this block (0 = infinite)'), 'class' => 'fixed-width-xs' ), array( 'type' => 'select', 'label' => $this->l('Sort'), 'name' => 'CATEG_NC_SORT', $this->retro ? 'desc' : 'hint' => $this->l('Set whether to sort categories by name or position'), 'default_value' => Tools::getValue('CATEG_NC_SORT', Configuration::get('CATEG_NC_SORT')), 'options' => array( 'query' => array( array( 'id' => 1, 'name' => $this->l('By name') ), array( 'id' => 0, 'name' => $this->l('By position') ), ), 'id' => 'id', 'name' => 'name' ) ), array( 'type' => 'select', 'label' => $this->l('Sort order'), 'name' => 'CATEG_NC_SORT_WAY', $this->retro ? 'desc' : 'hint' => $this->l('Set whether to sort categories ascending or descending'), 'default_value' => Tools::getValue('CATEG_NC_SORT_WAY', Configuration::get('CATEG_NC_SORT_WAY')), 'options' => array( 'query' => array( array( 'id' => 0, 'name' => $this->l('Ascending') ), array( 'id' => 1, 'name' => $this->l('Descending') ), ), 'id' => 'id', 'name' => 'name' ) ), array( 'type' => 'text', 'label' => $this->l('Number of footer columns'), 'name' => 'CATEG_NC_NBR_COLUMN_FOOTER', 'class' => 'fixed-width-xs', $this->retro ? 'desc' : 'hint' => $this->l('Set the number of footer columns'), ), array( 'type' => 'text', 'label' => $this->l('Footer maximum depth'), 'name' => 'CATEG_NC_FOOTER_MAX_DEPTH', $this->retro ? 'desc' : 'hint' => $this->l('Set the maximum depth of sublevels displayed in the footer (0 = infinite)'), 'class' => 'fixed-width-xs' ), array( 'type' => $this->retro ? 'radio' : 'switch', 'class' => $this->retro ? 'auto_width' : null, 'is_bool' => true, 'label' => $this->l('Show Go buttons'), 'name' => 'CATEG_NC_SHOW_GO_BUTTONS', $this->retro ? 'desc' : 'hint' => $this->l('Whether to show Go buttons next to each dropdown to allow navigation to parent categories'), 'values' => array( array( 'id' => 'active_on', 'value' => 1, 'label' => $this->l('Enabled') ), array( 'id' => 'active_off', 'value' => 0, 'label' => $this->l('Disabled') ) ), ), array( 'type' => $this->retro ? 'radio' : 'switch', 'is_bool' => true, 'class' => $this->retro ? 'auto_width' : null, 'label' => $this->l('Show all dropdowns'), 'name' => 'CATEG_NC_SHOW_ALL_DROPDOWNS', $this->retro ? 'desc' : 'hint' => $this->l('Whether to start with the dropdowns displayed in a disabled state'), 'values' => array( array( 'id' => 'active_on', 'value' => 1, 'label' => $this->l('Enabled') ), array( 'id' => 'active_off', 'value' => 0, 'label' => $this->l('Disabled') ) ), ), array( 'type' => $this->retro ? 'radio' : 'switch', 'is_bool' => true, 'class' => $this->retro ? 'auto_width' : null, 'label' => $this->l('Fix IE select width'), 'name' => 'CATEG_NC_FIX_IE_SELECT_WIDTH', $this->retro ? 'desc' : 'hint' => $this->l('Adds code to fix a display bug with long category names in IE8 and below'), 'values' => array( array( 'id' => 'active_on', 'value' => 1, 'label' => $this->l('Enabled') ), array( 'id' => 'active_off', 'value' => 0, 'label' => $this->l('Disabled') ) ), ), array( 'type' => $this->retro ? 'radio' : 'switch', 'is_bool' => true, 'class' => $this->retro ? 'auto_width' : null, 'label' => $this->l('Hide empty categories'), 'name' => 'CATEG_NC_HIDE_EMPTY_CATEG', $this->retro ? 'desc' : 'hint' => $this->l('Hide categories that do not contain any products unless subcategories have products'), 'values' => array( array( 'id' => 'active_on', 'value' => 1, 'label' => $this->l('Enabled') ), array( 'id' => 'active_off', 'value' => 0, 'label' => $this->l('Disabled') ) ), ), array( 'type' => $this->retro ? 'radio' : 'switch', 'is_bool' => true, 'class' => $this->retro ? 'auto_width' : null, 'label' => $this->l('Save state'), 'name' => 'CATEG_NC_SAVE', $this->retro ? 'desc' : 'hint' => $this->l('Set whether to keep categories open when the page changes'), 'values' => array( array( 'id' => 'active_on', 'value' => 1, 'label' => $this->l('Enabled') ), array( 'id' => 'active_off', 'value' => 0, 'label' => $this->l('Disabled') ) ), ), array( 'type' => $this->retro ? 'radio' : 'switch', 'is_bool' => true, 'class' => $this->retro ? 'auto_width' : null, 'label' => $this->l('Reload categories'), 'name' => 'CATEG_NC_RELOAD', $this->retro ? 'desc' : 'hint' => $this->l('Set whether to reload categories when the page changes'), 'values' => array( array( 'id' => 'active_on', 'value' => 1, 'label' => $this->l('Enabled') ), array( 'id' => 'active_off', 'value' => 0, 'label' => $this->l('Disabled') ) ), ), array( 'type' => $this->retro ? 'radio' : 'switch', 'is_bool' => true, 'class' => $this->retro ? 'auto_width' : null, 'label' => $this->l('Show products'), 'name' => 'CATEG_NC_SHOW_PRODUCTS', $this->retro ? 'desc' : 'hint' => $this->l('Set whether to display products in the dropdowns'), 'values' => array( array( 'id' => 'active_on', 'value' => 1, 'label' => $this->l('Enabled') ), array( 'id' => 'active_off', 'value' => 0, 'label' => $this->l('Disabled') ) ), ), array( 'type' => 'categories', 'is_bool' => true, 'label' => $this->l('Start from'), 'name' => 'from_category', $this->retro ? 'desc' : 'hint' => $this->l('Set which category the dropdowns start from (select Home to display all categories)'), $this->retro ? 'values' : 'tree' => array( 'id' => 'categories-tree', 'selected_categories' => array(Tools::getValue('from_category', Configuration::get('CATEG_NC_START_FROM_CATEG'))), 'use_search' => true, 'trads' => array( 'Root' => $root_category, 'selected' => $this->l('selected'), 'Collapse All' => $this->l('Collapse All'), 'Expand All' => $this->l('Expand All'), 'search' => $this->l('Find a category') ), 'selected_cat' => array(Tools::getValue('from_category', Configuration::get('CATEG_NC_START_FROM_CATEG'))), 'disabled_categories' => array(), 'input_name' => 'from_category', 'use_radio' => true, 'top_category' => Category::getTopCategory(), 'use_context' => true, ) ), array( 'type' => 'select', 'label' => $this->l('Dropdown label position'), 'name' => 'CATEG_NC_LABEL_POSITION', $this->retro ? 'desc' : 'hint' => $this->l('Set whether the labels appear inside the dropdowns or outside'), 'default_value' => Tools::getValue('CATEG_NC_LABEL_POSITION', Configuration::get('CATEG_NC_LABEL_POSITION')), 'options' => array( 'query' => array( array( 'id' => 0, 'name' => $this->l('Inside') ), array( 'id' => 1, 'name' => $this->l('Outside') ) ), 'id' => 'id', 'name' => 'name' ) ) ), 'submit' => array( 'name' => 'submitSettings', 'title' => $this->l('Save'), 'class' => $this->retro ? 'button' : null, ) ) ); $depth = $this->getNumberOfLevels(Tools::getValue('from_category', Configuration::get('CATEG_NC_START_FROM_CATEG'))); for ($i = 1; $i <= $depth; $i++) $settings_form['form']['input'][] = array( 'type' => 'text', 'lang' => true, 'label' => $this->l('Dropdown label for level').' '.$i, 'name' => 'CATEG_NC_LABEL_'.$i, 'hint' => $this->l('Set the label for each level that appears before a category is selected') ); $product_count_cache_form = array( 'form' => array( 'legend' => array( 'title' => $this->l('Product Number Settings'), 'icon' => 'icon-sort-numeric-asc', 'image' => $this->retro ? $this->_path.'img/sort_number.png' : null ), 'input' => array( array( 'type' => 'select', 'label' => $this->l('Product number'), 'name' => 'CATEG_NC_NUM_PRODUCTS', 'hint' => $this->retro ? null : $this->l('Display the number of products in a category (and its subcategories) in brackets after its name'), 'desc' => ($this->retro ? $this->l('Display the number of products in a category (and its subcategories) in brackets after its name'). '</p><p id="cache_instructions" class="preference_description">' : ''). $this->l('Cache is automatically updated when adding or deleting products,').' '. $this->l('but must be regenerated if they are enabled or disabled'). '<br /><br />'.$this->l('To automatically regenerate the cache on a regular basis, create a cron job with the following URL:'). '<br />http://'.Tools::getHttpHost(false, true).__PS_BASE_URI__.'modules/'.$this->name. '/cron.php?secure_key='.Configuration::get('CATEG_NC_SECURE_KEY'), 'onchange' => 'updateForm(\'productNumberForm\', $(this).attr(\'id\'));', 'options' => array( 'query' => array( array( 'id' => 0, 'name' => $this->l('None') ), array( 'id' => 1, 'name' => $this->l('Categories') ), array( 'id' => 2, 'name' => $this->l('Categories and subcategories') ) ), 'id' => 'id', 'name' => 'name' ) ), array( 'type' => $this->retro ? 'radio' : 'switch', 'is_bool' => true, 'class' => $this->retro ? 'auto_width' : null, 'label' => $this->l('Hide zero counts'), 'name' => 'CATEG_NC_HIDE_ZERO_COUNTS', $this->retro ? 'desc' : 'hint' => $this->l('Hide the product number on empty categories'), 'values' => array( array( 'id' => 'CATEG_NC_HIDE_ZERO_COUNTS_on', 'value' => 1, 'label' => $this->l('Enabled') ), array( 'id' => 'CATEG_NC_HIDE_ZERO_COUNTS_off', 'value' => 0, 'label' => $this->l('Disabled') ) ) ) ), 'submit' => array( 'name' => 'submitProductNumber', 'title' => $this->l('Save'), 'class' => $this->retro ? 'button' : null, ) ) ); $css_form = array( 'form' => array( 'legend' => array( 'title' => $this->l('Custom CSS'), 'icon' => 'icon-code', 'image' => $this->retro ? $this->_path.'img/css.png' : null ), 'input' => array( array( 'type' => 'textarea', 'cols' => $this->retro ? '100' : null, 'rows' => $this->retro ? '5' : null, 'label' => $this->l('Custom CSS'), 'name' => 'CATEG_NC_CUSTOM_CSS', $this->retro ? 'desc' : 'hint' => $this->l('Change the width, height and margin of dropdowns and add custom CSS'), ) ), 'submit' => array( 'name' => 'submitCSS', 'title' => $this->l('Save'), 'class' => $this->retro ? 'button' : null, ) ) ); $troubleshooting_form = array( 'form' => array( 'legend' => array( 'title' => $this->l('Troubleshooting'), 'icon' => 'icon-wrench', 'image' => $this->retro ? $this->_path.'img/wrench.png' : null ), 'input' => array( array( 'type' => 'text', 'label' => $this->l('Maximum categories per query'), 'name' => 'CATEG_NC_MAX_CATEGORIES', $this->retro ? 'desc' : 'hint' => $this->l('If the memory limit is being exceeded, reduce this number to the reduce memory usage'), 'class' => 'fixed-width-xs' ) ), 'submit' => array( 'name' => 'submitTroubleshooting', 'title' => $this->l('Save'), 'class' => $this->retro ? 'button' : null, ) ) ); $helper = new HelperForm(); $helper->show_toolbar = false; $helper->table = $this->table; $lang = new Language((int)Configuration::get('PS_LANG_DEFAULT')); $helper->default_form_language = $lang->id; $helper->allow_employee_form_lang = Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG') ? Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG') : 0; $this->fields_form = array(); $helper->identifier = $this->identifier; $helper->submit_action = 'submitCategoriesNC'; $helper->currentIndex = $this->context->link->getAdminLink('AdminModules', false). '&configure='.$this->name.'&tab_module='.$this->tab.'&module_name='.$this->name; $helper->token = Tools::getAdminTokenLite('AdminModules'); $helper->tpl_vars = array( 'fields_value' => $this->getConfigFieldsValues(), 'languages' => $this->context->controller->getLanguages(), 'id_language' => $this->context->language->id ); $output = ($this->retro ? '<style>.margin-form > input[type="radio"] { float: left; margin-right: 6px }.auto_width { width: auto }</style>' : ''). $helper->generateForm(array($settings_form)).($this->retro ? '<br />' : ''); $product_count_cache_form_output = $helper->generateForm(array($product_count_cache_form)); // Manually add Regenerate Cache button, since there's no helper to add the button to the form if ($this->retro) $product_count_cache_form_output = str_replace('name="submitProductNumber"', 'name="submitProductNumber" class="button" /> <input type="button" name="submitRegenerateCache" value="'.$this->l('Regenerate cache'). '" onclick="document.location = \''.AdminController::$currentIndex.'&configure='.$this->name.'&submitRegenerateCache=1&token='. Tools::getAdminTokenLite('AdminModules').'\';"', $product_count_cache_form_output); else $product_count_cache_form_output = str_replace('<i class="icon-sort-numeric-asc"></i>', '<i class="icon-sort-numeric-asc"></i><span class="panel-heading-action"><a href="'. AdminController::$currentIndex.'&configure='.$this->name.'&submitRegenerateCache=1&token='. Tools::getAdminTokenLite('AdminModules'). '" class="list-toolbar-btn" id="desc-'.$this->name. '-repair"><span data-html="true" data-original-title="'. $this->l('Regenerate cache'). '" class="label-tooltip" data-toggle="tooltip" title=""><i class="process-icon-refresh"></i></span></a></span>', $product_count_cache_form_output); if ($this->retro) { $product_count_cache_form_output = $this->strReplaceFirst('<div class="clear"></div>', '<div class="clear"></div><div id="productNumberForm">', $product_count_cache_form_output); $product_count_cache_form_output = $this->strReplaceLast('<div class="margin-form">', '</div><div class="margin-form">', $product_count_cache_form_output); } else { $start = Tools::substr($product_count_cache_form_output, 0, strpos($product_count_cache_form_output, '<div class="form-group') + 1); $end = Tools::substr($product_count_cache_form_output, strpos($product_count_cache_form_output, '<div class="form-group') + 1); $end = $this->strReplaceFirst('<div class="form-group', '<div id="productNumberForm"><div class="form-group', $end); $end = str_replace('<div class="panel-footer', '</div><div class="panel-footer', $end); $product_count_cache_form_output = $start.$end; } $output .= $product_count_cache_form_output.($this->retro ? '<br />' : '').$helper->generateForm(array($css_form)); // Manually add Revert button, since there's no helper to add the button to the form if ($this->retro) $output = str_replace('name="submitCSS"', 'name="submitCSS" class="button" /> <input type="button" name="submitRestore" value="'. $this->l('Revert').'" onclick="if (confirm(\''. str_replace("'", "\'", $this->l('Are you sure? All modifications will be lost')).' '. str_replace("'", "\'", $this->l('after reverting to the original CSS.')). '\')) document.location = \''.AdminController::$currentIndex.'&configure='. $this->name.'&submitRestore=1&token='. Tools::getAdminTokenLite('AdminModules').'\';"', $output); else $output = str_replace('<i class="icon-code"></i>', '<i class="icon-code"></i><span class="panel-heading-action"><a href="'. AdminController::$currentIndex.'&configure='.$this->name.'&submitRestore=1&token='. Tools::getAdminTokenLite('AdminModules').'" class="list-toolbar-btn" id="desc-'.$this->name.'-revert" onclick="if (!confirm(\''. $this->l('Are you sure? All modifications will be lost').' '. $this->l('after reverting to the original CSS.'). '\')) return false;"><span data-html="true" data-original-title="'. $this->l('Revert').'" class="label-tooltip" data-toggle="tooltip" title=""><i class="process-icon-mail-reply"></i></span></a></span>', $output); $output .= ($this->retro ? '<br />' : '').$helper->generateForm(array($troubleshooting_form)); // Manually add Repair Tree button, since there's no helper to add the button to the form if ($this->retro) $output = str_replace('name="submitTroubleshooting"', 'name="submitTroubleshooting" class="button" /> <input type="button" name="submitRepairTree" value="'. $this->l('Repair tree').'" onclick="document.location = \''.AdminController::$currentIndex.'&configure='.$this->name. '&submitRepairTree=1&token='.Tools::getAdminTokenLite('AdminModules').'\';"', $output); else $output = str_replace('<i class="icon-wrench"></i>', '<i class="icon-wrench"></i><span class="panel-heading-action"><a href="'.AdminController::$currentIndex.'&configure='. $this->name.'&submitRepairTree=1&token='.Tools::getAdminTokenLite('AdminModules'). '" class="list-toolbar-btn" id="desc-'.$this->name.'-repair"><span data-html="true" data-original-title="'. $this->l('Repair tree').'" class="label-tooltip" data-toggle="tooltip" title=""><i class="process-icon-refresh"></i></span></a></span>', $output); $output .= ' <script type="text/javascript"> $(document).ready(function() { if (!parseInt($(\'#CATEG_NC_NUM_PRODUCTS\').val())) $(\'#productNumberForm\').hide(); if (parseInt($(\'#CATEG_NC_NUM_PRODUCTS\').val()) != 2 && !$(\'#CATEG_NC_HIDE_EMPTY_CATEG_on\').is(\':checked\')) $(\''.($this->retro ? '#cache_instructions' : '#productNumberForm').'\')'.($this->retro ? '' : '.parent().find(\'.help-block\')').'.hide(); }); function updateForm(form, select) { if (!parseInt($(\'#\'+select).val())) $(\'#\'+form).slideUp(); else if (form != \'accordionForm\') $(\'#\'+form).slideDown(); if (form == \'productNumberForm\' && (parseInt($(\'#\'+select).val()) == 2 || $(\'#CATEG_NC_HIDE_EMPTY_CATEG_on\').is(\':checked\'))) $(\''.($this->retro ? '#cache_instructions\'' : '#\'+form').')'.($this->retro ? '' : '.parent().find(\'.help-block\')').'.slideDown(); else if (form == \'productNumberForm\') $(\''.($this->retro ? '#cache_instructions\'' : '#\'+form').')'.($this->retro ? '' : '.parent().find(\'.help-block\')').'.slideUp(); } </script>'; return $output; } public function strReplaceFirst($search, $replace, $subject) { $pos = strpos($subject, $search); if ($pos !== false) $subject = substr_replace($subject, $replace, $pos, Tools::strlen($search)); return $subject; } public function strReplaceLast($search, $replace, $subject) { $pos = strrpos($subject, $search); if ($pos !== false) $subject = substr_replace($subject, $replace, $pos, Tools::strlen($search)); return $subject; } public function getConfigFieldsValues() { $fields = array( 'CATEG_NC_MAX_DEPTH' => Tools::getValue('CATEG_NC_MAX_DEPTH', Configuration::get('CATEG_NC_MAX_DEPTH')), 'CATEG_NC_NBR_COLUMN_FOOTER' => Tools::getValue('CATEG_NC_NBR_COLUMN_FOOTER', Configuration::get('CATEG_NC_NBR_COLUMN_FOOTER')), 'CATEG_NC_FOOTER_MAX_DEPTH' => Tools::getValue('CATEG_NC_FOOTER_MAX_DEPTH', Configuration::get('CATEG_NC_FOOTER_MAX_DEPTH')), 'CATEG_NC_SORT_WAY' => Tools::getValue('CATEG_NC_SORT_WAY', Configuration::get('CATEG_NC_SORT_WAY')), 'CATEG_NC_SORT' => Tools::getValue('CATEG_NC_SORT', Configuration::get('CATEG_NC_SORT')), 'CATEG_NC_NUM_PRODUCTS' => Tools::getValue('CATEG_NC_NUM_PRODUCTS', Configuration::get('CATEG_NC_NUM_PRODUCTS')), 'CATEG_NC_HIDE_ZERO_COUNTS' => Tools::getValue('CATEG_NC_HIDE_ZERO_COUNTS', Configuration::get('CATEG_NC_HIDE_ZERO_COUNTS')), 'CATEG_NC_SHOW_GO_BUTTONS' => Tools::getValue('CATEG_NC_SHOW_GO_BUTTONS', Configuration::get('CATEG_NC_SHOW_GO_BUTTONS')), 'CATEG_NC_SHOW_ALL_DROPDOWNS' => Tools::getValue('CATEG_NC_SHOW_ALL_DROPDOWNS', Configuration::get('CATEG_NC_SHOW_ALL_DROPDOWNS')), 'CATEG_NC_FIX_IE_SELECT_WIDTH' => Tools::getValue('CATEG_NC_FIX_IE_SELECT_WIDTH', Configuration::get('CATEG_NC_FIX_IE_SELECT_WIDTH')), 'CATEG_NC_HIDE_EMPTY_CATEG' => Tools::getValue('CATEG_NC_HIDE_EMPTY_CATEG', Configuration::get('CATEG_NC_HIDE_EMPTY_CATEG')), 'CATEG_NC_SAVE' => Tools::getValue('CATEG_NC_SAVE', Configuration::get('CATEG_NC_SAVE')), 'CATEG_NC_RELOAD' => Tools::getValue('CATEG_NC_RELOAD', Configuration::get('CATEG_NC_RELOAD')), 'CATEG_NC_SHOW_PRODUCTS' => Tools::getValue('CATEG_NC_SHOW_PRODUCTS', Configuration::get('CATEG_NC_SHOW_PRODUCTS')), 'CATEG_NC_LABEL_POSITION' => Tools::getValue('CATEG_NC_LABEL_POSITION', Configuration::get('CATEG_NC_LABEL_POSITION')), 'CATEG_NC_MAX_CATEGORIES' => Tools::getValue('CATEG_NC_MAX_CATEGORIES', Configuration::get('CATEG_NC_MAX_CATEGORIES')), ); $languages = Language::getLanguages(false); $depth = $this->getNumberOfLevels(Tools::getValue('from_category', Configuration::get('CATEG_NC_START_FROM_CATEG'))); for ($i = 1; $i <= $depth; $i++) foreach ($languages as $lang) $fields['CATEG_NC_LABEL_'.$i][$lang['id_lang']] = Tools::getValue('CATEG_NC_LABEL_'.$i.'_'.$lang['id_lang'], Configuration::get('CATEG_NC_LABEL_'.$i, $lang['id_lang'])); $fname = _PS_MODULE_DIR_.$this->name.'/css/'.$this->name.'.css'; if (file_exists($fname)) { $fhandle = fopen($fname, 'r'); $custom_css = (filesize($fname) > 0 ? fread($fhandle, filesize($fname)) : ''); fclose($fhandle); } else $custom_css = ''; $fields['CATEG_NC_CUSTOM_CSS'] = Tools::getValue('CATEG_NC_CUSTOM_CSS', $custom_css); return $fields; } public function getTree($result_parents, $result_ids, $max_depth, $id_category = null, $current_depth = 0, $num_products = null, $cache = false, $repair = false) { if (is_null($id_category)) $id_category = $this->context->shop->getCategory(); $children = array(); $num_subcat_products = 0; if (array_key_exists($id_category, $result_parents) && count($result_parents[$id_category]) && ($max_depth == 0 || $current_depth < $max_depth)) { foreach ($result_parents[$id_category] as $subcat) $children[] = $this->getTree($result_parents, $result_ids, $max_depth, $subcat['id_category'], $current_depth + 1, $num_products, $cache, $repair); foreach ($children as $child) { $num_subcat_products += $child['numProductsSub']; if (count($child['children']) && $id_category > $this->context->shop->getCategory()) $this->parents[$id_category] = true; } } elseif (!array_key_exists($id_category, $result_parents) && Configuration::get('CATEG_NC_SHOW_PRODUCTS') && ($max_depth == 0 || $current_depth < $max_depth)) { $sql = ' SELECT p.`id_product`, p.`id_category_default`, pl.`name`, pl.`link_rewrite` FROM `'._DB_PREFIX_.'category_product` cp LEFT JOIN `'._DB_PREFIX_.'product` p ON (cp.`id_product` = p.`id_product`) LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (cp.`id_product` = pl.`id_product`) WHERE cp.`id_category` = '.$id_category.' && p.`active` = 1 && pl.`id_lang` = '.(int)$this->context->cookie->id_lang; $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); foreach ($result as $product) { $default_category = new Category($product['id_category_default'], (int)$this->context->cookie->id_lang); $children[] = array('id' => $product['id_product'], 'link' => $this->context->link->getProductLink($product['id_product'], $product['link_rewrite'], $default_category->link_rewrite), 'name' => $product['name'], 'nleft' => 0, 'nright' => 1, 'level_depth' => $current_depth + 1, 'numProducts' => 0, 'numProductsSub' => 0, 'children' => array()); } } if (!array_key_exists($id_category, $result_ids)) return false; if (Configuration::get('CATEG_NC_HIDE_EMPTY_CATEG') == 1 && $num_subcat_products == 0) $children = array(); if ($repair) Db::getInstance(_PS_USE_SQL_SLAVE_)->Execute(' UPDATE `'._DB_PREFIX_.'category` SET `level_depth` = '.$current_depth.' WHERE `id_category` = '.$id_category); return array( 'id' => $id_category, 'link' => $this->context->link->getCategoryLink($id_category, array_key_exists('link_rewrite', $result_ids[$id_category]) ? $result_ids[$id_category]['link_rewrite'] : null), 'nleft' => array_key_exists('nleft', $result_ids[$id_category]) ? $result_ids[$id_category]['nleft'] : 0, 'nright' => array_key_exists('nright', $result_ids[$id_category]) ? $result_ids[$id_category]['nright'] : 0, 'name' => array_key_exists('name', $result_ids[$id_category]) ? $result_ids[$id_category]['name'] : '', 'level_depth' => array_key_exists('level_depth', $result_ids[$id_category]) ? $result_ids[$id_category]['level_depth'] : $current_depth, 'desc' => array_key_exists('description', $result_ids[$id_category]) ? $result_ids[$id_category]['description'] : '', 'numProducts' => (Configuration::get('CATEG_NC_NUM_PRODUCTS') == 2 ? ($cache ? (($num_subcat_products + (is_array($num_products) && array_key_exists($id_category, $num_products) ? $num_products[$id_category] : 0))) : (array_key_exists('num_products', $result_ids[$id_category]) ? $result_ids[$id_category]['num_products'] : 0)) : (is_array($num_products) && array_key_exists($id_category, $num_products) ? $num_products[$id_category] : 0)), 'numProductsSub' => $cache ? (($num_subcat_products + (is_array($num_products) && array_key_exists($id_category, $num_products) ? $num_products[$id_category] : 0))) : (array_key_exists('num_products', $result_ids[$id_category]) ? $result_ids[$id_category]['num_products'] : 0), 'children' => $children); } public function getTreeFooter($result_parents, $result_ids, $max_depth, $id_category = null, $current_depth = 0) { if (is_null($id_category)) $id_category = $this->context->shop->getCategory(); $children = array(); if (array_key_exists($id_category, $result_parents) && count($result_parents[$id_category]) && ($max_depth == 0 || $current_depth < $max_depth)) foreach ($result_parents[$id_category] as $subcat) $children[] = $this->getTree($result_parents, $result_ids, $max_depth, $subcat['id_category'], $current_depth + 1); if (!array_key_exists($id_category, $result_ids)) return false; return array( 'id' => $id_category, 'link' => $this->context->link->getCategoryLink($id_category, $result_ids[$id_category]['link_rewrite']), 'name' => $result_ids[$id_category]['name'], 'desc'=> $result_ids[$id_category]['description'], 'children' => $children); } protected function createCache() { Db::getInstance(_PS_USE_SQL_SLAVE_)->Execute('TRUNCATE `'._DB_PREFIX_.'blockcategoriesnc_numproducts`'); $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT COUNT(*) as "num_categories" FROM `'._DB_PREFIX_.'category_product`'); $total = 0; if (is_array($result) && count($result) > 0) $total = $result[0]['num_categories']; // Load this many subcategories at a time to keep memory usage low $n = Configuration::get('CATEG_NC_MAX_CATEGORIES'); $i = 0; $percent = 0; echo '<div id="progress">'.$this->l('Counting number of products in each category').'...<span id="p'.$percent.'">'.$percent.'%</span>'; Db::getInstance(_PS_USE_SQL_SLAVE_)->execute(' INSERT INTO `'._DB_PREFIX_.'blockcategoriesnc_numproducts` (`id_category`, `num_products`) SELECT `id_category`, 0 FROM `'._DB_PREFIX_.'category` WHERE `id_category` NOT IN (SELECT DISTINCT(`id_category`) FROM `'._DB_PREFIX_.'category_product`)'); if ($total > 0) do { if (floor((($i * $n) / (float)$total) * 100) > $percent) { $previous_percent = $percent; $percent = floor((($i * $n) / (float)$total) * 100); echo '<span id="p'.$percent.'">'.$percent.'%</span><style type="text/css">#p'.$previous_percent.' { display: none }</style>'; } $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT DISTINCT `id_category` FROM `'._DB_PREFIX_.'category_product` LIMIT '.($i * $n).', '.$n); $num_results = count($result); foreach ($result as $row) Db::getInstance(_PS_USE_SQL_SLAVE_)->execute(' INSERT INTO `'._DB_PREFIX_.'blockcategoriesnc_numproducts` (`id_category`, `num_products`) SELECT '.$row['id_category'].', COUNT(*) FROM `'._DB_PREFIX_.'category_product` cp LEFT JOIN `'._DB_PREFIX_.'product` p ON cp.`id_product` = p.`id_product` WHERE cp.`id_category` = '.$row['id_category'].' && p.`active` = 1'); $i++; } while ($num_results == $n); echo '<span id="p100">100%</span><style type="text/css">#p'.$percent.' { display: none }</style>'; $i = 0; $previous_percent = 0; $percent = 0; echo '<br />'.$this->l('Adding counts to parent categories').'...<span id="pc'.$percent.'">'.$percent.'%</span>'; if ($total > 0) CategoriesNC::addProductCountsToParents(); echo '</div><style type="text/css">#pc'.$percent.', #progress { display: none }</style>'; } /** * Re-calculate the values of all branches of the nested tree */ protected static function addProductCountsToParents() { $id = Context::getContext()->shop->id; $id_shop = $id ? $id: Configuration::get('PS_SHOP_DEFAULT'); $categories = Db::getInstance()->executeS(' SELECT c.`id_category`, c.`id_parent` FROM `'._DB_PREFIX_.'category` c LEFT JOIN `'._DB_PREFIX_.'category_shop` cs ON (c.`id_category` = cs.`id_category` && cs.`id_shop` = '.(int)$id_shop.') ORDER BY c.`id_parent`, cs.`position` ASC'); $categories_array = array(); foreach ($categories as $category) $categories_array[$category['id_parent']]['subcategories'][] = $category['id_category']; $i = 0; $percent = 0; $total = count($categories); if (array_key_exists(0, $categories_array) && array_key_exists('subcategories', $categories_array[0])) CategoriesNC::countProducts($categories_array, 0, $categories_array[0]['subcategories'][0], $i, $percent, $total); } protected static function countProducts(&$categories, $id_parent, $id_category, &$i, &$percent, &$total) { if (array_key_exists((int)$id_category, $categories) && array_key_exists('subcategories', $categories[(int)$id_category])) foreach ($categories[(int)$id_category]['subcategories'] as $id_subcategory) CategoriesNC::countProducts($categories, $id_category, (int)$id_subcategory, $i, $percent, $total); $num_products = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT `num_products` FROM `'._DB_PREFIX_.'blockcategoriesnc_numproducts` WHERE `id_category` = '.$id_category); if (is_array($num_products) && count($num_products) > 0 && $num_products[0]['num_products'] > 0 && $id_parent > 0) Db::getInstance(_PS_USE_SQL_SLAVE_)->execute(' UPDATE `'._DB_PREFIX_.'blockcategoriesnc_numproducts` SET `num_products` = `num_products` + '.$num_products[0]['num_products'].' WHERE `id_category` = '.$id_parent); $i++; if (floor(($i / (float)$total) * 100) > $percent) { $previous_percent = $percent; $percent = floor(($i / (float)$total) * 100); echo '<span id="pc'.$percent.'">'.$percent.'%</span><style type="text/css">#pc'.$previous_percent.' { display: none }</style>'; } } protected function recalculateLevelDepth($id_category, &$i, &$percent, $total) { if (!is_numeric($id_category)) throw new PrestaShopException('id category is not numeric'); /* Gets all children */ $categories = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT id_category, id_parent, level_depth FROM '._DB_PREFIX_.'category WHERE id_parent = '.(int)$id_category); /* Gets level_depth */ $level = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT level_depth FROM '._DB_PREFIX_.'category WHERE id_category = '.(int)$id_category); /* Updates level_depth for all children */ foreach ($categories as $sub_category) { Db::getInstance()->execute(' UPDATE '._DB_PREFIX_.'category SET level_depth = '.((int)$level['level_depth'] + 1).' WHERE id_category = '.(int)$sub_category['id_category']); /* Recursive call */ $this->recalculateLevelDepth($sub_category['id_category'], $i, $percent, $total); } $i++; if (floor(($i / (float)$total) * 100) > $percent) { $previous_percent = $percent; $percent = floor(($i / (float)$total) * 100); echo '<span id="p'.$percent.'">'.$percent.'%</span><style type="text/css">#p'.$previous_percent.' { display: none }</style>'; } } /** * Re-calculate the values of all branches of the nested tree */ protected static function regenerateEntireNtree() { $id = Context::getContext()->shop->id; $id_shop = $id ? $id: Configuration::get('PS_SHOP_DEFAULT'); $categories = Db::getInstance()->executeS(' SELECT c.`id_category`, c.`id_parent` FROM `'._DB_PREFIX_.'category` c LEFT JOIN `'._DB_PREFIX_.'category_shop` cs ON (c.`id_category` = cs.`id_category` && cs.`id_shop` = '.(int)$id_shop.') ORDER BY c.`id_parent`, cs.`position` ASC'); $categories_array = array(); foreach ($categories as $category) $categories_array[$category['id_parent']]['subcategories'][] = $category['id_category']; $n = 1; $i = 0; $percent = 0; $total = count($categories); if (array_key_exists(0, $categories_array) && array_key_exists('subcategories', $categories_array[0])) CategoriesNC::subTree($categories_array, $categories_array[0]['subcategories'][0], $n, $i, $percent, $total); } protected static function subTree(&$categories, $id_category, &$n, &$i, &$percent, &$total) { $left = $n++; if (array_key_exists((int)$id_category, $categories) && array_key_exists('subcategories', $categories[(int)$id_category])) foreach ($categories[(int)$id_category]['subcategories'] as $id_subcategory) CategoriesNC::subTree($categories, (int)$id_subcategory, $n, $i, $percent, $total); $right = (int)$n++; Db::getInstance()->execute(' UPDATE '._DB_PREFIX_.'category SET nleft = '.(int)$left.', nright = '.(int)$right.' WHERE id_category = '.(int)$id_category.' LIMIT 1 '); $i++; if (floor(($i / (float)$total) * 100) > $percent) { $previous_percent = $percent; $percent = floor(($i / (float)$total) * 100); echo '<span id="pc'.$percent.'">'.$percent.'%</span><style type="text/css">#pc'.$previous_percent.' { display: none }</style>'; } } protected function repairTree() { $i = 0; $percent = 0; $total = 0; echo '<div id="progress">'.$this->l('Recalculating level depths').'...<span id="p'.$percent.'">'.$percent.'%</span>'; $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT COUNT(*) as "num_categories" FROM `'._DB_PREFIX_.'category`'); if (is_array($result) && count($result) > 0) $total = $result[0]['num_categories']; $category = new Category(Configuration::get('PS_ROOT_CATEGORY')); $this->recalculateLevelDepth($category->id, $i, $percent, $total); $i = 0; $percent = 0; $total = 0; echo '<br />'.$this->l('Recalculating nested tree').'...<span id="pc'.$percent.'">'.$percent.'%</span>'; $this->regenerateEntireNtree(); echo '</div><style type="text/css">#pc'.$percent.', #progress { display: none }</style>'; } public function hookAddProduct($params) { if ($params['product']->active == 1 && Configuration::get('CATEG_NC_NUM_PRODUCTS') == 2) { $categories = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS(' SELECT `id_category` FROM `'._DB_PREFIX_.'category_product` WHERE `id_product` = '.$params['product']->id); if (count($categories) > 0) { $sql = 'UPDATE `'._DB_PREFIX_.'blockcategoriesnc_numproducts` SET `num_products` = `num_products` + 1 WHERE '; foreach ($categories as $category) $sql .= '`id_category` = '.$category['id_category'].' OR '; $sql = Tools::substr($sql, 0, Tools::strlen($sql) - 4); Db::getInstance(_PS_USE_SQL_SLAVE_)->Execute($sql); } } } public function hookDeleteProduct($params) { if ($params['product']->active == 1 && Configuration::get('CATEG_NC_NUM_PRODUCTS') == 2) { $categories = Product::getProductCategories($params['product']->id); if (count($categories) > 0) { $sql = 'UPDATE `'._DB_PREFIX_.'blockcategoriesnc_numproducts` SET `num_products` = `num_products` - 1 WHERE '; foreach ($categories as $category) $sql .= '`id_category` = '.$category['id_category'].' OR '; $sql = Tools::substr($sql, 0, Tools::strlen($sql) - 4); Db::getInstance(_PS_USE_SQL_SLAVE_)->Execute($sql); } } } /* public function hookUpdateProduct($params) { return $this->createCache(); } */ protected function getIEVersion() { $ie_version = 0; if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE')) { $ie_version = Tools::substr($_SERVER['HTTP_USER_AGENT'], strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') + 5); $ie_version = (float)Tools::substr($ie_version, 0, strpos($ie_version, ';')); } return $ie_version; } public function hookHeader() { $ie_version = $this->getIEVersion(); $this->context->controller->addCSS(($this->_path).'css/'.$this->name.'.css'); if (Configuration::get('CATEG_NC_FIX_IE_SELECT_WIDTH') && $ie_version > 0 && $ie_version < 9) { $this->context->controller->addCSS($this->_path.'css/ie-select-width.css'); $this->context->controller->addJqueryPlugin('dimensions'); $this->context->controller->addJS($this->_path.'js/jquery.ie-select-width.js'); if ($ie_version <= 6) $this->context->controller->addJS($this->_path.'js/jquery.bgiframe.js'); } } public function hookDisplayHome($params) { $max_depth = Configuration::get('CATEG_NC_MAX_DEPTH'); $num_products = Configuration::get('CATEG_NC_NUM_PRODUCTS'); $home_category = Configuration::get('CATEG_NC_START_FROM_CATEG'); $id_category = (int)Tools::getValue('id_category'); $id_product = (int)Tools::getValue('id_product'); if (Tools::isSubmit('id_category')) { $this->context->cookie->last_visited_category = $id_category; $this->smarty->assign('currentCategoryId', $this->context->cookie->last_visited_category); } elseif (Tools::isSubmit('id_product')) { if (!$this->context->cookie->last_visited_category || !Product::idIsOnCategoryId($id_product, array('0' => array('id_category' => $this->context->cookie->last_visited_category)))) { $product = new Product($id_product); if (Validate::isLoadedObject($product)) $this->context->cookie->last_visited_category = (int)$product->id_category_default; } $this->smarty->assign('currentCategoryId', (int)$this->context->cookie->last_visited_category); } else $category = $home_category; if (Tools::isSubmit('id_category') || Tools::isSubmit('id_product')) $category = $this->context->cookie->last_visited_category; $category = $this->context->cookie->last_visited_category; $num_dropdowns = 1; $home_depth = 0; $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT `level_depth` FROM `'._DB_PREFIX_.'category` WHERE `id_category` = '.$home_category); if (is_array($result) && count($result) > 0) $home_depth = $result[0]['level_depth']; if (Configuration::get('CATEG_NC_SHOW_ALL_DROPDOWNS')) { $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT MAX(`level_depth`) as `max_depth` FROM `'._DB_PREFIX_.'category`'.(Configuration::get('CATEG_NC_HIDE_EMPTY_CATEG') ? ' c INNER JOIN `'._DB_PREFIX_.'blockcategoriesnc_numproducts` bn ON (c.`id_category` = bn.`id_category`) WHERE `num_products` > 0' : '')); if (is_array($result) && count($result) > 0) { $depth = ($max_depth > 0 && $result[0]['max_depth'] > $max_depth) ? $max_depth : $result[0]['max_depth']; $depth -= $home_depth; if (Configuration::get('CATEG_NC_SHOW_PRODUCTS')) $depth++; if ($max_depth > 0 && $depth > $max_depth) $depth = $max_depth; $num_dropdowns = $depth; } } $category_subquery = ' OR c.`id_category` = '.$home_category; $sql = 'SELECT `id_category` FROM `'._DB_PREFIX_.'category` WHERE `id_parent` = '.$home_category; $categories = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS($sql); foreach ($categories as $category) $category_subquery .= ' OR c.`id_category` = '.$category['id_category']; $subcategory_subquery = $category_subquery; if ($max_depth != 1 && ($id_category || Tools::isSubmit('id_product'))) { $sql = 'SELECT `id_category` FROM `'._DB_PREFIX_.'category` WHERE `id_parent` = '.$id_category; $subcategories = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS($sql); foreach ($subcategories as $subcategory) $subcategory_subquery .= ' OR c.`id_category` = '.$subcategory['id_category']; } else $subcategory_subquery = $category_subquery; $groups = ' && ('; if ((int)$this->context->cookie->id_customer) { $customer = new Customer((int)$this->context->cookie->id_customer); if (Validate::isLoadedObject($customer)) { $customer_groups = $customer->getGroups(); foreach ($customer_groups as $customer_group) $groups .= 'cg.`id_group` = '.(int)$customer_group.' OR '; } if (Tools::strlen($groups) > 6) $groups = Tools::substr($groups, 0, Tools::strlen($groups) - 4).')'; } else $groups .= 'cg.`id_group` = 1)'; if (Tools::isSubmit('id_category')) { $this->context->cookie->last_visited_category = $id_category; $this->smarty->assign('currentCategoryId', $this->context->cookie->last_visited_category); } elseif (Tools::isSubmit('id_product')) { if (!$this->context->cookie->last_visited_category || !Product::idIsOnCategoryId($id_product, array('0' => array('id_category' => $this->context->cookie->last_visited_category)))) { $product = new Product($id_product); if (Validate::isLoadedObject($product)) $this->context->cookie->last_visited_category = (int)$product->id_category_default; } $this->smarty->assign('currentCategoryId', (int)$this->context->cookie->last_visited_category); } else $category = $home_category; if (Tools::isSubmit('id_category') || Tools::isSubmit('id_product')) $category = $this->context->cookie->last_visited_category; $breadcrumbs = array(); $breadcrumb_names = array(); $breadcrumb_links = array(); $last_breadcrumb_is_product = false; if ($category > 1) { $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT `level_depth` FROM `'._DB_PREFIX_.'category` WHERE `id_category` = '.$category); if ($result != null && count($result) > 0) $depth = $result[0]['level_depth']; $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT `level_depth` FROM `'._DB_PREFIX_.'category` WHERE `id_category` = '.$home_category); if ($result != null && count($result) > 0) $depth -= $result[0]['level_depth']; $depth++; $sql = 'SELECT '; for ($i = 1; $i <= $depth; $i++) $sql .= 't'.$i.'.`id_category` as lev'.$i.($i < $depth ? ', ' : ''); $sql .= ' FROM `'._DB_PREFIX_.'category` as t1 '; for ($i = 1; $i < $depth; $i++) $sql .= 'LEFT JOIN `'._DB_PREFIX_.'category` as t'.($i + 1).' on t'.($i + 1).'.`id_parent` = t'.$i.'.`id_category` '; $sql .= 'WHERE t1.`id_category` = '.$home_category.' && t'.$depth.'.`id_category` = '.$category; $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); for ($i = 2; $i <= ($max_depth > 0 && $max_depth < $depth ? $max_depth : $depth) && array_key_exists('lev'.$i, $result[0]); $i++) $breadcrumbs[] = $result[0]['lev'.$i]; if (Tools::getValue('id_product') > 0 && Configuration::get('CATEG_NC_SHOW_PRODUCTS') && ($max_depth == 0 || ($max_depth > 0 && count($breadcrumbs <= $max_depth)))) $breadcrumbs[] = (int)Tools::getValue('id_product'); if (!Configuration::get('CATEG_NC_RELOAD')) { $num_breadcrumbs = count($breadcrumbs); for ($i = 0; $i < $num_breadcrumbs; $i++) { if (Tools::getValue('id_product') && Configuration::get('CATEG_NC_SHOW_PRODUCTS') && $i == $num_breadcrumbs - 1) { $product = new Product((int)Tools::getValue('id_product'), false, (int)$this->context->cookie->id_lang); $breadcrumb_names[] = $product->name; $breadcrumb_links[] = $this->context->link->getProductLink($product->id, $product->link_rewrite); $last_breadcrumb_is_product = true; } else { $category = new Category($breadcrumbs[$i], (int)$this->context->cookie->id_lang); $breadcrumb_names[] = $category->name; $breadcrumb_links[] = $this->context->link->getCategoryLink($category->id, $category->link_rewrite); } } } } if ($num_products == 2 && !Configuration::get('CATEG_NC_RELOAD')) foreach ($breadcrumbs as $breadcrumb) $subcategory_subquery .= ' OR c.`id_category` = '.$breadcrumb; $sql = ' SELECT DISTINCT c.`id_category`, c.`id_parent`, c.`level_depth`, c.`nleft`, c.`nright`, cl.`id_lang`, cl.`name`, cl.`link_rewrite`'. ((Configuration::get('CATEG_NC_HIDE_EMPTY_CATEG') == 1 || $num_products == 2) ? ', bn.`num_products`' : '').' FROM `'._DB_PREFIX_.'category` c LEFT JOIN `'._DB_PREFIX_.'category_shop` cs ON (c.`id_category` = cs.`id_category`) LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (c.`id_category` = cl.`id_category` && cl.`id_lang` = '. (int)$params['cookie']->id_lang.' && cl.`id_shop` = '.(int)$this->context->shop->id.') '.((Configuration::get('CATEG_NC_HIDE_EMPTY_CATEG') == 1 || $num_products == 2) ? 'LEFT JOIN `'._DB_PREFIX_.'blockcategoriesnc_numproducts` bn ON (c.`id_category` = bn.`id_category`)' : '').' LEFT JOIN `'._DB_PREFIX_.'category_group` cg ON (cg.`id_category` = c.`id_category`) WHERE c.`active` = 1'.$groups.' && (`level_depth` <= 1'.$subcategory_subquery.') ORDER BY `level_depth` ASC, '.(Configuration::get('CATEG_NC_SORT') ? 'cl.`name`' : 'cs.`position`').' '. (Configuration::get('CATEG_NC_SORT_WAY') ? 'DESC' : 'ASC'); if (!$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS($sql)) return; $result_parents = array(); $result_ids = array(); $result_products = array(); foreach ($result as $row) { $result_parents[$row['id_parent']][] = $row; $result_ids[$row['id_category']] = $row; } if ($num_products == 1) { $sql = ' SELECT `id_category`, COUNT(*) as "num_products" FROM `'._DB_PREFIX_.'category_product` cp LEFT JOIN `'._DB_PREFIX_.'product` p ON (cp.`id_product` = p.`id_product`) WHERE p.`active` = 1 AND '; $first = true; foreach ($result as $row) { if (!$first) $sql .= 'id_category = '.$row['id_category'].' OR '; else $first = false; } if (!Configuration::get('CATEG_NC_RELOAD')) foreach ($breadcrumbs as $breadcrumb) $sql .= 'id_category = '.$breadcrumb.' OR '; $sql = Tools::substr($sql, 0, Tools::strlen($sql) - 4); $sql .= ' GROUP BY `id_category`'; $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS($sql); if ($result) foreach ($result as $row) $result_products[$row['id_category']] = $row['num_products']; } $num_breadcrumb_names = count($breadcrumb_names); if ($num_products > 0 && !Configuration::get('CATEG_NC_RELOAD')) for ($i = 0; $i < $num_breadcrumb_names; $i++) if ($i < $num_breadcrumb_names - 1 || ($i == count($breadcrumb_names) - 1 && !$last_breadcrumb_is_product)) { $product_number = ($num_products == 1 ? (array_key_exists($breadcrumbs[$i], $result_products) ? $result_products[$breadcrumbs[$i]] : 0) : $result_ids[$breadcrumbs[$i]]['num_products']); if (!Configuration::get('CATEG_NC_HIDE_ZERO_COUNTS') || (Configuration::get('CATEG_NC_HIDE_ZERO_COUNTS') && $product_number > 0)) $breadcrumb_names[$i] .= ' ('.$product_number.')'; } $last_breadcrumb_has_children = false; if (count($breadcrumbs) > 0 && ($max_depth == 0 || ($max_depth > 0 && $home_depth + $depth <= $max_depth))) { $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS(' SELECT COUNT(`id_category`) as num_children FROM `'._DB_PREFIX_.'category` WHERE `id_parent` = '.$breadcrumbs[count($breadcrumbs) - 1]); if (is_array($result) && count($result) > 0 && $result[0]['num_children'] > 0) $last_breadcrumb_has_children = true; } $categ_tree = $this->getTree($result_parents, $result_ids, 0, $home_category, 0, $result_products); $ie_version = $this->getIEVersion(); $this->context->smarty->assign(array( 'retro' => $this->retro, 'lastBreadcrumbHasChildren' => $last_breadcrumb_has_children, 'numDropdowns' => $num_dropdowns, 'column' => array_key_exists('column', $params) ? $params['column'] : 0, 'friendlyURL' => (int)Configuration::get('PS_REWRITING_SETTINGS'), 'categTree' => $categ_tree, 'breadcrumbs' => $breadcrumbs, 'breadcrumbNames' => $breadcrumb_names, 'breadcrumbLinks' => $breadcrumb_links, 'maxDepth' => (int)Configuration::get('CATEG_NC_MAX_DEPTH'), 'showGoButtons' => (int)Configuration::get('CATEG_NC_SHOW_GO_BUTTONS'), 'showAllDropdowns' => (int)Configuration::get('CATEG_NC_SHOW_ALL_DROPDOWNS'), 'iefix' => (bool)Configuration::get('CATEG_NC_FIX_IE_SELECT_WIDTH') && $ie_version > 0 && $ie_version < 9, 'showProductNum' => (int)Configuration::get('CATEG_NC_NUM_PRODUCTS'), 'hideZeroCounts' => (int)Configuration::get('CATEG_NC_HIDE_ZERO_COUNTS'), 'hideEmptyCategories' => (int)Configuration::get('CATEG_NC_HIDE_EMPTY_CATEG'), 'save' => (int)Configuration::get('CATEG_NC_SAVE'), 'reload' => (int)Configuration::get('CATEG_NC_RELOAD'), 'showProducts' => (int)Configuration::get('CATEG_NC_SHOW_PRODUCTS'), 'labelPosition' => (int)Configuration::get('CATEG_NC_LABEL_POSITION'))); $i = 1; $labels = array(); do { $label = Configuration::getInt('CATEG_NC_LABEL_'.$i); if (is_array($label) && array_key_exists((int)$this->context->cookie->id_lang, $label) && trim($label[(int)$this->context->cookie->id_lang]) != '') $labels[$i] = $label[(int)$this->context->cookie->id_lang]; else break; $i++; } while (true); $this->context->smarty->assign('labels', $labels); return $this->display(__FILE__, $this->name.'.tpl'); } public function hookDisplayTop($params) { return $this->hookDisplayHome($params); } public function hookDisplayLeftColumn($params) { $params['column'] = 1; return $this->hookDisplayHome($params); } public function hookDisplayRightColumn($params) { $params['column'] = 1; return $this->hookDisplayHome($params); } public function hookDisplayFooter() { // Get all groups for this customer and concatenate them as a string: "1,2,3..." if (!$this->isCached('blockcategories_footer.tpl', $this->getCacheId())) { $maxdepth = Configuration::get('CATEG_NC_FOOTER_MAX_DEPTH'); $groups = implode(', ', Customer::getGroupsStatic((int)$this->context->customer->id)); $num_products = Configuration::get('CATEG_NC_NUM_PRODUCTS'); if (!$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT DISTINCT c.id_parent, c.id_category, cl.name, cl.description, cl.link_rewrite'. ((Configuration::get('CATEG_NC_HIDE_EMPTY_CATEG') == 1 || $num_products == 2) ? ', bn.`num_products`' : '').' FROM `'._DB_PREFIX_.'category` c '.Shop::addSqlAssociation('category', 'c').' LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (c.`id_category` = cl.`id_category` && cl.`id_lang` = '. (int)$this->context->language->id.Shop::addSqlRestrictionOnLang('cl').') LEFT JOIN `'._DB_PREFIX_.'category_group` cg ON (cg.`id_category` = c.`id_category`) '.((Configuration::get('CATEG_NC_HIDE_EMPTY_CATEG') == 1 || $num_products == 2) ? 'LEFT JOIN `'._DB_PREFIX_.'blockcategoriesnc_numproducts` bn ON (c.`id_category` = bn.`id_category`)' : '').' WHERE (c.`active` = 1 OR c.`id_category` = '.$this->context->shop->getCategory().') '.((int)$maxdepth != 0 ? ' && `level_depth` <= '.(int)$maxdepth : '').' AND cg.`id_group` IN ('.pSQL($groups).') ORDER BY `level_depth` ASC, '.(Configuration::get('CATEG_NC_SORT') ? 'cl.`name`' : 'category_shop.`position`').' '. (Configuration::get('CATEG_NC_SORT_WAY') ? 'DESC' : 'ASC'))) return; $result_parents = array(); $result_ids = array(); foreach ($result as &$row) { $result_parents[$row['id_parent']][] = &$row; $result_ids[$row['id_category']] = &$row; } $nbr_columns = Configuration::get('CATEG_NC_NBR_COLUMN_FOOTER'); if (!$nbr_columns) $nbr_columns = 3; $number_column = abs(count($result) / $nbr_columns); $width_column = floor(100 / $nbr_columns); $this->smarty->assign('numberColumn', $number_column); $this->smarty->assign('widthColumn', $width_column); $result_products = array(); if (Configuration::get('CATEG_NC_NUM_PRODUCTS') == 1) { $sql = ' SELECT `id_category`, COUNT(*) as "num_products" FROM `'._DB_PREFIX_.'category_product` cp LEFT JOIN `'._DB_PREFIX_.'product` p ON (cp.`id_product` = p.`id_product`) WHERE p.`active` = 1 AND '; $first = true; foreach ($result as $row) { if (!$first) $sql .= 'id_category = '.$row['id_category'].' OR '; else $first = false; } $sql = Tools::substr($sql, 0, Tools::strlen($sql) - 4); $sql .= ' GROUP BY `id_category`'; $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS($sql); if ($result) foreach ($result as $row) $result_products[$row['id_category']] = $row['num_products']; } $block_categ_tree = $this->getTreeFooter($result_parents, $result_ids, Configuration::get('CATEG_NC_FOOTER_MAX_DEPTH'), null, 0, $result_products); unset($result_parents, $result_ids); $id_category = (int)Tools::getValue('id_category'); $id_product = (int)Tools::getValue('id_product'); if (Tools::isSubmit('id_category')) { $this->context->cookie->last_visited_category = $id_category; $this->smarty->assign('currentCategoryId', $this->context->cookie->last_visited_category); } elseif (Tools::isSubmit('id_product')) { if (!$this->context->cookie->last_visited_category || !Product::idIsOnCategoryId($id_product, array('0' => array('id_category' => $this->context->cookie->last_visited_category)))) { $product = new Product($id_product); if (Validate::isLoadedObject($product)) $this->context->cookie->last_visited_category = (int)$product->id_category_default; } $this->smarty->assign('currentCategoryId', (int)$this->context->cookie->last_visited_category); } else $this->smarty->assign('currentCategoryId', $this->context->shop->getCategory()); $this->smarty->assign(array( 'retro' => $this->retro, 'blockCategTree' => $block_categ_tree, 'footerMaxDepth' => (int)Configuration::get('CATEG_NC_FOOTER_MAX_DEPTH'), 'hideEmptyCategories' => (int)Configuration::get('CATEG_NC_HIDE_EMPTY_CATEG'), 'showProductNum' => (int)Configuration::get('CATEG_NC_NUM_PRODUCTS'), 'hideZeroCounts' => (int)Configuration::get('CATEG_NC_HIDE_ZERO_COUNTS') )); if (file_exists(_PS_THEME_DIR_.'modules/'.$this->name.'/blockcategories_footer.tpl')) $this->smarty->assign('branche_tpl_path', _PS_THEME_DIR_.'modules/'.$this->name.'/category-tree-branch.tpl'); else $this->smarty->assign('branche_tpl_path', _PS_MODULE_DIR_.$this->name.'/views/templates/hook/category-tree-branch.tpl'); } $display = $this->display(__FILE__, 'blockcategories_footer.tpl', $this->getCacheId()); return $display; } } Je pense qu'il est possible de se servir de ce module pour récupérer le lien de la dernière sous rubrique qui contient les pneus pour créer un lien et placer un bouton en dessous du bouton d'ajout au panier mais je sèche totalement... Edited December 1, 2014 by John77 (see edit history) Link to comment Share on other sites More sharing options...
Alexandre Carette Posted December 1, 2014 Share Posted December 1, 2014 Regarde deja dans ta console DEBUG pour voir si tu as la variable Link to comment Share on other sites More sharing options...
Eolia Posted December 1, 2014 Share Posted December 1, 2014 essayez ça {if isset($subCategories) && count($subCategories) == 1} <a href="{$link->getCategoryLink($subCategories[0].id_category)|escape:'htmlall':'UTF-8'}" id="{$subCategories[0].id_category}">{$subCategories[0].name}</a> {/if} car $child n'existe pas dans product.tpl... Votre lien ne s'affichera que si la catégorie de votre produit ne contient qu'une seule sous-catégorie (pneus donc) Link to comment Share on other sites More sharing options...
John77 Posted December 1, 2014 Author Share Posted December 1, 2014 (edited) Je vais être grossier mais PUTAIIIINNNNNNN DE BORRDEEEEELLLLLL DE MERRRRDEEEEE !!!!!! Je me casse la tête depuis vendredi sur ça et je me rend compte que j'étais partie bien trop loin..... En effet cela fonctionne correctement et affiche très bien le lien de la sous catégorie. Que dire à part MERCI !!! Edited December 1, 2014 by John77 (see edit history) Link to comment Share on other sites More sharing options...
Eolia Posted December 1, 2014 Share Posted December 1, 2014 Rhôôô !!!! 1 Link to comment Share on other sites More sharing options...
John77 Posted December 1, 2014 Author Share Posted December 1, 2014 C'est le problème : chercher compliqué alors que c'est tout bête sur le fond comme sur la forme Link to comment Share on other sites More sharing options...
John77 Posted December 17, 2014 Author Share Posted December 17, 2014 (edited) Up. Je fais remonter le post car je cherche à afficher la sous sous catégorie. Actuellement j'utilise donc ceci pour afficher un lien vers la sous categorie : {if isset($subCategories) && count($subCategories) == 1} <center><a class="exclusive button" href="{$link->getCategoryLink($subCategories[0].id_category)|escape:'htmlall':'UTF-8'}" id="{$subCategories[0].id_category}"><span>CHOISIR</span></a></center> {/if} Maintenant je souhaite aller plus loin et afficher le lien vers la sous sous catégorie que j'affiche avec le code ci-dessus. J'ai créais un fichier dans /override/ avec le code suivant : <?php class CategoryController extends CategoryControllerCore { /** * Surcharge du contenu pour ajouter les sous-sous Catégories */ public function initContent() { parent::initContent(); //Rajout des information des sous-sous catégories $this->assignSubSubcategories(); } /** * Informations des sous-sous catégories */ protected function assignSubSubcategories() { $subCategories = $this->category->getSubCategories($this->context->language->id); $subsubCategories = array(); foreach ( $subCategories as $subCategory ) { //On charge les sous-catégories pour récupérer leurs sous-catégories $subCat = new Category($subCategory['id_category']); if ( $subCat->getSubCategories($this->context->language->id) ) $subsubCategories[$subCategory['id_category']] = $subCat->getSubCategories($this->context->language->id); } $this->context->smarty->assign('subsubCategories',$subsubCategories); } } ?> et dans le fichier product tpl : {foreach from=$subsubCategories item=subsubCategory} {foreach from=$subsubCategory item=subsubOk} {if $subsubOk.id_parent == $subcategory.id_category} <a href="{$link->getCategoryLink($subsubCategories[0].id_category)|escape:'htmlall':'UTF-8'}">test</a> {/if} {/foreach} {/foreach} Mais voilà sa ne fonctionne pas. Pour info sur la hiérarchie : --> Categorie Produit --> Sous Catégorie 1 --> Sous Catgégorie 1.1 Edited December 17, 2014 by John77 (see edit history) Link to comment Share on other sites More sharing options...
Broceliande Posted December 17, 2014 Share Posted December 17, 2014 John77, Tu surcharges CategoryController et tu fais ton assign smarty sur les pages listings pour le coup. Donc par conséquence tu ne retrouveras pas tes variables dans ProductController et donc dans product.tpl. De plus , si dans les listings $products est un tableau associatif, dans la fiche produit , $product est un objet de la classe Product. Pourquoi ne pas simplement créer une override de Product et y ajouter une méthode unique genre getSubCategories(); ça ressemblerait à ça (à la louche et de tête hein je n'approfondis pas... donc c'est du code un peu yahourt ): public function getSubCategories(){ $subcats = array(); $category = new Category($product->id_category_default); $subcats = $category->getSubCategories($this->context->language->id); foreach($subcats as &$subcat){ $subcat['subcategories']=array(); $subcatobj = new Category($subcat['id_category']); $subcat['subcategories'][] = $subcatobj->getSubCategories($this->context->language->id); return $subcats; } Pas certain qu'il n'y ait pas plus simple mais bon ... Dans product.tpl tu récupères un tableau complet en une seule fois avec $product->getSubCategories(); a toi de dumper la variable pour voir comment elle ressort pour l'exploiter ensuite. Link to comment Share on other sites More sharing options...
Eolia Posted December 17, 2014 Share Posted December 17, 2014 J'aime bien le yaourt j'avais pensé utiliser Category::recurseLiteCategTree(), mais bon ta solution fonctionne aussi. Link to comment Share on other sites More sharing options...
Broceliande Posted December 17, 2014 Share Posted December 17, 2014 J'aime bien le yaourt j'avais pensé utiliser Category::recurseLiteCategTree(), mais bon ta solution fonctionne aussi. C'est exactement à ça que je pensais en disant qu'il y avait surement plus simple , sauf qu'on a un peu moins de données avec celle ci et il ne faut pas oublier de spécifier la profondeur... Je voulais pas rentrer dans le compliqué et aller ouvrir la classe lol Link to comment Share on other sites More sharing options...
John77 Posted December 17, 2014 Author Share Posted December 17, 2014 Je pense qu'il y a plus simple et qu'encore une fois je cherche trop loin. A l'heure actuelle j'affiche un lien vers la sous categorie en utilisant : {if isset($subCategories) && count($subCategories) == 1} <center><a class="exclusive button" href="{$link->getCategoryLink($subCategories[0].id_category)|escape:'htmlall':'UTF-8'}" id="{$subCategories[0].id_category}"><span>CHOISIR</span></a></center> {/if} Cela fonctionne parfaitement aucun souci. Si je rajoute une sous catégorie il faudrait quelque chose comme ceci {if isset($subCategories) && count($subCategories) == 2} Il suffirait juste pouvoir distinguer les deux sous categories afin d'afficher celle que je veux sachant que le nom de cette sous categorie sera identique à tous les produits concernés. Est-il possible de ce baser la dessus ? Link to comment Share on other sites More sharing options...
Eolia Posted December 17, 2014 Share Posted December 17, 2014 oui aussi, si vos catégories sont toujours les mêmes $subCategories vous renvoie un tableau, donc vous récupérez les catégories comme ça: $subCategories[0].id_category //1ère sous-catégorie $subCategories[1].id_category //2ème sous-catégorie $subCategories[2].id_category //3ème sous-catégorie et ainsi de suite Link to comment Share on other sites More sharing options...
John77 Posted December 17, 2014 Author Share Posted December 17, 2014 Oui voilà c'est exactement ce que je viens de faire justement. J'ai tendance à vouloir compliquer les choses simples Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now