Commit db60a8c7 authored by alexpott's avatar alexpott

Issue #2273923 by mpdonadio, pfrenssen, effulgentsia, pcambra, xjm,...

Issue #2273923 by mpdonadio, pfrenssen, effulgentsia, pcambra, xjm, tim.plunkett, martin107, cilefen: Remove html => TRUE option from l() and link generator
parent d1c03228
......@@ -10,9 +10,9 @@
* @{
*/
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Component\Utility\String;
use Drupal\Core\Render\Element;
use Drupal\Core\Template\Attribute;
/**
......@@ -35,18 +35,17 @@ function template_preprocess_menu_local_task(&$variables) {
$link_text = $link['title'];
if (!empty($variables['element']['#active'])) {
// Add text to indicate active tab for non-visual users.
$active = '<span class="visually-hidden">' . t('(active tab)') . '</span>';
$variables['attributes']['class'] = array('active');
// If the link does not contain HTML already, String::checkPlain() it now.
// After we set 'html'=TRUE the link will not be sanitized by l().
if (empty($link['localized_options']['html'])) {
$link_text = String::checkPlain($link_text);
}
$link['localized_options']['html'] = TRUE;
$link_text = t('!local-task-title!active', array('!local-task-title' => $link_text, '!active' => $active));
// Add text to indicate active tab for non-visual users.
$active = String::format('<span class="visually-hidden">@label</span>', array('@label' => t('(active tab)')));
$link_text = t('@local-task-title@active', array('@local-task-title' => $link_text, '@active' => $active));
}
else {
// @todo Remove this once https://www.drupal.org/node/2338081 is fixed.
$link_text = String::checkPlain($link_text);
}
$link['localized_options']['set_active_class'] = TRUE;
$variables['link'] = array(
......
<?php
use Drupal\Core\Database\Connection;
use Drupal\Core\Database\Query\SelectExtender;
use Drupal\Core\Database\Query\SelectInterface;
use Drupal\Component\Utility\String;
use Drupal\Core\Url;
use Drupal\Component\Utility\UrlHelper;
......@@ -62,13 +60,12 @@ function tablesort_header(&$cell_content, array &$cell_attributes, array $header
$ts['sort'] = 'asc';
$image = '';
}
$cell_content = \Drupal::l($cell_content . $image, new Url('<current>', [], [
$cell_content = \Drupal::l(String::format('@cell_content@image', array('@cell_content' => $cell_content, '@image' => $image)), new Url('<current>', [], [
'attributes' => array('title' => $title),
'query' => array_merge($ts['query'], array(
'sort' => $ts['sort'],
'order' => $cell_content,
)),
'html' => TRUE,
]));
unset($cell_attributes['field'], $cell_attributes['sort']);
......
......@@ -532,9 +532,6 @@ function template_preprocess_status_messages(&$variables) {
* - title: The link text.
* - url: (optional) The url object to link to. If omitted, no a tag is
* printed out.
* - html: (optional) Whether or not 'title' is HTML. If set, the title
* will not be passed through
* \Drupal\Component\Utility\String::checkPlain().
* - attributes: (optional) Attributes for the anchor, or for the <span>
* tag used in its place if no 'href' is supplied. If element 'class' is
* included, it must be an array of one or more class names.
......@@ -658,8 +655,7 @@ function template_preprocess_links(&$variables) {
}
// Handle title-only text items.
$text = (!empty($link['html']) ? $link['title'] : String::checkPlain($link['title']));
$item['text'] = $text;
$item['text'] = $link['title'];
if (isset($link['attributes'])) {
$item['text_attributes'] = new Attribute($link['attributes']);
}
......
......@@ -90,8 +90,9 @@ public static function decodeEntities($text) {
* String::checkPlain() as part of that.
* - Some other special reason for suppressing sanitization.
*
* @return mixed
* The formatted string, or FALSE if no args specified.
* @return string
* The formatted string, which is marked as safe unless sanitization of an
* unsafe argument was suppressed (see above).
*
* @ingroup sanitization
*
......
......@@ -97,7 +97,6 @@ public static function preRenderActionsDropbutton(&$element, FormStateInterface
$button = drupal_render($element[$key]);
$dropbuttons[$dropbutton]['#links'][$key] = array(
'title' => $button,
'html' => TRUE,
);
}
}
......
......@@ -85,7 +85,6 @@ public function generate($text, Url $url) {
$variables['options'] += array(
'attributes' => array(),
'query' => array(),
'html' => FALSE,
'language' => NULL,
'set_active_class' => FALSE,
'absolute' => FALSE,
......@@ -135,9 +134,10 @@ public function generate($text, Url $url) {
// it here in an HTML argument context, we need to encode it properly.
$url = String::checkPlain($url->toString());
// Sanitize the link text if necessary.
$text = $variables['options']['html'] ? $variables['text'] : String::checkPlain($variables['text']);
return SafeMarkup::set('<a href="' . $url . '"' . $attributes . '>' . $text . '</a>');
// Make sure the link text is sanitized.
$safe_text = SafeMarkup::escape($variables['text']);
return SafeMarkup::set('<a href="' . $url . '"' . $attributes . '>' . $safe_text . '</a>');
}
}
......@@ -18,16 +18,30 @@ interface LinkGeneratorInterface {
/**
* Renders a link to a URL.
*
* Examples:
* @code
* $link_generator = \Drupal::service('link_generator');
* $installer_url = \Drupal\Core\Url::fromUri('base://core/install.php');
* $installer_link = $link_generator->generate($text, $installer_url);
* $external_url = \Drupal\Core\Url::fromUri('http://example.com', ['query' => ['foo' => 'bar']]);
* $external_link = $link_generator->generate($text, $external_url);
* $internal_url = \Drupal\Core\Url::fromRoute('system.admin');
* $internal_link = $link_generator->generate($text, $internal_url);
* @endcode
* However, for links enclosed in translatable text you should use t() and
* embed the HTML anchor tag directly in the translated string. For example:
* @code
* t('Visit the <a href="@url">content types</a> page', array('@url' => \Drupal::url('entity.node_type.collection')));
* $text = t('Visit the <a href="@url">content types</a> page', array('@url' => \Drupal::url('entity.node_type.collection')));
* @endcode
* This keeps the context of the link title ('settings' in the example) for
* translators.
*
* @param string|array $text
* The link text for the anchor tag as a translated string or render array.
* Strings will be sanitized automatically. If you need to output HTML in
* the link text, use a render array or an already sanitized string such as
* the output of \Drupal\Component\Utility\Xss::filter() or
* \Drupal\Component\Utility\String::format().
* @param \Drupal\Core\Url $url
* The URL object used for the link. Amongst its options, the following may
* be set to affect the generated link:
......@@ -36,11 +50,6 @@ interface LinkGeneratorInterface {
* must be a string; other elements are more flexible, as they just need
* to work as an argument for the constructor of the class
* Drupal\Core\Template\Attribute($options['attributes']).
* - html: Whether $text is HTML or just plain-text. For
* example, to make an image tag into a link, this must be set to TRUE, or
* you will see the escaped HTML image tag. $text is not sanitized if
* 'html' is TRUE. The calling function must ensure that $text is already
* safe. Defaults to FALSE.
* - language: An optional language object. If the path being linked to is
* internal to the site, $options['language'] is used to determine whether
* the link is "active", or pointing to the current page (the language as
......
......@@ -103,7 +103,6 @@ public function buildComponents(array &$build, array $entities, array $displays,
'#url' => Url::fromUri($link_href),
'#options' => array(
'attributes' => array('class' => array('feed-image')),
'html' => TRUE,
),
);
}
......@@ -127,7 +126,6 @@ public function buildComponents(array &$build, array $entities, array $displays,
)),
'#url' => Url::fromRoute('entity.aggregator_feed.canonical', ['aggregator_feed' => $entity->id()]),
'#options' => array(
'html' => TRUE,
'attributes' => array(
'title' => $title_stripped,
),
......
......@@ -43,7 +43,7 @@ function block_help($route_name, RouteMatchInterface $route_match) {
$demo_theme = $route_match->getParameter('theme') ?: \Drupal::config('system.theme')->get('default');
$themes = \Drupal::service('theme_handler')->listInfo();
$output = '<p>' . t('This page provides a drag-and-drop interface for adding a block to a region, and for controlling the order of blocks within regions. To add a block to a region, or to configure its specific title and visibility settings, click the block title under <em>Place blocks</em>. Since not all themes implement the same regions, or display regions in the same way, blocks are positioned on a per-theme basis. Remember that your changes will not be saved until you click the <em>Save blocks</em> button at the bottom of the page.') . '</p>';
$output .= '<p>' . \Drupal::l(t('Demonstrate block regions (!theme)', array('!theme' => $themes[$demo_theme]->info['name'])), new Url('block.admin_demo', array('theme' => $demo_theme))) . '</p>';
$output .= '<p>' . \Drupal::l(t('Demonstrate block regions (@theme)', array('@theme' => $themes[$demo_theme]->info['name'])), new Url('block.admin_demo', array('theme' => $demo_theme))) . '</p>';
return $output;
}
}
......
......@@ -7,6 +7,7 @@
namespace Drupal\book\Tests;
use Drupal\Component\Utility\String;
use Drupal\Core\Entity\EntityInterface;
use Drupal\simpletest\WebTestBase;
......@@ -224,22 +225,24 @@ function checkBookNode(EntityInterface $node, $nodes, $previous = FALSE, $up = F
if ($previous) {
/** @var \Drupal\Core\Url $url */
$url = $previous->urlInfo();
$url->setOptions(array('html' => TRUE, 'attributes' => array('rel' => array('prev'), 'title' => t('Go to previous page'))));
$this->assertRaw(\Drupal::l('<b>‹</b> ' . $previous->label(), $url), 'Previous page link found.');
$url->setOptions(array('attributes' => array('rel' => array('prev'), 'title' => t('Go to previous page'))));
$text = String::format('<b>‹</b> @label', array('@label' => $previous->label()));
$this->assertRaw(\Drupal::l($text, $url), 'Previous page link found.');
}
if ($up) {
/** @var \Drupal\Core\Url $url */
$url = $up->urlInfo();
$url->setOptions(array('html'=> TRUE, 'attributes' => array('title' => t('Go to parent page'))));
$url->setOptions(array('attributes' => array('title' => t('Go to parent page'))));
$this->assertRaw(\Drupal::l('Up', $url), 'Up page link found.');
}
if ($next) {
/** @var \Drupal\Core\Url $url */
$url = $next->urlInfo();
$url->setOptions(array('html'=> TRUE, 'attributes' => array('rel' => array('next'), 'title' => t('Go to next page'))));
$this->assertRaw(\Drupal::l($next->label() . ' <b>›</b>', $url), 'Next page link found.');
$url->setOptions(array('attributes' => array('rel' => array('next'), 'title' => t('Go to next page'))));
$text = String::format('@label <b>›</b>', array('@label' => $next->label()));
$this->assertRaw(\Drupal::l($text, $url), 'Next page link found.');
}
// Compute the expected breadcrumb.
......
......@@ -39,7 +39,6 @@ function hook_comment_links_alter(array &$links, CommentInterface $entity, array
'comment-report' => array(
'title' => t('Report'),
'url' => Url::fromRoute('comment_test.report', ['comment' => $entity->id()], ['query' => ['token' => \Drupal::getContainer()->get('csrf_token')->get("comment/{$entity->id()}/report")]]),
'html' => TRUE,
),
),
);
......
......@@ -151,7 +151,6 @@ public function buildCommentedEntityLinks(FieldableEntityInterface $entity, arra
elseif ($this->currentUser->isAnonymous()) {
$links['comment-forbidden'] = array(
'title' => $this->commentManager->forbiddenMessage($entity, $field_name),
'html' => TRUE,
);
}
}
......@@ -186,7 +185,6 @@ public function buildCommentedEntityLinks(FieldableEntityInterface $entity, arra
elseif ($this->currentUser->isAnonymous()) {
$links['comment-forbidden'] = array(
'title' => $this->commentManager->forbiddenMessage($entity, $field_name),
'html' => TRUE,
);
}
}
......
......@@ -195,7 +195,6 @@ protected function buildLinks(CommentInterface $entity, EntityInterface $comment
$links['comment-delete'] = array(
'title' => t('Delete'),
'url' => $entity->urlInfo('delete-form'),
'html' => TRUE,
);
}
......@@ -203,7 +202,6 @@ protected function buildLinks(CommentInterface $entity, EntityInterface $comment
$links['comment-edit'] = array(
'title' => t('Edit'),
'url' => $entity->urlInfo('edit-form'),
'html' => TRUE,
);
}
if ($entity->access('create')) {
......@@ -215,19 +213,16 @@ protected function buildLinks(CommentInterface $entity, EntityInterface $comment
'field_name' => $entity->getFieldName(),
'pid' => $entity->id(),
]),
'html' => TRUE,
);
}
if (!$entity->isPublished() && $entity->access('approve')) {
$links['comment-approve'] = array(
'title' => t('Approve'),
'url' => Url::fromRoute('comment.approve', ['comment' => $entity->id()]),
'html' => TRUE,
);
}
if (empty($links) && $this->currentUser->isAnonymous()) {
$links['comment-forbidden']['title'] = $this->commentManager->forbiddenMessage($commented_entity, $entity->getFieldName());
$links['comment-forbidden']['html'] = TRUE;
}
}
......@@ -236,7 +231,6 @@ protected function buildLinks(CommentInterface $entity, EntityInterface $comment
$links['comment-translations'] = array(
'title' => t('Translate'),
'url' => $entity->urlInfo('drupal:content-translation-overview'),
'html' => TRUE,
);
}
......
......@@ -38,7 +38,6 @@ function comment_test_comment_links_alter(array &$links, CommentInterface &$enti
'comment-report' => array(
'title' => t('Report'),
'url' => Url::fromRoute('comment_test.report', ['comment' => $entity->id()], ['query' => ['token' => \Drupal::getContainer()->get('csrf_token')->get("comment/{$entity->id()}/report")]]),
'html' => TRUE,
),
),
);
......
......@@ -8,8 +8,9 @@
namespace Drupal\dblog\Controller;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\Unicode;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Component\Utility\String;
use Drupal\Component\Utility\Unicode;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Database\Connection;
......@@ -176,13 +177,14 @@ public function overview() {
$message = $this->formatMessage($dblog);
if ($message && isset($dblog->wid)) {
// Truncate link_text to 56 chars of message.
$log_text = Unicode::truncate(Xss::filter($message, array()), 56, TRUE, TRUE);
// @todo Reevaluate the SafeMarkup::set() in
// https://www.drupal.org/node/2399261.
$log_text = SafeMarkup::set(Unicode::truncate(Xss::filter($message, array()), 56, TRUE, TRUE));
$message = $this->l($log_text, new Url('dblog.event', array('event_id' => $dblog->wid), array(
'attributes' => array(
// Provide a title for the link for useful hover hints.
'title' => Unicode::truncate(strip_tags($message), 256, TRUE, TRUE),
),
'html' => TRUE,
)));
}
$username = array(
......
......@@ -7,6 +7,7 @@
namespace Drupal\dblog\Tests\Views;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Component\Utility\String;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Logger\RfcLogLevel;
......@@ -77,7 +78,7 @@ public function testIntegration() {
'variables' => array(
'@token1' => $this->randomMachineName(),
'!token2' => $this->randomMachineName(),
'link' => \Drupal::l('<object>Link</object>', new Url('<front>')),
'link' => \Drupal::l(SafeMarkup::set('<object>Link</object>'), new Url('<front>')),
),
);
$logger_factory = $this->container->get('logger.factory');
......
......@@ -121,9 +121,6 @@ public function render() {
'#type' => 'link',
'#url' => Url::fromRoute($short_type == 'view' ? 'entity.entity_view_mode.add_form' : 'entity.entity_form_mode.add_form', ['entity_type_id' => $entity_type]),
'#title' => t('Add new %label @entity-type', array('%label' => $this->entityTypes[$entity_type]->getLabel(), '@entity-type' => $this->entityType->getLowercaseLabel())),
'#options' => array(
'html' => TRUE,
),
),
'colspan' => count($table['#header']),
);
......
......@@ -189,8 +189,8 @@ public function viewElements(FieldItemListInterface $items) {
// If the title field value is available, use it for the link text.
if (empty($settings['url_only']) && !empty($item->title)) {
// Unsanitized token replacement here because $options['html'] is FALSE
// by default in _l().
// Unsanitized token replacement here because the entire link title
// gets auto-escaped during link generation.
$link_title = \Drupal::token()->replace($item->title, array($entity->getEntityTypeId() => $entity), array('sanitize' => FALSE, 'clear' => TRUE));
}
......
......@@ -54,8 +54,8 @@ public function viewElements(FieldItemListInterface $items) {
// If the link text field value is available, use it for the text.
if (empty($settings['url_only']) && !empty($item->title)) {
// Unsanitized token replacement here because $options['html'] is FALSE
// by default in _l().
// Unsanitized token replacement here because the entire link title
// gets auto-escaped during link generation.
$link_title = \Drupal::token()->replace($item->title, array($entity->getEntityTypeId() => $entity), array('sanitize' => FALSE, 'clear' => TRUE));
}
......
......@@ -500,7 +500,6 @@ function hook_node_links_alter(array &$links, NodeInterface $entity, array &$con
'node-report' => array(
'title' => t('Report'),
'href' => "node/{$entity->id()}/report",
'html' => TRUE,
'query' => array('token' => \Drupal::getContainer()->get('csrf_token')->get("node/{$entity->id()}/report")),
),
),
......
......@@ -149,7 +149,6 @@ protected static function buildLinks(NodeInterface $entity, $view_mode) {
)),
'url' => $entity->urlInfo(),
'language' => $entity->language(),
'html' => TRUE,
'attributes' => array(
'rel' => 'tag',
'title' => $node_title_stripped,
......
......@@ -143,7 +143,7 @@ function theme_responsive_image_formatter($variables) {
$responsive_image['#title'] = $item->title;
}
if (isset($variables['url'])) {
return \Drupal::l($responsive_image, $variables['url']->setOption('html', TRUE));
return \Drupal::l($responsive_image, $variables['url']);
}
return drupal_render($responsive_image);
......
......@@ -5,6 +5,7 @@
* Allows users to manage customizable lists of shortcut links.
*/
use Drupal\Component\Utility\String;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Routing\RouteMatchInterface;
......@@ -348,9 +349,9 @@ function shortcut_preprocess_page(&$variables) {
),
'#prefix' => '<div class="add-or-remove-shortcuts ' . $link_mode . '-shortcut">',
'#type' => 'link',
'#title' => '<span class="icon"></span><span class="text">'. $link_text .'</span>',
'#title' => String::format('<span class="icon"></span><span class="text">@text</span>', array('@text' => $link_text)),
'#url' => Url::fromRoute($route_name, $route_parameters),
'#options' => array('query' => $query, 'html' => TRUE),
'#options' => array('query' => $query),
'#suffix' => '</div>',
);
}
......
......@@ -48,4 +48,16 @@ public function testEntityOperationAlter() {
}
}
/**
* {@inheritdoc}
*/
protected function drupalCreateRole(array $permissions, $rid = NULL, $name = NULL, $weight = NULL) {
// WebTestBase::drupalCreateRole() by default uses random strings which may
// include HTML entities for the entity label. Since in this test the entity
// label is used to generate a link, and AssertContentTrait::assertLink() is
// not designed to deal with links potentially containing HTML entities this
// causes random failures. Use a random HTML safe string instead.
$name = $name ?: $this->randomMachineName();
return parent::drupalCreateRole($permissions, $rid, $name, $weight);
}
}
......@@ -196,6 +196,9 @@ function testLinks() {
'plain text' => array(
'title' => 'Plain "text"',
),
'html text' => array(
'title' => String::format('<span class="unescaped">@text</span>', array('@text' => 'potentially unsafe text that <should> be escaped')),
),
'front page' => array(
'title' => 'Front page',
'url' => Url::fromRoute('<front>'),
......@@ -217,6 +220,7 @@ function testLinks() {
$expected_links .= '<ul id="somelinks">';
$expected_links .= '<li class="a-link"><a href="' . Url::fromUri('base:a/link')->toString() . '">' . String::checkPlain('A <link>') . '</a></li>';
$expected_links .= '<li class="plain-text">' . String::checkPlain('Plain "text"') . '</li>';
$expected_links .= '<li class="html-text"><span class="unescaped">' . String::checkPlain('potentially unsafe text that <should> be escaped') . '</span></li>';
$expected_links .= '<li class="front-page"><a href="' . Url::fromRoute('<front>')->toString() . '">' . String::checkPlain('Front page') . '</a></li>';
$expected_links .= '<li class="router-test"><a href="' . \Drupal::urlGenerator()->generate('router_test.1') . '">' . String::checkPlain('Test route') . '</a></li>';
$query = array('key' => 'value');
......@@ -256,6 +260,7 @@ function testLinks() {
$expected_links .= '<ul id="somelinks">';
$expected_links .= '<li class="a-link"><a href="' . Url::fromUri('base:a/link')->toString() . '">' . String::checkPlain('A <link>') . '</a></li>';
$expected_links .= '<li class="plain-text"><span class="a/class">' . String::checkPlain('Plain "text"') . '</span></li>';
$expected_links .= '<li class="html-text"><span class="unescaped">' . String::checkPlain('potentially unsafe text that <should> be escaped') . '</span></li>';
$expected_links .= '<li class="front-page"><a href="' . Url::fromRoute('<front>')->toString() . '">' . String::checkPlain('Front page') . '</a></li>';
$expected_links .= '<li class="router-test"><a href="' . \Drupal::urlGenerator()->generate('router_test.1') . '">' . String::checkPlain('Test route') . '</a></li>';
$query = array('key' => 'value');
......@@ -271,6 +276,7 @@ function testLinks() {
$expected_links .= '<ul id="somelinks">';
$expected_links .= '<li class="a-link"><a href="' . Url::fromUri('base:a/link')->toString() . '">' . String::checkPlain('A <link>') . '</a></li>';
$expected_links .= '<li class="plain-text"><span class="a/class">' . String::checkPlain('Plain "text"') . '</span></li>';
$expected_links .= '<li class="html-text"><span class="unescaped">' . String::checkPlain('potentially unsafe text that <should> be escaped') . '</span></li>';
$expected_links .= '<li data-drupal-link-system-path="&lt;front&gt;" class="front-page"><a href="' . Url::fromRoute('<front>')->toString() . '" data-drupal-link-system-path="&lt;front&gt;">' . String::checkPlain('Front page') . '</a></li>';
$expected_links .= '<li data-drupal-link-system-path="router_test/test1" class="router-test"><a href="' . \Drupal::urlGenerator()->generate('router_test.1') . '" data-drupal-link-system-path="router_test/test1">' . String::checkPlain('Test route') . '</a></li>';
$query = array('key' => 'value');
......
......@@ -19,7 +19,6 @@ function toolbar_test_toolbar() {
'#title' => t('Test tab'),
'#url' => Url::fromRoute('<front>'),
'#options' => array(
'html' => FALSE,
'attributes' => array(
'id' => 'toolbar-tab-testing',
'title' => t('Test tab'),
......
......@@ -99,7 +99,6 @@ function hook_toolbar() {
'#title' => t('Shopping cart'),
'#url' => Url::fromRoute('cart'),
'#options' => array(
'html' => FALSE,
'attributes' => array(
'title' => t('Shopping cart'),
),
......
......@@ -1376,7 +1376,6 @@ function user_toolbar() {
'account' => array(
'title' => t('View profile'),
'url' => Url::fromRoute('user.page'),
'html' => TRUE,
'attributes' => array(
'title' => t('User account'),
),
......@@ -1384,7 +1383,6 @@ function user_toolbar() {
'account_edit' => array(
'title' => t('Edit profile'),
'url' => Url::fromRoute('entity.user.edit_form', ['user' => $user->id()]),
'html' => TRUE,
'attributes' => array(
'title' => t('Edit user account'),
),
......
......@@ -1007,19 +1007,30 @@ public function overrideOption($option, $value) {
* {@inheritdoc}
*/
public function optionLink($text, $section, $class = '', $title = '') {
if (!empty($class)) {
$text = '<span>' . $text . '</span>';
}
if (!trim($text)) {
$text = $this->t('Broken field');
}
if (!empty($class)) {
$text = String::format('<span>@text</span>', array('@text' => $text));
}
if (empty($title)) {
$title = $text;
}
return \Drupal::l($text, new Url('views_ui.form_display', ['js' => 'nojs', 'view' => $this->view->storage->id(), 'display_id' => $this->display['id'], 'type' => $section], array('attributes' => array('class' => array('views-ajax-link', $class), 'title' => $title, 'id' => Html::getUniqueId('views-' . $this->display['id'] . '-' . $section)), 'html' => TRUE)));
return \Drupal::l($text, new Url('views_ui.form_display', array(
'js' => 'nojs',
'view' => $this->view->storage->id(),
'display_id' => $this->display['id'],
'type' => $section
), array(
'attributes' => array(
'class' => array('views-ajax-link', $class),
'title' => $title,
'id' => Html::getUniqueId('views-' . $this->display['id'] . '-' . $section)
)
)));
}
/**
......@@ -1102,12 +1113,12 @@ public function optionsSummary(&$categories, &$options) {
$options['display_id'] = array(
'category' => 'other',
'title' => $this->t('Machine Name'),
'value' => !empty($this->display['new_id']) ? String::checkPlain($this->display['new_id']) : String::checkPlain($this->display['id']),
'value' => !empty($this->display['new_id']) ? $this->display['new_id'] : $this->display['id'],
'desc' => $this->t('Change the machine name of this display.'),
);
}
$display_comment = String::checkPlain(Unicode::substr($this->getOption('display_comment'), 0, 10));
$display_comment = Unicode::substr($this->getOption('display_comment'), 0, 10);
$options['display_comment'] = array(
'category' => 'other',
'title' => $this->t('Administrative comment'),
......@@ -1304,7 +1315,7 @@ public function optionsSummary(&$categories, &$options) {
$display_id = $this->getLinkDisplay();
$displays = $this->view->storage->get('display');
if (!empty($displays[$display_id])) {
$link_display = String::checkPlain($displays[$display_id]['display_title']);
$link_display = $displays[$display_id]['display_title'];
}
}
......@@ -1345,7 +1356,7 @@ public function optionsSummary(&$categories, &$options) {
$options['exposed_form']['links']['exposed_form_options'] = $this->t('Exposed form settings for this exposed form style.');
}
$css_class = String::checkPlain(trim($this->getOption('css_class')));
$css_class = trim($this->getOption('css_class'));
if (!$css_class) {
$css_class = $this->t('None');
}
......
......@@ -1303,7 +1303,6 @@ protected function renderAsLink($alter, $text, $tokens) {
'entity' => NULL,
'entity_type' => NULL,
'fragment' => NULL,
'html' => TRUE,
'language' => NULL,
'query' => [],
);
......
......@@ -51,7 +51,7 @@ public function render(ResultRow $values) {
if (!empty($this->options['display_as_link'])) {
// @todo Views should expect and store a leading /. See:
// https://www.drupal.org/node/2423913
return \Drupal::l($this->sanitizeValue($value), CoreUrl::fromUserInput('/' . $value), array('html' => TRUE));
return \Drupal::l($this->sanitizeValue($value), CoreUrl::fromUserInput('/' . $value));
}
else {
return $this->sanitizeValue($value, 'url');
......
......@@ -120,12 +120,12 @@ public function testDisplayPlugin() {
$this->clickLink('Test option title');
$this->randomString = $this->randomString();
$this->drupalPostForm(NULL, array('test_option' => $this->randomString), t('Apply'));
$test_option = $this->randomString();
$this->drupalPostForm(NULL, array('test_option' => $test_option), t('Apply'));
// Check the new value has been saved by checking the UI summary text.
$this->drupalGet('admin/structure/views/view/test_view/edit/display_test_1');
$this->assertRaw($this->randomString);
$this->assertLink($test_option);
// Test the enable/disable status of a display.
$view->display_handler->setOption('enabled', FALSE);
......
......@@ -57,7 +57,6 @@ class FieldPluginBaseTest extends UnitTestCase {
'alias' => FALSE,
'entity' => NULL,
'entity_type' => NULL,
'html' => TRUE,
'language' => NULL,
'query' => [],
'set_active_class' => FALSE,
......
......@@ -487,7 +487,6 @@ function template_preprocess_views_view_table(&$variables) {
$query['order'] = $field;
$query['sort'] = $initial;
$link_options = array(
'html' => TRUE,
'attributes' => array('title' => $title),
'query' => $query,
);
......
......@@ -7,6 +7,7 @@
namespace Drupal\views_ui\Form\Ajax;
use Drupal\Component\Utility\String;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\views\ViewEntityInterface;
......@@ -128,7 +129,14 @@ public function buildForm(array $form, FormStateInterface $form_state) {
'#id' => 'views-removed-' . $id,
'#attributes' => array('class' => array('views-remove-checkbox')),
'#default_value' => 0,
'#suffix' => \Drupal::l('<span>' . $this->t('Remove') . '</span>', Url::fromRoute('<none>', [], array('attributes' => array('id' => 'views-remove-link-' . $id, 'class' => array('views-hidden', 'views-button-remove', 'views-remove-link'), 'alt' => $this->t('Remove this item'), 'title' => $this->t('Remove this item')), 'html' => TRUE))),
'#suffix' => \Drupal::l(String::format('<span>@text</span>', array('@text' => $this->t('Remove'))),
Url::fromRoute('<none>', array(), array('attributes' => array(
'id' => 'views-remove-link-' . $id,
'class' => array('views-hidden', 'views-button-remove', 'views-remove-link'),
'alt' => $this->t('Remove this item'),
'title' => $this->t('Remove this item')),
))
),
);
}
......
......@@ -7,6 +7,7 @@
namespace Drupal\views_ui\Form\Ajax;
use Drupal\Component\Utility\String;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;