New file |
0,0 → 1,979 |
<?php |
/** |
* Error Stack Implementation |
* |
* This is an incredibly simple implementation of a very complex error handling |
* facility. It contains the ability |
* to track multiple errors from multiple packages simultaneously. In addition, |
* it can track errors of many levels, save data along with the error, context |
* information such as the exact file, line number, class and function that |
* generated the error, and if necessary, it can raise a traditional PEAR_Error. |
* It has built-in support for PEAR::Log, to log errors as they occur |
* |
* Since version 0.2alpha, it is also possible to selectively ignore errors, |
* through the use of an error callback, see {@link pushCallback()} |
* |
* Since version 0.3alpha, it is possible to specify the exception class |
* returned from {@link push()} |
* |
* Since version PEAR1.3.2, ErrorStack no longer instantiates an exception class. This can |
* still be done quite handily in an error callback or by manipulating the returned array |
* @category Debugging |
* @package PEAR_ErrorStack |
* @author Greg Beaver <cellog@php.net> |
* @copyright 2004-2008 Greg Beaver |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR_ErrorStack |
*/ |
|
/** |
* Singleton storage |
* |
* Format: |
* <pre> |
* array( |
* 'package1' => PEAR_ErrorStack object, |
* 'package2' => PEAR_ErrorStack object, |
* ... |
* ) |
* </pre> |
* @access private |
* @global array $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] |
*/ |
$GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] = array(); |
|
/** |
* Global error callback (default) |
* |
* This is only used if set to non-false. * is the default callback for |
* all packages, whereas specific packages may set a default callback |
* for all instances, regardless of whether they are a singleton or not. |
* |
* To exclude non-singletons, only set the local callback for the singleton |
* @see PEAR_ErrorStack::setDefaultCallback() |
* @access private |
* @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'] |
*/ |
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'] = array( |
'*' => false, |
); |
|
/** |
* Global Log object (default) |
* |
* This is only used if set to non-false. Use to set a default log object for |
* all stacks, regardless of instantiation order or location |
* @see PEAR_ErrorStack::setDefaultLogger() |
* @access private |
* @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] |
*/ |
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = false; |
|
/** |
* Global Overriding Callback |
* |
* This callback will override any error callbacks that specific loggers have set. |
* Use with EXTREME caution |
* @see PEAR_ErrorStack::staticPushCallback() |
* @access private |
* @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] |
*/ |
$GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array(); |
|
/**#@+ |
* One of four possible return values from the error Callback |
* @see PEAR_ErrorStack::_errorCallback() |
*/ |
/** |
* If this is returned, then the error will be both pushed onto the stack |
* and logged. |
*/ |
define('PEAR_ERRORSTACK_PUSHANDLOG', 1); |
/** |
* If this is returned, then the error will only be pushed onto the stack, |
* and not logged. |
*/ |
define('PEAR_ERRORSTACK_PUSH', 2); |
/** |
* If this is returned, then the error will only be logged, but not pushed |
* onto the error stack. |
*/ |
define('PEAR_ERRORSTACK_LOG', 3); |
/** |
* If this is returned, then the error is completely ignored. |
*/ |
define('PEAR_ERRORSTACK_IGNORE', 4); |
/** |
* If this is returned, then the error is logged and die() is called. |
*/ |
define('PEAR_ERRORSTACK_DIE', 5); |
/**#@-*/ |
|
/** |
* Error code for an attempt to instantiate a non-class as a PEAR_ErrorStack in |
* the singleton method. |
*/ |
define('PEAR_ERRORSTACK_ERR_NONCLASS', 1); |
|
/** |
* Error code for an attempt to pass an object into {@link PEAR_ErrorStack::getMessage()} |
* that has no __toString() method |
*/ |
define('PEAR_ERRORSTACK_ERR_OBJTOSTRING', 2); |
/** |
* Error Stack Implementation |
* |
* Usage: |
* <code> |
* // global error stack |
* $global_stack = &PEAR_ErrorStack::singleton('MyPackage'); |
* // local error stack |
* $local_stack = new PEAR_ErrorStack('MyPackage'); |
* </code> |
* @author Greg Beaver <cellog@php.net> |
* @version 1.10.1 |
* @package PEAR_ErrorStack |
* @category Debugging |
* @copyright 2004-2008 Greg Beaver |
* @license http://opensource.org/licenses/bsd-license.php New BSD License |
* @link http://pear.php.net/package/PEAR_ErrorStack |
*/ |
class PEAR_ErrorStack { |
/** |
* Errors are stored in the order that they are pushed on the stack. |
* @since 0.4alpha Errors are no longer organized by error level. |
* This renders pop() nearly unusable, and levels could be more easily |
* handled in a callback anyway |
* @var array |
* @access private |
*/ |
var $_errors = array(); |
|
/** |
* Storage of errors by level. |
* |
* Allows easy retrieval and deletion of only errors from a particular level |
* @since PEAR 1.4.0dev |
* @var array |
* @access private |
*/ |
var $_errorsByLevel = array(); |
|
/** |
* Package name this error stack represents |
* @var string |
* @access protected |
*/ |
var $_package; |
|
/** |
* Determines whether a PEAR_Error is thrown upon every error addition |
* @var boolean |
* @access private |
*/ |
var $_compat = false; |
|
/** |
* If set to a valid callback, this will be used to generate the error |
* message from the error code, otherwise the message passed in will be |
* used |
* @var false|string|array |
* @access private |
*/ |
var $_msgCallback = false; |
|
/** |
* If set to a valid callback, this will be used to generate the error |
* context for an error. For PHP-related errors, this will be a file |
* and line number as retrieved from debug_backtrace(), but can be |
* customized for other purposes. The error might actually be in a separate |
* configuration file, or in a database query. |
* @var false|string|array |
* @access protected |
*/ |
var $_contextCallback = false; |
|
/** |
* If set to a valid callback, this will be called every time an error |
* is pushed onto the stack. The return value will be used to determine |
* whether to allow an error to be pushed or logged. |
* |
* The return value must be one an PEAR_ERRORSTACK_* constant |
* @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG |
* @var false|string|array |
* @access protected |
*/ |
var $_errorCallback = array(); |
|
/** |
* PEAR::Log object for logging errors |
* @var false|Log |
* @access protected |
*/ |
var $_logger = false; |
|
/** |
* Error messages - designed to be overridden |
* @var array |
* @abstract |
*/ |
var $_errorMsgs = array(); |
|
/** |
* Set up a new error stack |
* |
* @param string $package name of the package this error stack represents |
* @param callback $msgCallback callback used for error message generation |
* @param callback $contextCallback callback used for context generation, |
* defaults to {@link getFileLine()} |
* @param boolean $throwPEAR_Error |
*/ |
function __construct($package, $msgCallback = false, $contextCallback = false, |
$throwPEAR_Error = false) |
{ |
$this->_package = $package; |
$this->setMessageCallback($msgCallback); |
$this->setContextCallback($contextCallback); |
$this->_compat = $throwPEAR_Error; |
} |
|
/** |
* Return a single error stack for this package. |
* |
* Note that all parameters are ignored if the stack for package $package |
* has already been instantiated |
* @param string $package name of the package this error stack represents |
* @param callback $msgCallback callback used for error message generation |
* @param callback $contextCallback callback used for context generation, |
* defaults to {@link getFileLine()} |
* @param boolean $throwPEAR_Error |
* @param string $stackClass class to instantiate |
* |
* @return PEAR_ErrorStack |
*/ |
public static function &singleton( |
$package, $msgCallback = false, $contextCallback = false, |
$throwPEAR_Error = false, $stackClass = 'PEAR_ErrorStack' |
) { |
if (isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) { |
return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]; |
} |
if (!class_exists($stackClass)) { |
if (function_exists('debug_backtrace')) { |
$trace = debug_backtrace(); |
} |
PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_NONCLASS, |
'exception', array('stackclass' => $stackClass), |
'stack class "%stackclass%" is not a valid class name (should be like PEAR_ErrorStack)', |
false, $trace); |
} |
$GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package] = |
new $stackClass($package, $msgCallback, $contextCallback, $throwPEAR_Error); |
|
return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]; |
} |
|
/** |
* Internal error handler for PEAR_ErrorStack class |
* |
* Dies if the error is an exception (and would have died anyway) |
* @access private |
*/ |
function _handleError($err) |
{ |
if ($err['level'] == 'exception') { |
$message = $err['message']; |
if (isset($_SERVER['REQUEST_URI'])) { |
echo '<br />'; |
} else { |
echo "\n"; |
} |
var_dump($err['context']); |
die($message); |
} |
} |
|
/** |
* Set up a PEAR::Log object for all error stacks that don't have one |
* @param Log $log |
*/ |
public static function setDefaultLogger(&$log) |
{ |
if (is_object($log) && method_exists($log, 'log') ) { |
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log; |
} elseif (is_callable($log)) { |
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log; |
} |
} |
|
/** |
* Set up a PEAR::Log object for this error stack |
* @param Log $log |
*/ |
function setLogger(&$log) |
{ |
if (is_object($log) && method_exists($log, 'log') ) { |
$this->_logger = &$log; |
} elseif (is_callable($log)) { |
$this->_logger = &$log; |
} |
} |
|
/** |
* Set an error code => error message mapping callback |
* |
* This method sets the callback that can be used to generate error |
* messages for any instance |
* @param array|string Callback function/method |
*/ |
function setMessageCallback($msgCallback) |
{ |
if (!$msgCallback) { |
$this->_msgCallback = array(&$this, 'getErrorMessage'); |
} else { |
if (is_callable($msgCallback)) { |
$this->_msgCallback = $msgCallback; |
} |
} |
} |
|
/** |
* Get an error code => error message mapping callback |
* |
* This method returns the current callback that can be used to generate error |
* messages |
* @return array|string|false Callback function/method or false if none |
*/ |
function getMessageCallback() |
{ |
return $this->_msgCallback; |
} |
|
/** |
* Sets a default callback to be used by all error stacks |
* |
* This method sets the callback that can be used to generate error |
* messages for a singleton |
* @param array|string Callback function/method |
* @param string Package name, or false for all packages |
*/ |
public static function setDefaultCallback($callback = false, $package = false) |
{ |
if (!is_callable($callback)) { |
$callback = false; |
} |
$package = $package ? $package : '*'; |
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$package] = $callback; |
} |
|
/** |
* Set a callback that generates context information (location of error) for an error stack |
* |
* This method sets the callback that can be used to generate context |
* information for an error. Passing in NULL will disable context generation |
* and remove the expensive call to debug_backtrace() |
* @param array|string|null Callback function/method |
*/ |
function setContextCallback($contextCallback) |
{ |
if ($contextCallback === null) { |
return $this->_contextCallback = false; |
} |
if (!$contextCallback) { |
$this->_contextCallback = array(&$this, 'getFileLine'); |
} else { |
if (is_callable($contextCallback)) { |
$this->_contextCallback = $contextCallback; |
} |
} |
} |
|
/** |
* Set an error Callback |
* If set to a valid callback, this will be called every time an error |
* is pushed onto the stack. The return value will be used to determine |
* whether to allow an error to be pushed or logged. |
* |
* The return value must be one of the ERRORSTACK_* constants. |
* |
* This functionality can be used to emulate PEAR's pushErrorHandling, and |
* the PEAR_ERROR_CALLBACK mode, without affecting the integrity of |
* the error stack or logging |
* @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG |
* @see popCallback() |
* @param string|array $cb |
*/ |
function pushCallback($cb) |
{ |
array_push($this->_errorCallback, $cb); |
} |
|
/** |
* Remove a callback from the error callback stack |
* @see pushCallback() |
* @return array|string|false |
*/ |
function popCallback() |
{ |
if (!count($this->_errorCallback)) { |
return false; |
} |
return array_pop($this->_errorCallback); |
} |
|
/** |
* Set a temporary overriding error callback for every package error stack |
* |
* Use this to temporarily disable all existing callbacks (can be used |
* to emulate the @ operator, for instance) |
* @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG |
* @see staticPopCallback(), pushCallback() |
* @param string|array $cb |
*/ |
public static function staticPushCallback($cb) |
{ |
array_push($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'], $cb); |
} |
|
/** |
* Remove a temporary overriding error callback |
* @see staticPushCallback() |
* @return array|string|false |
*/ |
public static function staticPopCallback() |
{ |
$ret = array_pop($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK']); |
if (!is_array($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'])) { |
$GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array(); |
} |
return $ret; |
} |
|
/** |
* Add an error to the stack |
* |
* If the message generator exists, it is called with 2 parameters. |
* - the current Error Stack object |
* - an array that is in the same format as an error. Available indices |
* are 'code', 'package', 'time', 'params', 'level', and 'context' |
* |
* Next, if the error should contain context information, this is |
* handled by the context grabbing method. |
* Finally, the error is pushed onto the proper error stack |
* @param int $code Package-specific error code |
* @param string $level Error level. This is NOT spell-checked |
* @param array $params associative array of error parameters |
* @param string $msg Error message, or a portion of it if the message |
* is to be generated |
* @param array $repackage If this error re-packages an error pushed by |
* another package, place the array returned from |
* {@link pop()} in this parameter |
* @param array $backtrace Protected parameter: use this to pass in the |
* {@link debug_backtrace()} that should be used |
* to find error context |
* @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also |
* thrown. If a PEAR_Error is returned, the userinfo |
* property is set to the following array: |
* |
* <code> |
* array( |
* 'code' => $code, |
* 'params' => $params, |
* 'package' => $this->_package, |
* 'level' => $level, |
* 'time' => time(), |
* 'context' => $context, |
* 'message' => $msg, |
* //['repackage' => $err] repackaged error array/Exception class |
* ); |
* </code> |
* |
* Normally, the previous array is returned. |
*/ |
function push($code, $level = 'error', $params = array(), $msg = false, |
$repackage = false, $backtrace = false) |
{ |
$context = false; |
// grab error context |
if ($this->_contextCallback) { |
if (!$backtrace) { |
$backtrace = debug_backtrace(); |
} |
$context = call_user_func($this->_contextCallback, $code, $params, $backtrace); |
} |
|
// save error |
$time = explode(' ', microtime()); |
$time = $time[1] + $time[0]; |
$err = array( |
'code' => $code, |
'params' => $params, |
'package' => $this->_package, |
'level' => $level, |
'time' => $time, |
'context' => $context, |
'message' => $msg, |
); |
|
if ($repackage) { |
$err['repackage'] = $repackage; |
} |
|
// set up the error message, if necessary |
if ($this->_msgCallback) { |
$msg = call_user_func_array($this->_msgCallback, |
array(&$this, $err)); |
$err['message'] = $msg; |
} |
$push = $log = true; |
$die = false; |
// try the overriding callback first |
$callback = $this->staticPopCallback(); |
if ($callback) { |
$this->staticPushCallback($callback); |
} |
if (!is_callable($callback)) { |
// try the local callback next |
$callback = $this->popCallback(); |
if (is_callable($callback)) { |
$this->pushCallback($callback); |
} else { |
// try the default callback |
$callback = isset($GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package]) ? |
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package] : |
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']['*']; |
} |
} |
if (is_callable($callback)) { |
switch(call_user_func($callback, $err)){ |
case PEAR_ERRORSTACK_IGNORE: |
return $err; |
break; |
case PEAR_ERRORSTACK_PUSH: |
$log = false; |
break; |
case PEAR_ERRORSTACK_LOG: |
$push = false; |
break; |
case PEAR_ERRORSTACK_DIE: |
$die = true; |
break; |
// anything else returned has the same effect as pushandlog |
} |
} |
if ($push) { |
array_unshift($this->_errors, $err); |
if (!isset($this->_errorsByLevel[$err['level']])) { |
$this->_errorsByLevel[$err['level']] = array(); |
} |
$this->_errorsByLevel[$err['level']][] = &$this->_errors[0]; |
} |
if ($log) { |
if ($this->_logger || $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']) { |
$this->_log($err); |
} |
} |
if ($die) { |
die(); |
} |
if ($this->_compat && $push) { |
return $this->raiseError($msg, $code, null, null, $err); |
} |
return $err; |
} |
|
/** |
* Static version of {@link push()} |
* |
* @param string $package Package name this error belongs to |
* @param int $code Package-specific error code |
* @param string $level Error level. This is NOT spell-checked |
* @param array $params associative array of error parameters |
* @param string $msg Error message, or a portion of it if the message |
* is to be generated |
* @param array $repackage If this error re-packages an error pushed by |
* another package, place the array returned from |
* {@link pop()} in this parameter |
* @param array $backtrace Protected parameter: use this to pass in the |
* {@link debug_backtrace()} that should be used |
* to find error context |
* @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also |
* thrown. see docs for {@link push()} |
*/ |
public static function staticPush( |
$package, $code, $level = 'error', $params = array(), |
$msg = false, $repackage = false, $backtrace = false |
) { |
$s = &PEAR_ErrorStack::singleton($package); |
if ($s->_contextCallback) { |
if (!$backtrace) { |
if (function_exists('debug_backtrace')) { |
$backtrace = debug_backtrace(); |
} |
} |
} |
return $s->push($code, $level, $params, $msg, $repackage, $backtrace); |
} |
|
/** |
* Log an error using PEAR::Log |
* @param array $err Error array |
* @param array $levels Error level => Log constant map |
* @access protected |
*/ |
function _log($err) |
{ |
if ($this->_logger) { |
$logger = &$this->_logger; |
} else { |
$logger = &$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']; |
} |
if (is_a($logger, 'Log')) { |
$levels = array( |
'exception' => PEAR_LOG_CRIT, |
'alert' => PEAR_LOG_ALERT, |
'critical' => PEAR_LOG_CRIT, |
'error' => PEAR_LOG_ERR, |
'warning' => PEAR_LOG_WARNING, |
'notice' => PEAR_LOG_NOTICE, |
'info' => PEAR_LOG_INFO, |
'debug' => PEAR_LOG_DEBUG); |
if (isset($levels[$err['level']])) { |
$level = $levels[$err['level']]; |
} else { |
$level = PEAR_LOG_INFO; |
} |
$logger->log($err['message'], $level, $err); |
} else { // support non-standard logs |
call_user_func($logger, $err); |
} |
} |
|
|
/** |
* Pop an error off of the error stack |
* |
* @return false|array |
* @since 0.4alpha it is no longer possible to specify a specific error |
* level to return - the last error pushed will be returned, instead |
*/ |
function pop() |
{ |
$err = @array_shift($this->_errors); |
if (!is_null($err)) { |
@array_pop($this->_errorsByLevel[$err['level']]); |
if (!count($this->_errorsByLevel[$err['level']])) { |
unset($this->_errorsByLevel[$err['level']]); |
} |
} |
return $err; |
} |
|
/** |
* Pop an error off of the error stack, static method |
* |
* @param string package name |
* @return boolean |
* @since PEAR1.5.0a1 |
*/ |
function staticPop($package) |
{ |
if ($package) { |
if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) { |
return false; |
} |
return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->pop(); |
} |
} |
|
/** |
* Determine whether there are any errors on the stack |
* @param string|array Level name. Use to determine if any errors |
* of level (string), or levels (array) have been pushed |
* @return boolean |
*/ |
function hasErrors($level = false) |
{ |
if ($level) { |
return isset($this->_errorsByLevel[$level]); |
} |
return count($this->_errors); |
} |
|
/** |
* Retrieve all errors since last purge |
* |
* @param boolean set in order to empty the error stack |
* @param string level name, to return only errors of a particular severity |
* @return array |
*/ |
function getErrors($purge = false, $level = false) |
{ |
if (!$purge) { |
if ($level) { |
if (!isset($this->_errorsByLevel[$level])) { |
return array(); |
} else { |
return $this->_errorsByLevel[$level]; |
} |
} else { |
return $this->_errors; |
} |
} |
if ($level) { |
$ret = $this->_errorsByLevel[$level]; |
foreach ($this->_errorsByLevel[$level] as $i => $unused) { |
// entries are references to the $_errors array |
$this->_errorsByLevel[$level][$i] = false; |
} |
// array_filter removes all entries === false |
$this->_errors = array_filter($this->_errors); |
unset($this->_errorsByLevel[$level]); |
return $ret; |
} |
$ret = $this->_errors; |
$this->_errors = array(); |
$this->_errorsByLevel = array(); |
return $ret; |
} |
|
/** |
* Determine whether there are any errors on a single error stack, or on any error stack |
* |
* The optional parameter can be used to test the existence of any errors without the need of |
* singleton instantiation |
* @param string|false Package name to check for errors |
* @param string Level name to check for a particular severity |
* @return boolean |
*/ |
public static function staticHasErrors($package = false, $level = false) |
{ |
if ($package) { |
if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) { |
return false; |
} |
return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->hasErrors($level); |
} |
foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) { |
if ($obj->hasErrors($level)) { |
return true; |
} |
} |
return false; |
} |
|
/** |
* Get a list of all errors since last purge, organized by package |
* @since PEAR 1.4.0dev BC break! $level is now in the place $merge used to be |
* @param boolean $purge Set to purge the error stack of existing errors |
* @param string $level Set to a level name in order to retrieve only errors of a particular level |
* @param boolean $merge Set to return a flat array, not organized by package |
* @param array $sortfunc Function used to sort a merged array - default |
* sorts by time, and should be good for most cases |
* |
* @return array |
*/ |
public static function staticGetErrors( |
$purge = false, $level = false, $merge = false, |
$sortfunc = array('PEAR_ErrorStack', '_sortErrors') |
) { |
$ret = array(); |
if (!is_callable($sortfunc)) { |
$sortfunc = array('PEAR_ErrorStack', '_sortErrors'); |
} |
foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) { |
$test = $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->getErrors($purge, $level); |
if ($test) { |
if ($merge) { |
$ret = array_merge($ret, $test); |
} else { |
$ret[$package] = $test; |
} |
} |
} |
if ($merge) { |
usort($ret, $sortfunc); |
} |
return $ret; |
} |
|
/** |
* Error sorting function, sorts by time |
* @access private |
*/ |
public static function _sortErrors($a, $b) |
{ |
if ($a['time'] == $b['time']) { |
return 0; |
} |
if ($a['time'] < $b['time']) { |
return 1; |
} |
return -1; |
} |
|
/** |
* Standard file/line number/function/class context callback |
* |
* This function uses a backtrace generated from {@link debug_backtrace()} |
* and so will not work at all in PHP < 4.3.0. The frame should |
* reference the frame that contains the source of the error. |
* @return array|false either array('file' => file, 'line' => line, |
* 'function' => function name, 'class' => class name) or |
* if this doesn't work, then false |
* @param unused |
* @param integer backtrace frame. |
* @param array Results of debug_backtrace() |
*/ |
public static function getFileLine($code, $params, $backtrace = null) |
{ |
if ($backtrace === null) { |
return false; |
} |
$frame = 0; |
$functionframe = 1; |
if (!isset($backtrace[1])) { |
$functionframe = 0; |
} else { |
while (isset($backtrace[$functionframe]['function']) && |
$backtrace[$functionframe]['function'] == 'eval' && |
isset($backtrace[$functionframe + 1])) { |
$functionframe++; |
} |
} |
if (isset($backtrace[$frame])) { |
if (!isset($backtrace[$frame]['file'])) { |
$frame++; |
} |
$funcbacktrace = $backtrace[$functionframe]; |
$filebacktrace = $backtrace[$frame]; |
$ret = array('file' => $filebacktrace['file'], |
'line' => $filebacktrace['line']); |
// rearrange for eval'd code or create function errors |
if (strpos($filebacktrace['file'], '(') && |
preg_match(';^(.*?)\((\d+)\) : (.*?)\\z;', $filebacktrace['file'], |
$matches)) { |
$ret['file'] = $matches[1]; |
$ret['line'] = $matches[2] + 0; |
} |
if (isset($funcbacktrace['function']) && isset($backtrace[1])) { |
if ($funcbacktrace['function'] != 'eval') { |
if ($funcbacktrace['function'] == '__lambda_func') { |
$ret['function'] = 'create_function() code'; |
} else { |
$ret['function'] = $funcbacktrace['function']; |
} |
} |
} |
if (isset($funcbacktrace['class']) && isset($backtrace[1])) { |
$ret['class'] = $funcbacktrace['class']; |
} |
return $ret; |
} |
return false; |
} |
|
/** |
* Standard error message generation callback |
* |
* This method may also be called by a custom error message generator |
* to fill in template values from the params array, simply |
* set the third parameter to the error message template string to use |
* |
* The special variable %__msg% is reserved: use it only to specify |
* where a message passed in by the user should be placed in the template, |
* like so: |
* |
* Error message: %msg% - internal error |
* |
* If the message passed like so: |
* |
* <code> |
* $stack->push(ERROR_CODE, 'error', array(), 'server error 500'); |
* </code> |
* |
* The returned error message will be "Error message: server error 500 - |
* internal error" |
* @param PEAR_ErrorStack |
* @param array |
* @param string|false Pre-generated error message template |
* |
* @return string |
*/ |
public static function getErrorMessage(&$stack, $err, $template = false) |
{ |
if ($template) { |
$mainmsg = $template; |
} else { |
$mainmsg = $stack->getErrorMessageTemplate($err['code']); |
} |
$mainmsg = str_replace('%__msg%', $err['message'], $mainmsg); |
if (is_array($err['params']) && count($err['params'])) { |
foreach ($err['params'] as $name => $val) { |
if (is_array($val)) { |
// @ is needed in case $val is a multi-dimensional array |
$val = @implode(', ', $val); |
} |
if (is_object($val)) { |
if (method_exists($val, '__toString')) { |
$val = $val->__toString(); |
} else { |
PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_OBJTOSTRING, |
'warning', array('obj' => get_class($val)), |
'object %obj% passed into getErrorMessage, but has no __toString() method'); |
$val = 'Object'; |
} |
} |
$mainmsg = str_replace('%' . $name . '%', $val, $mainmsg); |
} |
} |
return $mainmsg; |
} |
|
/** |
* Standard Error Message Template generator from code |
* @return string |
*/ |
function getErrorMessageTemplate($code) |
{ |
if (!isset($this->_errorMsgs[$code])) { |
return '%__msg%'; |
} |
return $this->_errorMsgs[$code]; |
} |
|
/** |
* Set the Error Message Template array |
* |
* The array format must be: |
* <pre> |
* array(error code => 'message template',...) |
* </pre> |
* |
* Error message parameters passed into {@link push()} will be used as input |
* for the error message. If the template is 'message %foo% was %bar%', and the |
* parameters are array('foo' => 'one', 'bar' => 'six'), the error message returned will |
* be 'message one was six' |
* @return string |
*/ |
function setErrorMessageTemplate($template) |
{ |
$this->_errorMsgs = $template; |
} |
|
|
/** |
* emulate PEAR::raiseError() |
* |
* @return PEAR_Error |
*/ |
function raiseError() |
{ |
require_once 'PEAR.php'; |
$args = func_get_args(); |
return call_user_func_array(array('PEAR', 'raiseError'), $args); |
} |
} |
$stack = &PEAR_ErrorStack::singleton('PEAR_ErrorStack'); |
$stack->pushCallback(array('PEAR_ErrorStack', '_handleError')); |
?> |