Issue #2500931 by mikeker, jhedstrom, Berdir: Views feed doesn't encode embedded HTML anymore
parent
9f74e47286
commit
30c6960459
|
@ -50,7 +50,6 @@ class Rss extends RssPluginBase {
|
|||
|
||||
$item = new \stdClass();
|
||||
foreach ($entity as $name => $field) {
|
||||
// views_view_row_rss takes care about the escaping.
|
||||
$item->{$name} = $field->value;
|
||||
}
|
||||
|
||||
|
|
|
@ -84,8 +84,6 @@ class Rss extends RssPluginBase {
|
|||
return;
|
||||
}
|
||||
|
||||
$description_build = [];
|
||||
|
||||
$comment->link = $comment->url('canonical', array('absolute' => TRUE));
|
||||
$comment->rss_namespaces = array();
|
||||
$comment->rss_elements = array(
|
||||
|
@ -113,13 +111,11 @@ class Rss extends RssPluginBase {
|
|||
$this->view->style_plugin->namespaces = array_merge($this->view->style_plugin->namespaces, $comment->rss_namespaces);
|
||||
}
|
||||
|
||||
$item = new \stdClass();
|
||||
if ($view_mode != 'title') {
|
||||
// We render comment contents.
|
||||
$description_build = $build;
|
||||
$item->description = $build;
|
||||
}
|
||||
|
||||
$item = new \stdClass();
|
||||
$item->description = $description_build;
|
||||
$item->title = $comment->label();
|
||||
$item->link = $comment->link;
|
||||
// Provide a reference so that the render call in
|
||||
|
|
|
@ -108,8 +108,6 @@ class Rss extends RssPluginBase {
|
|||
return;
|
||||
}
|
||||
|
||||
$description_build = [];
|
||||
|
||||
$node->link = $node->url('canonical', array('absolute' => TRUE));
|
||||
$node->rss_namespaces = array();
|
||||
$node->rss_elements = array(
|
||||
|
@ -149,13 +147,11 @@ class Rss extends RssPluginBase {
|
|||
$this->view->style_plugin->namespaces += $xml_rdf_namespaces;
|
||||
}
|
||||
|
||||
$item = new \stdClass();
|
||||
if ($display_mode != 'title') {
|
||||
// We render node contents.
|
||||
$description_build = $build;
|
||||
$item->description = $build;
|
||||
}
|
||||
|
||||
$item = new \stdClass();
|
||||
$item->description = $description_build;
|
||||
$item->title = $node->label();
|
||||
$item->link = $node->link;
|
||||
// Provide a reference so that the render call in
|
||||
|
|
|
@ -147,8 +147,10 @@ class RssFields extends RowPluginBase {
|
|||
// @todo Views should expect and store a leading /. See:
|
||||
// https://www.drupal.org/node/2423913
|
||||
$item->link = Url::fromUserInput('/' . $this->getField($row_index, $this->options['link_field']))->setAbsolute()->toString();
|
||||
|
||||
$field = $this->getField($row_index, $this->options['description_field']);
|
||||
$item->description = is_array($field) ? $field : ['#markup' => $field];
|
||||
|
||||
$item->elements = array(
|
||||
array('key' => 'pubDate', 'value' => $this->getField($row_index, $this->options['date_field'])),
|
||||
array(
|
||||
|
|
|
@ -48,9 +48,13 @@ class DisplayFeedTest extends PluginTestBase {
|
|||
|
||||
// Verify a title with HTML entities is properly escaped.
|
||||
$node_title = 'This "cool" & "neat" article\'s title';
|
||||
$node = $this->drupalCreateNode(array(
|
||||
'title' => $node_title
|
||||
));
|
||||
$node = $this->drupalCreateNode([
|
||||
'title' => $node_title,
|
||||
'body' => [0 => [
|
||||
'value' => 'A paragraph',
|
||||
'format' => filter_default_format(),
|
||||
]],
|
||||
]);
|
||||
|
||||
// Test the site name setting.
|
||||
$site_name = $this->randomMachineName();
|
||||
|
@ -60,6 +64,8 @@ class DisplayFeedTest extends PluginTestBase {
|
|||
$result = $this->xpath('//title');
|
||||
$this->assertEqual($result[0], $site_name, 'The site title is used for the feed title.');
|
||||
$this->assertEqual($result[1], $node_title, 'Node title with HTML entities displays correctly.');
|
||||
// Verify HTML is properly escaped in the description field.
|
||||
$this->assertRaw('<p>A paragraph</p>');
|
||||
|
||||
$view = $this->container->get('entity.manager')->getStorage('view')->load('test_display_feed');
|
||||
$display = &$view->getDisplay('feed_1');
|
||||
|
@ -101,12 +107,18 @@ class DisplayFeedTest extends PluginTestBase {
|
|||
// Verify a title with HTML entities is properly escaped.
|
||||
$node_title = 'This "cool" & "neat" article\'s title';
|
||||
$this->drupalCreateNode(array(
|
||||
'title' => $node_title
|
||||
'title' => $node_title,
|
||||
'body' => [0 => [
|
||||
'value' => 'A paragraph',
|
||||
'format' => filter_default_format(),
|
||||
]],
|
||||
));
|
||||
|
||||
$this->drupalGet('test-feed-display-fields.xml');
|
||||
$result = $this->xpath('//title/a');
|
||||
$this->assertEqual($result[0], $node_title, 'Node title with HTML entities displays correctly.');
|
||||
// Verify HTML is properly escaped in the description field.
|
||||
$this->assertRaw('<p>A paragraph</p>');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
config:
|
||||
- core.entity_view_mode.node.teaser
|
||||
- field.storage.node.body
|
||||
module:
|
||||
- node
|
||||
- text
|
||||
- user
|
||||
id: test_display_feed
|
||||
label: test_display_feed
|
||||
|
@ -41,6 +45,68 @@ display:
|
|||
plugin_id: field
|
||||
entity_type: node
|
||||
entity_field: title
|
||||
body:
|
||||
id: body
|
||||
table: node__body
|
||||
field: body
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: ''
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
text: ''
|
||||
make_link: false
|
||||
path: ''
|
||||
absolute: false
|
||||
external: false
|
||||
replace_spaces: false
|
||||
path_case: none
|
||||
trim_whitespace: false
|
||||
alt: ''
|
||||
rel: ''
|
||||
link_class: ''
|
||||
prefix: ''
|
||||
suffix: ''
|
||||
target: ''
|
||||
nl2br: false
|
||||
max_length: 0
|
||||
word_boundary: true
|
||||
ellipsis: true
|
||||
more_link: false
|
||||
more_link_text: ''
|
||||
more_link_path: ''
|
||||
strip_tags: false
|
||||
trim: false
|
||||
preserve_tags: ''
|
||||
html: false
|
||||
element_type: ''
|
||||
element_class: ''
|
||||
element_label_type: ''
|
||||
element_label_class: ''
|
||||
element_label_colon: false
|
||||
element_wrapper_type: ''
|
||||
element_wrapper_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
click_sort_column: value
|
||||
type: text_default
|
||||
settings: { }
|
||||
group_column: value
|
||||
group_columns: { }
|
||||
group_rows: true
|
||||
delta_limit: 0
|
||||
delta_offset: 0
|
||||
delta_reversed: false
|
||||
delta_first_last: false
|
||||
multi_type: separator
|
||||
separator: ', '
|
||||
field_api_classes: false
|
||||
plugin_id: field
|
||||
filters:
|
||||
status:
|
||||
expose:
|
||||
|
@ -75,10 +141,21 @@ display:
|
|||
style:
|
||||
type: default
|
||||
title: test_display_feed
|
||||
display_extenders: { }
|
||||
display_plugin: default
|
||||
display_title: Master
|
||||
id: default
|
||||
position: 0
|
||||
cache_metadata:
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url.query_args
|
||||
- 'user.node_grants:view'
|
||||
- user.permissions
|
||||
max-age: -1
|
||||
tags:
|
||||
- 'config:field.storage.node.body'
|
||||
feed_1:
|
||||
display_options:
|
||||
displays: { }
|
||||
|
@ -90,10 +167,20 @@ display:
|
|||
style:
|
||||
type: rss
|
||||
sitename_title: true
|
||||
display_extenders: { }
|
||||
display_plugin: feed
|
||||
display_title: Feed
|
||||
id: feed_1
|
||||
position: 0
|
||||
cache_metadata:
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- 'user.node_grants:view'
|
||||
- user.permissions
|
||||
max-age: -1
|
||||
tags:
|
||||
- 'config:field.storage.node.body'
|
||||
feed_2:
|
||||
display_options:
|
||||
displays: { }
|
||||
|
@ -105,7 +192,7 @@ display:
|
|||
options:
|
||||
title_field: title
|
||||
link_field: title
|
||||
description_field: title
|
||||
description_field: body
|
||||
creator_field: title
|
||||
date_field: title
|
||||
guid_field_options:
|
||||
|
@ -115,14 +202,35 @@ display:
|
|||
type: rss
|
||||
sitename_title: true
|
||||
display_description: ''
|
||||
display_extenders: { }
|
||||
display_plugin: feed
|
||||
display_title: 'Feed with Fields'
|
||||
id: feed_2
|
||||
position: 0
|
||||
cache_metadata:
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- 'user.node_grants:view'
|
||||
- user.permissions
|
||||
max-age: -1
|
||||
tags:
|
||||
- 'config:field.storage.node.body'
|
||||
page:
|
||||
display_options:
|
||||
path: test-feed-display
|
||||
display_extenders: { }
|
||||
display_plugin: page
|
||||
display_title: <em>Page</em>
|
||||
display_title: '<em>Page</em>'
|
||||
id: page
|
||||
position: 0
|
||||
cache_metadata:
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url.query_args
|
||||
- 'user.node_grants:view'
|
||||
- user.permissions
|
||||
max-age: -1
|
||||
tags:
|
||||
- 'config:field.storage.node.body'
|
||||
|
|
|
@ -863,11 +863,14 @@ function template_preprocess_views_view_row_rss(&$variables) {
|
|||
$variables['title'] = $item->title;
|
||||
$variables['link'] = $item->link;
|
||||
|
||||
/** @var \Drupal\Core\Render\RendererInterface $renderer */
|
||||
$renderer = \Drupal::service('renderer');
|
||||
// We render the item description. It might contain entities, which attach rss
|
||||
// elements via hook_entity_view, see comment_entity_view().
|
||||
$variables['description'] = is_array($item->description) ? $renderer->render($item->description) : $item->description;
|
||||
// The description is the only place where we should find HTML.
|
||||
// @see https://validator.w3.org/feed/docs/rss2.html#hrelementsOfLtitemgt
|
||||
// If we have a render array, render it here and pass the result to the
|
||||
// template, letting Twig autoescape it.
|
||||
if (isset($item->description) && is_array($item->description)) {
|
||||
$variables['description'] = (string) \Drupal::service('renderer')->render($item->description);
|
||||
}
|
||||
|
||||
$variables['item_elements'] = array();
|
||||
foreach ($item->elements as $element) {
|
||||
if (isset($element['attributes']) && is_array($element['attributes'])) {
|
||||
|
|
Loading…
Reference in New Issue