user5119999
user5119999

Reputation:

In Prestashop 1.7, how to display categories thumb in the Main menu module

I can't manage to display categories thumbs in the Main menu module (ps_mainmenu). I manage it in Prestashop 1.6, but the module has changed.

In the Prestashop 1.7 admin you can add a category thumb image.

Here is an image to show what I try to achieve : Category thumb above category labels in main menu

Best regards,

Quentin

Upvotes: 1

Views: 7651

Answers (2)

Quentin
Quentin

Reputation: 1

I am coming back to my project and updraded my Prestashop and then my menu disapeared and I forgot about this answer. Thanks again Alexander Grosul.

Here what to do to make an override of PS_MainMenu and make categories thumb show even when categories has no children.

  1. Go to override / modules / ps_mainmenu
  2. You can duplicate the file ps_mainenu.php from the orginal module and clean it up or just create a new php file
  3. New file :

    class Ps_MainMenuOverride extends Ps_MainMenu {
    
    protected function generateCategoriesMenu($categories, $is_children = 0)
    {
    $nodes = [];
    
    foreach ($categories as $key => $category) {
        $node = $this->makeNode([]);
    
        if ($category['level_depth'] > 1) {
            $cat = new Category($category['id_category']);
            $link = $cat->getLink();
        } else {
            $link = $this->context->link->getPageLink('index');
        }
    
        $node['url'] = $link;
        $node['type'] = 'category';
        $node['page_identifier'] = 'category-' . $category['id_category'];
    
        /* Whenever a category is not active we shouldnt display it to customer */
        if ((bool)$category['active'] === false) {
            continue;
        }
    
        $current = $this->page_name == 'category' && (int)Tools::getValue('id_category') == (int)$category['id_category'];
        $node['current'] = $current;
        $node['label']   = $category['name'];
        $node['image_urls']  = [];
    
        $files = scandir(_PS_CAT_IMG_DIR_);
    
        if (count(preg_grep('/^'.$category['id_category'].'-([0-9])?_thumb.jpg/i', $files)) > 0) {
            foreach ($files as $file) {
                if (preg_match('/^'.$category['id_category'].'-([0-9])?_thumb.jpg/i', $file) === 1) {
                    $image_url = $this->context->link->getMediaLink(_THEME_CAT_DIR_.$file);
                    $node['image_urls'][] = $image_url;
                }
            }
        }
    
        if (isset($category['children']) && !empty($category['children'])) {
            $node['children'] = $this->generateCategoriesMenu($category['children'], 1);
        }
    
        $nodes[] = $node;
    }
    
    return $nodes;
    }
    }
    
  4. Make sure you remove cache or force compilation

That should do the trick and will remain even after updates.

Upvotes: 0

Alexander Grosul
Alexander Grosul

Reputation: 1814

You need to modify your menu's template file and better do it inside your theme themes/your_theme/modules/ps_mainmenu/ps_mainmenu.tpl and add there similar part of a code

{if $node.type == 'category'}
  {if isset($node.image_urls) && $node.image_urls}
    {foreach from=$node.image_urls item='thumb'}
      <img src="{$thumb}" alt="" />
    {/foreach}
  {/if}
{/if}

inside {foreach from=$nodes item=node} in my case it's look like this

{assign var=_counter value=0}
{function name="menu" nodes=[] depth=0 parent=null}
    {if $nodes|count}
      <ul class="top-menu" {if $depth == 0}id="top-menu"{/if} data-depth="{$depth}">
        {foreach from=$nodes item=node}
          <li class="{$node.type}{if $node.current} current {/if}" id="{$node.page_identifier}">
            {if $node.type == 'category'}
              {if isset($node.image_urls) && $node.image_urls}
                {foreach from=$node.image_urls item='thumb'}
                  <img src="{$thumb}" alt="" />
                {/foreach}
              {/if}
            {/if}
            {assign var=_counter value=$_counter+1}
              <a
                class="{if $depth >= 0}dropdown-item{/if}{if $depth === 1} dropdown-submenu{/if}"
                href="{$node.url}" data-depth="{$depth}"
                {if $node.open_in_new_window} target="_blank" {/if}
              >
                {if $node.children|count}
                  {* Cannot use page identifier as we can have the same page several times *}
                  {assign var=_expand_id value=10|mt_rand:100000}
                  <span class="float-xs-right hidden-md-up">
                    <span data-target="#top_sub_menu_{$_expand_id}" data-toggle="collapse" class="navbar-toggler collapse-icons">
                      <i class="material-icons add">&#xE313;</i>
                      <i class="material-icons remove">&#xE316;</i>
                    </span>
                  </span>
                {/if}
                {$node.label}
              </a>
              {if $node.children|count}
              <div {if $depth === 0} class="popover sub-menu js-sub-menu collapse"{else} class="collapse"{/if} id="top_sub_menu_{$_expand_id}">
                {menu nodes=$node.children depth=$node.depth parent=$node}
              </div>
              {/if}
            </li>
        {/foreach}
      </ul>
    {/if}
  {/function}

<div class="menu js-top-menu position-static hidden-sm-down" id="_desktop_top_menu">
    {menu nodes=$menu.children}
    <div class="clearfix"></div>
</div>

and it works but not absolutely predictable for me. Because it adds images only to categories that have children categories. So if it ok for you can leave it in this condition, but if not and you want to display images for all categories you need to modify module controller file. Go to your module inside core modules folder modules/ps_mainmenu/ps_mainmenu.php and modify a method generateCategoriesMenu. Remove a code

$files = scandir(_PS_CAT_IMG_DIR_);

if (count(preg_grep('/^'.$category['id_category'].'-([0-9])?_thumb.jpg/i', $files)) > 0) {
  foreach ($files as $file) {
    if (preg_match('/^'.$category['id_category'].'-([0-9])?_thumb.jpg/i', $file) === 1) {
      $image_url = $this->context->link->getMediaLink(_THEME_CAT_DIR_.$file);
      $node['image_urls'][] = $image_url;
    }
  }
}

from condition if (isset($category['children']) && !empty($category['children'])) and put it exactly before the condition.

Upvotes: 2

Related Questions