Index: feeds.plugins.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/feeds/feeds.plugins.inc,v
retrieving revision 1.6
diff -r1.6 feeds.plugins.inc
149c149
< 'parent' => 'FeedsProcessor',
---
> 'parent' => 'FeedsNodeProcessor',
Index: plugins/FeedsFeedNodeProcessor.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/feeds/plugins/FeedsFeedNodeProcessor.inc,v
retrieving revision 1.14
diff -r1.14 FeedsFeedNodeProcessor.inc
13,56c13
< class FeedsFeedNodeProcessor extends FeedsProcessor {
<
< /**
< * Implementation of FeedsProcessor::process().
< */
< public function process(FeedsImportBatch $batch, FeedsSource $source) {
< while ($item = $batch->shiftItem()) {
<
< // If the target item does not exist OR if update_existing is enabled,
< // map and save.
< if (!$nid = $this->existingItemId($item, $source) || $this->config['update_existing']) {
<
< // Map item to a node.
< $node = $this->map($item);
<
< // If updating populate nid and vid avoiding an expensive node_load().
< if (!empty($nid)) {
< $node->nid = $nid;
< $node->vid = db_result(db_query("SELECT vid FROM {node} WHERE nid = %d", $nid));
< }
<
< // Save the node.
< node_save($node);
<
< if ($nid) {
< $batch->updated++;
< }
< else {
< $batch->created++;
< }
< }
< }
<
< // Set messages.
< if ($batch->created) {
< drupal_set_message(format_plural($batch->created, 'Created @number @type node.', 'Created @number @type nodes.', array('@number' => $batch->created, '@type' => $this->config['content_type'])));
< }
< elseif ($batch->updated) {
< drupal_set_message(format_plural($batch->updated, 'Updated @number @type node.', 'Updated @number @type nodes.', array('@number' => $batch->updated, '@type' => $this->config['content_type'])));
< }
< else {
< drupal_set_message(t('There is no new content.'));
< }
< }
---
> class FeedsFeedNodeProcessor extends FeedsNodeProcessor {
71,72c28
< protected function map($source_item) {
<
---
> protected function map($source_item, $target_node) {
79,80d34
< $target_node = new stdClass();
< $target_node->type = $this->config['content_type'];
84d37
< node_object_prepare($target_node);
104,108c57,59
< return array(
< 'content_type' => '',
< 'update_existing' => 0,
< 'mappings' => array(),
< );
---
> $defaults = parent::configDefaults();
> $defaults['content_type'] = ''; // reset content type
> return $defaults;
114a66,67
> $form = parent::configForm($form_state);
>
134c87
< '#description' => t('Choose node type to create from this feed. Only node types with attached importer configurations are listed here. Note: Users with "import !feed_id feeds" permissions will be able to import nodes of the content type selected here regardless of the node level permissions. However, users with "clear !feed_id permissions" need to have sufficient node level permissions to delete the imported nodes.', array('!feed_id' => $this->id)),
---
> '#description' => t('Choose default node type to create from this feed. Only node types with attached importer configurations are listed here. Note: Users with "import !feed_id feeds" permissions will be able to import nodes of the content type selected here regardless of the node level permissions. However, users with "clear !feed_id permissions" need to have sufficient node level permissions to delete the imported nodes.', array('!feed_id' => $this->id)),
138,144d90
< // @todo Implement real updating.
< $form['update_existing'] = array(
< '#type' => 'checkbox',
< '#title' => t('Replace existing feed nodes'),
< '#description' => t('If an existing node is found for an imported node, replace it. Existing nodes will be determined using mappings that are a "unique target".'),
< '#default_value' => $this->config['update_existing'],
< );
152c98,99
< if ($target_element == 'source') {
---
> parent::setTargetElement($target_node, $target_element, $value);
> if ($target_element == 'url') {
158,163c105,113
< elseif ($target_element == 'body') {
< $target_node->teaser = $value;
< $target_node->body = $value;
< }
< elseif (in_array($target_element, array('title', 'status', 'created'))) {
< $target_node->$target_element = $value;
---
> elseif ($target_element == 'type') {
> if (feeds_get_importer_id($value)) {
> // only accept node types with attached import configuration
> $target_node->type = $value;
> }
> else {
> // set default value
> $target_node->type = $this->config['content_type'];
> }
171,206c121,127
< $targets = array(
< 'title' => array(
< 'name' => t('Title'),
< 'description' => t('The title of the feed node.'),
< ),
< 'status' => array(
< 'name' => t('Published status'),
< 'description' => t('Whether a feed node is published or not. 1 stands for published, 0 for not published.'),
< ),
< 'created' => array(
< 'name' => t('Published date'),
< 'description' => t('The UNIX time when a node has been published.'),
< ),
< 'body' => array(
< 'name' => t('Body'),
< 'description' => t('The body of the node. The teaser will be the same as the entire body.'),
< ),
< 'source' => array(
< 'name' => t('Feed source'),
< 'description' => t('Depending on the selected fetcher, this could be for example a URL or a path to a file.'),
< 'optional_unique' => TRUE,
< ),
< );
< return $targets;
< }
<
< /**
< * Get nid of an existing feed item node if available.
< */
< protected function existingItemId($source_item, FeedsSource $source) {
<
< // We only support one unique target: source
< foreach ($this->uniqueTargets($source_item) as $target => $value) {
< if ($target == 'source') {
< return db_result(db_query("SELECT fs.feed_nid FROM {node} n JOIN {feeds_source} fs ON n.nid = fs.feed_nid WHERE fs.id = '%s' AND fs.source = '%s'", $this->feedNodeImporter()->id, $value));
< }
---
> if (empty($this->config['content_type'])) {
> // issue warning
> drupal_set_message(t('No default content type selected'), 'warning');
> return array();
> }
> else {
> return parent::getMappingTargets();
208d128
< return 0;
Index: tests/feeds.test
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/feeds/tests/feeds.test,v
retrieving revision 1.23
diff -r1.23 feeds.test
1033a1034,1212
>
> /**
> * Test importing OPML that creates feed nodes.
> */
> class FeedsOPMLToFeedNodesTest extends FeedsWebTestCase {
>
> /**
> * Describe this test.
> */
> public function getInfo() {
> return array(
> 'name' => t('OPML import to feed nodes.'),
> 'description' => t('Tests a feed configuration with file import, uses OPML parser and a feed node processor.'),
> 'group' => t('Feeds'),
> );
> }
>
> /**
> * Set up test.
> */
> public function setUp() {
> parent::setUp('feeds', 'feeds_ui', 'ctools');
> $this->drupalLogin(
> $this->drupalCreateUser(
> array(
> 'administer feeds', 'administer nodes',
> )
> )
> );
> }
>
> /**
> * Generate an OPML test feed that points to RSS feeds.
> */
> public function generateOPML() {
> $path = $GLOBALS['base_url'] .'/'. drupal_get_path('module', 'feeds') .'/tests/feeds/';
>
> $output =
> '
>
>
> OPML
> Fri, 16 Oct 2009 02:53:17 GMT
> Nuvole
>
>
>
>
>
>
>
> ';
>
> // UTF 8 encode output string and write it to disk
> $output = utf8_encode($output);
> $file = $this->absolute() .'/'. file_directory_path() .'/test-opml-'. $this->randomName() .'.opml';
> $handle = fopen($file, 'w');
> fwrite($handle, $output);
> fclose($handle);
> return $file;
> }
>
> /**
> * Test feedfeed node and feed node creation.
> */
> public function test() {
> $this->createFeed('feed');
> $this->createFeedFeed('feedfeed', 'feed');
>
> // Import OPML and assert.
> $file = $this->generateOPML();
> $this->importFile('feedfeed', $file);
> $count = db_result(db_query('SELECT COUNT(*) FROM {feeds_source}'));
> // Check that we have 3 feeds added (the feedfeed + two created feeds)
> $this->assertEqual($count, 3, 'Found '. $count .' number of items.');
>
> // Assert DB status for feed nodes
> $count = db_result(db_query('SELECT COUNT(*) FROM {feeds_node_item} WHERE id="%s"', 'feedfeed'));
> $this->assertEqual($count, 2, 'Found '. $count .' number of items.');
>
> // run cron so that feeds import nodes
> $this->drupalGet('cron.php');
>
> // Assert DB status for feed nodes.
> $count = db_result(db_query('SELECT COUNT(*) FROM {feeds_node_item} WHERE id="%s"', 'feed'));
> $this->assertEqual($count, 35, 'Accurate number of items in database: '. $count);
> }
>
> public function createFeedFeed($id, $feed_id) {
> // Create our master feed that will import a listing of feeds.
> $this->createFeedConfiguration('Import OPML files generating feed node types.', $id);
>
> // Set and configure plugins.
> $this->setPlugin($id, 'FeedsFileFetcher');
> $this->setPlugin($id, 'FeedsOPMLParser');
> $this->setPlugin($id, 'FeedsFeedNodeProcessor');
>
> // Change feed node type to recently created 'feed'.
> $edit = array(
> 'content_type' => $feed_id,
> );
> $this->drupalPost('admin/build/feeds/edit/' . $id .'/settings/FeedsFeedNodeProcessor', $edit, 'Save');
>
> // Change some of the basic configuration.
> $edit = array(
> 'content_type' => '', // don't attach
> 'import_period' => FEEDS_SCHEDULE_NEVER,
> );
> $this->drupalPost('admin/build/feeds/edit/'. $id .'/settings', $edit, 'Save');
>
> // Add mappings
> $this->addMappings($id,
> array(
> array(
> 'source' => 'title',
> 'target' => 'title',
> 'unique' => FALSE,
> ),
> array(
> 'source' => 'xmlurl',
> 'target' => 'url',
> 'unique' => TRUE,
> )
> )
> );
> }
>
> public function createFeed($id) {
> // Create content type
> $this->drupalCreateContentType(array('type' => $id));
>
> // Create feed.
> $this->createFeedConfiguration('Feed', $id);
>
> // Set and configure plugins.
> $this->setPlugin($id, 'FeedsHTTPFetcher');
> $this->setPlugin($id, 'FeedsSyndicationParser');
> $this->setPlugin($id, 'FeedsNodeProcessor');
>
> // Change some of the basic configuration.
> $edit = array(
> 'content_type' => $id,
> 'import_period' => 0, // we need to schedule import as often as possible, as import on create is disabled here
> 'import_on_create' => 1,
> );
> $this->drupalPost('admin/build/feeds/edit/' . $id .'/settings', $edit, 'Save');
>
> // Add mappings
> $this->addMappings($id,
> array(
> array(
> 'source' => 'title',
> 'target' => 'title',
> 'unique' => FALSE,
> ),
> array(
> 'source' => 'description',
> 'target' => 'body',
> 'unique' => FALSE,
> ),
> array(
> 'source' => 'timestamp',
> 'target' => 'created',
> 'unique' => FALSE,
> ),
> array(
> 'source' => 'url',
> 'target' => 'url',
> 'unique' => TRUE,
> ),
> array(
> 'source' => 'guid',
> 'target' => 'guid',
> 'unique' => TRUE,
> ),
> )
> );
> }
> }