Open Journal Systems  3.3.0
ErrorStack.php
1 <?php
43 $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] = array();
44 
57 $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'] = array(
58  '*' => false,
59 );
60 
70 $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = false;
71 
81 $GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array();
82 
91 define('PEAR_ERRORSTACK_PUSHANDLOG', 1);
96 define('PEAR_ERRORSTACK_PUSH', 2);
101 define('PEAR_ERRORSTACK_LOG', 3);
105 define('PEAR_ERRORSTACK_IGNORE', 4);
109 define('PEAR_ERRORSTACK_DIE', 5);
116 define('PEAR_ERRORSTACK_ERR_NONCLASS', 1);
117 
122 define('PEAR_ERRORSTACK_ERR_OBJTOSTRING', 2);
150  var $_errors = array();
151 
160  var $_errorsByLevel = array();
161 
167  var $_package;
168 
174  var $_compat = false;
175 
183  var $_msgCallback = false;
184 
194  var $_contextCallback = false;
195 
206  var $_errorCallback = array();
207 
213  var $_logger = false;
214 
220  var $_errorMsgs = array();
221 
231  function __construct($package, $msgCallback = false, $contextCallback = false,
232  $throwPEAR_Error = false)
233  {
234  $this->_package = $package;
235  $this->setMessageCallback($msgCallback);
236  $this->setContextCallback($contextCallback);
237  $this->_compat = $throwPEAR_Error;
238  }
239 
254  public static function &singleton(
255  $package, $msgCallback = false, $contextCallback = false,
256  $throwPEAR_Error = false, $stackClass = 'PEAR_ErrorStack'
257  ) {
258  if (isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
259  return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package];
260  }
261  if (!class_exists($stackClass)) {
262  if (function_exists('debug_backtrace')) {
263  $trace = debug_backtrace();
264  }
265  PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_NONCLASS,
266  'exception', array('stackclass' => $stackClass),
267  'stack class "%stackclass%" is not a valid class name (should be like PEAR_ErrorStack)',
268  false, $trace);
269  }
270  $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package] =
271  new $stackClass($package, $msgCallback, $contextCallback, $throwPEAR_Error);
272 
273  return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package];
274  }
275 
282  function _handleError($err)
283  {
284  if ($err['level'] == 'exception') {
285  $message = $err['message'];
286  if (isset($_SERVER['REQUEST_URI'])) {
287  echo '<br />';
288  } else {
289  echo "\n";
290  }
291  var_dump($err['context']);
292  die($message);
293  }
294  }
295 
300  public static function setDefaultLogger(&$log)
301  {
302  if (is_object($log) && method_exists($log, 'log') ) {
303  $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log;
304  } elseif (is_callable($log)) {
305  $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log;
306  }
307  }
308 
313  function setLogger(&$log)
314  {
315  if (is_object($log) && method_exists($log, 'log') ) {
316  $this->_logger = &$log;
317  } elseif (is_callable($log)) {
318  $this->_logger = &$log;
319  }
320  }
321 
329  function setMessageCallback($msgCallback)
330  {
331  if (!$msgCallback) {
332  $this->_msgCallback = array(&$this, 'getErrorMessage');
333  } else {
334  if (is_callable($msgCallback)) {
335  $this->_msgCallback = $msgCallback;
336  }
337  }
338  }
339 
347  function getMessageCallback()
348  {
349  return $this->_msgCallback;
350  }
351 
360  public static function setDefaultCallback($callback = false, $package = false)
361  {
362  if (!is_callable($callback)) {
363  $callback = false;
364  }
365  $package = $package ? $package : '*';
366  $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$package] = $callback;
367  }
368 
377  function setContextCallback($contextCallback)
378  {
379  if ($contextCallback === null) {
380  return $this->_contextCallback = false;
381  }
382  if (!$contextCallback) {
383  $this->_contextCallback = array(&$this, 'getFileLine');
384  } else {
385  if (is_callable($contextCallback)) {
386  $this->_contextCallback = $contextCallback;
387  }
388  }
389  }
390 
406  function pushCallback($cb)
407  {
408  array_push($this->_errorCallback, $cb);
409  }
410 
416  function popCallback()
417  {
418  if (!count($this->_errorCallback)) {
419  return false;
420  }
421  return array_pop($this->_errorCallback);
422  }
423 
433  public static function staticPushCallback($cb)
434  {
435  array_push($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'], $cb);
436  }
437 
443  public static function staticPopCallback()
444  {
445  $ret = array_pop($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK']);
446  if (!is_array($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'])) {
447  $GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array();
448  }
449  return $ret;
450  }
451 
493  function push($code, $level = 'error', $params = array(), $msg = false,
494  $repackage = false, $backtrace = false)
495  {
496  $context = false;
497  // grab error context
498  if ($this->_contextCallback) {
499  if (!$backtrace) {
500  $backtrace = debug_backtrace();
501  }
502  $context = call_user_func($this->_contextCallback, $code, $params, $backtrace);
503  }
504 
505  // save error
506  $time = explode(' ', microtime());
507  $time = $time[1] + $time[0];
508  $err = array(
509  'code' => $code,
510  'params' => $params,
511  'package' => $this->_package,
512  'level' => $level,
513  'time' => $time,
514  'context' => $context,
515  'message' => $msg,
516  );
517 
518  if ($repackage) {
519  $err['repackage'] = $repackage;
520  }
521 
522  // set up the error message, if necessary
523  if ($this->_msgCallback) {
524  $msg = call_user_func_array($this->_msgCallback,
525  array(&$this, $err));
526  $err['message'] = $msg;
527  }
528  $push = $log = true;
529  $die = false;
530  // try the overriding callback first
531  $callback = $this->staticPopCallback();
532  if ($callback) {
533  $this->staticPushCallback($callback);
534  }
535  if (!is_callable($callback)) {
536  // try the local callback next
537  $callback = $this->popCallback();
538  if (is_callable($callback)) {
539  $this->pushCallback($callback);
540  } else {
541  // try the default callback
542  $callback = isset($GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package]) ?
543  $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package] :
544  $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']['*'];
545  }
546  }
547  if (is_callable($callback)) {
548  switch(call_user_func($callback, $err)){
549  case PEAR_ERRORSTACK_IGNORE:
550  return $err;
551  break;
552  case PEAR_ERRORSTACK_PUSH:
553  $log = false;
554  break;
555  case PEAR_ERRORSTACK_LOG:
556  $push = false;
557  break;
558  case PEAR_ERRORSTACK_DIE:
559  $die = true;
560  break;
561  // anything else returned has the same effect as pushandlog
562  }
563  }
564  if ($push) {
565  array_unshift($this->_errors, $err);
566  if (!isset($this->_errorsByLevel[$err['level']])) {
567  $this->_errorsByLevel[$err['level']] = array();
568  }
569  $this->_errorsByLevel[$err['level']][] = &$this->_errors[0];
570  }
571  if ($log) {
572  if ($this->_logger || $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']) {
573  $this->_log($err);
574  }
575  }
576  if ($die) {
577  die();
578  }
579  if ($this->_compat && $push) {
580  return $this->raiseError($msg, $code, null, null, $err);
581  }
582  return $err;
583  }
584 
603  public static function staticPush(
604  $package, $code, $level = 'error', $params = array(),
605  $msg = false, $repackage = false, $backtrace = false
606  ) {
607  $s = &PEAR_ErrorStack::singleton($package);
608  if ($s->_contextCallback) {
609  if (!$backtrace) {
610  if (function_exists('debug_backtrace')) {
611  $backtrace = debug_backtrace();
612  }
613  }
614  }
615  return $s->push($code, $level, $params, $msg, $repackage, $backtrace);
616  }
617 
624  function _log($err)
625  {
626  if ($this->_logger) {
627  $logger = &$this->_logger;
628  } else {
629  $logger = &$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'];
630  }
631  if (is_a($logger, 'Log')) {
632  $levels = array(
633  'exception' => PEAR_LOG_CRIT,
634  'alert' => PEAR_LOG_ALERT,
635  'critical' => PEAR_LOG_CRIT,
636  'error' => PEAR_LOG_ERR,
637  'warning' => PEAR_LOG_WARNING,
638  'notice' => PEAR_LOG_NOTICE,
639  'info' => PEAR_LOG_INFO,
640  'debug' => PEAR_LOG_DEBUG);
641  if (isset($levels[$err['level']])) {
642  $level = $levels[$err['level']];
643  } else {
644  $level = PEAR_LOG_INFO;
645  }
646  $logger->log($err['message'], $level, $err);
647  } else { // support non-standard logs
648  call_user_func($logger, $err);
649  }
650  }
651 
652 
660  function pop()
661  {
662  $err = @array_shift($this->_errors);
663  if (!is_null($err)) {
664  @array_pop($this->_errorsByLevel[$err['level']]);
665  if (!count($this->_errorsByLevel[$err['level']])) {
666  unset($this->_errorsByLevel[$err['level']]);
667  }
668  }
669  return $err;
670  }
671 
679  static function staticPop($package)
680  {
681  if ($package) {
682  if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
683  return false;
684  }
685  return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->pop();
686  }
687  }
688 
695  function hasErrors($level = false)
696  {
697  if ($level) {
698  return isset($this->_errorsByLevel[$level]);
699  }
700  return count($this->_errors);
701  }
702 
710  function getErrors($purge = false, $level = false)
711  {
712  if (!$purge) {
713  if ($level) {
714  if (!isset($this->_errorsByLevel[$level])) {
715  return array();
716  } else {
717  return $this->_errorsByLevel[$level];
718  }
719  } else {
720  return $this->_errors;
721  }
722  }
723  if ($level) {
724  $ret = $this->_errorsByLevel[$level];
725  foreach ($this->_errorsByLevel[$level] as $i => $unused) {
726  // entries are references to the $_errors array
727  $this->_errorsByLevel[$level][$i] = false;
728  }
729  // array_filter removes all entries === false
730  $this->_errors = array_filter($this->_errors);
731  unset($this->_errorsByLevel[$level]);
732  return $ret;
733  }
734  $ret = $this->_errors;
735  $this->_errors = array();
736  $this->_errorsByLevel = array();
737  return $ret;
738  }
739 
749  public static function staticHasErrors($package = false, $level = false)
750  {
751  if ($package) {
752  if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
753  return false;
754  }
755  return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->hasErrors($level);
756  }
757  foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) {
758  if ($obj->hasErrors($level)) {
759  return true;
760  }
761  }
762  return false;
763  }
764 
776  public static function staticGetErrors(
777  $purge = false, $level = false, $merge = false,
778  $sortfunc = array('PEAR_ErrorStack', '_sortErrors')
779  ) {
780  $ret = array();
781  if (!is_callable($sortfunc)) {
782  $sortfunc = array('PEAR_ErrorStack', '_sortErrors');
783  }
784  foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) {
785  $test = $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->getErrors($purge, $level);
786  if ($test) {
787  if ($merge) {
788  $ret = array_merge($ret, $test);
789  } else {
790  $ret[$package] = $test;
791  }
792  }
793  }
794  if ($merge) {
795  usort($ret, $sortfunc);
796  }
797  return $ret;
798  }
799 
804  public static function _sortErrors($a, $b)
805  {
806  if ($a['time'] == $b['time']) {
807  return 0;
808  }
809  if ($a['time'] < $b['time']) {
810  return 1;
811  }
812  return -1;
813  }
814 
828  public static function getFileLine($code, $params, $backtrace = null)
829  {
830  if ($backtrace === null) {
831  return false;
832  }
833  $frame = 0;
834  $functionframe = 1;
835  if (!isset($backtrace[1])) {
836  $functionframe = 0;
837  } else {
838  while (isset($backtrace[$functionframe]['function']) &&
839  $backtrace[$functionframe]['function'] == 'eval' &&
840  isset($backtrace[$functionframe + 1])) {
841  $functionframe++;
842  }
843  }
844  if (isset($backtrace[$frame])) {
845  if (!isset($backtrace[$frame]['file'])) {
846  $frame++;
847  }
848  $funcbacktrace = $backtrace[$functionframe];
849  $filebacktrace = $backtrace[$frame];
850  $ret = array('file' => $filebacktrace['file'],
851  'line' => $filebacktrace['line']);
852  // rearrange for eval'd code or create function errors
853  if (strpos($filebacktrace['file'], '(') &&
854  preg_match(';^(.*?)\((\d+)\) : (.*?)\\z;', $filebacktrace['file'],
855  $matches)) {
856  $ret['file'] = $matches[1];
857  $ret['line'] = $matches[2] + 0;
858  }
859  if (isset($funcbacktrace['function']) && isset($backtrace[1])) {
860  if ($funcbacktrace['function'] != 'eval') {
861  if ($funcbacktrace['function'] == '__lambda_func') {
862  $ret['function'] = 'create_function() code';
863  } else {
864  $ret['function'] = $funcbacktrace['function'];
865  }
866  }
867  }
868  if (isset($funcbacktrace['class']) && isset($backtrace[1])) {
869  $ret['class'] = $funcbacktrace['class'];
870  }
871  return $ret;
872  }
873  return false;
874  }
875 
903  public static function getErrorMessage(&$stack, $err, $template = false)
904  {
905  if ($template) {
906  $mainmsg = $template;
907  } else {
908  $mainmsg = $stack->getErrorMessageTemplate($err['code']);
909  }
910  $mainmsg = str_replace('%__msg%', $err['message'], $mainmsg);
911  if (is_array($err['params']) && count($err['params'])) {
912  foreach ($err['params'] as $name => $val) {
913  if (is_array($val)) {
914  // @ is needed in case $val is a multi-dimensional array
915  $val = @implode(', ', $val);
916  }
917  if (is_object($val)) {
918  if (method_exists($val, '__toString')) {
919  $val = $val->__toString();
920  } else {
921  PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_OBJTOSTRING,
922  'warning', array('obj' => get_class($val)),
923  'object %obj% passed into getErrorMessage, but has no __toString() method');
924  $val = 'Object';
925  }
926  }
927  $mainmsg = str_replace('%' . $name . '%', $val, $mainmsg);
928  }
929  }
930  return $mainmsg;
931  }
932 
937  function getErrorMessageTemplate($code)
938  {
939  if (!isset($this->_errorMsgs[$code])) {
940  return '%__msg%';
941  }
942  return $this->_errorMsgs[$code];
943  }
944 
959  function setErrorMessageTemplate($template)
960  {
961  $this->_errorMsgs = $template;
962  }
963 
964 
970  function raiseError()
971  {
972  require_once 'PEAR.php';
973  $args = func_get_args();
974  return call_user_func_array(array('PEAR', 'raiseError'), $args);
975  }
976 }
977 $stack = &PEAR_ErrorStack::singleton('PEAR_ErrorStack');
978 $stack->pushCallback(array('PEAR_ErrorStack', '_handleError'));
979 ?>
PEAR_ErrorStack\setLogger
setLogger(&$log)
Definition: ErrorStack.php:340
PEAR_ErrorStack\getMessageCallback
getMessageCallback()
Definition: ErrorStack.php:374
PEAR_ErrorStack\$_package
$_package
Definition: ErrorStack.php:176
PEAR_ErrorStack\$_compat
$_compat
Definition: ErrorStack.php:186
PEAR_ErrorStack\setDefaultLogger
static setDefaultLogger(&$log)
Definition: ErrorStack.php:327
PEAR_ErrorStack\popCallback
popCallback()
Definition: ErrorStack.php:443
PEAR_ErrorStack\_handleError
_handleError($err)
Definition: ErrorStack.php:309
PEAR_ErrorStack\$_contextCallback
$_contextCallback
Definition: ErrorStack.php:212
PEAR_ErrorStack\staticPush
static staticPush( $package, $code, $level='error', $params=array(), $msg=false, $repackage=false, $backtrace=false)
Definition: ErrorStack.php:630
PEAR_ErrorStack\push
push($code, $level='error', $params=array(), $msg=false, $repackage=false, $backtrace=false)
Definition: ErrorStack.php:520
PEAR_ErrorStack\_log
_log($err)
Definition: ErrorStack.php:651
PEAR_ErrorStack\staticPopCallback
static staticPopCallback()
Definition: ErrorStack.php:470
PEAR_ErrorStack\staticGetErrors
static staticGetErrors( $purge=false, $level=false, $merge=false, $sortfunc=array('PEAR_ErrorStack', '_sortErrors'))
Definition: ErrorStack.php:803
PEAR_ErrorStack\getErrorMessage
static getErrorMessage(&$stack, $err, $template=false)
Definition: ErrorStack.php:930
PEAR_ErrorStack\_sortErrors
static _sortErrors($a, $b)
Definition: ErrorStack.php:831
PEAR_ErrorStack
PEAR_ErrorStack\pop
pop()
Definition: ErrorStack.php:687
Seboettg\Collection\count
count()
Definition: ArrayListTrait.php:253
$GLOBALS
$GLOBALS['PHPUNIT_COVERAGE_DATA_DIRECTORY']
Definition: prependCoverageReport.php:17
PEAR_ErrorStack\setDefaultCallback
static setDefaultCallback($callback=false, $package=false)
Definition: ErrorStack.php:387
PEAR_ErrorStack\pushCallback
pushCallback($cb)
Definition: ErrorStack.php:433
PEAR_ErrorStack\singleton
static & singleton( $package, $msgCallback=false, $contextCallback=false, $throwPEAR_Error=false, $stackClass='PEAR_ErrorStack')
Definition: ErrorStack.php:281
PEAR_ErrorStack\setErrorMessageTemplate
setErrorMessageTemplate($template)
Definition: ErrorStack.php:986
PEAR_ErrorStack\__construct
__construct($package, $msgCallback=false, $contextCallback=false, $throwPEAR_Error=false)
Definition: ErrorStack.php:258
PEAR_ErrorStack\$_errorsByLevel
$_errorsByLevel
Definition: ErrorStack.php:166
PEAR_ErrorStack\$_msgCallback
$_msgCallback
Definition: ErrorStack.php:198
PEAR_ErrorStack\getErrors
getErrors($purge=false, $level=false)
Definition: ErrorStack.php:737
PEAR_ErrorStack\hasErrors
hasErrors($level=false)
Definition: ErrorStack.php:722
PEAR_ErrorStack\setMessageCallback
setMessageCallback($msgCallback)
Definition: ErrorStack.php:356
PEAR_ErrorStack\$_logger
$_logger
Definition: ErrorStack.php:237
PEAR_ErrorStack\staticPushCallback
static staticPushCallback($cb)
Definition: ErrorStack.php:460
PEAR_ErrorStack\$_errors
$_errors
Definition: ErrorStack.php:153
PEAR_ErrorStack\getErrorMessageTemplate
getErrorMessageTemplate($code)
Definition: ErrorStack.php:964
PEAR_ErrorStack\getFileLine
static getFileLine($code, $params, $backtrace=null)
Definition: ErrorStack.php:855
PEAR_ErrorStack\$_errorMsgs
$_errorMsgs
Definition: ErrorStack.php:247
PEAR_ErrorStack\staticHasErrors
static staticHasErrors($package=false, $level=false)
Definition: ErrorStack.php:776
PEAR_ErrorStack\raiseError
raiseError()
Definition: ErrorStack.php:997
PEAR_ErrorStack\staticPop
static staticPop($package)
Definition: ErrorStack.php:706
PEAR_ErrorStack\$_errorCallback
$_errorCallback
Definition: ErrorStack.php:227
PEAR_ErrorStack\setContextCallback
setContextCallback($contextCallback)
Definition: ErrorStack.php:404