Bearsampp 2026.9.23
Loading...
Searching...
No Matches
ErrorStack.php
Go to the documentation of this file.
1<?php
28
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
91define('PEAR_ERRORSTACK_PUSHANDLOG', 1);
96define('PEAR_ERRORSTACK_PUSH', 2);
101define('PEAR_ERRORSTACK_LOG', 3);
105define('PEAR_ERRORSTACK_IGNORE', 4);
109define('PEAR_ERRORSTACK_DIE', 5);
111
116define('PEAR_ERRORSTACK_ERR_NONCLASS', 1);
117
122define('PEAR_ERRORSTACK_ERR_OBJTOSTRING', 2);
150 var $_errors = array();
151
160 var $_errorsByLevel = array();
161
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 }
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
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)){
550 return $err;
551 break;
553 $log = false;
554 break;
556 $push = false;
557 break;
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 {
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
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?>
const PEAR_ERRORSTACK_ERR_NONCLASS
$stack
const PEAR_ERRORSTACK_DIE
const PEAR_ERRORSTACK_LOG
const PEAR_ERRORSTACK_ERR_OBJTOSTRING
const PEAR_ERRORSTACK_PUSH
$GLOBALS['_PEAR_ERRORSTACK_SINGLETON']
const PEAR_ERRORSTACK_IGNORE
$GLOBALS['_PEAR_default_error_mode']
Definition PEAR.php:46
__construct($package, $msgCallback=false, $contextCallback=false, $throwPEAR_Error=false)
static staticPop($package)
getErrorMessageTemplate($code)
static staticHasErrors($package=false, $level=false)
setErrorMessageTemplate($template)
setMessageCallback($msgCallback)
static _sortErrors($a, $b)
static staticPush( $package, $code, $level='error', $params=array(), $msg=false, $repackage=false, $backtrace=false)
setContextCallback($contextCallback)
static & singleton( $package, $msgCallback=false, $contextCallback=false, $throwPEAR_Error=false, $stackClass='PEAR_ErrorStack')
static setDefaultLogger(&$log)
static staticGetErrors( $purge=false, $level=false, $merge=false, $sortfunc=array('PEAR_ErrorStack', '_sortErrors'))
getErrors($purge=false, $level=false)
hasErrors($level=false)
static staticPopCallback()
static getFileLine($code, $params, $backtrace=null)
push($code, $level='error', $params=array(), $msg=false, $repackage=false, $backtrace=false)
static staticPushCallback($cb)
static setDefaultCallback($callback=false, $package=false)
static getErrorMessage(&$stack, $err, $template=false)