diff --git a/core/includes/theme.inc b/core/includes/theme.inc index 4d134b5..d90c3a9 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -2656,12 +2656,9 @@ function drupal_common_theme() { 'template' => 'pager', ), // From menu.inc. - 'menu_link' => array( - 'render element' => 'element', - ), - 'menu_tree' => array( - 'render element' => 'tree', - 'template' => 'menu-tree', + 'menu' => array( + 'variables' => array('items' => array()), + 'template' => 'menu', ), 'menu_local_task' => array( 'render element' => 'element', diff --git a/core/lib/Drupal/Core/CoreServiceProvider.php b/core/lib/Drupal/Core/CoreServiceProvider.php index a006a98..3dc17a1 100644 --- a/core/lib/Drupal/Core/CoreServiceProvider.php +++ b/core/lib/Drupal/Core/CoreServiceProvider.php @@ -84,6 +84,7 @@ public static function registerTwig(ContainerBuilder $container) { $twig_extension = new Definition('Drupal\Core\Template\TwigExtension'); $twig_extension->addMethodCall('setGenerators', array(new Reference('url_generator'))); + $twig_extension->addMethodCall('setLinkGenerator', array(new Reference('link_generator'))); $container->register('twig', 'Drupal\Core\Template\TwigEnvironment') ->addArgument(new Reference('twig.loader')) diff --git a/core/lib/Drupal/Core/Menu/MenuLinkTree.php b/core/lib/Drupal/Core/Menu/MenuLinkTree.php index ddf924c..62ac7ee 100644 --- a/core/lib/Drupal/Core/Menu/MenuLinkTree.php +++ b/core/lib/Drupal/Core/Menu/MenuLinkTree.php @@ -12,6 +12,7 @@ use Drupal\Core\Controller\ControllerResolverInterface; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Routing\RouteProviderInterface; +use Drupal\Core\Template\Attribute; /** * Implements the loading, transforming and rendering of menu link trees. @@ -197,8 +198,8 @@ public function transform(array $tree, array $manipulators) { /** * {@inheritdoc} */ - public function build(array $tree) { - $build = array(); + public function build(array $tree, $level = 0) { + $items = array(); foreach ($tree as $data) { $class = array(); @@ -225,31 +226,40 @@ public function build(array $tree) { } // Allow menu-specific theme overrides. - $element['#theme'] = 'menu_link__' . strtr($link->getMenuName(), '-', '_'); - $element['#attributes']['class'] = $class; - $element['#title'] = $link->getTitle(); - $element['#url'] = $link->getUrlObject(); - $element['#below'] = $data->subtree ? $this->build($data->subtree) : array(); + $element = array(); + $element['attributes'] = new Attribute(); + $element['attributes']['class'] = $class; + $element['title'] = $link->getTitle(); + $element['url'] = $link->getUrlObject(); + $element['below'] = $data->subtree ? $this->build($data->subtree, $level + 1) : array(); if (isset($data->options)) { - $element['#url']->setOptions(NestedArray::mergeDeep($element['#url']->getOptions(), $data->options)); + $element['url']->setOptions(NestedArray::mergeDeep($element['url']->getOptions(), $data->options)); } - $element['#original_link'] = $link; + $element['original_link'] = $link; // Index using the link's unique ID. - $build[$link->getPluginId()] = $element; + $items[$link->getPluginId()] = $element; } - if ($build) { + + if (!$items) { + return array(); + } + elseif ($level == 0) { + $build = array(); // Make sure drupal_render() does not re-order the links. $build['#sorted'] = TRUE; // Get the menu name from the last link. $menu_name = $link->getMenuName(); // Add the theme wrapper for outer markup. // Allow menu-specific theme overrides. - $build['#theme_wrappers'][] = 'menu_tree__' . strtr($menu_name, '-', '_'); + $build['#theme'] = 'menu__' . strtr($menu_name, '-', '_'); + $build['#items'] = $items; // Set cache tag. $build['#cache']['tags']['menu'][$menu_name] = $menu_name; + return $build; + } + else { + return $items; } - - return $build; } /** diff --git a/core/lib/Drupal/Core/Template/TwigExtension.php b/core/lib/Drupal/Core/Template/TwigExtension.php index cf3500e..401e2c8 100644 --- a/core/lib/Drupal/Core/Template/TwigExtension.php +++ b/core/lib/Drupal/Core/Template/TwigExtension.php @@ -13,6 +13,8 @@ namespace Drupal\Core\Template; use Drupal\Core\Routing\UrlGeneratorInterface; +use Drupal\Core\Url; +use Drupal\Core\Utility\LinkGeneratorInterface; /** * A class providing Drupal Twig extensions. @@ -31,6 +33,13 @@ class TwigExtension extends \Twig_Extension { protected $urlGenerator; /** + * The link generator. + * + * @var \Drupal\Core\Utility\LinkGeneratorInterface + */ + protected $linkGenerator; + + /** * Constructs \Drupal\Core\Template\TwigExtension. * * @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator @@ -42,6 +51,19 @@ public function setGenerators(UrlGeneratorInterface $url_generator) { } /** + * Sets the link generator. + * + * @param \Drupal\Core\Utility\LinkGeneratorInterface $link_generator + * The link generator. + * + * @return $this + */ + public function setLinkGenerator(LinkGeneratorInterface $link_generator) { + $this->linkGenerator = $link_generator; + return $this; + } + + /** * {@inheritdoc} */ public function getFunctions() { @@ -53,6 +75,7 @@ public function getFunctions() { new \Twig_SimpleFunction('url', array($this, 'getUrl'), array('is_safe_callback' => array($this, 'isUrlGenerationSafe'))), new \Twig_SimpleFunction('path', array($this, 'getPath'), array('is_safe_callback' => array($this, 'isUrlGenerationSafe'))), new \Twig_SimpleFunction('url_from_path', array($this, 'getUrlFromPath'), array('is_safe_callback' => array($this, 'isUrlGenerationSafe'))), + new \Twig_SimpleFunction('link_from_url', array($this, 'getLinkFromUrl')), ); } @@ -175,6 +198,21 @@ public function getUrlFromPath($path, $options = array()) { } /** + * Gets a rendered link from an url object. + * + * @param string $text + * The link text for the anchor tag as a translated string. + * @param \Drupal\Core\Url $url + * The URL object used for the link. + * + * @return string + * An HTML string containing a link to the given url. + */ + public function getLinkFromUrl($text, Url $url) { + return $this->linkGenerator->generateFromUrl($text, $url); + } + + /** * Determines at compile time whether the generated URL will be safe. * * Saves the unneeded automatic escaping for performance reasons. diff --git a/core/modules/system/templates/menu.html.twig b/core/modules/system/templates/menu.html.twig new file mode 100644 index 0000000..0722334 --- /dev/null +++ b/core/modules/system/templates/menu.html.twig @@ -0,0 +1,40 @@ +{# +/** + * @file + * Default theme implementation to display a menu. + * + * Available variables: + * - menu_name: The machine name of the menu. + * - items: A nested list of menu items. Each menu item contains: + * - attributes: HTML attributes for the menu item. + * - below: The menu item child items. + * - title: The menu link title. + * - href: The menu link url. + * - localized_options: Menu link localized options. + * + * @ingroup themeable + */ +#} +{% import _self as menus %} +{# @TODO Add a nav element around.#} + +{#We call a macro which calls itself to render the full tree. +@see http://twig.sensiolabs.org/doc/tags/macro.html +#} +{{ menus.menu_links(items, 0) }} + +{% macro menu_links(items, menu_level) %} + {% import _self as menus %} + {% if items %} + + {% endif %} +{% endmacro %}