monster_menus-9.0.x-dev/src/MMRenderer/DefaultMMRenderer.php

src/MMRenderer/DefaultMMRenderer.php
<?php
namespace Drupal\monster_menus\MMRenderer;

/**
 * @file
 * The default renderer for the monster_menus.tree_renderer service.
 */

use Drupal\Core\Template\Attribute;
use Drupal\monster_menus\Constants;

class DefaultMMRenderer implements MMRendererInterface {

  protected $tree, $current;
  protected $state_to_css, $state_cache, $state_max;

  public function create(array $tree, $start = 0) {
    // To avoid having to sort, this array must be in increasing order
    $this->state_to_css = [
        // Do not translate these with t()
        Constants::MM_GET_TREE_STATE_COLLAPSED => 'menu-item--collapsed',
        Constants::MM_GET_TREE_STATE_DENIED =>    'menu-item--denied',
        Constants::MM_GET_TREE_STATE_EXPANDED =>  'menu-item--expanded',
        Constants::MM_GET_TREE_STATE_HERE =>      'menu-item--active-trail',
        Constants::MM_GET_TREE_STATE_HIDDEN =>    'menu-item--hidden-entry',
        Constants::MM_GET_TREE_STATE_LEAF =>      'menu-item--leaf',
        Constants::MM_GET_TREE_STATE_NOT_WORLD => 'menu-item--not-world',
        Constants::MM_GET_TREE_STATE_RECYCLE =>   'menu-item--recycle-bin',
    ];
    $this->tree = $tree;
    $this->current = $start;
    $this->state_cache = [];
    $keys = array_keys($this->state_to_css);
    $this->state_max = array_pop($keys);
    return $this;
  }

  public function render() {
    // Speed up future calls to mm_content_get() by pre-fetching everything all
    // at once (well, up to 50 at once.)
    foreach (array_chunk($this->tree, 50) as $chunk) {
      $mmtids = [];
      foreach ($chunk as $item) {
        $mmtids[] = $item->mmtid;
      }
      mm_content_get($mmtids, Constants::MM_GET_PARENTS);
    }

    return [
      '#theme' => 'mm_tree_menu',
      '#items' => $this->walk(),
    ];
  }

  public function walk($is_top = TRUE) {
    if ($this->current >= count($this->tree)) {
      return [];
    }

    $items = [];
    $lev0 = $this->tree[$this->current]->level;
    while ($this->current < count($this->tree) && $this->tree[$this->current]->level == $lev0) {
      $leaf = $this->tree[$this->current];
      $name = mm_content_get_name($leaf);
      $plain_name = is_string($name) ? $name : $name->render();

      if (!$this->leafIsVisible($leaf) ||
          $plain_name[0] == '.' && !(isset($leaf->perms) ? $leaf->perms[Constants::MM_PERMS_READ] : mm_content_user_can($leaf->mmtid, Constants::MM_PERMS_READ))) {
        while (++$this->current < count($this->tree) && $this->tree[$this->current]->level > $lev0) ; // skip kids
        continue;   // get next sibling
      }

      $item = [
        'title' => $name,
        'attributes' => new Attribute(),
        'url' => mm_content_get_mmtid_url($leaf->mmtid),
      ];
      if (!empty($leaf->hover)) {
        $item['attributes']->setAttribute('title', $leaf->hover);
      }

      $item = $this->alterItem($leaf, $item);

      while (++$this->current < count($this->tree) && $this->tree[$this->current]->level > $lev0) {
        if ($this->tree[$this->current]->level == $lev0 + 1 && ($is_top || $leaf->state & Constants::MM_GET_TREE_STATE_EXPANDED)) {
          $kids = $this->walk(FALSE);
          if ($kids) {
            $item['below'] = $kids;
          }
          $this->current--;
        }
      }

      $items[] = $item;
    }
    return $items;
  }

  public function getLeafStateClass($leaf) {
    if (!isset($this->state_cache[$leaf->state])) {
      $state = $leaf->state;
      $state_css = [];
      $i = 0;
      $bit = 0;
      while ($state && $bit != $this->state_max) {
        $bit = 1 << $i++;
        if ($state & $bit && isset($this->state_to_css[$bit])) {
          $state_css[] = $this->state_to_css[$bit];
          $state ^= $bit;
        }
      }
      $this->state_cache[$leaf->state] = join(' ', $state_css);
    }
    return 'menu-item ' . $this->state_cache[$leaf->state];
  }

  public function alterItem(\stdClass $leaf, array $item) {
/** if (isset($leaf->nodecount) && $leaf->nodecount === '0') {
      $item['title'] .= t(' [no pages]');
    }**/

    if ($item['url'] != mm_get_current_path() &&
        ($leaf->state & (Constants::MM_GET_TREE_STATE_EXPANDED|Constants::MM_GET_TREE_STATE_HERE)) == (Constants::MM_GET_TREE_STATE_EXPANDED|Constants::MM_GET_TREE_STATE_HERE)) {
      $item['attributes']->addClass('active');
    }

    if ($leaf->state & Constants::MM_GET_TREE_STATE_HIDDEN) {
      $item['title'] .= ' ' . t('(hidden)');
    }

    if ($leaf->state & Constants::MM_GET_TREE_STATE_DENIED) {
      $item['attributes']->setAttribute('rel', 'nofollow');
    }

    $item['attributes']->addClass($this->getLeafStateClass($leaf));

    return $item;
  }

  public function leafIsVisible(\stdClass $leaf) {
    if ($leaf->name == Constants::MM_ENTRY_NAME_RECYCLE) {
      return mm_content_user_can_recycle($leaf->mmtid, Constants::MM_PERMS_READ);
    }

    if (isset($leaf->perms) && ($leaf->perms[Constants::MM_PERMS_WRITE] || $leaf->perms[Constants::MM_PERMS_SUB] || $leaf->perms[Constants::MM_PERMS_APPLY])) {
      return TRUE;
    }

    return !isset($leaf->nodecount) || $leaf->nodecount !== '0' || !mm_get_setting('pages.hide_empty_pages_in_menu');
  }
}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc