From ed4ed9f86e44fbd9f8845eb4b09ac4a999132a37 Mon Sep 17 00:00:00 2001 From: megachriz <megachriz@654114.no-reply.drupal.org> Date: Wed, 27 Apr 2016 11:21:06 +0200 Subject: [PATCH] Issue #2648304 by MegaChriz, OWast: RSS 2.0: add support for item->source element. --- libraries/common_syndication_parser.inc | 10 ++++ plugins/FeedsSyndicationParser.inc | 8 +++ tests/feeds/developmentseed.rss2 | 1 + tests/feeds_parser_syndication.test | 66 ++++++++++++++++++++++++- 4 files changed, 84 insertions(+), 1 deletion(-) diff --git a/libraries/common_syndication_parser.inc b/libraries/common_syndication_parser.inc index 2fa1bbd1..a0c1e319 100644 --- a/libraries/common_syndication_parser.inc +++ b/libraries/common_syndication_parser.inc @@ -357,6 +357,9 @@ function _parser_common_syndication_RSS20_parse($feed_XML) { foreach ($feed_XML->xpath('//item') as $news) { $title = $body = $original_author = $original_url = $guid = ''; + // Get optional source url. + $source_url = (string) $news->source['url']; + $category = $news->xpath('category'); // Get children for current namespace. $content = (array)$news->children($ns["content"]); @@ -454,6 +457,13 @@ function _parser_common_syndication_RSS20_parse($feed_XML) { } $item['url'] = trim($original_url); $item['guid'] = $guid; + if (!empty($news['source'])) { + $item['source:title'] = $news['source']; + } + else { + $item['source:title'] = NULL; + } + $item['source:url'] = trim($source_url); $item['geolocations'] = array(); if (isset($geoname, $lat, $lon)) { diff --git a/plugins/FeedsSyndicationParser.inc b/plugins/FeedsSyndicationParser.inc index 884b975d..3da4af9a 100644 --- a/plugins/FeedsSyndicationParser.inc +++ b/plugins/FeedsSyndicationParser.inc @@ -76,6 +76,14 @@ class FeedsSyndicationParser extends FeedsParser { 'name' => t('Geo Locations'), 'description' => t('An array of geographic locations with a name and a position.'), ), + 'source:url' => array( + 'name' => t('Source: URL'), + 'description' => t('The URL of the RSS channel that the item came from.'), + ), + 'source:title' => array( + 'name' => t('Source: Title'), + 'description' => t('The title of the RSS channel that the item came from.'), + ), ) + parent::getMappingSources(); } diff --git a/tests/feeds/developmentseed.rss2 b/tests/feeds/developmentseed.rss2 index 90f5deaf..54106859 100644 --- a/tests/feeds/developmentseed.rss2 +++ b/tests/feeds/developmentseed.rss2 @@ -42,6 +42,7 @@ <pubDate>Tue, 06 Oct 2009 15:21:48 +0000</pubDate> <dc:creator>Development Seed</dc:creator> <guid isPermaLink="false">974 at http://developmentseed.org</guid> + <source url="http://developmentseed.org/node/974">Technological Solutions for Progressive Organizations</source> </item> <item> <title>Week in DC Tech: October 5th Edition</title> diff --git a/tests/feeds_parser_syndication.test b/tests/feeds_parser_syndication.test index a62759f8..83f4bf3a 100644 --- a/tests/feeds_parser_syndication.test +++ b/tests/feeds_parser_syndication.test @@ -8,7 +8,7 @@ /** * Test single feeds. */ -class FeedsSyndicationParserTestCase extends FeedsWebTestCase { +class FeedsSyndicationParserTestCase extends FeedsMapperTestCase { public static function getInfo() { return array( @@ -66,4 +66,68 @@ class FeedsSyndicationParserTestCase extends FeedsWebTestCase { ); } + /** + * Tests if the "<source>" element of a RSS feed is parsed correctly. + * + * This element is optional according to the RSS 2.0 specification. + */ + public function testRSSSourceElement() { + // Do not use curl as that will result into HTTP requests returning a 404. + variable_set('feeds_never_use_curl', TRUE); + + // Create content type with two text fields. + $typename = $this->createContentType(array(), array( + 'source_title' => 'text', + 'source_url' => 'text', + )); + + // Create importer and map sources from source element to text fields. + $this->createImporterConfiguration('Syndication', 'syndication'); + $this->setSettings('syndication', 'FeedsNodeProcessor', array('bundle' => $typename)); + $this->addMappings('syndication', + array( + 0 => array( + 'source' => 'title', + 'target' => 'title', + 'unique' => FALSE, + ), + 1 => array( + 'source' => 'source:title', + 'target' => 'field_source_title', + ), + 2 => array( + 'source' => 'source:url', + 'target' => 'field_source_url', + ), + ) + ); + + // Import url. + $url = $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'feeds') . '/tests/feeds/developmentseed.rss2'; + $this->createFeedNode('syndication', $url); + + // Assert that the contents for the source element were imported for the + // first imported node. + $node = node_load(2); + $fields = array( + 'field_source_title' => array( + 'expected' => 'Technological Solutions for Progressive Organizations', + 'actual' => $node->field_source_title[LANGUAGE_NONE][0]['value'], + ), + 'field_source_url' => array( + 'expected' => 'http://developmentseed.org/node/974', + 'actual' => $node->field_source_url[LANGUAGE_NONE][0]['value'], + ), + ); + foreach ($fields as $field_name => $value) { + $this->assertEqual($value['expected'], $value['actual'], format_string('The field %field has the expected value (actual: @actual).', array('%field' => $field_name, '@actual' => $value['actual']))); + } + + // Assert that for the second imported node, no values were imported, + // because the second item does not contain a source element. + $node = node_load(3); + foreach ($fields as $field_name => $value) { + $this->assertTrue(!isset($node->{$field_name}[LANGUAGE_NONE][0]['value']), format_string('The field %field does not contain a value (actual: @actual).', array('%field' => $field_name, '@actual' => $value['actual']))); + } + } } -- GitLab