I am currently struggling to wrap my head around how the menu tree and menu link services work for outputting part of a menu with some custom requirements. Admittedly I don't have to do this very often, but it seems like there must be a way.
I tried with Menu Block, but that does not seem to be able to do what I need to do.
First, when I am on level 3 and a certain content type, (or the parent route is nolink), I need to print the current level of the menu like this:
The menu links represent what is under the current page.
Second, if it is level 2+ (and not a certain content type), the section parent needs to sit on the top as a blue link, in a different treatment:
Third, if the current page in the menu is active, no siblings are printed, only this page menu link and its children:
I started here, in a menu block:
/** @var \Drupal\Core\Menu\MenuLinkManager $menu_link_manager */
$menu_link_manager = \Drupal::service('plugin.manager.menu.link');
$route_params = array('node' => $node->id());
$menu_links = $menu_link_manager->loadLinksByRoute('entity.node.canonical', $route_params, 'main');
// Attach the top parent, if we are at level 3 (for a project) or level 2 (for a basic page)
// top parent cannot go above level 3.... but also level 2?
// show the current node menu tree and its siblings
// show the siblings if the current page has no children
$parent = reset($menu_links)->getParent();
$uuid = str_replace('menu_link_content:', '', $parent);
$parent_menu_content = current(\Drupal::entityTypeManager()
->getStorage('menu_link_content')
->loadByProperties(array('uuid' => $uuid)));
$params = new MenuTreeParameters();
$params->setRoot($parent);
$params->setActiveTrail([$parent, reset($menu_links)->getPluginId()]);
$tree = $this->menuTree->load($parent, $params);
$built_tree = $this->menuTree->build($tree);
$link = end($parent_menu_content->link->getValue())['uri'];
$element = $this->menuTree->build($tree);
$build['#items'] = $element['#items'][$parent]['below'];
if ($link != 'route:<nolink>') {
$build['#top_parent'] = $element['#items'][$parent];
}
if (empty($build['#cache']['contexts'])) {
$build['#cache']['contexts'] = ['user.permissions'];
$build['#cache']['tags'] = ['config:system.menu.main'];
}
return $build;
But the children of a link (in below
) don't render correctly in Twig, its blank, and I am not sure if there is some easier way to do this.
top_parent
is a new theme variable I have added to menu
so I can render it separately in Twig.
Edit: below
now renders right - I forgot to {% import _self as menus %}
in my second macro.