Skip to content
Snippets Groups Projects
Commit 9f755bc1 authored by Alex Barth's avatar Alex Barth
Browse files

#728534 alex_b: Remove FeedsFeedNodeProcessor.

parent 8483ae18
No related branches found
No related tags found
No related merge requests found
......@@ -3,6 +3,10 @@
Feeds 7.x 2.0 XXXXXXXXXXXXXXXXXXX
---------------------------------
- #728534 alex_b: Remove FeedsFeedNodeProcessor. If you have used
FeedsFeedNodeProcessor in the past, use FeedsNodeProcessor (Node Processor)
instead now. It supports all of FeedsFeedNodeProcessor's functionality and
more.
- #929066 alex_b: Track all imported items. Note: All views that use 'Feeds
Item' fields or relationships need updating.
- #930018 alex_b: Don't show file upload when 'Supply path directly' is
......
......@@ -141,17 +141,6 @@ function _feeds_feeds_plugins() {
'path' => $path,
),
);
$info['FeedsFeedNodeProcessor'] = array(
'name' => 'Feed Node processor',
'description' => 'Create <em>Feed nodes</em>.',
'help' => 'Create <em>Feed nodes</em> from parsed content. Feed nodes are nodes that can import feeds themselves. This can be useful for instance when importing OPML feeds.',
'handler' => array(
'parent' => 'FeedsProcessor',
'class' => 'FeedsFeedNodeProcessor',
'file' => 'FeedsFeedNodeProcessor.inc',
'path' => $path,
),
);
$info['FeedsUserProcessor'] = array(
'name' => 'User processor',
'description' => 'Create users.',
......
......@@ -87,10 +87,11 @@ function feeds_news_feeds_importer_default() {
'config' => array(),
),
'processor' => array(
'plugin_key' => 'FeedsFeedNodeProcessor',
'plugin_key' => 'FeedsNodeProcessor',
'config' => array(
'content_type' => 'feed',
'update_existing' => 0,
'expire' => '-1',
'mappings' => array(
0 => array(
'source' => 'title',
......@@ -99,7 +100,7 @@ function feeds_news_feeds_importer_default() {
),
1 => array(
'source' => 'xmlurl',
'target' => 'source',
'target' => 'feeds_source',
'unique' => 1,
),
),
......
<?php
// $Id$
/**
* @file
* Class definition of FeedsFeedNodeProcessor.
*/
/**
* Creates *feed* nodes from feed items. The difference to FeedsNodeProcessor is
* that this plugin only creates nodes that are feed nodes themselves.
*/
class FeedsFeedNodeProcessor extends FeedsProcessor {
/**
* Implements FeedsProcessor::process().
*/
public function process(FeedsSource $source, FeedsParserResult $parser_result) {
$state = $source->state(FEEDS_PROCESS);
while ($item = $parser_result->shiftItem()) {
// If the target item does not exist OR if update_existing is enabled,
// map and save.
if (!$nid = $this->existingItemId($source, $parser_result) || $this->config['update_existing']) {
// Map item to a node.
$node = $this->map($source, $parser_result);
// If updating populate nid and vid avoiding an expensive node_load().
if (!empty($nid)) {
$node->nid = $nid;
$node->vid = db_query("SELECT vid FROM {node} WHERE nid = :nid", array(':nid' => $nid))->fetchField();
}
// Save the node.
node_save($node);
if ($nid) {
$state->updated++;
}
else {
$state->created++;
}
}
}
if ($source->progressImporting() != FEEDS_BATCH_COMPLETE) {
return;
}
// Set messages.
if ($state->created) {
drupal_set_message(format_plural($state->created, 'Created @number @type node.', 'Created @number @type nodes.', array('@number' => $state->created, '@type' => $this->config['content_type'])));
}
elseif ($state->updated) {
drupal_set_message(format_plural($state->updated, 'Updated @number @type node.', 'Updated @number @type nodes.', array('@number' => $state->updated, '@type' => $this->config['content_type'])));
}
else {
drupal_set_message(t('There is no new content.'));
}
}
/**
* Implements FeedsProcessor::clear().
*/
public function clear(FeedsSource $source) {
// Do not support deleting imported items as we would have to delete all
// items of the content type we imported which may contain nodes that a
// user created by hand.
throw new Exception(t('This configuration does not support deleting imported items.'));
}
/**
* Execute mapping on an item.
*/
protected function map(FeedsSource $source, FeedsParserResult $result) {
// Prepare node object.
static $included;
if (!$included) {
module_load_include('inc', 'node', 'node.pages');
$included = TRUE;
}
$target_node = new stdClass();
$target_node->type = $this->config['content_type'];
$target_node->feeds = array();
// Suppress auto import, we may be creating many feeds
$target_node->feeds['suppress_import'] = TRUE;
node_object_prepare($target_node);
/*
Assign an aggregated node always to current user.
@todo This won't work in all cases as the assumption here is that
import is happening one off when user is logged in. Assumption breaks if
feed node processor is being used for aggregation on cron time and a
specific user should still be the owner of the imported feed nodes.
*/
global $user;
$target_node->uid = $user->uid;
// Have parent class do the iterating.
return parent::map($source, $result, $target_node);
}
/**
* Override parent::configDefaults().
*/
public function configDefaults() {
return array(
'content_type' => '',
'update_existing' => 0,
'mappings' => array(),
);
}
/**
* Override parent::configForm().
*/
public function configForm(&$form_state) {
$feeds = feeds_importer_load_all();
$types = array();
foreach ($feeds as $feed) {
if ($feed->id != $this->id && !empty($feed->config['content_type'])) {
$types[$feed->config['content_type']] = check_plain(node_type_get_name($feed->config['content_type']));
}
}
if (empty($types)) {
$types[''] = t('No feed node content type available');
}
else {
$types = array(
'' => t('Select'),
) + $types;
}
$form = array();
$form['content_type'] = array(
'#type' => 'select',
'#title' => t('Content type'),
'#description' => t('Choose node type to create from this feed. Only node types with attached importer configurations are listed here. <strong>Note:</strong> Users with "import !feed_id feeds" permissions will be able to <strong>import</strong> 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)),
'#options' => $types,
'#default_value' => $this->config['content_type'],
);
// @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'],
);
return $form;
}
/**
* Override setTargetElement to operate on a target item that is a node.
*/
public function setTargetElement($target_node, $target_element, $value) {
if ($target_element == 'source') {
// Get the class of the feed node importer's fetcher and set the source
// property. See feeds_node_update() how $node->feeds gets stored.
$class = get_class($this->feedNodeImporter()->fetcher);
$target_node->feeds[$class]['source'] = $value;
}
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;
}
}
/**
* Return available mapping targets.
*/
public function getMappingTargets() {
$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(FeedsSource $source, FeedsParserResult $result) {
// We only support one unique target: source
foreach ($this->uniqueTargets($source, $result) as $target => $value) {
if ($target == 'source') {
return db_query("SELECT fs.feed_nid FROM {node} n JOIN {feeds_source} fs ON n.nid = fs.feed_nid WHERE fs.id = :id AND fs.source = :source", array(':id' => $this->feedNodeImporter()->id, ':source' => $value))->fetchField();
}
}
return 0;
}
/**
* Helper for retrieving the importer object for the feed nodes to produce.
*/
protected function feedNodeImporter() {
if ($id = feeds_get_importer_id($this->config['content_type'])) {
return feeds_importer($id);
}
else {
throw new Exception(t('Content type to be created is not a valid Feed content type.'));
}
}
}
......@@ -261,6 +261,17 @@ class FeedsNodeProcessor extends FeedsProcessor {
$target_node->created = $value->getValue();
}
break;
case 'feeds_source':
// Get the class of the feed node importer's fetcher and set the source
// property. See feeds_node_update() how $node->feeds gets stored.
if ($id = feeds_get_importer_id($this->config['content_type'])) {
$class = get_class(feeds_importer($id)->fetcher);
$target_node->feeds[$class]['source'] = $value;
// This effectively suppresses 'import on submission' feature.
// See feeds_node_insert().
$target_node->feeds['suppress_import'] = TRUE;
}
break;
default:
parent::setTargetElement($target_node, $target_element, $value);
break;
......@@ -298,6 +309,15 @@ class FeedsNodeProcessor extends FeedsProcessor {
'description' => t('The UNIX time when a node has been published.'),
),
);
// If the target content type is a Feed node, expose its source field.
if ($id = feeds_get_importer_id($this->config['content_type'])) {
$name = feeds_importer($id)->config['name'];
$targets['feeds_source'] = array(
'name' => t('Feed source'),
'description' => t('The content type created by this processor is a Feed Node, it represents a source itself. Depending on the fetcher selected on the importer "@importer", this field is expected to be for example a URL or a path to a file.', array('@importer' => $name)),
'optional_unique' => TRUE,
);
}
// Let other modules expose mapping targets.
self::loadMappers();
......@@ -321,6 +341,11 @@ class FeedsNodeProcessor extends FeedsProcessor {
case 'nid':
$nid = db_query("SELECT nid FROM {node} WHERE nid = :nid", array(':nid' => $value))->fetchField();
break;
case 'feeds_source':
if ($id = feeds_get_importer_id($this->importer->config['content_type'])) {
$nid = db_query("SELECT fs.feed_nid FROM {node} n JOIN {feeds_source} fs ON n.nid = fs.feed_nid WHERE fs.id = :id AND fs.source = :source", array(':id' => $id, ':source' => $value))->fetchField();
}
break;
}
if ($nid) {
// Return with the first nid found.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment