2017-09-14 63 views
0

我想重写Magento 2中的Topmenu块,以便我可以更改我的子菜单的HTML结构,但我似乎无法通过此问题。覆盖Magento 2中的Topmenu块

我做了什么

我创建了一个叫做电子商务\顶部菜单模块。

文件

应用程序/代码/电子商务/ TopMenu的

- 等/

--- di.xml

--- module.xml

- 插件/

--- 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; 
    } 
} 

**预计水煤浆**

我的模块应该重写Magento的顶部菜单模块,同时继承它允许我改变输出标记

问题

运行安装程序之后:升级和重新编译,我只是出现以下错误:

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

它就像我的代码是不正确延长顶部菜单块。

任何想法?

回答

0

这个问题是最近Magento update的一个结果,它解释了为什么我使用之前在早期的Magento版本中为我工作过的代码出现过这个问题。

最终解决 最终的解决方案来解决这个问题后,Magento的更新与$this->getMenu()

现在我的自定义模块的工作版本替换$this->_menu扩展Magento的顶部菜单类,只是重写_getHtml功能变化根据需要添加标记。