Search the Community
Showing results for tags 'number products'.
-
Hi everyone! I'm trying to display the number of products near the category name in the left sidebar using the module Category Tree. Here is an example of what i would like to obtain: • Category (50) - - Subcategory (27) - - Subcategory (3) - - Subcategory (12) - - Subcategory (8) I'm using the code found here https://blog.prestatuts.com/show-number-of-products-next-to-each-category-in-category-tree-menu/ But i'm facing two problems: the main category shows 0 products but I would like to show the sum of all products in subcategories, this is what I got: • Category (0) - - Subcategory (27) - - Subcategory (3) - - Subcategory (12) - - Subcategory (8) The worst thing is that when the code is implemented the loading of the category page becomes extremely slow, like 20 seconds everytime. This is the edited file modules/ps_categorytree/ps_categorytree.php <?php /** * Copyright since 2007 PrestaShop SA and Contributors * PrestaShop is an International Registered Trademark & Property of PrestaShop SA * * NOTICE OF LICENSE * * This source file is subject to the Academic Free License 3.0 (AFL-3.0) * that is bundled with this package in the file LICENSE.md. * It is also available through the world-wide-web at this URL: * https://opensource.org/licenses/AFL-3.0 * If you did not receive a copy of the license and are unable to * obtain it through the world-wide-web, please send an email * to [email protected] so we can send you a copy immediately. * * DISCLAIMER * * Do not edit or add to this file if you wish to upgrade PrestaShop to newer * versions in the future. If you wish to customize PrestaShop for your * needs please refer to https://devdocs.prestashop.com/ for more information. * * @author PrestaShop SA and Contributors <[email protected]> * @copyright Since 2007 PrestaShop SA and Contributors * @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0) */ if (!defined('_PS_VERSION_')) { exit; } use PrestaShop\PrestaShop\Core\Module\WidgetInterface; class Ps_CategoryTree extends Module implements WidgetInterface { /** * @var string Name of the module running on PS 1.6.x. Used for data migration. */ const PS_16_EQUIVALENT_MODULE = 'blockcategories'; public function __construct() { $this->name = 'ps_categorytree'; $this->tab = 'front_office_features'; $this->version = '2.0.2'; $this->author = 'PrestaShop'; $this->bootstrap = true; parent::__construct(); $this->displayName = $this->getTranslator()->trans('Category tree links', [], 'Modules.Categorytree.Admin'); $this->description = $this->getTranslator()->trans('Help navigation on your store, show your visitors current category and subcategories.', [], 'Modules.Categorytree.Admin'); $this->ps_versions_compliancy = ['min' => '1.7.1.0', 'max' => _PS_VERSION_]; } public function install() { // If the PS 1.6 module wasn't here, set the default values if (!$this->uninstallPrestaShop16Module()) { Configuration::updateValue('BLOCK_CATEG_MAX_DEPTH', 4); Configuration::updateValue('BLOCK_CATEG_ROOT_CATEGORY', 1); } return parent::install() && $this->registerHook('displayLeftColumn') ; } /** * Migrate data from 1.6 equivalent module (if applicable), then uninstall */ public function uninstallPrestaShop16Module() { if (!Module::isInstalled(self::PS_16_EQUIVALENT_MODULE)) { return false; } $oldModule = Module::getInstanceByName(self::PS_16_EQUIVALENT_MODULE); if ($oldModule) { // This closure calls the parent class to prevent data to be erased // It allows the new module to be configured without migration $parentUninstallClosure = function () { return parent::uninstall(); }; $parentUninstallClosure = $parentUninstallClosure->bindTo($oldModule, get_class($oldModule)); $parentUninstallClosure(); } return true; } public function uninstall() { if (!parent::uninstall() || !Configuration::deleteByName('BLOCK_CATEG_MAX_DEPTH') || !Configuration::deleteByName('BLOCK_CATEG_ROOT_CATEGORY')) { return false; } return true; } public function getContent() { $output = ''; if (Tools::isSubmit('submitBlockCategories')) { $maxDepth = (int) (Tools::getValue('BLOCK_CATEG_MAX_DEPTH')); if ($maxDepth < 0) { $output .= $this->displayError($this->getTranslator()->trans('Maximum depth: Invalid number.', [], 'Admin.Notifications.Error')); } else { Configuration::updateValue('BLOCK_CATEG_MAX_DEPTH', (int) $maxDepth); Configuration::updateValue('BLOCK_CATEG_SORT_WAY', Tools::getValue('BLOCK_CATEG_SORT_WAY')); Configuration::updateValue('BLOCK_CATEG_SORT', Tools::getValue('BLOCK_CATEG_SORT')); Configuration::updateValue('BLOCK_CATEG_ROOT_CATEGORY', Tools::getValue('BLOCK_CATEG_ROOT_CATEGORY')); //$this->_clearBlockcategoriesCache(); Tools::redirectAdmin(AdminController::$currentIndex . '&configure=' . $this->name . '&token=' . Tools::getAdminTokenLite('AdminModules') . '&conf=6'); } } return $output . $this->renderForm(); } private function getCategories($category) { $range = ''; $maxdepth = Configuration::get('BLOCK_CATEG_MAX_DEPTH'); if (Validate::isLoadedObject($category)) { if ($maxdepth > 0) { $maxdepth += $category->level_depth; } $range = 'AND nleft >= ' . (int) $category->nleft . ' AND nright <= ' . (int) $category->nright; } $resultIds = []; $resultParents = []; $result = Db::getInstance((bool) _PS_USE_SQL_SLAVE_)->executeS(' SELECT c.id_parent, c.id_category, cl.name, cl.description, cl.link_rewrite FROM `' . _DB_PREFIX_ . 'category` c INNER JOIN `' . _DB_PREFIX_ . 'category_lang` cl ON (c.`id_category` = cl.`id_category` AND cl.`id_lang` = ' . (int) $this->context->language->id . Shop::addSqlRestrictionOnLang('cl') . ') INNER JOIN `' . _DB_PREFIX_ . 'category_shop` cs ON (cs.`id_category` = c.`id_category` AND cs.`id_shop` = ' . (int) $this->context->shop->id . ') WHERE (c.`active` = 1 OR c.`id_category` = ' . (int) Configuration::get('PS_HOME_CATEGORY') . ') AND c.`id_category` != ' . (int) Configuration::get('PS_ROOT_CATEGORY') . ' ' . ((int) $maxdepth != 0 ? ' AND `level_depth` <= ' . (int) $maxdepth : '') . ' ' . $range . ' AND c.id_category IN ( SELECT id_category FROM `' . _DB_PREFIX_ . 'category_group` WHERE `id_group` IN (' . pSQL(implode(', ', Customer::getGroupsStatic((int) $this->context->customer->id))) . ') ) ORDER BY `level_depth` ASC, ' . (Configuration::get('BLOCK_CATEG_SORT') ? 'cl.`name`' : 'cs.`position`') . ' ' . (Configuration::get('BLOCK_CATEG_SORT_WAY') ? 'DESC' : 'ASC')); foreach ($result as &$row) { $resultParents[$row['id_parent']][] = &$row; $resultIds[$row['id_category']] = &$row; } return $this->getTree($resultParents, $resultIds, $maxdepth, ($category ? $category->id : null)); } public function getTree($resultParents, $resultIds, $maxDepth, $id_category = null, $currentDepth = 0) { if (is_null($id_category)) { $id_category = $this->context->shop->getCategory(); } $children = []; if (isset($resultParents[$id_category]) && count($resultParents[$id_category]) && ($maxDepth == 0 || $currentDepth < $maxDepth)) { foreach ($resultParents[$id_category] as $subcat) { $children[] = $this->getTree($resultParents, $resultIds, $maxDepth, $subcat['id_category'], $currentDepth + 1); } } if (isset($resultIds[$id_category])) { $link = $this->context->link->getCategoryLink($id_category, $resultIds[$id_category]['link_rewrite']); $name = $resultIds[$id_category]['name']; $desc = $resultIds[$id_category]['description']; } else { $link = $name = $desc = ''; } return [ 'id' => $id_category, 'link' => $link, 'name' => $name, 'desc' => $desc, 'children' => $children, ]; } public function renderForm() { $fields_form = [ 'form' => [ 'legend' => [ 'title' => $this->getTranslator()->trans('Settings', [], 'Admin.Global'), 'icon' => 'icon-cogs', ], 'input' => [ [ 'type' => 'radio', 'label' => $this->getTranslator()->trans('Category root', [], 'Modules.Categorytree.Admin'), 'name' => 'BLOCK_CATEG_ROOT_CATEGORY', 'hint' => $this->getTranslator()->trans('Select which category is displayed in the block. The current category is the one the visitor is currently browsing.', [], 'Modules.Categorytree.Admin'), 'values' => [ [ 'id' => 'home', 'value' => 0, 'label' => $this->getTranslator()->trans('Home category', [], 'Modules.Categorytree.Admin'), ], [ 'id' => 'current', 'value' => 1, 'label' => $this->getTranslator()->trans('Current category', [], 'Modules.Categorytree.Admin'), ], [ 'id' => 'parent', 'value' => 2, 'label' => $this->getTranslator()->trans('Parent category', [], 'Modules.Categorytree.Admin'), ], [ 'id' => 'current_parent', 'value' => 3, 'label' => $this->getTranslator()->trans('Current category, unless it has no subcategories, in which case the parent category of the current category is used', [], 'Modules.Categorytree.Admin'), ], ], ], [ 'type' => 'text', 'label' => $this->getTranslator()->trans('Maximum depth', [], 'Modules.Categorytree.Admin'), 'name' => 'BLOCK_CATEG_MAX_DEPTH', 'desc' => $this->getTranslator()->trans('Set the maximum depth of category sublevels displayed in this block (0 = infinite).', [], 'Modules.Categorytree.Admin'), ], [ 'type' => 'radio', 'label' => $this->getTranslator()->trans('Sort', [], 'Admin.Actions'), 'name' => 'BLOCK_CATEG_SORT', 'values' => [ [ 'id' => 'name', 'value' => 1, 'label' => $this->getTranslator()->trans('By name', [], 'Admin.Global'), ], [ 'id' => 'position', 'value' => 0, 'label' => $this->getTranslator()->trans('By position', [], 'Admin.Global'), ], ], ], [ 'type' => 'radio', 'label' => $this->getTranslator()->trans('Sort order', [], 'Admin.Actions'), 'name' => 'BLOCK_CATEG_SORT_WAY', 'values' => [ [ 'id' => 'name', 'value' => 1, 'label' => $this->getTranslator()->trans('Descending', [], 'Admin.Global'), ], [ 'id' => 'position', 'value' => 0, 'label' => $this->getTranslator()->trans('Ascending', [], 'Admin.Global'), ], ], ], ], 'submit' => [ 'title' => $this->getTranslator()->trans('Save', [], 'Admin.Actions'), ], ], ]; $helper = new HelperForm(); $helper->show_toolbar = false; $helper->table = $this->table; $helper->submit_action = 'submitBlockCategories'; $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 = [ 'fields_value' => $this->getConfigFieldsValues(), ]; return $helper->generateForm([$fields_form]); } public function getConfigFieldsValues() { return [ 'BLOCK_CATEG_MAX_DEPTH' => Tools::getValue('BLOCK_CATEG_MAX_DEPTH', Configuration::get('BLOCK_CATEG_MAX_DEPTH')), 'BLOCK_CATEG_SORT_WAY' => Tools::getValue('BLOCK_CATEG_SORT_WAY', Configuration::get('BLOCK_CATEG_SORT_WAY')), 'BLOCK_CATEG_SORT' => Tools::getValue('BLOCK_CATEG_SORT', Configuration::get('BLOCK_CATEG_SORT')), 'BLOCK_CATEG_ROOT_CATEGORY' => Tools::getValue('BLOCK_CATEG_ROOT_CATEGORY', Configuration::get('BLOCK_CATEG_ROOT_CATEGORY')), ]; } public function setLastVisitedCategory() { if (method_exists($this->context->controller, 'getCategory') && ($category = $this->context->controller->getCategory())) { $this->context->cookie->last_visited_category = $category->id; } elseif (method_exists($this->context->controller, 'getProduct') && ($product = $this->context->controller->getProduct())) { if (!isset($this->context->cookie->last_visited_category) || !Product::idIsOnCategoryId($product->id, [['id_category' => $this->context->cookie->last_visited_category]]) || !Category::inShopStatic($this->context->cookie->last_visited_category, $this->context->shop) ) { $this->context->cookie->last_visited_category = (int) $product->id_category_default; } } } public function renderWidget($hookName = null, array $configuration = []) { $this->setLastVisitedCategory(); $this->smarty->assign($this->getWidgetVariables($hookName, $configuration)); return $this->fetch('module:ps_categorytree/views/templates/hook/ps_categorytree.tpl'); } public function getWidgetVariables($hookName = null, array $configuration = []) { $category = new Category((int) Configuration::get('PS_HOME_CATEGORY'), $this->context->language->id); if (Configuration::get('BLOCK_CATEG_ROOT_CATEGORY') && isset($this->context->cookie->last_visited_category) && $this->context->cookie->last_visited_category) { $category = new Category($this->context->cookie->last_visited_category, $this->context->language->id); if (Configuration::get('BLOCK_CATEG_ROOT_CATEGORY') == 2 && !$category->is_root_category && $category->id_parent) { $category = new Category($category->id_parent, $this->context->language->id); } elseif (Configuration::get('BLOCK_CATEG_ROOT_CATEGORY') == 3 && !$category->is_root_category && !$category->getSubCategories($category->id, true)) { $category = new Category($category->id_parent, $this->context->language->id); } } $categories = $this->getCategories($category); return [ 'categories' => $categories, 'c_tree_path' => isset($categories['children']) && count($categories['children']) && method_exists($this->context->controller, 'getCategory') && ($curr_category = $this->context->controller->getCategory()) ? self::getTreePath($categories['children'], $curr_category->id) : false, 'currentCategory' => $category->id, ]; } public static function getTreePath($categories, $id, array $path = []) { foreach ($categories as $cate) { if ($cate['id'] == $id){ if(is_array($cate['children']) && count($cate['children'])) $path[] = $cate['id']; return $path; } $path[] = $cate['id']; if(is_array($cate['children']) && count($cate['children'])) { if ($result = self::getTreePath($cate['children'], $id, $path)) return $result; } array_pop($path); } return false; } public static function countProductInCat($idCategory){ $category=new Category((int)$idCategory); $id_lang=Context::getContext()->language->id; $productCount=$category->getProducts($id_lang, 1, 10000, null, null, false); return $productCount; } } And this is the edited (and overrided) file modules/ps_categorytree/views/templates/hook/ps_categorytree.tpl {function name="categories" nodes=[] depth=0} {strip} {if $nodes|count} <ul class="category-sub-menu"> {foreach from=$nodes item=node} {assign var=category_products value=Module::getInstanceByName('ps_categorytree')->countProductInCat($node.id)} <li data-depth="{$depth}" class="{if (isset($category) && is_array($category) && isset($category.id) && $category.id==$node.id) || (isset($id_category_current) && $id_category_current==$node.id)} current_cate {/if}"> {if $depth===0} <a href="{$node.link}">{$node.name} ({count($category_products)})</a> {if $node.children} <span class="collapse-icons{if $c_tree_path && !in_array($node.id, $c_tree_path)} collapsed{/if}" data-toggle="collapse" data-target="#exCollapsingNavbar{$node.id}" aria-expanded="{if $c_tree_path && in_array($node.id, $c_tree_path)}true{else}false{/if}"> <i class="fa fa-angle-down add" aria-hidden="true"></i> <i class="fa fa-angle-up remove" aria-hidden="true"></i> </span> <div class="collapse{if $c_tree_path && in_array($node.id, $c_tree_path)} show{/if}" id="exCollapsingNavbar{$node.id}"> {categories nodes=$node.children depth=$depth+1} </div> {/if} {else} <a class="category-sub-link" href="{$node.link}">{$node.name} ({count($category_products)})</a> {if $node.children} <span class="arrows{if $c_tree_path && !in_array($node.id, $c_tree_path)} collapsed{/if} collapse-icons" data-toggle="collapse" data-target="#exCollapsingNavbar{$node.id}" aria-expanded="{if $c_tree_path && in_array($node.id, $c_tree_path)}true{else}false{/if}"> <i class="fa fa-angle-down add" aria-hidden="true"></i> <i class="fa fa-angle-up remove" aria-hidden="true"></i> </span> <div class="collapse{if $c_tree_path && in_array($node.id, $c_tree_path)} show{/if}" id="exCollapsingNavbar{$node.id}"> {categories nodes=$node.children depth=$depth+1} </div> {/if} {/if} </li> {/foreach} </ul> {/if} {/strip} {/function} {if $categories.children|count} {assign var=category_products_dva value=Module::getInstanceByName('ps_categorytree')->countProductInCat($categories.id)} <div class="block block-toggle block-categories block-links js-block-toggle"> <h5 class="block-title"><span><a href="{$categories.link nofilter}">{$categories.name} ({count($category_products_dva)})</a></span> </h5> <div class="category-top-menu block-content"> {categories nodes=$categories.children} </div> </div> {/if} If anyone can help me I would really appreciate, this is an important function for my client and I can't get what I'm doing wrong. Thank you very much!
- 17 replies
-
- number products
- category
-
(and 2 more)
Tagged with:
-
Hello everyone, Can I get number of products in category on product page, and how can I do it?
- 2 replies
-
- number products
- category on product page
-
(and 1 more)
Tagged with: