2017-09-14 1 views
0

J'essaye de remplacer le bloc Topmenu dans Magento 2 pour que je puisse changer la structure HTML de mes sous-menus mais je n'arrive pas à surmonter ce problème.Override Topmenu Block dans Magento 2

Ce que je l'ai fait

J'ai créé un module appelé Ecommerce \ Topmenu.

Fichiers

app/code/E-commerce/Topmenu

- etc/

--- di.xml

--- module.xml

- Plugin/

--- Topm enu.php

- registration.php

Topmenu.php

<?php 
/** 
* Copyright © 2013-2017 Magento, Inc. All rights reserved. 
* See COPYING.txt for license details. 
*/ 
namespace Ecommerce\Topmenu\Plugin; 

use \Magento\Framework\DataObject\IdentityInterface; 
use \Magento\Framework\View\Element\Template; 
use \Magento\Framework\Data\TreeFactory; 
use \Magento\Framework\Data\Tree\Node; 
use \Magento\Framework\Data\Tree\NodeFactory; 

/** 
* Html page top menu block 
*/ 
class Topmenu extends \Magento\Theme\Block\Html\Topmenu 
{ 


    /** 
    * Get top menu html 
    * 
    * @param string $outermostClass 
    * @param string $childrenWrapClass 
    * @param int $limit 
    * @return string 
    */ 
    public function getHtml($outermostClass = '', $childrenWrapClass = '', $limit = 0) 
    { 
     $this->_eventManager->dispatch(
      'page_block_html_topmenu_gethtml_before', 
      ['menu' => $this->_menu, 'block' => $this] 
     ); 

     $this->_menu->setOutermostClass($outermostClass); 
     $this->_menu->setChildrenWrapClass($childrenWrapClass); 

     $html = $this->_getHtml($this->_menu, $childrenWrapClass, $limit); 

     $transportObject = new \Magento\Framework\DataObject(['html' => $html]); 
     $this->_eventManager->dispatch(
      'page_block_html_topmenu_gethtml_after', 
      ['menu' => $this->_menu, 'transportObject' => $transportObject] 
     ); 
     $html = $transportObject->getHtml(); 
     return $html; 
    } 

    /** 
    * Count All Subnavigation Items 
    * 
    * @param \Magento\Backend\Model\Menu $items 
    * @return int 
    */ 
    protected function _countItems($items) 
    { 
     $total = $items->count(); 
     foreach ($items as $item) { 
      /** @var $item \Magento\Backend\Model\Menu\Item */ 
      if ($item->hasChildren()) { 
       $total += $this->_countItems($item->getChildren()); 
      } 
     } 
     return $total; 
    } 

    /** 
    * Building Array with Column Brake Stops 
    * 
    * @param \Magento\Backend\Model\Menu $items 
    * @param int $limit 
    * @return array|void 
    * 
    * @todo: Add Depth Level limit, and better logic for columns 
    */ 
    protected function _columnBrake($items, $limit) 
    { 
     $total = $this->_countItems($items); 
     if ($total <= $limit) { 
      return; 
     } 

     $result[] = ['total' => $total, 'max' => (int)ceil($total/ceil($total/$limit))]; 

     $count = 0; 
     $firstCol = true; 

     foreach ($items as $item) { 
      $place = $this->_countItems($item->getChildren()) + 1; 
      $count += $place; 

      if ($place >= $limit) { 
       $colbrake = !$firstCol; 
       $count = 0; 
      } elseif ($count >= $limit) { 
       $colbrake = !$firstCol; 
       $count = $place; 
      } else { 
       $colbrake = false; 
      } 

      $result[] = ['place' => $place, 'colbrake' => $colbrake]; 

      $firstCol = false; 
     } 

     return $result; 
    } 

    /** 
    * Add sub menu HTML code for current menu item 
    * 
    * @param \Magento\Framework\Data\Tree\Node $child 
    * @param string $childLevel 
    * @param string $childrenWrapClass 
    * @param int $limit 
    * @return string HTML code 
    */ 
    protected function _addSubMenu($child, $childLevel, $childrenWrapClass, $limit) 
    { 
     $html = ''; 
     if (!$child->hasChildren()) { 
      return $html; 
     } 

     $colStops = null; 
     if ($childLevel == 0 && $limit) { 
      $colStops = $this->_columnBrake($child->getChildren(), $limit); 
     } 

     $html .= '<ul class="level' . $childLevel . ' megaSub">'; 
     $html .= $this->_getHtml($child, $childrenWrapClass, $limit, $colStops); 
     $html .= '</ul>'; 

     return $html; 
    } 

    /** 
    * Recursively generates top menu html from data that is specified in $menuTree 
    * 
    * @param \Magento\Framework\Data\Tree\Node $menuTree 
    * @param string $childrenWrapClass 
    * @param int $limit 
    * @param array $colBrakes 
    * @return string 
    * 
    * @SuppressWarnings(PHPMD.CyclomaticComplexity) 
    * @SuppressWarnings(PHPMD.NPathComplexity) 
    */ 
    protected function _getHtml(
     \Magento\Framework\Data\Tree\Node $menuTree, 
     $childrenWrapClass, 
     $limit, 
     $colBrakes = [] 
    ) { 
     $html = ''; 

     $children = $menuTree->getChildren(); 
     $parentLevel = $menuTree->getLevel(); 
     $childLevel = $parentLevel === null ? 0 : $parentLevel + 1; 

     $counter = 1; 
     $itemPosition = 1; 
     $childrenCount = $children->count(); 

     $parentPositionClass = $menuTree->getPositionClass(); 
     $itemPositionClassPrefix = $parentPositionClass ? $parentPositionClass . '-' : 'nav-'; 

     foreach ($children as $child) { 
      $child->setLevel($childLevel); 
      $child->setIsFirst($counter == 1); 
      $child->setIsLast($counter == $childrenCount); 
      $child->setPositionClass($itemPositionClassPrefix . $counter); 

      $outermostClassCode = ''; 
      $outermostClass = $menuTree->getOutermostClass(); 

      if ($childLevel == 0 && $outermostClass) { 
       $outermostClassCode = ' class="' . $outermostClass . '" '; 
       $child->setClass($outermostClass); 
      } 

      if (count($colBrakes) && $colBrakes[$counter]['colbrake']) { 
       // $html .= '</ul></li><li class="column"><ul>'; 
      } 

      if($counter > 1 && $childLevel == 1){ 
       continue; 
      } 


       $html .= '<li ' . $this->_getRenderedMenuItemAttributes($child) . '>'; 
       $html .= '<a href="' . $child->getUrl() . '" ' . $outermostClassCode . '><span>' . $this->escapeHtml(
        $child->getName() 
       ) . '</span></a>' . $this->_addSubMenu(
        $child, 
        $childLevel, 
        $childrenWrapClass, 
        $limit 
       ) . '</li>'; 
       $itemPosition++; 
       $counter++; 
     } 

     if (count($colBrakes) && $limit) { 
      $html = '<li class="column"><ul>' . $html . '</ul></li>'; 
     } 

     return $html; 
    } 

    /** 
    * Generates string with all attributes that should be present in menu item element 
    * 
    * @param \Magento\Framework\Data\Tree\Node $item 
    * @return string 
    */ 
    protected function _getRenderedMenuItemAttributes(\Magento\Framework\Data\Tree\Node $item) 
    { 
     $html = ''; 
     $attributes = $this->_getMenuItemAttributes($item); 
     foreach ($attributes as $attributeName => $attributeValue) { 
      $html .= ' ' . $attributeName . '="' . str_replace('"', '\"', $attributeValue) . '"'; 
     } 
     return $html; 
    } 

    /** 
    * Returns array of menu item's attributes 
    * 
    * @param \Magento\Framework\Data\Tree\Node $item 
    * @return array 
    */ 
    protected function _getMenuItemAttributes(\Magento\Framework\Data\Tree\Node $item) 
    { 
     $menuItemClasses = $this->_getMenuItemClasses($item); 
     return ['class' => implode(' ', $menuItemClasses)]; 
    } 

    /** 
    * Returns array of menu item's classes 
    * 
    * @param \Magento\Framework\Data\Tree\Node $item 
    * @return array 
    */ 
    protected function _getMenuItemClasses(\Magento\Framework\Data\Tree\Node $item) 
    { 
     $classes = []; 

     $classes[] = 'level' . $item->getLevel(); 
     $classes[] = $item->getPositionClass(); 

     if ($item->getIsFirst()) { 
      $classes[] = 'first'; 
     } 

     if ($item->getIsActive()) { 
      $classes[] = 'active'; 
     } elseif ($item->getHasActive()) { 
      $classes[] = 'has-active'; 
     } 

     if ($item->getIsLast()) { 
      $classes[] = 'last'; 
     } 

     if ($item->getClass()) { 
      $classes[] = $item->getClass(); 
     } 

     if ($item->hasChildren()) { 
      $classes[] = 'parent'; 
     } 

     return $classes; 
    } 

    /** 
    * Add identity 
    * 
    * @param array $identity 
    * @return void 
    */ 
    public function addIdentity($identity) 
    { 
     if (!in_array($identity, $this->identities)) { 
      $this->identities[] = $identity; 
     } 
    } 

    /** 
    * Get identities 
    * 
    * @return array 
    */ 
    public function getIdentities() 
    { 
     return $this->identities; 
    } 

    /** 
    * Get cache key informative items 
    * 
    * @return array 
    */ 
    public function getCacheKeyInfo() 
    { 
     $keyInfo = parent::getCacheKeyInfo(); 
     $keyInfo[] = $this->getUrl('*/*/*', ['_current' => true, '_query' => '']); 
     return $keyInfo; 
    } 

    /** 
    * Get tags array for saving cache 
    * 
    * @return array 
    */ 
    protected function getCacheTags() 
    { 
     return array_merge(parent::getCacheTags(), $this->getIdentities()); 
    } 

    /** 
    * Get menu object. 
    * 
    * @return Node 
    */ 
    public function getMenu() 
    { 
     return $this->_menu; 
    } 
} 

** behavour attendu **

Mon module devra remplacer le module Magento Topmenu tout en héritant ce qui permet moi de changer le balisage de sortie

Le problème

Après l'installation en cours d'exécution: la mise à niveau et recompilation, je suis juste présenté avec l'erreur suivante:

Fatal error: Call to a member function setOutermostClass() on null in /var/www/myecom.co.uk/app/code/Ecommerce/Topmenu/Plugin/Topmenu.php on line 36

Il est comme mon code ne prolonge pas correctement le bloc Topmenu.

Des idées?

Répondre

0

Ce problème est le résultat d'un récent Magento update qui explique pourquoi j'avais ce problème en utilisant du code qui avait précédemment fonctionné pour moi sur les versions antérieures de Magento.

Solution finale La solution finale pour résoudre ce problème après la mise à jour de Magento est de remplacer $this->_menu avec $this->getMenu()

Maintenant, la version de travail de mon module personnalisé étend la classe de menu haut Magento et remplace simplement la fonction _getHtml au changement le balisage au besoin.