Unverified Commit 8ed835c0 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #2999549 by mtift, Daniel Korte, mherchel, alexpott, larowlan: Allow...

Issue #2999549 by mtift, Daniel Korte, mherchel, alexpott, larowlan: Allow button tag in LinkGenerator for better accessibility
parent b389f67d
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\Core;

/**
 * This class holds a <button> generated from the <button> route.
 *
 * Unlike \Drupal\Core\Render\Element\Button, this is not for generating
 * buttons for forms. This class is for putting a button in a list of links
 * such as a multi-level menu.
 */
class GeneratedButton extends GeneratedLink {

  /**
   * {@inheritdoc}
   */
  const TAG = 'button';

}
+30 −7
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
use Drupal\Component\Render\MarkupInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\GeneratedLink;
use Drupal\Core\GeneratedButton;
use Drupal\Core\GeneratedNoLink;
use Drupal\Core\Link;
use Drupal\Core\Render\RendererInterface;
@@ -165,19 +166,41 @@ public function generate($text, Url $url) {
    if ($url->isExternal()) {
      $generated_link = new GeneratedLink();
      $attributes['href'] = $url->toString(FALSE);
      return $this->doGenerate($generated_link, $attributes, $variables);
    }
    elseif ($url->isRouted() && $url->getRouteName() === '<nolink>') {
    if ($url->isRouted() && $url->getRouteName() === '<nolink>') {
      $generated_link = new GeneratedNoLink();
      unset($attributes['href']);
      return $this->doGenerate($generated_link, $attributes, $variables);
    }
    if ($url->isRouted() && $url->getRouteName() === '<button>') {
      $generated_link = new GeneratedButton();
      $attributes['type'] = 'button';
      unset($attributes['href']);
      return $this->doGenerate($generated_link, $attributes, $variables);
    }
    else {
    $generated_url = $url->toString(TRUE);
    $generated_link = GeneratedLink::createFromObject($generated_url);
    // The result of the URL generator is a plain-text URL to use as the href
    // attribute, and it is escaped by \Drupal\Core\Template\Attribute.
    $attributes['href'] = $generated_url->getGeneratedUrl();
    return $this->doGenerate($generated_link, $attributes, $variables);
  }

  /**
   * Generates the link.
   *
   * @param Drupal\Core\GeneratedLink $generated_link
   *   The generated link, along with its associated cacheability metadata.
   * @param array $attributes
   *   The attributes of the generated link.
   * @param array $variables
   *   The link text, url, and other options.
   *
   * @return Drupal\Core\GeneratedLink
   *   The generated link, along with its associated cacheability metadata.
   */
  protected function doGenerate($generated_link, $attributes, $variables) {
    if (!($variables['text'] instanceof MarkupInterface)) {
      $variables['text'] = Html::escape($variables['text']);
    }
+7 −0
Original line number Diff line number Diff line
@@ -412,6 +412,13 @@ system.theme_settings_theme:
  requirements:
    _access: 'TRUE'

'<button>':
  path: ''
  options:
    _no_path: TRUE
  requirements:
    _access: 'TRUE'

'<current>':
  path: '<current>'

+21 −0
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@
namespace Drupal\Tests\Core\Utility;

use Drupal\Component\Render\MarkupInterface;
use Drupal\Core\GeneratedButton;
use Drupal\Core\GeneratedNoLink;
use Drupal\Core\GeneratedUrl;
use Drupal\Core\Language\Language;
@@ -199,6 +200,26 @@ public function testGenerateNone() {
    $this->assertSame('<a href="">Test</a>', (string) $result);
  }

  /**
   * Tests the generate() method with the <button> route.
   *
   * @covers ::generate
   */
  public function testGenerateButton() {
    $this->urlGenerator->expects($this->never())
      ->method('generateFromRoute');
    $this->moduleHandler->expects($this->once())
      ->method('alter')
      ->with('link', $this->isType('array'));

    $url = Url::fromRoute('<button>');
    $url->setUrlGenerator($this->urlGenerator);

    $result = $this->linkGenerator->generate('Test', $url);
    $this->assertTrue($result instanceof GeneratedButton);
    $this->assertSame('<button type="button">Test</button>', (string) $result);
  }

  /**
   * Tests the generate() method with an external URL.
   *