diff --git a/core/modules/aggregator/aggregator.module b/core/modules/aggregator/aggregator.module index 2f25526..927162e 100644 --- a/core/modules/aggregator/aggregator.module +++ b/core/modules/aggregator/aggregator.module @@ -6,6 +6,7 @@ */ use Drupal\aggregator\Plugin\Core\Entity\Feed; +use Drupal\Component\Plugin\Exception\PluginException; /** * Denotes that a feed's items should never expire. @@ -405,7 +406,13 @@ function aggregator_remove(Feed $feed) { // Call ProcessorInterface::remove() on all processors. $manager = drupal_container()->get('plugin.manager.aggregator.processor'); foreach ($manager->getDefinitions() as $id => $definition) { - $manager->createInstance($id)->remove($feed); + try { + $manager->createInstance($id)->remove($feed); + } + catch (PluginException $e) { + // Fail silently + // @todo Maybe add a watchdog entry? + } } // Reset feed. $feed->checked->value = 0; @@ -433,6 +440,7 @@ function aggregator_refresh(Feed $feed) { } catch (PluginException $e) { $success = FALSE; + // @todo Maybe add a watchdog entry? } // Retrieve processor manager now. @@ -440,7 +448,13 @@ function aggregator_refresh(Feed $feed) { // Store instances in an array so we dont have to instantiate new objects. $processor_instances = array(); foreach ($config->get('processors') as $processor) { - $processor_instances[$processor] = $processor_manager->createInstance($processor); + try { + $processor_instances[$processor] = $processor_manager->createInstance($processor); + } + catch (PluginException $e) { + // Fail silently + // @todo Maybe add a watchdog entry? + } } // We store the hash of feed data in the database. When refreshing a @@ -451,29 +465,35 @@ function aggregator_refresh(Feed $feed) { if ($success && ($feed->hash->value != $hash)) { // Parse the feed. $parser_manager = drupal_container()->get('plugin.manager.aggregator.parser'); - if ($parser_manager->createInstance($config->get('parser'))->parse($feed)) { - if (empty($feed->link->value)) { - $feed->link->value = $feed->url->value; - } - $feed->hash->value = $hash; - // Update feed with parsed data. - $feed->save(); + try { + if ($parser_manager->createInstance($config->get('parser'))->parse($feed)) { + if (empty($feed->link->value)) { + $feed->link->value = $feed->url->value; + } + $feed->hash->value = $hash; + // Update feed with parsed data. + $feed->save(); - // Log if feed URL has changed. - if ($feed->url->value != $feed_url) { - watchdog('aggregator', 'Updated URL for feed %title to %url.', array('%title' => $feed->label(), '%url' => $feed->url->value)); - } + // Log if feed URL has changed. + if ($feed->url->value != $feed_url) { + watchdog('aggregator', 'Updated URL for feed %title to %url.', array('%title' => $feed->label(), '%url' => $feed->url->value)); + } - watchdog('aggregator', 'There is new syndicated content from %site.', array('%site' => $feed->label())); - drupal_set_message(t('There is new syndicated content from %site.', array('%site' => $feed->label()))); + watchdog('aggregator', 'There is new syndicated content from %site.', array('%site' => $feed->label())); + drupal_set_message(t('There is new syndicated content from %site.', array('%site' => $feed->label()))); - // If there are items on the feed, let all enabled processors do their work on it. - if (@count($feed->items)) { - foreach ($processor_instances as $instance) { - $instance->process($feed); + // If there are items on the feed, let all enabled processors do their work on it. + if (@count($feed->items)) { + foreach ($processor_instances as $instance) { + $instance->process($feed); + } } } } + catch (PluginException $e) { + // Fail silently + // @todo Maybe add a watchdog entry? + } } else { drupal_set_message(t('There is no new syndicated content from %site.', array('%site' => $feed->label()))); diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorConfigurationTest.php b/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorConfigurationTest.php index a7f8357..bad753e 100644 --- a/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorConfigurationTest.php +++ b/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorConfigurationTest.php @@ -29,13 +29,15 @@ function testSettingsPage() { $this->assertText(t('Test parser')); $this->assertText(t('Test processor')); - // Set new values and enable test processor. + // Set new values and enable test plugins. $edit = array( 'aggregator_allowed_html_tags' => '', 'aggregator_summary_items' => 10, 'aggregator_clear' => 3600, 'aggregator_category_selector' => 'select', 'aggregator_teaser_length' => 200, + 'aggregator_fetcher' => 'aggregator_test_fetcher', + 'aggregator_parser' => 'aggregator_test_parser', 'aggregator_processors[aggregator_test_processor]' => 'aggregator_test_processor', ); $this->drupalPost('admin/config/services/aggregator/settings', $edit, t('Save configuration')); @@ -54,5 +56,12 @@ function testSettingsPage() { $this->drupalPost('admin/config/services/aggregator/settings', $edit, t('Save configuration')); $this->assertText(t('The configuration options have been saved.')); $this->assertFieldByName('dummy_length', 100, '"dummy_length" has correct default value.'); + + // Make sure settings form is still accessible even after disabling a module + // that provides the selected plugins. + module_disable(array('aggregator_test')); + $this->drupalGet('admin/config/services/aggregator/settings'); + // @todo Re-enable when http://drupal.org/node/1780396 is fixed + //$this->assertResponse(200); } } diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorTestBase.php b/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorTestBase.php index c061c3b..b43e4f8 100644 --- a/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorTestBase.php +++ b/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorTestBase.php @@ -149,9 +149,9 @@ function getDefaultFeedItemCount() { * @param \Drupal\aggregator\Plugin\Core\Entity\Feed $feed * Feed object representing the feed. * @param $expected_count - * Expected number of feed items. + * Expected number of feed items. If omitted no check will happen. */ - function updateFeedItems(Feed $feed, $expected_count) { + function updateFeedItems(Feed $feed, $expected_count = NULL) { // First, let's ensure we can get to the rss xml. $this->drupalGet($feed->url->value); $this->assertResponse(200, format_string('!url is reachable.', array('!url' => $feed->url->value))); @@ -171,8 +171,11 @@ function updateFeedItems(Feed $feed, $expected_count) { foreach ($result as $item) { $feed->items[] = $item->iid; } - $feed->item_count = count($feed->items); - $this->assertEqual($expected_count, $feed->item_count, format_string('Total items in feed equal to the total items in database (!val1 != !val2)', array('!val1' => $expected_count, '!val2' => $feed->item_count))); + + if ($expected_count !== NULL) { + $feed->item_count = count($feed->items); + $this->assertEqual($expected_count, $feed->item_count, format_string('Total items in feed equal to the total items in database (!val1 != !val2)', array('!val1' => $expected_count, '!val2' => $feed->item_count))); + } } /** @@ -361,4 +364,18 @@ function createSampleNodes($count = 5) { $this->drupalPost('node/add/article', $edit, t('Save')); } } + + /** + * Enable the plugins coming with aggregator_test module. + */ + function enableTestPlugins() { + config('aggregator.settings') + ->set('fetcher', 'aggregator_test_fetcher') + ->set('parser', 'aggregator_test_parser') + ->set('processors', array( + 'aggregator_test_processor' => 'aggregator_test_processor', + 'aggregator' => 'aggregator' + )) + ->save(); + } } diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Tests/FeedFetcherPluginTest.php b/core/modules/aggregator/lib/Drupal/aggregator/Tests/FeedFetcherPluginTest.php new file mode 100644 index 0000000..6f87aef --- /dev/null +++ b/core/modules/aggregator/lib/Drupal/aggregator/Tests/FeedFetcherPluginTest.php @@ -0,0 +1,54 @@ + 'Feed fetcher plugins', + 'description' => 'Test the fetcher plugins functionality and discoverability.', + 'group' => 'Aggregator', + ); + } + + /** + * Overrides \Drupal\simpletest\WebTestBase::setUp(). + */ + public function setUp() { + parent::setUp(); + // Enable test plugins. + $this->enableTestPlugins(); + // Create some nodes. + $this->createSampleNodes(); + } + + /** + * Test fetching functionality. + */ + public function testfetch() { + // Create feed with local url. + $feed = $this->createFeed(); + $this->updateFeedItems($feed); + $this->assertFalse(empty($feed->items)); + + // Remove items and restore checked property to 0. + $this->removeFeedItems($feed); + // Change its name and try again. + $feed->title->value = 'Test feed'; + $feed->save(); + $this->updateFeedItems($feed); + // Fetch should fail due to feed name. + $this->assertTrue(empty($feed->items)); + } +} diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Tests/FeedProcessorPluginTest.php b/core/modules/aggregator/lib/Drupal/aggregator/Tests/FeedProcessorPluginTest.php new file mode 100644 index 0000000..8b157d5 --- /dev/null +++ b/core/modules/aggregator/lib/Drupal/aggregator/Tests/FeedProcessorPluginTest.php @@ -0,0 +1,69 @@ + 'Feed processor plugins', + 'description' => 'Test the processor plugins functionality and discoverability.', + 'group' => 'Aggregator', + ); + } + + /** + * Overrides \Drupal\simpletest\WebTestBase::setUp(). + */ + public function setUp() { + parent::setUp(); + // Enable test plugins. + $this->enableTestPlugins(); + // Create some nodes. + $this->createSampleNodes(); + } + + /** + * Test processing functionality. + */ + public function testProcess() { + $feed = $this->createFeed(); + $this->updateFeedItems($feed); + foreach ($feed->items as $iid) { + $item = entity_load('aggregator_item', $iid); + $this->assertTrue(strpos($item->title->value, 'testProcessor') === 0); + } + } + + /** + * Test removing functionality. + */ + public function testRemove() { + $feed = $this->createFeed(); + $this->updateAndRemove($feed, NULL); + // Make sure the feed title is changed. + $entities = entity_load_multiple_by_properties('aggregator_feed', array('title' => $feed->label())); + $this->assertTrue(empty($entities)); + } + + /** + * Test post-processing functionality. + */ + public function testPostProcess() { + $feed = $this->createFeed(); + $this->updateFeedItems($feed); + // Reload the feed to get new values. + $feed = entity_load('aggregator_feed', $feed->id(), TRUE); + $this->assertEqual($feed->refresh->value, AGGREGATOR_CLEAR_NEVER); + } +} diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Tests/UpdateFeedItemTest.php b/core/modules/aggregator/lib/Drupal/aggregator/Tests/UpdateFeedItemTest.php index 54eaec5..2cc1c8c 100644 --- a/core/modules/aggregator/lib/Drupal/aggregator/Tests/UpdateFeedItemTest.php +++ b/core/modules/aggregator/lib/Drupal/aggregator/Tests/UpdateFeedItemTest.php @@ -68,5 +68,12 @@ function testUpdateFeedItem() { $after = db_query('SELECT timestamp FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->id()))->fetchField(); $this->assertTrue($before === $after, format_string('Publish timestamp of feed item was not updated (!before === !after)', array('!before' => $before, '!after' => $after))); + + // Make sure updating items works even after disabling a module + // that provides the selected plugins. + $this->enableTestPlugins(); + module_disable(array('aggregator_test')); + $this->updateFeedItems($feed); + $this->assertResponse(200); } } diff --git a/core/modules/aggregator/tests/lib/Drupal/aggregator_test/Plugin/aggregator/fetcher/TestFetcher.php b/core/modules/aggregator/tests/lib/Drupal/aggregator_test/Plugin/aggregator/fetcher/TestFetcher.php index fa99d47..5688434 100644 --- a/core/modules/aggregator/tests/lib/Drupal/aggregator_test/Plugin/aggregator/fetcher/TestFetcher.php +++ b/core/modules/aggregator/tests/lib/Drupal/aggregator_test/Plugin/aggregator/fetcher/TestFetcher.php @@ -8,6 +8,7 @@ namespace Drupal\aggregator_test\Plugin\aggregator\fetcher; use Drupal\aggregator\Plugin\FetcherInterface; +use Drupal\aggregator\Plugin\aggregator\fetcher\DefaultFetcher; use Drupal\aggregator\Plugin\Core\Entity\Feed; use Drupal\Core\Annotation\Plugin; use Drupal\Core\Annotation\Translation; @@ -24,12 +25,15 @@ * description = @Translation("Dummy fetcher for testing purposes.") * ) */ -class TestFetcher implements FetcherInterface { +class TestFetcher extends DefaultFetcher implements FetcherInterface { /** * Implements \Drupal\aggregator\Plugin\FetcherInterface::fetch(). - * - * @todo Actually test this. */ - public function fetch(Feed $feed) {} + public function fetch(Feed $feed) { + if ($feed->label() == 'Test feed') { + return FALSE; + } + return parent::fetch($feed); + } } diff --git a/core/modules/aggregator/tests/lib/Drupal/aggregator_test/Plugin/aggregator/parser/TestParser.php b/core/modules/aggregator/tests/lib/Drupal/aggregator_test/Plugin/aggregator/parser/TestParser.php index a01076f..011ebc4 100644 --- a/core/modules/aggregator/tests/lib/Drupal/aggregator_test/Plugin/aggregator/parser/TestParser.php +++ b/core/modules/aggregator/tests/lib/Drupal/aggregator_test/Plugin/aggregator/parser/TestParser.php @@ -9,6 +9,7 @@ use Drupal\aggregator\Plugin\ParserInterface; use Drupal\aggregator\Plugin\Core\Entity\Feed; +use Drupal\aggregator\Plugin\aggregator\parser\DefaultParser; use Drupal\Core\Annotation\Plugin; use Drupal\Core\Annotation\Translation; @@ -23,12 +24,14 @@ * description = @Translation("Dummy parser for testing purposes.") * ) */ -class TestParser implements ParserInterface { +class TestParser extends DefaultParser implements ParserInterface { /** * Implements \Drupal\aggregator\Plugin\ParserInterface::parse(). * * @todo Actually test this. */ - public function parse(Feed $feed) {} + public function parse(Feed $feed) { + return parent::parse($feed); + } } diff --git a/core/modules/aggregator/tests/lib/Drupal/aggregator_test/Plugin/aggregator/processor/TestProcessor.php b/core/modules/aggregator/tests/lib/Drupal/aggregator_test/Plugin/aggregator/processor/TestProcessor.php index 02c66ff..a07809b 100644 --- a/core/modules/aggregator/tests/lib/Drupal/aggregator_test/Plugin/aggregator/processor/TestProcessor.php +++ b/core/modules/aggregator/tests/lib/Drupal/aggregator_test/Plugin/aggregator/processor/TestProcessor.php @@ -62,22 +62,31 @@ public function settingsSubmit(array $form, array &$form_state) { /** * Implements \Drupal\aggregator\Plugin\ProcessorInterface::process(). - * - * @todo Actually test this. */ - public function process(Feed $feed) {} + public function process(Feed $feed) { + foreach ($feed->items as &$item) { + // Do not truncate on 255 but 240, so we prepend our test string. + $item['title'] = truncate_utf8($item['title'], 240, TRUE, TRUE); + $item['title'] = 'testProcessor' . $item['title']; + } + } /** * Implements \Drupal\aggregator\Plugin\ProcessorInterface::remove(). - * - * @todo Actually test this. */ - public function remove(Feed $feed) {} + public function remove(Feed $feed) { + parent::remove($feed); + // Remove feed title. + $feed->title->value = ''; + $feed->save(); + } /** * Implements \Drupal\aggregator\Plugin\ProcessorInterface::postProcess(). - * - * @todo Actually test this. */ - public function postProcess(Feed $feed) {} + public function postProcess(Feed $feed) { + // Dont let this feed be updated again. + $feed->refresh->value = AGGREGATOR_CLEAR_NEVER; + $feed->save(); + } }