/** * @covers ::build * * MenuLinkTree::build() gathers both: * 1. the tree's access cacheability: the cacheability of the access result * of checking a link in a menu tree's access. Callers can opt out of * this by MenuLinkTreeElement::access to NULL (the default) value, in * which case the menu link is always visible. Only when an * AccessResultInterface object is specified, we gather this cacheability * metadata. * This means there are three cases: * a. no access result (NULL): menu link is visible * b. AccessResultInterface object that is allowed: menu link is visible * c. AccessResultInterface object that is not allowed: menu link is * invisible, but cacheability metadata is still applicable * 2. the tree's menu links' cacheability: the cacheability of a menu link * itself, because it may be dynamic. For this reason, MenuLinkInterface * extends CacheableDependencyInterface. It allows any menu link plugin to * mark itself as uncacheable (max-age=0) or dynamic (by specifying cache * tags and/or contexts), to indicate the extent of dynamism. * This means there are two cases: * a. permanently cacheable, no cache tags, no cache contexts * b. anything else: non-permanently cacheable, and/or cache tags, and/or * cache contexts. * * Finally, there are four important shapes of trees, all of which we want to * test: * 1. the empty tree * 2. a single-element tree * 3. a single-level tree (>1 element; just 1 element is case 2) * 4. a multi-level tree * * The associated data provider aims to test the handling of both of these * types of cacheability, and for all four tree shapes, for each of the types * of values for the two types of cacheability. * * There is another level of cacheability involved when actually rendering * built menu trees (i.e. when invoking RendererInterface::render() on the * return value of MenuLinkTreeInterface::build()): the cacheability of the * generated URLs. * Fortunately, that doesn't need additional test coverage here because that * cacheability is handled at the level of the Renderer (i.e. menu.html.twig * template's link() function invocation). It also has its own test coverage. * * @see \Drupal\menu_link_content\Tests\MenuLinkContentCacheabilityBubblingTest * * @dataProvider providerTestBuildCacheability */ public function testBuildCacheability($description, $tree, $expected_build, $access, array $access_cache_contexts = []) { if ($access !== NULL) { $access->addCacheContexts($access_cache_contexts); } $build = $this->menuLinkTree->build($tree); sort($expected_build['#cache']['contexts']); $this->assertEquals($expected_build, $build, $description); }
/** * {@inheritdoc} */ public function build(array $tree) { $build = parent::build($tree); /** @var \Drupal\Core\Menu\MenuLinkInterface $first_link */ $first_link = reset($tree)->link; $menu_name = $first_link->getMenuName(); // Add a more specific theme suggestion to differentiate this rendered // menu from others. $build['#menu_name'] = $menu_name; $build['#theme'] = 'menu__mega_menu__' . strtr($menu_name, '-', '_'); return $build; }
/** * {@inheritdoc} */ public function build(array $tree, $level = 0) { if ($level == 0) { if (!$tree) { return array(); } $build = parent::build($tree, $level); /** @var \Drupal\Core\Menu\MenuLinkInterface $link */ $first_link = reset($tree)->link; // Get the menu name of the first link. $menu_name = $first_link->getMenuName(); // Add a more specific theme suggestion to differentiate this rendered // menu from others. $build['#theme'] = 'menu__toolbar__' . strtr($menu_name, '-', '_'); return $build; } else { return parent::build($tree, $level); } }
/** * @covers ::build * * MenuLinkTree::build() gathers both: * 1. the tree's access cacheability: the cacheability of the access result * of checking a link in a menu tree's access. Callers can opt out of * this by MenuLinkTreeElement::access to NULL (the default) value, in * which case the menu link is always visible. Only when an * AccessResultInterface object is specified, we gather this cacheability * metadata. * This means there are three cases: * a. no access result (NULL): menu link is visible * b. AccessResultInterface object that is allowed: menu link is visible * c. AccessResultInterface object that is not allowed: menu link is * invisible, but cacheability metadata is still applicable * 2. the tree's menu links' cacheability: the cacheability of a menu link * itself, because it may be dynamic. For this reason, MenuLinkInterface * extends CacheableDependencyInterface. It allows any menu link plugin to * mark itself as uncacheable (max-age=0) or dynamic (by specifying cache * tags and/or contexts), to indicate the extent of dynamism. * This means there are two cases: * a. permanently cacheable, no cache tags, no cache contexts * b. anything else: non-permanently cacheable, and/or cache tags, and/or * cache contexts. * * Finally, there are four important shapes of trees, all of which we want to * test: * 1. the empty tree * 2. a single-element tree * 3. a single-level tree (>1 element; just 1 element is case 2) * 4. a multi-level tree * * The associated data provider aims to test the handling of both of these * types of cacheability, and for all four tree shapes, for each of the types * of values for the two types of cacheability. * * There is another level of cacheability involved when actually rendering * built menu trees (i.e. when invoking RendererInterface::render() on the * return value of MenuLinkTreeInterface::build()): the cacheability of the * generated URLs. * Fortunately, that doesn't need additional test coverage here because that * cacheability is handled at the level of the Renderer (i.e. menu.html.twig * template's link() function invocation). It also has its own test coverage. * * @see \Drupal\menu_link_content\Tests\MenuLinkContentCacheabilityBubblingTest * * @dataProvider providerTestBuildCacheability */ public function testBuildCacheability($description, $tree, $expected_build) { $build = $this->menuLinkTree->build($tree); sort($expected_build['#cache']['contexts']); $this->assertEquals($expected_build, $build, $description); }