Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
Menu.php
Go to the documentation of this file.
1 <?php
7 namespace Magento\Backend\Block;
8 
20 {
21  const CACHE_TAGS = 'BACKEND_MAINMENU';
22 
27 
31  protected $_itemRenderer;
32 
38  protected $_url;
39 
45  protected $_activeItemModel = null;
46 
50  protected $_iteratorFactory;
51 
55  protected $_authSession;
56 
60  protected $_menuConfig;
61 
65  protected $_localeResolver;
66 
70  private $menuItemChecker;
71 
75  private $anchorRenderer;
76 
80  private $routeConfig;
81 
96  public function __construct(
97  \Magento\Backend\Block\Template\Context $context,
98  \Magento\Backend\Model\UrlInterface $url,
99  \Magento\Backend\Model\Menu\Filter\IteratorFactory $iteratorFactory,
100  \Magento\Backend\Model\Auth\Session $authSession,
101  \Magento\Backend\Model\Menu\Config $menuConfig,
102  \Magento\Framework\Locale\ResolverInterface $localeResolver,
103  array $data = [],
104  MenuItemChecker $menuItemChecker = null,
105  AnchorRenderer $anchorRenderer = null,
106  \Magento\Framework\App\Route\ConfigInterface $routeConfig = null
107  ) {
108  $this->_url = $url;
109  $this->_iteratorFactory = $iteratorFactory;
110  $this->_authSession = $authSession;
111  $this->_menuConfig = $menuConfig;
112  $this->_localeResolver = $localeResolver;
113  $this->menuItemChecker = $menuItemChecker;
114  $this->anchorRenderer = $anchorRenderer;
115  $this->routeConfig = $routeConfig ?:
117  ->get(\Magento\Framework\App\Route\ConfigInterface::class);
118  parent::__construct($context, $data);
119  }
120 
126  protected function _construct()
127  {
128  parent::_construct();
129  $this->setCacheTags([self::CACHE_TAGS]);
130  }
131 
138  protected function _getAnchorLabel($menuItem)
139  {
140  return $this->escapeHtml(__($menuItem->getTitle()));
141  }
142 
149  protected function _renderMouseEvent($menuItem)
150  {
151  return $menuItem->hasChildren()
152  ? 'onmouseover="Element.addClassName(this,\'over\')" onmouseout="Element.removeClassName(this,\'over\')"'
153  : '';
154  }
155 
163  protected function _renderItemCssClass($menuItem, $level)
164  {
165  $isLast = 0 == $level && (bool)$this->getMenuModel()->isLast($menuItem) ? 'last' : '';
166  $isItemActive = $this->menuItemChecker->isItemActive(
167  $this->getActiveItemModel(),
168  $menuItem,
169  $level
170  ) ? '_current _active' : '';
171 
172  $output = $isItemActive .
173  ' ' .
174  ($menuItem->hasChildren() ? 'parent' : '') .
175  ' ' .
176  $isLast .
177  ' ' .
178  'level-' .
179  $level;
180  return $output;
181  }
182 
189  protected function _getMenuIterator($menu)
190  {
191  return $this->_iteratorFactory->create(['iterator' => $menu->getIterator()]);
192  }
193 
200  protected function _afterToHtml($html)
201  {
202  $html = preg_replace_callback(
203  '#' . \Magento\Backend\Model\UrlInterface::SECRET_KEY_PARAM_NAME . '/\$([^\/].*)/([^\/].*)/([^\$].*)\$#U',
204  [$this, '_callbackSecretKey'],
205  $html
206  );
207 
208  return $html;
209  }
210 
217  protected function _callbackSecretKey($match)
218  {
219  $routeId = $this->routeConfig->getRouteByFrontName($match[1]);
220  return \Magento\Backend\Model\UrlInterface::SECRET_KEY_PARAM_NAME . '/' . $this->_url->getSecretKey(
221  $routeId ?: $match[1],
222  $match[2],
223  $match[3]
224  );
225  }
226 
232  public function getCacheLifetime()
233  {
234  return 86400;
235  }
236 
242  public function getCacheKeyInfo()
243  {
244  $cacheKeyInfo = [
245  'admin_top_nav',
246  $this->getActive(),
247  $this->_authSession->getUser()->getId(),
248  $this->_localeResolver->getLocale(),
249  ];
250  // Add additional key parameters if needed
251  $newCacheKeyInfo = $this->getAdditionalCacheKeyInfo();
252  if (is_array($newCacheKeyInfo) && !empty($newCacheKeyInfo)) {
253  $cacheKeyInfo = array_merge($cacheKeyInfo, $newCacheKeyInfo);
254  }
255  return $cacheKeyInfo;
256  }
257 
263  public function getMenuModel()
264  {
265  return $this->_menuConfig->getMenu();
266  }
267 
275  public function renderMenu($menu, $level = 0)
276  {
277  $output = '<ul ' . (0 == $level ? 'id="nav" role="menubar"' : '') . ' >';
278 
280  foreach ($this->_getMenuIterator($menu) as $menuItem) {
281  $output .= '<li ' . $this->_renderMouseEvent(
282  $menuItem
283  ) . ' class="' . $this->_renderItemCssClass(
284  $menuItem,
285  $level
286  ) . '"' . $this->getUiId(
287  $menuItem->getId()
288  ) . 'role="menuitem">';
289 
290  $output .= $this->anchorRenderer->renderAnchor($this->getActiveItemModel(), $menuItem, $level);
291 
292  if ($menuItem->hasChildren()) {
293  $output .= $this->renderMenu($menuItem->getChildren(), $level + 1);
294  }
295  $output .= '</li>';
296  }
297  $output .= '</ul>';
298 
299  return $output;
300  }
301 
308  protected function _countItems($items)
309  {
310  $total = count($items);
311  foreach ($items as $item) {
313  if ($item->hasChildren()) {
314  $total += $this->_countItems($item->getChildren());
315  }
316  }
317  return $total;
318  }
319 
328  protected function _columnBrake($items, $limit)
329  {
330  $total = $this->_countItems($items);
331  if ($total <= $limit) {
332  return;
333  }
334  $result[] = ['total' => $total, 'max' => ceil($total / ceil($total / $limit))];
335  $count = 0;
336  foreach ($items as $item) {
337  $place = $this->_countItems($item->getChildren()) + 1;
338  $count += $place;
339  if ($place - $result[0]['max'] > $limit - $result[0]['max']) {
340  $colbrake = true;
341  $count = 0;
342  } elseif ($count - $result[0]['max'] > $limit - $result[0]['max']) {
343  $colbrake = true;
344  $count = $place;
345  } else {
346  $colbrake = false;
347  }
348  $result[] = ['place' => $place, 'colbrake' => $colbrake];
349  }
350  return $result;
351  }
352 
362  protected function _addSubMenu($menuItem, $level, $limit, $id = null)
363  {
364  $output = '';
365  if (!$menuItem->hasChildren()) {
366  return $output;
367  }
368  $output .= '<div class="submenu"' . ($level == 0 && isset($id) ? ' aria-labelledby="' . $id . '"' : '') . '>';
369  $colStops = [];
370  if ($level == 0 && $limit) {
371  $colStops = $this->_columnBrake($menuItem->getChildren(), $limit);
372  $output .= '<strong class="submenu-title">' . $this->_getAnchorLabel($menuItem) . '</strong>';
373  $output .= '<a href="#" class="action-close _close" data-role="close-submenu"></a>';
374  }
375 
376  $output .= $this->renderNavigation($menuItem->getChildren(), $level + 1, $limit, $colStops);
377  $output .= '</div>';
378  return $output;
379  }
380 
392  public function renderNavigation($menu, $level = 0, $limit = 0, $colBrakes = [])
393  {
394  $itemPosition = 1;
395  $outputStart = '<ul ' . (0 == $level ? 'id="nav" role="menubar"' : 'role="menu"') . ' >';
396  $output = '';
397 
399  foreach ($this->_getMenuIterator($menu) as $menuItem) {
400  $menuId = $menuItem->getId();
401  $itemName = substr($menuId, strrpos($menuId, '::') + 2);
402  $itemClass = str_replace('_', '-', strtolower($itemName));
403 
404  if (is_array($colBrakes)
405  && count($colBrakes)
406  && $colBrakes[$itemPosition]['colbrake']
407  && $itemPosition != 1
408  ) {
409  $output .= '</ul></li><li class="column"><ul role="menu">';
410  }
411 
412  $id = $this->getJsId($menuItem->getId());
413  $subMenu = $this->_addSubMenu($menuItem, $level, $limit, $id);
414  $anchor = $this->anchorRenderer->renderAnchor($this->getActiveItemModel(), $menuItem, $level);
415  $output .= '<li ' . $this->getUiId($menuItem->getId())
416  . ' class="item-' . $itemClass . ' ' . $this->_renderItemCssClass($menuItem, $level)
417  . ($level == 0 ? '" id="' . $id . '" aria-haspopup="true' : '')
418  . '" role="menu-item">' . $anchor . $subMenu . '</li>';
419  $itemPosition++;
420  }
421 
422  if (is_array($colBrakes) && count($colBrakes) && $limit) {
423  $output = '<li class="column"><ul role="menu">' . $output . '</ul></li>';
424  }
425 
426  return $outputStart . $output . '</ul>';
427  }
428 
434  public function getActiveItemModel()
435  {
436  if ($this->_activeItemModel === null) {
437  $this->_activeItemModel = $this->getMenuModel()->get($this->getActive());
438  if (false == $this->_activeItemModel instanceof \Magento\Backend\Model\Menu\Item) {
439  $this->_activeItemModel = false;
440  }
441  }
443  }
444 }
getJsId($arg1=null, $arg2=null, $arg3=null, $arg4=null, $arg5=null)
elseif(isset( $params[ 'redirect_parent']))
Definition: iframe.phtml:17
getUiId($arg1=null, $arg2=null, $arg3=null, $arg4=null, $arg5=null)
$id
Definition: fieldset.phtml:14
$count
Definition: recent.phtml:13
__()
Definition: __.php:13
_columnBrake($items, $limit)
Definition: Menu.php:328
_getAnchorLabel($menuItem)
Definition: Menu.php:138
__construct(\Magento\Backend\Block\Template\Context $context, \Magento\Backend\Model\UrlInterface $url, \Magento\Backend\Model\Menu\Filter\IteratorFactory $iteratorFactory, \Magento\Backend\Model\Auth\Session $authSession, \Magento\Backend\Model\Menu\Config $menuConfig, \Magento\Framework\Locale\ResolverInterface $localeResolver, array $data=[], MenuItemChecker $menuItemChecker=null, AnchorRenderer $anchorRenderer=null, \Magento\Framework\App\Route\ConfigInterface $routeConfig=null)
Definition: Menu.php:96
_callbackSecretKey($match)
Definition: Menu.php:217
_renderItemCssClass($menuItem, $level)
Definition: Menu.php:163
_addSubMenu($menuItem, $level, $limit, $id=null)
Definition: Menu.php:362
_renderMouseEvent($menuItem)
Definition: Menu.php:149
$items