Issue #2500931 by mikeker, jhedstrom, Berdir: Views feed doesn't encode embedded HTML anymore

8.0.x
Alex Pott 2015-10-30 13:56:47 +00:00
parent 9f74e47286
commit 30c6960459
7 changed files with 140 additions and 24 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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(

View File

@ -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>');
}
/**

View File

@ -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'

View File

@ -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'])) {