diff --git a/core/lib/Drupal/Core/Menu/MenuLinkTree.php b/core/lib/Drupal/Core/Menu/MenuLinkTree.php
index 090293c..56e1215 100644
--- a/core/lib/Drupal/Core/Menu/MenuLinkTree.php
+++ b/core/lib/Drupal/Core/Menu/MenuLinkTree.php
@@ -243,26 +243,28 @@ protected function buildItems(array $tree, CacheableMetadata &$tree_access_cache
if ($data->access instanceof AccessResultInterface && !$data->access->isAllowed()) {
continue;
}
+ $element = [];
- $class = ['menu-item'];
- // Set a class for the
-tag. Only set 'expanded' class if the link
- // also has visible children within the current tree.
+ // Set a variable for the -tag. Only set 'expanded' to true if the
+ // link also has visible children within the current tree.
+ $element['is_expanded'] = FALSE;
+ $element['is_collapsed'] = FALSE;
if ($data->hasChildren && !empty($data->subtree)) {
- $class[] = 'menu-item--expanded';
+ $element['is_expanded'] = TRUE;
}
elseif ($data->hasChildren) {
- $class[] = 'menu-item--collapsed';
+ $element['is_collapsed'] = TRUE;
}
- // Set a class if the link is in the active trail.
+ // Set a helper variable to indicate whether the link is in the active
+ // trail.
+ $element['in_active_trail'] = FALSE;
if ($data->inActiveTrail) {
- $class[] = 'menu-item--active-trail';
+ $element['in_active_trail'] = TRUE;
}
// Note: links are rendered in the menu.html.twig template; and they
// automatically bubble their associated cacheability metadata.
- $element = array();
$element['attributes'] = new Attribute();
- $element['attributes']['class'] = $class;
$element['title'] = $link->getTitle();
$element['url'] = $link->getUrlObject();
$element['url']->setOption('set_active_class', TRUE);
diff --git a/core/modules/book/src/BookManager.php b/core/modules/book/src/BookManager.php
index bd0d419..ef8a40e 100644
--- a/core/modules/book/src/BookManager.php
+++ b/core/modules/book/src/BookManager.php
@@ -539,30 +539,33 @@ protected function buildItems(array $tree) {
$items = [];
foreach ($tree as $data) {
- $class = ['menu-item'];
+ $element = [];
+
// Generally we only deal with visible links, but just in case.
if (!$data['link']['access']) {
continue;
}
// Set a class for the -tag. Since $data['below'] may contain local
- // tasks, only set 'expanded' class if the link also has children within
+ // tasks, only set 'expanded' to true if the link also has children within
// the current book.
+ $element['is_expanded'] = FALSE;
+ $element['is_collapsed'] = FALSE;
if ($data['link']['has_children'] && $data['below']) {
- $class[] = 'menu-item--expanded';
+ $element['is_expanded'] = TRUE;
}
elseif ($data['link']['has_children']) {
- $class[] = 'menu-item--collapsed';
+ $element['is_collapsed'] = TRUE;
}
- // Set a class if the link is in the active trail.
+ // Set a helper variable to indicate whether the link is in the active
+ // trail.
+ $element['in_active_trail'] = FALSE;
if ($data['link']['in_active_trail']) {
- $class[] = 'menu-item--active-trail';
+ $element['in_active_trail'] = TRUE;
}
// Allow book-specific theme overrides.
- $element = [];
$element['attributes'] = new Attribute();
- $element['attributes']['class'] = $class;
$element['title'] = $data['link']['title'];
$node = $this->entityManager->getStorage('node')->load($data['link']['nid']);
$element['url'] = $node->urlInfo();
diff --git a/core/modules/book/templates/book-tree.html.twig b/core/modules/book/templates/book-tree.html.twig
index a4edb37..9aa60be 100644
--- a/core/modules/book/templates/book-tree.html.twig
+++ b/core/modules/book/templates/book-tree.html.twig
@@ -11,6 +11,11 @@
* - below: The book item child items.
* - title: The book link title.
* - url: The book link URL, instance of \Drupal\Core\Url.
+ * - is_expanded: TRUE if the link has visible children within the current
+ * book tree.
+ * - is_collapsed: TRUE if the link has children within the current book tree
+ * that are not currently visible.
+ * - in_active_trail: TRUE if the link is in the active trail.
*
* @ingroup themeable
*/
diff --git a/core/modules/system/templates/menu.html.twig b/core/modules/system/templates/menu.html.twig
index a9c7899..5d26fa1 100644
--- a/core/modules/system/templates/menu.html.twig
+++ b/core/modules/system/templates/menu.html.twig
@@ -11,6 +11,11 @@
* - title: The menu link title.
* - url: The menu link url, instance of \Drupal\Core\Url
* - localized_options: Menu link localized options.
+ * - is_expanded: TRUE if the link has visible children within the current
+ * menu tree.
+ * - is_collapsed: TRUE if the link has children within the current menu tree
+ * that are not currently visible.
+ * - in_active_trail: TRUE if the link is in the active trail.
*
* @ingroup themeable
*/
diff --git a/core/modules/system/tests/src/Unit/Menu/MenuLinkTreeTest.php b/core/modules/system/tests/src/Unit/Menu/MenuLinkTreeTest.php
index da545b2..9faa03d 100644
--- a/core/modules/system/tests/src/Unit/Menu/MenuLinkTreeTest.php
+++ b/core/modules/system/tests/src/Unit/Menu/MenuLinkTreeTest.php
@@ -140,14 +140,29 @@ public function providerTestBuildCacheability() {
]
];
- $get_built_element = function(MenuLinkTreeElement $element, array $classes) {
- return [
- 'attributes' => new Attribute(['class' => array_merge(['menu-item'], $classes)]),
+ $get_built_element = function(MenuLinkTreeElement $element) {
+ $return = [
+ 'attributes' => new Attribute(),
'title' => $element->link->getTitle(),
'url' => new Url($element->link->getRouteName(), $element->link->getRouteParameters(), ['set_active_class' => TRUE]),
'below' => [],
'original_link' => $element->link,
+ 'is_expanded' => FALSE,
+ 'is_collapsed' => FALSE,
+ 'in_active_trail' => FALSE,
];
+
+ if ($element->hasChildren && !empty($element->subtree)) {
+ $return['is_expanded'] = TRUE;
+ }
+ elseif ($element->hasChildren) {
+ $return['is_collapsed'] = TRUE;
+ }
+ if ($element->inActiveTrail) {
+ $return['in_active_trail'] = TRUE;
+ }
+
+ return $return;
};
// The three access scenarios described in this method's documentation.
@@ -195,7 +210,7 @@ public function providerTestBuildCacheability() {
$tree[0]->access = $access;
if ($access === NULL || $access->isAllowed()) {
$expected_build = $base_expected_build;
- $expected_build['#items']['test.example1'] = $get_built_element($tree[0], []);
+ $expected_build['#items']['test.example1'] = $get_built_element($tree[0]);
}
else {
$expected_build = $base_expected_build_empty;
@@ -217,9 +232,9 @@ public function providerTestBuildCacheability() {
$tree[0]->access = $access;
$expected_build = $base_expected_build;
if ($access === NULL || $access->isAllowed()) {
- $expected_build['#items']['test.example1'] = $get_built_element($tree[0], []);
+ $expected_build['#items']['test.example1'] = $get_built_element($tree[0]);
}
- $expected_build['#items']['test.example2'] = $get_built_element($tree[1], []);
+ $expected_build['#items']['test.example2'] = $get_built_element($tree[1]);
$expected_build['#cache']['contexts'] = array_merge($expected_build['#cache']['contexts'], $access_cache_contexts, $links[0]->getCacheContexts(), $links[1]->getCacheContexts());
$data[] = [
'description' => "Single-level tree; access=$i; link=$j.",
@@ -245,13 +260,13 @@ public function providerTestBuildCacheability() {
];
$tree[0]->subtree[0]->subtree[0]->access = $access;
$expected_build = $base_expected_build;
- $expected_build['#items']['test.roota'] = $get_built_element($tree[0], ['menu-item--expanded']);
- $expected_build['#items']['test.roota']['below']['test.parentc'] = $get_built_element($tree[0]->subtree[0], ['menu-item--expanded']);
+ $expected_build['#items']['test.roota'] = $get_built_element($tree[0]);
+ $expected_build['#items']['test.roota']['below']['test.parentc'] = $get_built_element($tree[0]->subtree[0]);
if ($access === NULL || $access->isAllowed()) {
- $expected_build['#items']['test.roota']['below']['test.parentc']['below']['test.example1'] = $get_built_element($tree[0]->subtree[0]->subtree[0], []);
+ $expected_build['#items']['test.roota']['below']['test.parentc']['below']['test.example1'] = $get_built_element($tree[0]->subtree[0]->subtree[0]);
}
- $expected_build['#items']['test.rootb'] = $get_built_element($tree[1], ['menu-item--expanded']);
- $expected_build['#items']['test.rootb']['below']['test.example2'] = $get_built_element($tree[1]->subtree[0], []);
+ $expected_build['#items']['test.rootb'] = $get_built_element($tree[1]);
+ $expected_build['#items']['test.rootb']['below']['test.example2'] = $get_built_element($tree[1]->subtree[0]);
$expected_build['#cache']['contexts'] = array_merge($expected_build['#cache']['contexts'], $access_cache_contexts, $links[0]->getCacheContexts(), $links[1]->getCacheContexts());
$data[] = [
'description' => "Multi-level tree; access=$i; link=$j.",
diff --git a/core/modules/toolbar/templates/menu--toolbar.html.twig b/core/modules/toolbar/templates/menu--toolbar.html.twig
index 3578b95..5a6ba20 100644
--- a/core/modules/toolbar/templates/menu--toolbar.html.twig
+++ b/core/modules/toolbar/templates/menu--toolbar.html.twig
@@ -11,6 +11,11 @@
* - title: The menu link title.
* - url: The menu link url, instance of \Drupal\Core\Url
* - localized_options: Menu link localized options.
+ * - is_expanded: TRUE if the link has visible children within the current
+ * menu tree.
+ * - is_collapsed: TRUE if the link has children within the current menu tree
+ * that are not currently visible.
+ * - in_active_trail: TRUE if the link is in the active trail.
*
* @ingroup themeable
*/
@@ -32,7 +37,15 @@