Skip to content
Snippets Groups Projects
Commit b87d1e99 authored by David Cameron's avatar David Cameron
Browse files

Issue #2552037 by dcam, geertvd, dawehner, larowlan, Lendude: Aggregator RSS...

Issue #2552037 by dcam, geertvd, dawehner, larowlan, Lendude: Aggregator RSS feed outputting empty feed items
parent 4398b61c
No related branches found
No related tags found
No related merge requests found
...@@ -11,3 +11,77 @@ ...@@ -11,3 +11,77 @@
function aggregator_update_last_removed() { function aggregator_update_last_removed() {
return 8501; return 8501;
} }
/**
* Update views.view.aggregator_rss_feed.
*/
function aggregator_update_8601() {
if (!aggregator_rss_view_config_is_default()) {
return t("The Aggregator RSS feed view was updated in version 2.0.x.
Unfortunately, this site's view has been modified from the original and
cannot be updated automatically. If you want to get the latest changes to
the view, then you will need to manually import the configuration at
aggregator/config/optional/views.view.aggregator_rss_feed.yml.");
}
$view_config = \Drupal::configFactory()->getEditable('views.view.aggregator_rss_feed');
$view_config->set('dependencies.config', [
'core.entity_view_mode.aggregator_item.summary',
]);
$view_config->set('display.default.display_options.fields', []);
$view_config->set('display.default.display_options.sorts', [
'timestamp' => [
'id' => 'timestamp',
'table' => 'aggregator_item',
'field' => 'timestamp',
'relationship' => 'none',
'group_type' => 'group',
'admin_label' => '',
'entity_type' => 'aggregator_item',
'entity_field' => 'timestamp',
'plugin_id' => 'date',
'order' => 'DESC',
'expose' => [
'label' => '',
'field_identifier' => '',
],
'exposed' => FALSE,
'granularity' => 'second',
],
]);
$view_config->set('display.feed_items.display_options', [
'row' => [
'type' => 'aggregator_rss',
'options' => [
'relationship' => 'none',
'view_mode' => 'summary',
],
],
]);
$view_config->save();
}
/**
* Determines whether the RSS view config has been altered from the default.
*
* @return bool
* TRUE if the hash of the current config matches the value of the
* default_config_hash, FALSE if the hash key does not exist or does not
* match.
*/
function aggregator_rss_view_config_is_default() {
// Get an editable config object here so that properties can be cleared before
// serialization. Just be sure to not save()!
$view_config = \Drupal::configFactory()->getEditable('views.view.aggregator_rss_feed');
$default_config_hash = $view_config->get('_core.default_config_hash');
// If the default config hash doesn't exist, then the config was overridden.
if ($default_config_hash == NULL) {
return FALSE;
}
// Clear properties that are not part of the original file.
$view_config->clear('uuid')
->clear('_core');
$config_string = serialize($view_config->getRawData());
return \Drupal\Component\Utility\Crypt::hashBase64($config_string) == $default_config_hash;
}
langcode: en langcode: en
status: true status: true
dependencies: dependencies:
config:
- core.entity_view_mode.aggregator_item.summary
module: module:
- aggregator - aggregator
- user - user
...@@ -19,59 +21,7 @@ display: ...@@ -19,59 +21,7 @@ display:
position: 0 position: 0
display_options: display_options:
title: 'Aggregator RSS feed' title: 'Aggregator RSS feed'
fields: fields: { }
iid:
id: iid
table: aggregator_item
field: iid
relationship: none
group_type: group
admin_label: ''
entity_type: aggregator_item
entity_field: iid
plugin_id: field
label: 'Item ID'
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: true
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_empty: false
empty_zero: false
hide_alter_empty: true
type: number_integer
pager: pager:
type: full type: full
options: options:
...@@ -111,7 +61,23 @@ display: ...@@ -111,7 +61,23 @@ display:
type: tag type: tag
options: { } options: { }
empty: { } empty: { }
sorts: { } sorts:
timestamp:
id: timestamp
table: aggregator_item
field: timestamp
relationship: none
group_type: group
admin_label: ''
entity_type: aggregator_item
entity_field: timestamp
plugin_id: date
order: DESC
expose:
label: ''
field_identifier: ''
exposed: false
granularity: second
arguments: { } arguments: { }
filters: { } filters: { }
style: style:
...@@ -145,6 +111,11 @@ display: ...@@ -145,6 +111,11 @@ display:
display_plugin: feed display_plugin: feed
position: 1 position: 1
display_options: display_options:
row:
type: aggregator_rss
options:
relationship: none
view_mode: summary
defaults: defaults:
arguments: true arguments: true
display_description: '' display_description: ''
......
...@@ -48,6 +48,11 @@ class Rss extends RssPluginBase { ...@@ -48,6 +48,11 @@ class Rss extends RssPluginBase {
$item->{$name} = $field->value; $item->{$name} = $field->value;
} }
// Item descriptions must be render arrays.
if (isset($item->description) && !is_array($item->description)) {
$item->description = ['#markup' => $item->description];
}
$item->elements = [ $item->elements = [
[ [
'key' => 'pubDate', 'key' => 'pubDate',
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
namespace Drupal\Tests\aggregator\Functional; namespace Drupal\Tests\aggregator\Functional;
use Drupal\aggregator\Entity\Item;
use Drupal\views\Entity\View; use Drupal\views\Entity\View;
/** /**
...@@ -102,6 +103,12 @@ class AggregatorRenderingTest extends AggregatorTestBase { ...@@ -102,6 +103,12 @@ class AggregatorRenderingTest extends AggregatorTestBase {
$feed = $this->createFeed(); $feed = $this->createFeed();
$this->updateFeedItems($feed, 30); $this->updateFeedItems($feed, 30);
// Change the post date for an item to be the most recent item to ensure
// consistency in sorting.
/** @var \Drupal\aggregator\Entity\Item $latest_item */
$latest_item = Item::load(30);
$latest_item->setPostedTime(time() + 1000);
$latest_item->save();
// Verify that items are loaded on the page by checking for the pager. // Verify that items are loaded on the page by checking for the pager.
$this->drupalGet('aggregator'); $this->drupalGet('aggregator');
...@@ -137,13 +144,27 @@ class AggregatorRenderingTest extends AggregatorTestBase { ...@@ -137,13 +144,27 @@ class AggregatorRenderingTest extends AggregatorTestBase {
$this->assertSession()->statusCodeEquals(200); $this->assertSession()->statusCodeEquals(200);
$this->assertSession()->responseHeaderEquals('Content-Type', 'application/rss+xml; charset=utf-8'); $this->assertSession()->responseHeaderEquals('Content-Type', 'application/rss+xml; charset=utf-8');
// We can't use Mink xpath queries for checking the content of the RSS and
// OPML pages because they are XML. Mink only supports HTML.
$rss_content = $this->getSession()->getPage()->getContent();
$rss_xml = simplexml_load_string($rss_content);
$rss_xml->registerXPathNamespace('dc', 'http://purl.org/dc/elements/1.1/');
$rss = $rss_xml->xpath('//rss/channel');
$this->assertEquals((string) $rss[0]->title, 'Aggregator RSS feed');
$this->assertEquals(count($rss[0]->item), 10, 'Found 10 feed items.');
// Check for item content in the RSS feed.
$this->assertEquals((string) $rss[0]->item[0]->title, $latest_item->label());
$this->assertEquals((string) $rss[0]->item[0]->description, $latest_item->getDescription());
$this->assertEquals((string) $rss[0]->item[0]->pubDate, gmdate('r', $latest_item->getPostedTime()));
$this->assertEquals((string) $rss[0]->item[0]->xpath('//dc:creator')[0], $latest_item->getAuthor());
$this->assertEquals((string) $rss[0]->item[0]->guid, $latest_item->getGuid());
// Check the opml aggregator page. // Check the opml aggregator page.
$this->drupalGet('aggregator/opml'); $this->drupalGet('aggregator/opml');
$content = $this->getSession()->getPage()->getContent(); $opml_content = $this->getSession()->getPage()->getContent();
// We can't use Mink xpath queries here because it only supports HTML pages, $opml_xml = simplexml_load_string($opml_content);
// but we are dealing with XML here. $attributes = $opml_xml->xpath('//outline[1]')[0]->attributes();
$xml = simplexml_load_string($content);
$attributes = $xml->xpath('//outline[1]')[0]->attributes();
$this->assertEquals('rss', $attributes->type); $this->assertEquals('rss', $attributes->type);
$this->assertEquals($feed->label(), $attributes->text); $this->assertEquals($feed->label(), $attributes->text);
$this->assertEquals($feed->getUrl(), $attributes->xmlUrl); $this->assertEquals($feed->getUrl(), $attributes->xmlUrl);
......
<?php
namespace Drupal\Tests\aggregator\Functional\Update;
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
/**
* @covers aggregator_update_8601()
* @group Update
* @group aggregator
*/
class AggregatorUpdateRssFeedViewTest extends UpdatePathTestBase {
/**
* {@inheritdoc}
*/
protected function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [
DRUPAL_ROOT . '/core/modules/system/tests/fixtures/update/drupal-9.4.0.bare.standard.php.gz',
__DIR__ . '/../../../fixtures/update/aggregator.php',
];
}
/**
* Ensure views.view.aggregator_rss_feed is updated.
*/
public function testUpdateHookConfigMatch(): void {
$this->runUpdates();
$view_config = \Drupal::config('views.view.aggregator_rss_feed');
$this->assertSame([
'core.entity_view_mode.aggregator_item.summary',
], $view_config->get('dependencies.config'));
$this->assertSame([], $view_config->get('display.default.display_options.fields'));
$this->assertSame([
'timestamp' => [
'id' => 'timestamp',
'table' => 'aggregator_item',
'field' => 'timestamp',
'relationship' => 'none',
'group_type' => 'group',
'admin_label' => '',
'entity_type' => 'aggregator_item',
'entity_field' => 'timestamp',
'plugin_id' => 'date',
'order' => 'DESC',
'expose' => [
'label' => '',
'field_identifier' => '',
],
'exposed' => FALSE,
'granularity' => 'second',
],
], $view_config->get('display.default.display_options.sorts'));
$this->assertSame([
'row' => [
'type' => 'aggregator_rss',
'options' => [
'relationship' => 'none',
'view_mode' => 'summary',
],
],
], $view_config->get('display.feed_items.display_options'));
}
/**
* Ensure a message is displayed informing that the view cannot be updated.
*/
public function testUpdateHookConfigMismatch(): void {
$view_config = \Drupal::configFactory()->getEditable('views.view.aggregator_rss_feed');
// Change the view so that the config will not match the default hash.
$view_config->set('status', FALSE);
$view_config->save();
$this->runUpdates();
$this->assertSession()->responseContains("Unfortunately, this site's view has been modified from the original and
cannot be updated automatically.");
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment