class FeedsAtomRDFProcessor in Feeds Atom 6
Same name and namespace in other branches
- 7 plugins/FeedsAtomRDFProcessor.inc \FeedsAtomRDFProcessor
Creates nodes from feed items.
Hierarchy
- class \FeedsConfigurable
- class \FeedsPlugin implements FeedsSourceInterface
- class \FeedsProcessor
- class \FeedsNodeProcessor
- class \FeedsAtomRDFProcessor
- class \FeedsNodeProcessor
- class \FeedsProcessor
- class \FeedsPlugin implements FeedsSourceInterface
Expanded class hierarchy of FeedsAtomRDFProcessor
1 string reference to 'FeedsAtomRDFProcessor'
- feeds_atom_feeds_plugins in ./
feeds_atom.module - Implementation of hook_feeds_plugins().
File
- plugins/
FeedsAtomRDFProcessor.inc, line 11 - Contains the feeds atom RDF processor class.
View source
class FeedsAtomRDFProcessor extends FeedsNodeProcessor {
/**
* Implementation of FeedsProcessor::process().
*/
public function process(FeedsImportBatch $batch, FeedsSource $source) {
// Keep track of processed items in this pass, set total number of items.
$processed = 0;
if (!$batch
->getTotal(FEEDS_PROCESSING)) {
$batch
->setTotal(FEEDS_PROCESSING, $batch
->getItemCount());
// These two calls to setTotal() were added as a workaround to problems
// upstream in Feeds. See http://drupal.org/node/1139376
$batch
->setTotal(FEEDS_FETCHING, $batch
->getProgress(FEEDS_FETCHING));
$batch
->setTotal(FEEDS_PARSING, $batch
->getProgress(FEEDS_PARSING));
}
// These variables are set outsite of the while loop to reduce the total
// number of function calls.
$feeds_node_batch_size = variable_get('feeds_node_batch_size', FEEDS_NODE_BATCH_SIZE);
$batch_total = $batch
->getTotal(FEEDS_PROCESSING);
while ($item = $batch
->shiftItem()) {
// If the item already exists and we're flagged to delete it, do that instead.
// If the item doesn't already exists and we're flagged to delete it, do nothing.
// This part is added from the parent class.
if (!empty($item['deleted'])) {
$nid = $this
->existingItemIdGlobal($batch, $source);
if (!empty($nid)) {
node_delete($nid);
}
continue;
}
// Create/update if item does not exist or update existing is enabled.
if (!($nid = $this
->existingItemId($batch, $source)) || $this->config['update_existing'] != FEEDS_SKIP_EXISTING) {
// Only proceed if item has actually changed.
$hash = $this
->hash($item);
if (!empty($nid) && $hash == $this
->getHash($nid)) {
continue;
}
$node = $this
->buildNode($nid, $source->feed_nid);
$node->feeds_node_item->hash = $hash;
// Map and save node. If errors occur don't stop but report them.
try {
$this
->map($batch, $node, $source);
node_save($node);
if (!empty($nid)) {
$batch->updated++;
}
else {
$batch->created++;
}
} catch (Exception $e) {
drupal_set_message($e
->getMessage(), 'warning');
watchdog('feeds', $e
->getMessage(), array(), WATCHDOG_WARNING);
}
}
$processed++;
// setProgress() does not handle well the case in which the feeds_node_batch_size
// is exactly equal to the number of incoming items.
// This first if statement is a workaround for that bug with setProgress.
if ($processed == $batch_total && $processed == $feeds_node_batch_size) {
// Explicitly set the progress to FEED_BATCH_COMPLETE rather than calculating
// the value as the next 'else if' will do.
$batch
->setProgress(FEEDS_PROCESSING, FEEDS_BATCH_COMPLETE);
return;
}
else {
if ($processed >= $feeds_node_batch_size) {
$batch
->setProgress(FEEDS_PROCESSING, $batch->created + $batch->updated);
return;
}
}
}
// 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' => node_get_types('name', $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' => node_get_types('name', $this->config['content_type']),
)));
}
else {
drupal_set_message(t('There is no new content.'));
}
$batch
->setProgress(FEEDS_PROCESSING, FEEDS_BATCH_COMPLETE);
}
/**
* Add handler to find an id globally
*
* Because our deletion feeds are not necessarily the same feed as the "create new"
* feed, we need to check for existing items across all feeds, not just
* the current feed. As long as the GUID is really unique that should not
* cause a problem.
*
* @todo Refactor this once http://drupal.org/node/828176 gets resolved.
*
* @see FeedsNodeProcessor
*/
protected function existingItemIdGlobal($source_item, FeedsSource $source) {
// Iterate through all unique targets and test whether they do already
// exist in the database.
foreach ($this
->uniqueTargets($source_item) as $target => $value) {
switch ($target) {
case 'url':
$nid = db_result(db_query("SELECT nid FROM {feeds_node_item} WHERE id = '%s' AND url = '%s'", $source->id, $value));
break;
case 'guid':
$nid = db_result(db_query("SELECT nid FROM {feeds_node_item} WHERE id = '%s' AND guid = '%s'", $source->id, $value));
break;
}
if ($nid) {
// Return with the first nid found.
return $nid;
}
}
return 0;
}
/**
* Override parent::map() to load all available add-on mappers.
*
* We also add a $source parameter that contains the FeedsSource object that
* controls this feed.
*/
protected function map(FeedsImportBatch $batch, $target_item = NULL, FeedsSource $source) {
// Static cache $targets as getMappingTargets() may be an expensive method.
static $sources;
if (!isset($sources[$this->id])) {
$sources[$this->id] = feeds_importer($this->id)->parser
->getMappingSources();
}
static $targets;
if (!isset($targets[$this->id])) {
$targets[$this->id] = $this
->getMappingTargets();
}
$parser = feeds_importer($this->id)->parser;
if (empty($target_item)) {
$target_item = array();
}
// Many mappers add to existing fields rather than replacing them. Hence we
// need to clear target elements of each item before mapping in case we are
// mapping on a prepopulated item such as an existing node.
if (is_array($target_item)) {
$target_item = (object) $target_item;
$convert_to_array = TRUE;
}
foreach ($this->config['mappings'] as $mapping) {
if (isset($targets[$mapping['target']]['real_target'])) {
unset($target_item->{$targets[$mapping['target']]['real_target']});
}
elseif (isset($target_item->{$mapping['target']})) {
unset($target_item->{$mapping['target']});
}
}
if ($convert_to_array) {
$target_item = (array) $target_item;
}
// Set custom fields
// http://groups.drupal.org/node/8796
// http://www.stonemind.net/blog/index.php?s=cck
// http://civicactions.com/blog/cck_import_and_update
// http://www.lullabot.com/articles/quick-and-dirty-cck-imports
$source_item = $batch
->currentItem();
foreach ($source_item['rdf'] as $key => $value) {
if (empty($key)) {
continue;
}
$value = $source_item['rdf'][$key];
$fname = drupal_substr($key, 0, 6);
if ($fname == "field_") {
// Build up a field value.
$target_item->{$key} = $value;
}
else {
// Set properties on the node. There's a couple we know we don't want,
// because their meaning is site-specific anyway.
// @todo Replace this logic with the mapping engine for more flexibility.
if (!in_array($key, array(
'nid',
'vid',
'revision_uid',
'log',
'created',
'changed',
'revision_timestamp',
'last_comment_timestamp',
))) {
$target_item->{$key} = $value;
}
}
}
// This is where the actual mapping happens: For every mapping we envoke
// the parser's getSourceElement() method to retrieve the value of the
// source element and pass it to the processor's setTargetElement() to stick
// it on the right place of the target item.
//
// If the mapping specifies a callback method, use the callback instead of
// setTargetElement().
self::loadMappers();
foreach ($this->config['mappings'] as $mapping) {
// Retrieve source element's value from parser.
if (is_array($sources[$this->id][$mapping['source']]) && isset($sources[$this->id][$mapping['source']]['callback']) && function_exists($sources[$this->id][$mapping['source']]['callback'])) {
$callback = $sources[$this->id][$mapping['source']]['callback'];
$value = $callback($batch, $mapping['source']);
}
else {
$value = $parser
->getSourceElement($batch, $mapping['source']);
}
// Map the source element's value to the target.
if (is_array($targets[$this->id][$mapping['target']]) && isset($targets[$this->id][$mapping['target']]['callback']) && function_exists($targets[$this->id][$mapping['target']]['callback'])) {
$callback = $targets[$this->id][$mapping['target']]['callback'];
$callback($target_item, $mapping['target'], $value);
}
else {
$this
->setTargetElement($target_item, $mapping['target'], $value);
}
}
// Allow other modules to add additional mapping
// Invokes hook_feeds_atom_rdf_map_alter().
drupal_alter('feeds_atom_rdf_map', $target_item, $source_item, $source);
return $target_item;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
FeedsAtomRDFProcessor:: |
protected | function | Add handler to find an id globally | |
FeedsAtomRDFProcessor:: |
protected | function |
Override parent::map() to load all available add-on mappers. Overrides FeedsProcessor:: |
|
FeedsAtomRDFProcessor:: |
public | function |
Implementation of FeedsProcessor::process(). Overrides FeedsNodeProcessor:: |
|
FeedsConfigurable:: |
protected | property | ||
FeedsConfigurable:: |
protected | property | CTools export enabled status of this object. | |
FeedsConfigurable:: |
protected | property | ||
FeedsConfigurable:: |
protected | property | ||
FeedsConfigurable:: |
public | function | Similar to setConfig but adds to existing configuration. | 1 |
FeedsConfigurable:: |
public | function | Copy a configuration. | 1 |
FeedsConfigurable:: |
public | function | Determine whether this object is persistent and enabled. I. e. it is defined either in code or in the database and it is enabled. | 1 |
FeedsConfigurable:: |
public | function | Implementation of getConfig(). | 1 |
FeedsConfigurable:: |
public static | function | Instantiate a FeedsConfigurable object. | 1 |
FeedsConfigurable:: |
public | function | Set configuration. | 1 |
FeedsConfigurable:: |
public | function | Override magic method __get(). Make sure that $this->config goes through getConfig() | |
FeedsConfigurable:: |
public | function | Override magic method __isset(). This is needed due to overriding __get(). | |
FeedsNodeProcessor:: |
protected | function | Creates a new node object in memory and returns it. | |
FeedsNodeProcessor:: |
public | function |
Implementation of FeedsProcessor::clear(). Overrides FeedsProcessor:: |
|
FeedsNodeProcessor:: |
public | function |
Override parent::configDefaults(). Overrides FeedsProcessor:: |
|
FeedsNodeProcessor:: |
public | function |
Override parent::configForm(). Overrides FeedsConfigurable:: |
|
FeedsNodeProcessor:: |
public | function |
Reschedule if expiry time changes. Overrides FeedsConfigurable:: |
|
FeedsNodeProcessor:: |
public | function |
Override parent::configFormValidate(). Overrides FeedsConfigurable:: |
|
FeedsNodeProcessor:: |
protected | function |
Get nid of an existing feed item node if available. Overrides FeedsProcessor:: |
|
FeedsNodeProcessor:: |
public | function |
Implement expire(). Overrides FeedsProcessor:: |
|
FeedsNodeProcessor:: |
public | function |
Return expiry time. Overrides FeedsProcessor:: |
|
FeedsNodeProcessor:: |
protected | function | Retrieves the MD5 hash of $entity_id from the database. | |
FeedsNodeProcessor:: |
public | function |
Return available mapping targets. Overrides FeedsProcessor:: |
|
FeedsNodeProcessor:: |
protected | function | Create MD5 hash of item and mappings array. | |
FeedsNodeProcessor:: |
public | function |
Override setTargetElement to operate on a target item that is a node. Overrides FeedsProcessor:: |
|
FeedsPlugin:: |
public | function |
Returns TRUE if $this->sourceForm() returns a form. Overrides FeedsSourceInterface:: |
|
FeedsPlugin:: |
protected static | function | Loads on-behalf implementations from mappers/ directory. | |
FeedsPlugin:: |
public | function |
Save changes to the configuration of this object.
Delegate saving to parent (= Feed) which will collect
information from this object by way of getConfig() and store it. Overrides FeedsConfigurable:: |
|
FeedsPlugin:: |
public | function |
Implementation of FeedsSourceInterface::sourceDefaults(). Overrides FeedsSourceInterface:: |
1 |
FeedsPlugin:: |
public | function |
A source is being deleted. Overrides FeedsSourceInterface:: |
1 |
FeedsPlugin:: |
public | function |
Callback methods, exposes source form. Overrides FeedsSourceInterface:: |
3 |
FeedsPlugin:: |
public | function |
Validation handler for sourceForm. Overrides FeedsSourceInterface:: |
2 |
FeedsPlugin:: |
public | function |
A source is being saved. Overrides FeedsSourceInterface:: |
1 |
FeedsPlugin:: |
protected | function |
Constructor. Overrides FeedsConfigurable:: |
|
FeedsProcessor:: |
public | function | Get mappings. | |
FeedsProcessor:: |
protected | function | Utility function that iterates over a target array and retrieves all sources that are unique. |