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

Move ->import() and ->clear() into from FeedsImporter to FeedsSource.

This is a preemptory step to enable cleaner result handling and prepare the ground for Batch API use.
parent 369915cf
No related branches found
No related tags found
No related merge requests found
...@@ -170,13 +170,11 @@ function feeds_access($action, $param) { ...@@ -170,13 +170,11 @@ function feeds_access($action, $param) {
$importer_id = $param; $importer_id = $param;
} }
elseif ($param->type) { elseif ($param->type) {
if ($importer = feeds_importer_by_content_type($param->type)) { $importer_id = feeds_get_importer_id($param->type);
$importer_id = $importer->id;
}
} }
// Check for permissions if feed id is present, otherwise return FALSE. // Check for permissions if feed id is present, otherwise return FALSE.
if (isset($importer_id)) { if ($importer_id) {
if (user_access('administer feeds') || user_access($action .' '. $importer_id .' feeds')) { if (user_access('administer feeds') || user_access($action .' '. $importer_id .' feeds')) {
return TRUE; return TRUE;
} }
...@@ -243,20 +241,21 @@ function feeds_nodeapi(&$node, $op, $form) { ...@@ -243,20 +241,21 @@ function feeds_nodeapi(&$node, $op, $form) {
// Break out node processor related nodeapi functionality. // Break out node processor related nodeapi functionality.
_feeds_nodeapi_node_processor($node, $op); _feeds_nodeapi_node_processor($node, $op);
if ($importer = feeds_importer_by_content_type($node->type)) { if ($importer_id = feeds_get_importer_id($node->type)) {
switch ($op) { switch ($op) {
case 'validate': case 'validate':
// On validation stage we are working with a FeedsSource object that is // On validation stage we are working with a FeedsSource object that is
// not tied to a nid - when creating a new node there is $node->nid at // not tied to a nid - when creating a new node there is $node->nid at
// this stage. // this stage.
$source = feeds_source($importer); $source = feeds_source($importer_id);
// If node title is empty, try to retrieve title from feed. // If node title is empty, try to retrieve title from feed.
if (trim($node->title) == '') { if (trim($node->title) == '') {
try { try {
$source->addConfig($node->feeds); $source->addConfig($node->feeds);
$result = $importer->fetcher->fetch($source); // @todo: Too many indirections. Clean up.
$result = $importer->parser->parse($result, $source); $result = $source->importer->fetcher->fetch($source);
$result = $source->importer->parser->parse($result, $source);
if (!isset($result->value['title']) || trim($result->value['title']) == '') { if (!isset($result->value['title']) || trim($result->value['title']) == '') {
form_set_error('title', t('Could not retrieve title from feed.'), 'error'); form_set_error('title', t('Could not retrieve title from feed.'), 'error');
} }
...@@ -285,25 +284,25 @@ function feeds_nodeapi(&$node, $op, $form) { ...@@ -285,25 +284,25 @@ function feeds_nodeapi(&$node, $op, $form) {
case 'insert': case 'insert':
case 'update': case 'update':
// Add configuration to feed source and save. // Add configuration to feed source and save.
$source = feeds_source($importer, $node->nid); $source = feeds_source($importer_id, $node->nid);
$source->addConfig($node->feeds); $source->addConfig($node->feeds);
$source->save(); $source->save();
// Refresh feed if import on create is selected and suppress_import is // Refresh feed if import on create is selected and suppress_import is
// not set. // not set.
if ($op == 'insert' && $importer->config['import_on_create'] && !isset($node->feeds['suppress_import'])) { if ($op == 'insert' && feeds_importer($importer_id)->config['import_on_create'] && !isset($node->feeds['suppress_import'])) {
$importer->import($source); $source->import();
} }
// Add import to scheduler. // Add import to scheduler.
feeds_scheduler()->add($importer->id, 'import', $node->nid); feeds_scheduler()->add($importer_id, 'import', $node->nid);
// Add expiry to schedule, in case this is the first feed of this // Add expiry to schedule, in case this is the first feed of this
// configuration. // configuration.
feeds_scheduler()->add($importer->id, 'expire'); feeds_scheduler()->add($importer_id, 'expire');
break; break;
case 'delete': case 'delete':
// Remove feed from scheduler and delete source. // Remove feed from scheduler and delete source.
feeds_scheduler()->remove($importer->id, 'import', $node->nid); feeds_scheduler()->remove($importer_id, 'import', $node->nid);
feeds_source($importer, $node->nid)->delete(); feeds_source($importer_id, $node->nid)->delete();
break; break;
} }
} }
...@@ -344,21 +343,19 @@ function _feeds_nodeapi_node_processor($node, $op) { ...@@ -344,21 +343,19 @@ function _feeds_nodeapi_node_processor($node, $op) {
*/ */
function feeds_form_alter(&$form, $form_state, $form_id) { function feeds_form_alter(&$form, $form_state, $form_id) {
if ($form['#id'] == 'node-form') { if ($form['#id'] == 'node-form') {
if ($importer = feeds_importer_by_content_type($form['type']['#value'])) { if ($importer_id = feeds_get_importer_id($form['type']['#value'])) {
// Set title to not required, try to retrieve it from feed. // Set title to not required, try to retrieve it from feed.
$form['title']['#required'] = FALSE; $form['title']['#required'] = FALSE;
// Build form. // Build form.
$source = feeds_source($importer, empty($form['nid']['#value']) ? 0 : $form['nid']['#value']); $source = feeds_source($importer_id, empty($form['nid']['#value']) ? 0 : $form['nid']['#value']);
$form['feeds'] = array( $form['feeds'] = array(
'#type' => 'fieldset', '#type' => 'fieldset',
'#title' => t('Feed'), '#title' => t('Feed'),
'#tree' => TRUE, '#tree' => TRUE,
); );
$form['feeds'] += $source->configForm($form_state); $form['feeds'] += $source->configForm($form_state);
$form['#feed_id'] = $importer_id;
// Cannot pass on the FeedsImporter object, pass on id.
$form['#feed_id'] = $importer->id;
} }
} }
} }
...@@ -447,21 +444,21 @@ function feeds_importer_enabled($id) { ...@@ -447,21 +444,21 @@ function feeds_importer_enabled($id) {
* A node type string. * A node type string.
* *
* @return * @return
* A FeedsImporter object if one is available, FALSE otherwise. * A FeedsImporter id if there is an importer for the given content type,
* FALSE otherwise.
*/ */
function feeds_importer_by_content_type($content_type) { function feeds_get_importer_id($content_type) {
static $feeds = array(); static $ids = array();
if (!isset($ids[$content_type])) {
if (!isset($feeds[$content_type])) { $ids[$content_type] = FALSE;
$feeds[$content_type] = FALSE;
foreach (feeds_importer_load_all() as $importer) { foreach (feeds_importer_load_all() as $importer) {
if ((!$importer->disabled) && $importer->config['content_type'] == $content_type) { if ((!$importer->disabled) && $importer->config['content_type'] == $content_type) {
$feeds[$content_type] = $importer; $ids[$content_type] = $importer->id;
break; break;
} }
} }
} }
return $feeds[$content_type]; return $ids[$content_type];
} }
/** /**
...@@ -503,8 +500,8 @@ function feeds_importer($id) { ...@@ -503,8 +500,8 @@ function feeds_importer($id) {
/** /**
* Get an instance of a source object. * Get an instance of a source object.
* *
* @param $importer * @param $importer_id
* A FeedsImporter object. * A FeedsImporter id.
* @param $feed_nid * @param $feed_nid
* The node id of a feed node if the source is attached to a feed node. * The node id of a feed node if the source is attached to a feed node.
* *
...@@ -512,9 +509,9 @@ function feeds_importer($id) { ...@@ -512,9 +509,9 @@ function feeds_importer($id) {
* A FeedsSource object or an object of a class defiend by the Drupal * A FeedsSource object or an object of a class defiend by the Drupal
* variable 'source_class'. * variable 'source_class'.
*/ */
function feeds_source($importer, $feed_nid = 0) { function feeds_source($importer_id, $feed_nid = 0) {
feeds_include('FeedsImporter'); feeds_include('FeedsImporter');
return FeedsSource::instance($importer, $feed_nid); return FeedsSource::instance($importer_id, $feed_nid);
} }
/** /**
......
...@@ -42,12 +42,11 @@ function feeds_page() { ...@@ -42,12 +42,11 @@ function feeds_page() {
/** /**
* Render a feeds import form on import/[config] pages. * Render a feeds import form on import/[config] pages.
*/ */
function feeds_import_form(&$form_state, $feed_id) { function feeds_import_form(&$form_state, $importer_id) {
$importer = feeds_importer($feed_id); $source = feeds_source($importer_id, empty($form['nid']['#value']) ? 0 : $form['nid']['#value']);
$source = feeds_source($importer, empty($form['nid']['#value']) ? 0 : $form['nid']['#value']);
$form = array(); $form = array();
$form['#importer_id'] = $importer->id; $form['#importer_id'] = $importer_id;
// @todo: Move this into fetcher? // @todo: Move this into fetcher?
$form['#attributes']['enctype'] = 'multipart/form-data'; $form['#attributes']['enctype'] = 'multipart/form-data';
$form['feeds'] = array( $form['feeds'] = array(
...@@ -68,42 +67,39 @@ function feeds_import_form(&$form_state, $feed_id) { ...@@ -68,42 +67,39 @@ function feeds_import_form(&$form_state, $feed_id) {
* Has to live in feeds.module, needs to be callable from node form. * Has to live in feeds.module, needs to be callable from node form.
*/ */
function feeds_import_form_validate($form, &$form_state) { function feeds_import_form_validate($form, &$form_state) {
$importer = feeds_importer($form['#importer_id']);
$source = feeds_source($importer);
// @todo: this may be a problem here, as we don't have a feed_nid at this point. // @todo: this may be a problem here, as we don't have a feed_nid at this point.
$source->configFormValidate($form_state['values']['feeds']); feeds_source($form['#importer_id'])->configFormValidate($form_state['values']['feeds']);
} }
/** /**
* Submit handler for feeds_import_form(). * Submit handler for feeds_import_form().
*/ */
function feeds_import_form_submit($form, &$form_state) { function feeds_import_form_submit($form, &$form_state) {
$importer = feeds_importer($form['#importer_id']);
$source = feeds_source($importer);
// Save source and import. // Save source and import.
$source = feeds_source($form['#importer_id']);
$source->addConfig($form_state['values']['feeds']); $source->addConfig($form_state['values']['feeds']);
$source->save(); $source->save();
// Refresh feed if import on create is selected. // Refresh feed if import on create is selected.
if ($importer->config['import_on_create']) { if ($source->importer->config['import_on_create']) {
$importer->import($source); $source->import();
} }
// Add importer to schedule. // Add importer to schedule.
feeds_scheduler()->add($importer->id, 'import'); feeds_scheduler()->add($form['#importer_id'], 'import');
feeds_scheduler()->add($importer->id, 'expire'); feeds_scheduler()->add($form['#importer_id'], 'expire');
} }
/** /**
* Render a feeds import form on node/id/import pages. * Render a feeds import form on node/id/import pages.
*/ */
function feeds_import_tab_form(&$form_state, $node) { function feeds_import_tab_form(&$form_state, $node) {
$importer = feeds_importer_by_content_type($node->type); $importer_id = feeds_get_importer_id($node->type);
$form = array(); $form = array();
$form['#feed_nid'] = $node->nid; $form['#feed_nid'] = $node->nid;
$form['#importer_id'] = $importer->id; $form['#importer_id'] = $importer_id;
return confirm_form($form, t('Import all content from feed?'), 'node/'. $node->nid, '', t('Import'), t('Cancel'), 'confirm feeds update'); return confirm_form($form, t('Import all content from feed?'), 'node/'. $node->nid, '', t('Import'), t('Cancel'), 'confirm feeds update');
} }
...@@ -111,9 +107,7 @@ function feeds_import_tab_form(&$form_state, $node) { ...@@ -111,9 +107,7 @@ function feeds_import_tab_form(&$form_state, $node) {
* Submit handler for feeds_import_tab_form(). * Submit handler for feeds_import_tab_form().
*/ */
function feeds_import_tab_form_submit($form, $form_state) { function feeds_import_tab_form_submit($form, $form_state) {
$importer = feeds_importer($form['#importer_id']); feeds_source($form['#importer_id'], $form['#feed_nid'])->import();
$source = feeds_source($importer, $form['#feed_nid']);
$importer->import($source);
} }
/** /**
...@@ -122,18 +116,17 @@ function feeds_import_tab_form_submit($form, $form_state) { ...@@ -122,18 +116,17 @@ function feeds_import_tab_form_submit($form, $form_state) {
* Used on both node pages and configuration pages. * Used on both node pages and configuration pages.
* Therefore either $feed_id or $node may be missing. * Therefore either $feed_id or $node may be missing.
*/ */
function feeds_delete_tab_form(&$form_state, $feed_id, $node = NULL) { function feeds_delete_tab_form(&$form_state, $importer_id, $node = NULL) {
if (empty($node)) { if (empty($node)) {
$importer = feeds_importer($feed_id);
$path = 'import/'. $feed_id .'/delete-items'; $path = 'import/'. $feed_id .'/delete-items';
} }
else { else {
$importer = feeds_importer_by_content_type($node->type); $importer_id = feeds_get_importer_id($node->type);
$form['#feed_nid'] = $node->nid; $form['#feed_nid'] = $node->nid;
$path = 'node/'. $node->nid; $path = 'node/'. $node->nid;
} }
// Form cannot pass on feed object. // Form cannot pass on feed object.
$form['#importer_id'] = $importer->id; $form['#importer_id'] = $importer_id;
return confirm_form($form, t('Delete all items from feed?'), $path, '', t('Delete'), t('Cancel'), 'confirm feeds update'); return confirm_form($form, t('Delete all items from feed?'), $path, '', t('Delete'), t('Cancel'), 'confirm feeds update');
} }
...@@ -141,7 +134,5 @@ function feeds_delete_tab_form(&$form_state, $feed_id, $node = NULL) { ...@@ -141,7 +134,5 @@ function feeds_delete_tab_form(&$form_state, $feed_id, $node = NULL) {
* Submit handler for feeds_delete_tab_form(). * Submit handler for feeds_delete_tab_form().
*/ */
function feeds_delete_tab_form_submit($form, &$form_state) { function feeds_delete_tab_form_submit($form, &$form_state) {
$importer = feeds_importer($form['#importer_id']); feeds_source($form['#importer_id'], empty($form['#feed_nid']) ? 0 : $form['#feed_nid'])->clear();
$source = feeds_source($importer, empty($form['#feed_nid']) ? 0 : $form['#feed_nid']);
$importer->clear($source);
} }
...@@ -123,41 +123,6 @@ class FeedsImporter extends FeedsConfigurable { ...@@ -123,41 +123,6 @@ class FeedsImporter extends FeedsConfigurable {
} }
} }
/**
* Import a feed: execute, fetching, parsing and processing stage.
*
* @throws Exception
* If a problem with fetching, parsing or processing occured.
* @todo: Iron out and document potential Exceptions.
* @todo: Support batching.
* @todo: catch exceptions outside of import(), clear() and expire().
*/
public function import(FeedsSource $source) {
try {
$result = $this->fetcher->fetch($source);
$result = $this->parser->parse($result, $source);
$this->processor->process($result, $source);
}
catch (Exception $e) {
drupal_set_message($e->getMessage(), 'error');
}
module_invoke_all('feeds_after_import', $this, $source);
}
/**
* Remove all items from a feed.
*/
public function clear(FeedsSource $source) {
try {
$this->fetcher->clear($source);
$this->parser->clear($source);
$this->processor->clear($source);
}
catch (Exception $e) {
drupal_set_message($e->getMessage(), 'error');
}
}
/** /**
* Remove items older than $time. If $time is not given, processor settings * Remove items older than $time. If $time is not given, processor settings
* will be used. * will be used.
......
...@@ -216,13 +216,13 @@ class FeedsScheduler implements FeedsSchedulerInterface { ...@@ -216,13 +216,13 @@ class FeedsScheduler implements FeedsSchedulerInterface {
} }
elseif ($feed_info['callback'] == 'import') { elseif ($feed_info['callback'] == 'import') {
// Import feed if source is available. // Import feed if source is available.
$source = feeds_source($importer, $feed_info['feed_nid']); $source = feeds_source($importer->id, $feed_info['feed_nid']);
if ($source->export_type & FEEDS_EXPORT_NONE) { if ($source->export_type & FEEDS_EXPORT_NONE) {
watchdog('FeedsScheduler', 'Expected source information in database for '. $importer->id .'/'. $feed_info['feed_nid'] .'. Could not find any.', array(), WATCHDOG_ERROR); watchdog('FeedsScheduler', 'Expected source information in database for '. $importer->id .'/'. $feed_info['feed_nid'] .'. Could not find any.', array(), WATCHDOG_ERROR);
return; return;
} }
try { try {
$importer->import($source); $source->import();
} }
catch (Exception $e) { catch (Exception $e) {
watchdog('FeedsScheduler', $e->getMessage(), array(), WATCHDOG_ERROR); watchdog('FeedsScheduler', $e->getMessage(), array(), WATCHDOG_ERROR);
......
...@@ -75,32 +75,60 @@ class FeedsSource extends FeedsConfigurable { ...@@ -75,32 +75,60 @@ class FeedsSource extends FeedsConfigurable {
* Instantiate a unique object per class/id/feed_nid. Don't use * Instantiate a unique object per class/id/feed_nid. Don't use
* directly, use feeds_source() instead. * directly, use feeds_source() instead.
*/ */
public static function instance($importer, $feed_nid = 0) { public static function instance($importer_id, $feed_nid = 0) {
// This is useful at least as long as we're developing.
if (empty($importer)) {
throw new Exception(t('Empty FeedsImporter.'));
}
// Let others override which class to instantiate.
$class = variable_get('feeds_source_class', 'FeedsSource'); $class = variable_get('feeds_source_class', 'FeedsSource');
static $instances = array(); static $instances = array();
if (!isset($instances[$class][$importer->id][$feed_nid])) { if (!isset($instances[$class][$importer_id][$feed_nid])) {
$instances[$class][$importer->id][$feed_nid] = new $class($importer, $feed_nid); $instances[$class][$importer_id][$feed_nid] = new $class($importer_id, $feed_nid);
} }
return $instances[$class][$importer->id][$feed_nid]; return $instances[$class][$importer_id][$feed_nid];
} }
/** /**
* Constructor. * Constructor.
*/ */
protected function __construct(FeedsImporter $importer, $feed_nid) { protected function __construct($importer_id, $feed_nid) {
$this->feed_nid = $feed_nid; $this->feed_nid = $feed_nid;
$this->importer = $importer; $this->importer = feeds_importer($importer_id);
parent::__construct($importer->id); parent::__construct($importer_id);
$this->load(); $this->load();
} }
/**
* Import a feed: execute, fetching, parsing and processing stage.
*
* @throws Exception
* If a problem with fetching, parsing or processing occured.
* @todo: Iron out and document potential Exceptions.
* @todo: Support batching.
* @todo: catch exceptions outside of import(), clear() and expire().
*/
public function import() {
try {
$result = $this->importer->fetcher->fetch($this);
$result = $this->importer->parser->parse($result, $this);
$this->importer->processor->process($result, $this);
}
catch (Exception $e) {
drupal_set_message($e->getMessage(), 'error');
}
module_invoke_all('feeds_after_import', $this->importer, $this);
}
/**
* Remove all items from a feed.
*/
public function clear() {
try {
$this->importer->fetcher->clear($this);
$this->importer->parser->clear($this);
$this->importer->processor->clear($this);
}
catch (Exception $e) {
drupal_set_message($e->getMessage(), 'error');
}
}
/** /**
* Save configuration. * Save configuration.
*/ */
......
...@@ -217,8 +217,8 @@ class FeedsFeedNodeProcessor extends FeedsProcessor { ...@@ -217,8 +217,8 @@ class FeedsFeedNodeProcessor extends FeedsProcessor {
* Helper for retrieving the importer object for the feed nodes to produce. * Helper for retrieving the importer object for the feed nodes to produce.
*/ */
protected function feedNodeImporter() { protected function feedNodeImporter() {
if ($importer = feeds_importer_by_content_type($this->config['content_type'])) { if ($id = feeds_get_importer_id($this->config['content_type'])) {
return $importer; return feeds_importer($id);
} }
else { else {
throw new Exception(t('Content type to be created is not a valid Feed content type.')); throw new Exception(t('Content type to be created is not a valid Feed content type.'));
......
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