3 // +----------------------------------------------------------------------+
5 // +----------------------------------------------------------------------+
6 // | Copyright (c) 1997-2002 The PHP Group |
7 // +----------------------------------------------------------------------+
8 // | This source file is subject to version 2.0 of the PHP license, |
9 // | that is bundled with this package in the file LICENSE, and is |
10 // | available at through the world-wide-web at |
11 // | http://www.php.net/license/2_02.txt. |
12 // | If you did not receive a copy of the PHP license and are unable to |
13 // | obtain it through the world-wide-web, please send a note to |
14 // | license@php.net so we can mail you a copy immediately. |
15 // +----------------------------------------------------------------------+
16 // | Authors: Sterling Hughes <sterling@php.net> |
17 // | Stig Bakken <ssb@fast.no> |
18 // | Tomas V.V.Cox <cox@idecnet.com> |
20 // +----------------------------------------------------------------------+
22 // Based on code from the PHP CVS repository. The only modifications made
23 // have been modification of the include paths.
25 rcs_id('$Id: PEAR.php,v 1.1 2002-01-28 04:01:56 dairiki Exp $');
26 rcs_id('From Pear CVS: Id: PEAR.php,v 1.29 2001/12/15 15:01:35 mj Exp');
29 define('PEAR_ERROR_RETURN', 1);
30 define('PEAR_ERROR_PRINT', 2);
31 define('PEAR_ERROR_TRIGGER', 4);
32 define('PEAR_ERROR_DIE', 8);
33 define('PEAR_ERROR_CALLBACK', 16);
35 if (substr(PHP_OS, 0, 3) == 'WIN') {
36 define('OS_WINDOWS', true);
37 define('OS_UNIX', false);
38 define('PEAR_OS', 'Windows');
40 define('OS_WINDOWS', false);
41 define('OS_UNIX', true);
42 define('PEAR_OS', 'Unix'); // blatant assumption
45 $GLOBALS['_PEAR_default_error_mode'] = PEAR_ERROR_RETURN;
46 $GLOBALS['_PEAR_default_error_options'] = E_USER_NOTICE;
47 $GLOBALS['_PEAR_default_error_callback'] = '';
48 $GLOBALS['_PEAR_destructor_object_list'] = array();
51 // Tests needed: - PEAR inheritance
55 * Base class for other PEAR classes. Provides rudimentary
56 * emulation of destructors.
58 * If you want a destructor in your class, inherit PEAR and make a
59 * destructor method called _yourclassname (same name as the
60 * constructor, but with a "_" prefix). Also, in your constructor you
61 * have to call the PEAR constructor: $this->PEAR();.
62 * The destructor method will be called without parameters. Note that
63 * at in some SAPI implementations (such as Apache), any output during
64 * the request shutdown (in which destructors are called) seems to be
65 * discarded. If you need to get any debug information from your
66 * destructor, use error_log(), syslog() or something similar.
69 * @author Stig Bakken <ssb@fast.no>
76 * Whether to enable internal debug messages.
84 * Default error mode for this object.
89 var $_default_error_mode = null;
92 * Default error options used for this object when error mode
93 * is PEAR_ERROR_TRIGGER.
98 var $_default_error_options = null;
101 * Default error handler (callback) for this object, if error mode is
102 * PEAR_ERROR_CALLBACK.
107 var $_default_error_handler = '';
110 * Which class to use for error objects.
115 var $_error_class = 'PEAR_Error';
118 * An array of expected errors.
123 var $_expected_errors = array();
130 * Constructor. Registers this object in
131 * $_PEAR_destructor_object_list for destructor emulation if a
132 * destructor object exists.
134 * @param string (optional) which class to use for error objects,
135 * defaults to PEAR_Error.
139 function PEAR($error_class = null)
141 $classname = get_class($this);
143 print "PEAR constructor called, class=$classname\n";
145 if ($error_class !== null) {
146 $this->_error_class = $error_class;
149 $destructor = "_$classname";
150 if (method_exists($this, $destructor)) {
151 global $_PEAR_destructor_object_list;
152 $_PEAR_destructor_object_list[] = &$this;
155 $classname = get_parent_class($classname);
164 * Destructor (the emulated type of...). Does nothing right now,
165 * but is included for forward compatibility, so subclass
166 * destructors should always call it.
168 * See the note in the class desciption about output from
176 printf("PEAR destructor called, class=%s\n", get_class($this));
184 * Tell whether a value is a PEAR error.
186 * @param mixed the value to test
188 * @return bool true if parameter is an error
190 function isError($data) {
191 return (bool)(is_object($data) &&
192 (get_class($data) == 'pear_error' ||
193 is_subclass_of($data, 'pear_error')));
197 // {{{ setErrorHandling()
200 * Sets how errors generated by this DB object should be handled.
201 * Can be invoked both in objects and statically. If called
202 * statically, setErrorHandling sets the default behaviour for all
203 * PEAR objects. If called in an object, setErrorHandling sets
204 * the default behaviour for that object.
207 * One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
208 * PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE or
209 * PEAR_ERROR_CALLBACK.
211 * @param mixed $options
212 * When $mode is PEAR_ERROR_TRIGGER, this is the error level (one
213 * of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
215 * When $mode is PEAR_ERROR_CALLBACK, this parameter is expected
216 * to be the callback function or method. A callback
217 * function is a string with the name of the function, a
218 * callback method is an array of two elements: the element
219 * at index 0 is the object, and the element at index 1 is
220 * the name of the method to call in the object.
222 * When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is
223 * a printf format string used when printing the error
228 * @see PEAR_ERROR_RETURN
229 * @see PEAR_ERROR_PRINT
230 * @see PEAR_ERROR_TRIGGER
231 * @see PEAR_ERROR_DIE
232 * @see PEAR_ERROR_CALLBACK
237 function setErrorHandling($mode = null, $options = null)
240 $setmode = &$this->_default_error_mode;
241 $setoptions = &$this->_default_error_options;
242 //$setcallback = &$this->_default_error_callback;
244 $setmode = &$GLOBALS['_PEAR_default_error_mode'];
245 $setoptions = &$GLOBALS['_PEAR_default_error_options'];
246 //$setcallback = &$GLOBALS['_PEAR_default_error_callback'];
250 case PEAR_ERROR_RETURN:
251 case PEAR_ERROR_PRINT:
252 case PEAR_ERROR_TRIGGER:
256 $setoptions = $options;
259 case PEAR_ERROR_CALLBACK:
261 if ((is_string($options) && function_exists($options)) ||
262 (is_array($options) && method_exists(@$options[0], @$options[1])))
264 $setoptions = $options;
266 trigger_error("invalid error callback", E_USER_WARNING);
271 trigger_error("invalid error mode", E_USER_WARNING);
280 * This method is used to tell which errors you expect to get.
281 * Expected errors are always returned with error mode
282 * PEAR_ERROR_RETURN. Expected error codes are stored in a stack,
283 * and this method pushes a new element onto it. The list of
284 * expected errors are in effect until they are popped off the
285 * stack with the popExpect() method.
287 * @param mixed a single error code or an array of error codes
290 * @return int the new depth of the "expected errors" stack
292 function expectError($code = "*")
294 if (is_array($code)) {
295 array_push($this->_expected_errors, $code);
297 array_push($this->_expected_errors, array($code));
299 return sizeof($this->_expected_errors);
306 * This method pops one element off the expected error codes
309 * @return array the list of error codes that were popped
313 return array_pop($this->_expected_errors);
320 * This method is a wrapper that returns an instance of the
321 * configured error class with this object's default error
322 * handling applied. If the $mode and $options parameters are not
323 * specified, the object's defaults are used.
325 * @param $message a text error message or a PEAR error object
327 * @param $code a numeric error code (it is up to your class
328 * to define these if you want to use codes)
330 * @param $mode One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
331 * PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE or
332 * PEAR_ERROR_CALLBACK.
334 * @param $options If $mode is PEAR_ERROR_TRIGGER, this parameter
335 * specifies the PHP-internal error level (one of
336 * E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
337 * If $mode is PEAR_ERROR_CALLBACK, this
338 * parameter specifies the callback function or
339 * method. In other error modes this parameter
342 * @param $userinfo If you need to pass along for example debug
343 * information, this parameter is meant for that.
345 * @param $error_class The returned error object will be instantiated
346 * from this class, if specified.
348 * @param $skipmsg If true, raiseError will only pass error codes,
349 * the error message parameter will be dropped.
352 * @return object a PEAR error object
353 * @see PEAR::setErrorHandling
356 function &raiseError($message = null,
364 // The error is yet a PEAR error object
365 if (is_object($message)) {
366 $code = $message->getCode();
367 $userinfo = $message->getUserInfo();
368 $error_class = $message->getType();
369 $message = $message->getMessage();
372 if (isset($this) && isset($this->_expected_errors) && sizeof($this->_expected_errors) > 0 && sizeof($exp = end($this->_expected_errors))) {
373 if ($exp[0] == "*" ||
374 (is_int(reset($exp)) && in_array($code, $exp)) ||
375 (is_string(reset($exp)) && in_array($message, $exp))) {
376 $mode = PEAR_ERROR_RETURN;
380 if ($mode === null) {
381 if (isset($this) && isset($this->_default_error_mode)) {
382 $mode = $this->_default_error_mode;
384 $mode = $GLOBALS['_PEAR_default_error_mode'];
388 if ($mode == PEAR_ERROR_TRIGGER && $options === null) {
390 if (isset($this->_default_error_options)) {
391 $options = $this->_default_error_options;
394 $options = $GLOBALS['_PEAR_default_error_options'];
398 if ($mode == PEAR_ERROR_CALLBACK) {
399 if (!is_string($options) &&
400 !(is_array($options) && sizeof($options) == 2 &&
401 is_object($options[0]) && is_string($options[1])))
403 if (isset($this) && isset($this->_default_error_options)) {
404 $options = $this->_default_error_options;
406 $options = $GLOBALS['_PEAR_default_error_options'];
410 if ($options === null) {
412 if (isset($this->_default_error_options)) {
413 $options = $this->_default_error_options;
416 $options = $GLOBALS['_PEAR_default_error_options'];
420 if ($error_class !== null) {
422 } elseif (isset($this) && isset($this->_error_class)) {
423 $ec = $this->_error_class;
428 return new $ec($code, $mode, $options, $userinfo);
430 return new $ec($message, $code, $mode, $options, $userinfo);
435 // {{{ pushErrorHandling()
438 * Push a new error handler on top of the error handler options stack. With this
439 * you can easely override the actual error handler for some code and restore
440 * it later with popErrorHandling.
442 * @param $mode mixed (same as setErrorHandling)
443 * @param $options mixed (same as setErrorHandling)
445 * @return bool Always true
447 * @see PEAR::setErrorHandling
449 function pushErrorHandling($mode, $options = null)
451 $stack = &$GLOBALS['_PEAR_error_handler_stack'];
452 if (!is_array($stack)) {
454 $def_mode = &$this->_default_error_mode;
455 $def_options = &$this->_default_error_options;
456 // XXX Used anywhere?
457 //$def_callback = &$this->_default_error_callback;
459 $def_mode = &$GLOBALS['_PEAR_default_error_mode'];
460 $def_options = &$GLOBALS['_PEAR_default_error_options'];
461 // XXX Used anywhere?
462 //$def_callback = &$GLOBALS['_PEAR_default_error_callback'];
465 $stack[] = array($def_mode, $def_options);
469 $this->setErrorHandling($mode, $options);
471 PEAR::setErrorHandling($mode, $options);
473 $stack[] = array($mode, $options);
478 // {{{ popErrorHandling()
481 * Pop the last error handler used
483 * @return bool Always true
485 * @see PEAR::pushErrorHandling
487 function popErrorHandling()
489 $stack = &$GLOBALS['_PEAR_error_handler_stack'];
491 list($mode, $options) = $stack[sizeof($stack) - 1];
493 $this->setErrorHandling($mode, $options);
495 PEAR::setErrorHandling($mode, $options);
503 // {{{ _PEAR_call_destructors()
505 function _PEAR_call_destructors()
507 global $_PEAR_destructor_object_list;
508 if (is_array($_PEAR_destructor_object_list) &&
509 sizeof($_PEAR_destructor_object_list))
511 reset($_PEAR_destructor_object_list);
512 while (list($k, $objref) = each($_PEAR_destructor_object_list)) {
513 $classname = get_class($objref);
515 $destructor = "_$classname";
516 if (method_exists($objref, $destructor)) {
517 $objref->$destructor();
520 $classname = get_parent_class($classname);
524 // Empty the object list to ensure that destructors are
525 // not called more than once.
526 $_PEAR_destructor_object_list = array();
536 var $error_message_prefix = '';
537 var $mode = PEAR_ERROR_RETURN;
538 var $level = E_USER_NOTICE;
543 // Wait until we have a stack-groping function in PHP.
552 * PEAR_Error constructor
554 * @param $message error message
556 * @param $code (optional) error code
558 * @param $mode (optional) error mode, one of: PEAR_ERROR_RETURN,
559 * PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER or
560 * PEAR_ERROR_CALLBACK
562 * @param $level (optional) error level, _OR_ in the case of
563 * PEAR_ERROR_CALLBACK, the callback function or object/method
569 function PEAR_Error($message = 'unknown error', $code = null,
570 $mode = null, $options = null, $userinfo = null)
572 if ($mode === null) {
573 $mode = PEAR_ERROR_RETURN;
575 $this->message = $message;
578 $this->userinfo = $userinfo;
579 if ($mode & PEAR_ERROR_CALLBACK) {
580 $this->level = E_USER_NOTICE;
581 $this->callback = $options;
583 if ($options === null) {
584 $options = E_USER_NOTICE;
586 $this->level = $options;
587 $this->callback = null;
589 if ($this->mode & PEAR_ERROR_PRINT) {
590 if (is_null($options) || is_int($options)) {
595 printf($format, $this->getMessage());
597 if ($this->mode & PEAR_ERROR_TRIGGER) {
598 trigger_error($this->getMessage(), $this->level);
600 if ($this->mode & PEAR_ERROR_DIE) {
601 $msg = $this->getMessage();
602 if (is_null($options) || is_int($options)) {
604 if (substr($msg, -1) != "\n") {
610 die(sprintf($format, $msg));
612 if ($this->mode & PEAR_ERROR_CALLBACK) {
613 if (is_string($this->callback) && strlen($this->callback)) {
614 call_user_func($this->callback, $this);
615 } elseif (is_array($this->callback) &&
616 sizeof($this->callback) == 2 &&
617 is_object($this->callback[0]) &&
618 is_string($this->callback[1]) &&
619 strlen($this->callback[1])) {
620 @call_user_method($this->callback[1], $this->callback[0],
630 * Get the error mode from an error object.
632 * @return int error mode
643 * Get the callback function/method from an error object.
645 * @return mixed callback function or object/method array
648 function getCallback() {
649 return $this->callback;
657 * Get the error message from an error object.
659 * @return string full error message
662 function getMessage ()
664 return ($this->error_message_prefix . $this->message);
672 * Get error code from an error object
674 * @return int error code
686 * Get the name of this error/exception.
688 * @return string error/exception name (type)
693 return get_class($this);
700 * Get additional user-supplied information.
702 * @return string user-supplied information
705 function getUserInfo ()
707 return $this->userinfo;
711 // {{{ getDebugInfo()
714 * Get additional debug information supplied by the application.
716 * @return string debug information
719 function getDebugInfo ()
721 return $this->getUserInfo();
727 function addUserInfo($info)
729 if (empty($this->userinfo)) {
730 $this->userinfo = $info;
732 $this->userinfo .= " ** $info";
740 * Make a string representation of this object.
742 * @return string a string with an object summary
745 function toString() {
747 $levels = array(E_USER_NOTICE => 'notice',
748 E_USER_WARNING => 'warning',
749 E_USER_ERROR => 'error');
750 if ($this->mode & PEAR_ERROR_CALLBACK) {
751 if (is_array($this->callback)) {
752 $callback = get_class($this->callback[0]) . '::' .
755 $callback = $this->callback;
757 return sprintf('[%s: message="%s" code=%d mode=callback '.
758 'callback=%s prefix="%s" info="%s"]',
759 get_class($this), $this->message, $this->code,
760 $callback, $this->error_message_prefix,
763 if ($this->mode & PEAR_ERROR_CALLBACK) {
764 $modes[] = 'callback';
766 if ($this->mode & PEAR_ERROR_PRINT) {
769 if ($this->mode & PEAR_ERROR_TRIGGER) {
770 $modes[] = 'trigger';
772 if ($this->mode & PEAR_ERROR_DIE) {
775 if ($this->mode & PEAR_ERROR_RETURN) {
778 return sprintf('[%s: message="%s" code=%d mode=%s level=%s '.
779 'prefix="%s" info="%s"]',
780 get_class($this), $this->message, $this->code,
781 implode("|", $modes), $levels[$this->level],
782 $this->error_message_prefix,
789 register_shutdown_function("_PEAR_call_destructors");