? 955236-3_error_handling.patch
? 955236-4_error_handling.patch
Index: feeds.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/feeds/feeds.module,v
retrieving revision 1.74.2.11
diff -u -p -r1.74.2.11 feeds.module
--- feeds.module 27 Oct 2010 19:53:21 -0000 1.74.2.11
+++ feeds.module 1 Nov 2010 18:56:45 -0000
@@ -738,6 +738,39 @@ function feeds_log($importer_id, $feed_n
}
/**
+ * Gets the last caller from a backtrace.
+ *
+ * Modeled after _drupal_get_last_caller().
+ *
+ * @param $backtrace
+ * A standard PHP backtrace.
+ * @return
+ * An associative array with keys 'file', 'line' and 'function'.
+ */
+function feeds_get_last_caller($backtrace) {
+ // Shift off one to not report Feeds error handler methods.
+ array_shift($backtrace);
+
+ // The first trace is the call itself.
+ // It gives us the line and the file of the last call.
+ $call = $backtrace[0];
+
+ // The second call give us the function where the call originated.
+ if (isset($backtrace[1])) {
+ if (isset($backtrace[1]['class'])) {
+ $call['function'] = $backtrace[1]['class'] . $backtrace[1]['type'] . $backtrace[1]['function'] . '()';
+ }
+ else {
+ $call['function'] = $backtrace[1]['function'] . '()';
+ }
+ }
+ else {
+ $call['function'] = 'main()';
+ }
+ return $call;
+}
+
+/**
* Loads an item info object.
*
* Example usage:
Index: includes/FeedsSource.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/feeds/includes/FeedsSource.inc,v
retrieving revision 1.26.2.8
diff -u -p -r1.26.2.8 FeedsSource.inc
--- includes/FeedsSource.inc 26 Oct 2010 03:05:58 -0000 1.26.2.8
+++ includes/FeedsSource.inc 1 Nov 2010 18:56:45 -0000
@@ -328,6 +328,8 @@ class FeedsSource extends FeedsConfigura
*/
public function import() {
$this->acquireLock();
+ set_error_handler(array($this, 'importError'));
+
try {
// Fetch.
if (empty($this->fetcher_result) || FEEDS_BATCH_COMPLETE == $this->progressParsing()) {
@@ -354,6 +356,8 @@ class FeedsSource extends FeedsConfigura
unset($this->fetcher_result, $this->state);
}
$this->save();
+ restore_error_handler();
+
if (isset($e)) {
throw $e;
}
@@ -376,6 +380,8 @@ class FeedsSource extends FeedsConfigura
*/
public function clear() {
$this->acquireLock();
+ set_error_handler(array($this, 'clearError'));
+
try {
$this->importer->fetcher->clear($this);
$this->importer->parser->clear($this);
@@ -391,6 +397,8 @@ class FeedsSource extends FeedsConfigura
unset($this->state);
}
$this->save();
+ restore_error_handler();
+
if (isset($e)) {
throw $e;
}
@@ -398,6 +406,57 @@ class FeedsSource extends FeedsConfigura
}
/**
+ * Handles errors on import.
+ */
+ public function importError($error_level, $message, $filename, $line, $context) {
+ if ($error_level & error_reporting()) {
+ // If this is NOT a recoverable error, attempt to clean up.
+ // @todo: does this make sense or do we know that if an error was not
+ // recoverable we can't clean up?
+ // @todo: it may be safer to delete the state every time when loading it.
+ if ($this->handleError($error_level, $message, $filename, $line, $context)) {
+ unset($this->state);
+ $this->save();
+ }
+ _drupal_error_handler($error_level, $message, $filename, $line, $context);
+ }
+ }
+
+ /**
+ * Handles errors on clear.
+ */
+ public function clearError($error_level, $message, $filename, $line, $context) {
+ if ($error_level & error_reporting()) {
+ if ($this->handleError($error_level, $message, $filename, $line, $context)) {
+ unset($this->state);
+ $this->save();
+ }
+ _drupal_error_handler($error_level, $message, $filename, $line, $context);
+ }
+ }
+
+ /**
+ * Logs error and determines whether error is fatal
+ *
+ * @return
+ * TRUE if error is fatal, FALSE otherwise.
+ */
+ protected function handleError($error_level, $message, $filename, $line, $context) {
+ require_once DRUPAL_ROOT . '/includes/errors.inc';
+ $levels = drupal_error_levels();
+ list ($severity_message, $severity_level) = $levels[$error_level];
+ $caller = feeds_get_last_caller(debug_backtrace());
+ $variables = array(
+ '@message' => $message,
+ '%function' => $caller['function'],
+ '%file' => isset($caller['file']) ? $caller['file'] : '',
+ '%line' => isset($caller['line']) ? $caller['line'] : '',
+ );
+ $this->log('import', "@message
%function
%file
%line", $variables, $severity_level);
+ return $error_level & array(E_ERROR | E_COMPILE_ERROR | E_COMPILE_ERROR | E_USER_ERROR);
+ }
+
+ /**
* Report progress as float between 0 and 1. 1 = FEEDS_BATCH_COMPLETE.
*/
public function progressParsing() {