/** * A replacement error handler with improved debugging features * - Backtraces including function parameters will be printed using TextMate URLs when running on localhost * - Only the IMP_FATAL_ERROR_MESSAGE will be displayed if IMP_DEBUG is not defined and true * - Most errors (all if IMP_DEBUG is true, < E_STRICT otherwise) are fatal to avoid continuing in abnormal situations * - Errors will always be recorded using error_log() * - MySQL's error will be printed if non-empty * - E_STRICT errors in system paths will be ignored to avoid PEAR/PHP5 compatibility issues */ function ImpErrorHandler($error, $message, $file, $line, $context) { if (!(error_reporting() & $error)) { return; // Obey the error_report() level and ignore the error } if (substr($file, 0, 5) == '/usr/' and $error == E_STRICT) { // TODO: come up with a more precise way to avoid reporting E_STRICT errors for PEAR classes return; } $ErrorTypes = array(E_ERROR => 'Error', E_WARNING => 'Warning', E_PARSE => 'Parsing Error', E_NOTICE => 'Notice', E_CORE_ERROR => 'Core Error', E_CORE_WARNING => 'Core Warning', E_COMPILE_ERROR => 'Compile Error', E_COMPILE_WARNING => 'Compile Warning', E_USER_ERROR => 'User Error', E_USER_WARNING => 'User Warning', E_USER_NOTICE => 'User Notice', E_STRICT => 'Runtime Notice', E_RECOVERABLE_ERROR => 'Catchable Fatal Error'); $ErrorType = isset($ErrorTypes[$error]) ? $ErrorTypes[$error] : 'Unknown'; // If IMP_DEBUG is defined we make everything fatal - otherwise we abort for anything else than an E_STRICT: $fatal = (defined("IMP_DEBUG") and IMP_DEBUG) ? true : $error != E_STRICT; $dbt = debug_backtrace(); assert($dbt[0]['function'] == __FUNCTION__); array_shift($dbt); // Remove our own entry from the backtrace if (defined('IMP_DEBUG') and IMP_DEBUG) { print '<div class="Error">'; print "<p><b>{$ErrorType}</b> at "; generate_debug_source_link($file, $line, $message); print "</p>"; if (function_exists('mysql_errno') and mysql_errno() > 0) { print '<p>Last MySQL error #' . mysql_errno() . ': <code>' . mysql_error() . '</code></p>'; } generate_debug_backtrace($dbt); phpinfo(INFO_ENVIRONMENT | INFO_VARIABLES); print '</div>'; } elseif (defined('IMP_FATAL_ERROR_MESSAGE')) { print "\n\n\n"; print IMP_FATAL_ERROR_MESSAGE; print "\n\n\n"; } error_log(__FUNCTION__ . ": {$ErrorType} in {$file} on line {$line}: " . quotemeta($message) . (!empty($dbt) ? ' (Began at ' . kimplode(array_filter_keys(array_last($dbt), array('file', 'line'))) . ')' : '')); if ($fatal) { if (!headers_sent()) { header("HTTP/1.1 500 {$ErrorType}"); } exit(1); } }
function query($sql) { $args = func_get_args(); $sql = array_shift($args); assert(!empty($sql)); $this->startTimer(); if (empty($args)) { $ret = call_user_func_array(array($this->PDO, 'query'), array($sql))->fetchAll(PDO::FETCH_ASSOC); } else { $st = $this->PDO->prepare($sql); if (!$st) { throw new Exception("Unable to prepare '{$sql}': " . kimplode($this->PDO->errorInfo())); } $st->execute($args); $ret = $st->fetchAll(PDO::FETCH_ASSOC); } $this->stopTimer($sql); return $ret; }