]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/pear/PEAR.php
Include (and use) latest PEAR DB code from the PEAR CVS repository.
[SourceForge/phpwiki.git] / lib / pear / PEAR.php
1 <?php
2 //
3 // +----------------------------------------------------------------------+
4 // | PHP Version 4                                                        |
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>                             |
19 // |                                                                      |
20 // +----------------------------------------------------------------------+
21 //
22 // Based on code from the PHP CVS repository.  The only modifications made
23 // have been modification of the include paths.
24 //
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');
27 //
28
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);
34
35 if (substr(PHP_OS, 0, 3) == 'WIN') {
36     define('OS_WINDOWS', true);
37     define('OS_UNIX',    false);
38     define('PEAR_OS',    'Windows');
39 } else {
40     define('OS_WINDOWS', false);
41     define('OS_UNIX',    true);
42     define('PEAR_OS',    'Unix'); // blatant assumption
43 }
44
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();
49
50 //
51 // Tests needed: - PEAR inheritance
52 //
53
54 /**
55  * Base class for other PEAR classes.  Provides rudimentary
56  * emulation of destructors.
57  *
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.
67  *
68  * @since PHP 4.0.2
69  * @author Stig Bakken <ssb@fast.no>
70  */
71 class PEAR
72 {
73     // {{{ properties
74
75     /**
76      * Whether to enable internal debug messages.
77      *
78      * @var     bool
79      * @access  private
80      */
81     var $_debug = false;
82
83     /**
84      * Default error mode for this object.
85      *
86      * @var     int
87      * @access  private
88      */
89     var $_default_error_mode = null;
90
91     /**
92      * Default error options used for this object when error mode
93      * is PEAR_ERROR_TRIGGER.
94      *
95      * @var     int
96      * @access  private
97      */
98     var $_default_error_options = null;
99
100     /**
101      * Default error handler (callback) for this object, if error mode is
102      * PEAR_ERROR_CALLBACK.
103      *
104      * @var     string
105      * @access  private
106      */
107     var $_default_error_handler = '';
108
109     /**
110      * Which class to use for error objects.
111      *
112      * @var     string
113      * @access  private
114      */
115     var $_error_class = 'PEAR_Error';
116
117     /**
118      * An array of expected errors.
119      *
120      * @var     array
121      * @access  private
122      */
123     var $_expected_errors = array();
124
125     // }}}
126
127     // {{{ constructor
128
129     /**
130      * Constructor.  Registers this object in
131      * $_PEAR_destructor_object_list for destructor emulation if a
132      * destructor object exists.
133      *
134      * @param string      (optional) which class to use for error objects,
135      *                    defaults to PEAR_Error.
136      * @access public
137      * @return void
138      */
139     function PEAR($error_class = null)
140     {
141         $classname = get_class($this);
142         if ($this->_debug) {
143             print "PEAR constructor called, class=$classname\n";
144         }
145         if ($error_class !== null) {
146             $this->_error_class = $error_class;
147         }
148         while ($classname) {
149             $destructor = "_$classname";
150             if (method_exists($this, $destructor)) {
151                 global $_PEAR_destructor_object_list;
152                 $_PEAR_destructor_object_list[] = &$this;
153                 break;
154             } else {
155                 $classname = get_parent_class($classname);
156             }
157         }
158     }
159
160     // }}}
161     // {{{ destructor
162
163     /**
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.
167      *
168      * See the note in the class desciption about output from
169      * destructors.
170      *
171      * @access public
172      * @return void
173      */
174     function _PEAR() {
175         if ($this->_debug) {
176             printf("PEAR destructor called, class=%s\n", get_class($this));
177         }
178     }
179
180     // }}}
181     // {{{ isError()
182
183     /**
184      * Tell whether a value is a PEAR error.
185      *
186      * @param   mixed   the value to test
187      * @access  public
188      * @return  bool    true if parameter is an error
189      */
190     function isError($data) {
191         return (bool)(is_object($data) &&
192                       (get_class($data) == 'pear_error' ||
193                       is_subclass_of($data, 'pear_error')));
194     }
195
196     // }}}
197     // {{{ setErrorHandling()
198
199     /**
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.
205      *
206      * @param int $mode
207      *        One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
208      *        PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE or
209      *        PEAR_ERROR_CALLBACK.
210      *
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).
214      *
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.
221      *
222      *        When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is
223      *        a printf format string used when printing the error
224      *        message.
225      *
226      * @access public
227      * @return void
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
233      *
234      * @since PHP 4.0.5
235      */
236
237     function setErrorHandling($mode = null, $options = null)
238     {
239         if (isset($this)) {
240             $setmode     = &$this->_default_error_mode;
241             $setoptions  = &$this->_default_error_options;
242             //$setcallback = &$this->_default_error_callback;
243         } else {
244             $setmode     = &$GLOBALS['_PEAR_default_error_mode'];
245             $setoptions  = &$GLOBALS['_PEAR_default_error_options'];
246             //$setcallback = &$GLOBALS['_PEAR_default_error_callback'];
247         }
248
249         switch ($mode) {
250             case PEAR_ERROR_RETURN:
251             case PEAR_ERROR_PRINT:
252             case PEAR_ERROR_TRIGGER:
253             case PEAR_ERROR_DIE:
254             case null:
255                 $setmode = $mode;
256                 $setoptions = $options;
257                 break;
258
259             case PEAR_ERROR_CALLBACK:
260                 $setmode = $mode;
261                 if ((is_string($options) && function_exists($options)) ||
262                     (is_array($options) && method_exists(@$options[0], @$options[1])))
263                 {
264                     $setoptions = $options;
265                 } else {
266                     trigger_error("invalid error callback", E_USER_WARNING);
267                 }
268                 break;
269
270             default:
271                 trigger_error("invalid error mode", E_USER_WARNING);
272                 break;
273         }
274     }
275
276     // }}}
277     // {{{ expectError()
278
279     /**
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.
286      *
287      * @param mixed    a single error code or an array of error codes
288      *                 to expect
289      *
290      * @return int     the new depth of the "expected errors" stack
291      */
292     function expectError($code = "*")
293     {
294         if (is_array($code)) {
295             array_push($this->_expected_errors, $code);
296         } else {
297             array_push($this->_expected_errors, array($code));
298         }
299         return sizeof($this->_expected_errors);
300     }
301
302     // }}}
303     // {{{ popExpect()
304
305     /**
306      * This method pops one element off the expected error codes
307      * stack.
308      *
309      * @return array   the list of error codes that were popped
310      */
311     function popExpect()
312     {
313         return array_pop($this->_expected_errors);
314     }
315
316     // }}}
317     // {{{ raiseError()
318
319     /**
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.
324      *
325      * @param $message  a text error message or a PEAR error object
326      *
327      * @param $code     a numeric error code (it is up to your class
328      *                  to define these if you want to use codes)
329      *
330      * @param $mode     One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
331      *                  PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE or
332      *                  PEAR_ERROR_CALLBACK.
333      *
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
340      *                  is ignored.
341      *
342      * @param $userinfo If you need to pass along for example debug
343      *                  information, this parameter is meant for that.
344      *
345      * @param $error_class The returned error object will be instantiated
346      *                  from this class, if specified.
347      *
348      * @param $skipmsg  If true, raiseError will only pass error codes,
349      *                  the error message parameter will be dropped.
350      *
351      * @access public
352      * @return object   a PEAR error object
353      * @see PEAR::setErrorHandling
354      * @since PHP 4.0.5
355      */
356     function &raiseError($message = null,
357                          $code = null,
358                          $mode = null,
359                          $options = null,
360                          $userinfo = null,
361                          $error_class = null,
362                          $skipmsg = false)
363     {
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();
370         }
371
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;
377             }
378         }
379
380         if ($mode === null) {
381             if (isset($this) && isset($this->_default_error_mode)) {
382                 $mode = $this->_default_error_mode;
383             } else {
384                 $mode = $GLOBALS['_PEAR_default_error_mode'];
385             }
386         }
387
388         if ($mode == PEAR_ERROR_TRIGGER && $options === null) {
389             if (isset($this)) {
390                 if (isset($this->_default_error_options)) {
391                     $options = $this->_default_error_options;
392                 }
393             } else {
394                 $options = $GLOBALS['_PEAR_default_error_options'];
395             }
396         }
397
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])))
402             {
403                 if (isset($this) && isset($this->_default_error_options)) {
404                     $options = $this->_default_error_options;
405                 } else {
406                     $options = $GLOBALS['_PEAR_default_error_options'];
407                 }
408             }
409         } else {
410             if ($options === null) {
411                 if (isset($this)) {
412                     if (isset($this->_default_error_options)) {
413                         $options = $this->_default_error_options;
414                     }
415                 } else {
416                     $options = $GLOBALS['_PEAR_default_error_options'];
417                 }
418             }
419         }
420         if ($error_class !== null) {
421             $ec = $error_class;
422         } elseif (isset($this) && isset($this->_error_class)) {
423             $ec = $this->_error_class;
424         } else {
425             $ec = 'PEAR_Error';
426         }
427         if ($skipmsg) {
428             return new $ec($code, $mode, $options, $userinfo);
429         } else {
430             return new $ec($message, $code, $mode, $options, $userinfo);
431         }
432     }
433
434     // }}}
435     // {{{ pushErrorHandling()
436
437     /**
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.
441     *
442     * @param $mode mixed (same as setErrorHandling)
443     * @param $options mixed (same as setErrorHandling)
444     *
445     * @return bool Always true
446     *
447     * @see PEAR::setErrorHandling
448     */
449     function pushErrorHandling($mode, $options = null)
450     {
451         $stack = &$GLOBALS['_PEAR_error_handler_stack'];
452         if (!is_array($stack)) {
453             if (isset($this)) {
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;
458             } else {
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'];
463             }
464             $stack = array();
465             $stack[] = array($def_mode, $def_options);
466         }
467
468         if (isset($this)) {
469             $this->setErrorHandling($mode, $options);
470         } else {
471             PEAR::setErrorHandling($mode, $options);
472         }
473         $stack[] = array($mode, $options);
474         return true;
475     }
476
477     // }}}
478     // {{{ popErrorHandling()
479
480     /**
481     * Pop the last error handler used
482     *
483     * @return bool Always true
484     *
485     * @see PEAR::pushErrorHandling
486     */
487     function popErrorHandling()
488     {
489         $stack = &$GLOBALS['_PEAR_error_handler_stack'];
490         array_pop($stack);
491         list($mode, $options) = $stack[sizeof($stack) - 1];
492         if (isset($this)) {
493             $this->setErrorHandling($mode, $options);
494         } else {
495             PEAR::setErrorHandling($mode, $options);
496         }
497         return true;
498     }
499
500     // }}}
501 }
502
503 // {{{ _PEAR_call_destructors()
504
505 function _PEAR_call_destructors()
506 {
507     global $_PEAR_destructor_object_list;
508     if (is_array($_PEAR_destructor_object_list) &&
509         sizeof($_PEAR_destructor_object_list))
510     {
511         reset($_PEAR_destructor_object_list);
512         while (list($k, $objref) = each($_PEAR_destructor_object_list)) {
513             $classname = get_class($objref);
514             while ($classname) {
515                 $destructor = "_$classname";
516                 if (method_exists($objref, $destructor)) {
517                     $objref->$destructor();
518                     break;
519                 } else {
520                     $classname = get_parent_class($classname);
521                 }
522             }
523         }
524         // Empty the object list to ensure that destructors are
525         // not called more than once.
526         $_PEAR_destructor_object_list = array();
527     }
528 }
529
530 // }}}
531
532 class PEAR_Error
533 {
534     // {{{ properties
535
536     var $error_message_prefix = '';
537     var $mode                 = PEAR_ERROR_RETURN;
538     var $level                = E_USER_NOTICE;
539     var $code                 = -1;
540     var $message              = '';
541     var $userinfo             = '';
542
543     // Wait until we have a stack-groping function in PHP.
544     //var $file    = '';
545     //var $line    = 0;
546
547
548     // }}}
549     // {{{ constructor
550
551     /**
552      * PEAR_Error constructor
553      *
554      * @param $message error message
555      *
556      * @param $code (optional) error code
557      *
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
561      *
562      * @param $level (optional) error level, _OR_ in the case of
563      * PEAR_ERROR_CALLBACK, the callback function or object/method
564      * tuple.
565      *
566      * @access public
567      *
568      */
569     function PEAR_Error($message = 'unknown error', $code = null,
570                         $mode = null, $options = null, $userinfo = null)
571     {
572         if ($mode === null) {
573             $mode = PEAR_ERROR_RETURN;
574         }
575         $this->message   = $message;
576         $this->code      = $code;
577         $this->mode      = $mode;
578         $this->userinfo  = $userinfo;
579         if ($mode & PEAR_ERROR_CALLBACK) {
580             $this->level = E_USER_NOTICE;
581             $this->callback = $options;
582         } else {
583             if ($options === null) {
584                 $options = E_USER_NOTICE;
585             }
586             $this->level = $options;
587             $this->callback = null;
588         }
589         if ($this->mode & PEAR_ERROR_PRINT) {
590             if (is_null($options) || is_int($options)) {
591                 $format = "%s";
592             } else {
593                 $format = $options;
594             }
595             printf($format, $this->getMessage());
596         }
597         if ($this->mode & PEAR_ERROR_TRIGGER) {
598             trigger_error($this->getMessage(), $this->level);
599         }
600         if ($this->mode & PEAR_ERROR_DIE) {
601             $msg = $this->getMessage();
602             if (is_null($options) || is_int($options)) {
603                 $format = "%s";
604                 if (substr($msg, -1) != "\n") {
605                     $msg .= "\n";
606                 }
607             } else {
608                 $format = $options;
609             }
610             die(sprintf($format, $msg));
611         }
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],
621                                  $this);
622             }
623         }
624     }
625
626     // }}}
627     // {{{ getMode()
628
629     /**
630      * Get the error mode from an error object.
631      *
632      * @return int error mode
633      * @access public
634      */
635     function getMode() {
636         return $this->mode;
637     }
638
639     // }}}
640     // {{{ getCallback()
641
642     /**
643      * Get the callback function/method from an error object.
644      *
645      * @return mixed callback function or object/method array
646      * @access public
647      */
648     function getCallback() {
649         return $this->callback;
650     }
651
652     // }}}
653     // {{{ getMessage()
654
655
656     /**
657      * Get the error message from an error object.
658      *
659      * @return  string  full error message
660      * @access public
661      */
662     function getMessage ()
663     {
664         return ($this->error_message_prefix . $this->message);
665     }
666
667
668     // }}}
669     // {{{ getCode()
670
671     /**
672      * Get error code from an error object
673      *
674      * @return int error code
675      * @access public
676      */
677      function getCode()
678      {
679         return $this->code;
680      }
681
682     // }}}
683     // {{{ getType()
684
685     /**
686      * Get the name of this error/exception.
687      *
688      * @return string error/exception name (type)
689      * @access public
690      */
691     function getType ()
692     {
693         return get_class($this);
694     }
695
696     // }}}
697     // {{{ getUserInfo()
698
699     /**
700      * Get additional user-supplied information.
701      *
702      * @return string user-supplied information
703      * @access public
704      */
705     function getUserInfo ()
706     {
707         return $this->userinfo;
708     }
709
710     // }}}
711     // {{{ getDebugInfo()
712
713     /**
714      * Get additional debug information supplied by the application.
715      *
716      * @return string debug information
717      * @access public
718      */
719     function getDebugInfo ()
720     {
721         return $this->getUserInfo();
722     }
723
724     // }}}
725     // {{{ addUserInfo()
726
727     function addUserInfo($info)
728     {
729         if (empty($this->userinfo)) {
730             $this->userinfo = $info;
731         } else {
732             $this->userinfo .= " ** $info";
733         }
734     }
735
736     // }}}
737     // {{{ toString()
738
739     /**
740      * Make a string representation of this object.
741      *
742      * @return string a string with an object summary
743      * @access public
744      */
745     function toString() {
746         $modes = array();
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]) . '::' .
753                     $this->callback[1];
754             } else {
755                 $callback = $this->callback;
756             }
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,
761                            $this->userinfo);
762         }
763         if ($this->mode & PEAR_ERROR_CALLBACK) {
764             $modes[] = 'callback';
765         }
766         if ($this->mode & PEAR_ERROR_PRINT) {
767             $modes[] = 'print';
768         }
769         if ($this->mode & PEAR_ERROR_TRIGGER) {
770             $modes[] = 'trigger';
771         }
772         if ($this->mode & PEAR_ERROR_DIE) {
773             $modes[] = 'die';
774         }
775         if ($this->mode & PEAR_ERROR_RETURN) {
776             $modes[] = 'return';
777         }
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,
783                        $this->userinfo);
784     }
785
786     // }}}
787 }
788
789 register_shutdown_function("_PEAR_call_destructors");
790
791 /*
792  * Local Variables:
793  * mode: php
794  * tab-width: 4
795  * c-basic-offset: 4
796  * End:
797  */
798 ?>