diff --git a/core/includes/common.inc b/core/includes/common.inc index 8eec0ac..30d7948 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -3409,7 +3409,7 @@ function drupal_pre_render_link($element) { * Pre-render callback: Collects child links into a single array. * * This function can be added as a pre_render callback for a renderable array, - * usually one which will be themed by theme_links(). It iterates through all + * usually one which will be themed by links.html.twig. It iterates through all * unrendered children of the element, collects any #links properties it finds, * merges them into the parent element's #links array, and prevents those * children from being rendered separately. @@ -3430,21 +3430,21 @@ function drupal_pre_render_link($element) { * '#theme' => 'links__node__comment', * '#links' => array( * // An array of links associated with node comments, suitable for - * // passing in to theme_links(). + * // passing in to links.html.twig. * ), * ), * 'statistics' => array( * '#theme' => 'links__node__statistics', * '#links' => array( * // An array of links associated with node statistics, suitable for - * // passing in to theme_links(). + * // passing in to links.html.twig. * ), * ), * 'translation' => array( * '#theme' => 'links__node__translation', * '#links' => array( * // An array of links associated with node translation, suitable for - * // passing in to theme_links(). + * // passing in to links.html.twig. * ), * ), * ); diff --git a/core/includes/form.inc b/core/includes/form.inc index 5d4a943..32a67a5 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -1400,7 +1400,7 @@ function form_pre_render_actions_dropbutton(array $element) { } // Add this button to the corresponding dropbutton. // @todo Change #type 'dropbutton' to be based on theme_item_list() - // instead of theme_links() to avoid this preemptive rendering. + // instead of links.html.twig to avoid this preemptive rendering. $button = drupal_render($element[$key]); $dropbuttons[$dropbutton]['#links'][$key] = array( 'title' => $button, diff --git a/core/includes/menu.inc b/core/includes/menu.inc index c959a72..778e10e 100644 --- a/core/includes/menu.inc +++ b/core/includes/menu.inc @@ -1889,7 +1889,7 @@ function menu_navigation_links($menu_name, $level = 0) { if ($item['link']['href'] == $router_item['tab_root_href'] && $item['link']['href'] != current_path()) { $l['attributes']['class'][] = 'active'; } - // Keyed with the unique mlid to generate classes in theme_links(). + // Keyed with the unique mlid to generate classes in links.html.twig. $links['menu-' . $item['link']['mlid'] . $class] = $l; } } diff --git a/core/includes/theme.inc b/core/includes/theme.inc index bfd1aaf..b6f7a61 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -1168,9 +1168,11 @@ function template_preprocess_status_messages(&$variables) { } /** - * Returns HTML for a set of links. + * Prepares variables for links templates. * - * @param $variables + * Default template: links.html.twig. + * + * @param array $variables * An associative array containing: * - links: An associative array of links to be themed. The key for each link * is used as its CSS class. Each link should be itself an array, with the @@ -1236,11 +1238,9 @@ function template_preprocess_status_messages(&$variables) { * @see \Drupal\Core\Utility\LinkGenerator::generate() * @see system_page_build() */ -function theme_links($variables) { +function template_preprocess_links(&$variables) { $links = $variables['links']; - $attributes = $variables['attributes']; - $heading = $variables['heading']; - $output = ''; + $heading = &$variables['heading']; if (!empty($links)) { // Prepend the heading to the list, if any. @@ -1258,15 +1258,14 @@ function theme_links($variables) { if (isset($heading['class'])) { $heading['attributes']['class'] = $heading['class']; } - - $output .= '<' . $heading['level'] . new Attribute($heading['attributes']) . '>'; - $output .= String::checkPlain($heading['text']); - $output .= ''; + // Convert the attributes array into an attributes object. + $heading['attributes'] = new Attribute($heading['attributes']); + $heading['text'] = String::checkPlain($heading['text']); } - $output .= ''; - + $variables['links'] = array(); foreach ($links as $key => $link) { + $item = array(); $link += array( 'href' => NULL, 'route_name' => NULL, @@ -1320,29 +1319,23 @@ function theme_links($variables) { $li_attributes['data-drupal-link-system-path'] = \Drupal::service('path.alias_manager.cached')->getSystemPath($path); } - $item = drupal_render($link_element); + $item['link'] = $link_element; } + // Handle title-only text items. - else { - // Merge in default array properties into $link. - $link += array( - 'html' => FALSE, - ); - $item = ($link['html'] ? $link['title'] : String::checkPlain($link['title'])); - if (isset($link['attributes'])) { - $item = '' . $item . ''; - } + $text = (!empty($link['html']) ? $link['title'] : String::checkPlain($link['title'])); + $item['text'] = $text; + if (isset($link['attributes'])) { + $item['text_attributes'] = new Attribute($link['attributes']); } - $output .= ''; - $output .= $item; - $output .= ''; - } + // Handle list item attributes. + $item['attributes'] = new Attribute($li_attributes); - $output .= ''; + // Add the item to the list of links. + $variables['links'][] = $item; + } } - - return $output; } /** @@ -2601,6 +2594,7 @@ function drupal_common_theme() { ), 'links' => array( 'variables' => array('links' => array(), 'attributes' => array('class' => array('links')), 'heading' => array(), 'set_active_class' => FALSE), + 'template' => 'links', ), 'dropbutton_wrapper' => array( 'variables' => array('children' => NULL), diff --git a/core/lib/Drupal/Core/Menu/ContextualLinkManagerInterface.php b/core/lib/Drupal/Core/Menu/ContextualLinkManagerInterface.php index 801990b..1b43dec 100644 --- a/core/lib/Drupal/Core/Menu/ContextualLinkManagerInterface.php +++ b/core/lib/Drupal/Core/Menu/ContextualLinkManagerInterface.php @@ -24,7 +24,7 @@ public function getContextualLinkPluginsByGroup($group_name); /** - * Gets the contextual links prepared as expected by theme_links(). + * Gets the contextual links prepared as expected by links.html.twig. * * @param string $group_name * The group name. diff --git a/core/modules/contextual/contextual.module b/core/modules/contextual/contextual.module index 3fd2cb9..cb0cdee 100644 --- a/core/modules/contextual/contextual.module +++ b/core/modules/contextual/contextual.module @@ -271,7 +271,7 @@ function contextual_pre_render_links($element) { $items += $contextual_links_manager->getContextualLinksArrayByGroup($group, $args['route_parameters'], $args['metadata']); } - // Transform contextual links into parameters suitable for theme_links(). + // Transform contextual links into parameters suitable for links.html.twig. $links = array(); foreach ($items as $class => $item) { $class = drupal_html_class($class); diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php index 05195e0..38c492b 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php @@ -2843,7 +2843,7 @@ protected function assertNoTitle($title, $message = '', $group = 'Other') { * Asserts themed output. * * @param $callback - * The name of the theme function to invoke; e.g. 'links' for theme_links(). + * The name of the theme function to invoke; e.g. 'links' for links.html.twig. * @param $variables * An array of variables to pass to the theme function. * @param $expected diff --git a/core/modules/system/css/system.theme.css b/core/modules/system/css/system.theme.css index 4e83886..f205034 100644 --- a/core/modules/system/css/system.theme.css +++ b/core/modules/system/css/system.theme.css @@ -398,7 +398,7 @@ ul.menu a.active { } /** - * Markup generated by theme_links(). + * Markup generated by links.html.twig. */ ul.inline, ul.links.inline { diff --git a/core/modules/system/lib/Drupal/system/Tests/Theme/FunctionsTest.php b/core/modules/system/lib/Drupal/system/Tests/Theme/FunctionsTest.php index 0ae413f..ee4bb10 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Theme/FunctionsTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Theme/FunctionsTest.php @@ -149,9 +149,13 @@ function testItemList() { } /** - * Tests theme_links(). + * Tests links.html.twig. */ function testLinks() { + // Turn off the query for the l() function to compare the active + // link correctly. + $original_query = \Drupal::request()->query->all(); + \Drupal::request()->query->replace(array()); // Verify that empty variables produce no output. $variables = array(); $expected = ''; @@ -198,6 +202,9 @@ function testLinks() { $expected = $expected_heading . $expected_links; $this->assertThemeOutput('links', $variables, $expected); + // Restore the original request's query. + \Drupal::request()->query->replace($original_query); + // Verify that passing an array as heading works (core support). $variables['heading'] = array('text' => 'Links heading', 'level' => 'h3', 'class' => 'heading'); $expected_heading = '

Links heading

'; diff --git a/core/modules/system/templates/links.html.twig b/core/modules/system/templates/links.html.twig new file mode 100644 index 0000000..65d87c2 --- /dev/null +++ b/core/modules/system/templates/links.html.twig @@ -0,0 +1,59 @@ +{# +/** + * @file + * Default theme implementation for a set of links. + * + * Available variables: + * - attributes: Attributes for the UL containing the list of links. + * - links: Links to be output. + * Each link will have the following elements: + * - title: The link text. + * - href: The link URL. If omitted, the 'title' is shown as a plain text + * item in the links list. If 'href' is supplied, the entire link is passed + * to l() as its $options parameter. + * - html: (optional) Whether or not 'title' is HTML. If set, the title will + * not be passed through check_plain(). + * - attributes: (optional) HTML attributes for the anchor, or for the + * tag if no 'href' is supplied. + * - heading: (optional) A heading to precede the links. + * - text: The heading text. + * - level: The heading level (e.g. 'h2', 'h3'). + * - attributes: (optional) A keyed list of attributes for the heading. + * If the heading is a string, it will be used as the text of the heading and + * the level will default to 'h2'. + * + * Headings should be used on navigation menus and any list of links that + * consistently appears on multiple pages. To make the heading invisible use + * the 'visually-hidden' CSS class. Do not use 'display:none', which + * removes it from screen-readers and assistive technology. Headings allow + * screen-reader and keyboard only users to navigate to or skip the links. + * See http://juicystudio.com/article/screen-readers-display-none.php and + * http://www.w3.org/TR/WCAG-TECHS/H42.html for more information. + * + * @see template_preprocess_links() + * + * @ingroup themeable + */ +#} +{% if links -%} + {%- if heading -%} + {%- if heading.level -%} + <{{ heading.level }}{{ heading.attributes }}>{{ heading.text }} + {%- else -%} + {{ heading.text }} + {%- endif -%} + {%- endif -%} + + {%- for item in links -%} + + {%- if item.link -%} + {{ item.link }} + {%- elseif item.text_attributes -%} + {{ item.text }} + {%- else -%} + {{ item.text }} + {%- endif -%} + + {%- endfor -%} + +{%- endif %} diff --git a/core/modules/system/tests/modules/ajax_test/ajax_test.module b/core/modules/system/tests/modules/ajax_test/ajax_test.module index 2ea9eb9..e78d163 100644 --- a/core/modules/system/tests/modules/ajax_test/ajax_test.module +++ b/core/modules/system/tests/modules/ajax_test/ajax_test.module @@ -120,7 +120,7 @@ function ajax_test_dialog() { ), ); - // Dialog behavior applied to links rendered by theme_links(). + // Dialog behavior applied to links rendered by links.html.twig. $build['links'] = array( '#theme' => 'links', '#links' => array( diff --git a/core/modules/views_ui/lib/Drupal/views_ui/ViewEditFormController.php b/core/modules/views_ui/lib/Drupal/views_ui/ViewEditFormController.php index 05c11cc..61022f0 100644 --- a/core/modules/views_ui/lib/Drupal/views_ui/ViewEditFormController.php +++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewEditFormController.php @@ -962,7 +962,7 @@ public function getFormBucket(ViewUI $view, $type, $display) { break; } - // Create an array of actions to pass to theme_links + // Create an array of actions to pass to links template. $actions = array(); $count_handlers = count($executable->display_handler->getHandlers($type));