Problem/Motivation

Right now, Feeds has no way of handling any errors besides displaying a message and incrementing a failed counter. It'd be nice to give modules a chance to respond to individual item errors for logging or notification purposes.

Proposed resolution

Add a hook_feeds_item_error() module_invoke within the FeedsProcessor Exception handler that gives modules a chance to log or otherwise handle these exceptions.

Remaining tasks

User interface changes

None.

API changes

Add hook_feeds_item_error():

/**
 * Invoked when a feed item throws an error during import.
 *
 * @param FeedsSource $source
 *  FeedsSource object that describes the source that is being imported.
 * @param $entity
 *   The entity object that has just been saved.
 * @param array $item
 *   The parser result for this entity.
 * @param Exception $e
 *  The exception that was thrown.
 */
function hook_feeds_item_error(FeedsSource $source, $entity, $item, Exception $exception) {
  $tmp = array_merge($item, array('error' => $exception->getMessage()));
  $filename = 'public://feeds_errors_' . $source->importer()->id . '-' . date('Y-m-d', time()) . '.csv';

  $file_is_new = !file_exists($filename);
  $file = fopen($filename, 'a');

  if ($file_is_new) {
    fputcsv($file, array_keys($tmp));
  }

  fputcsv($file, $tmp);
  fclose($file);
}

Data model changes

None.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

nvahalik created an issue. See original summary.

nvahalik’s picture

nvahalik’s picture

Issue summary: View changes
twistor’s picture

Status: Active » Needs work

This is very interesting. I've been looking for a way to separate out error handling. It would need to extend to updated, deleted, etc. I'm not sure if this is the correct approach, but it does look promising.

nvahalik’s picture

@twistor, can you be a little more specific about what you mean about it needing to "extend to updated, deleted, etc."?

MegaChriz’s picture

Related issue in which is explained what the current possibilities are for handling with failed imports: #2565069-2: Email alert on failure.

My guess is that twistor means that it would be great if you could react not only to the event of failed items, but also when $state->created, $state->updated, $state->deleted, $state->unpublished and $state->blocked are incremented.
This could be implemented by adding a method to the FeedsState class. The method would then be responsible for incrementing the particular state and invoking the hook.

Something like this in FeedsState:

public function reportItem($type, $source, $item, $entity, $message = '') {
  $this->reported[$type]++;
  module_invoke_all('feeds_state_update', $type, $source, $item, $entity, $message);
}

Not sure if this is right as parsers and fetchers also use a FeedsSource object and these do not have item nor entity.

And then something like this in FeedsProcessor:

// Track progress.
if (empty($entity_id)) {
  $state->reportItem(self::STATE_CREATED, $source, $item, $entity);
}
else {
  $state->reportItem(self::STATE_UPDATED, $source, $item, $entity);
}
// (...)
// Something bad happened, log it.
catch (Exception $e) {
  $state->reportItem(self::STATE_FAILED, $source, $item, $entity, $e->getMessage());
  drupal_set_message($e->getMessage(), 'warning');
  list($message, $arguments) = $this->createLogEntry($e, $entity, $item);
  $source->log('import', $message, $arguments, WATCHDOG_ERROR);
}
MegaChriz’s picture