source: github/program/lib/PEAR.php @ 8c124b9

HEADcourier-fixdev-browser-capabilitiespdorelease-0.7release-0.8
Last change on this file since 8c124b9 was 8c124b9, checked in by alecpl <alec@…>, 20 months ago
  • Fix is_a() usage
  • Property mode set to 100644
File size: 33.8 KB
Line 
1<?php
2/**
3 * PEAR, the PHP Extension and Application Repository
4 *
5 * PEAR class and PEAR_Error class
6 *
7 * PHP versions 4 and 5
8 *
9 * @category   pear
10 * @package    PEAR
11 * @author     Sterling Hughes <sterling@php.net>
12 * @author     Stig Bakken <ssb@php.net>
13 * @author     Tomas V.V.Cox <cox@idecnet.com>
14 * @author     Greg Beaver <cellog@php.net>
15 * @copyright  1997-2009 The Authors
16 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
17 * @version    CVS: $Id$
18 * @link       http://pear.php.net/package/PEAR
19 * @since      File available since Release 0.1
20 */
21
22/**#@+
23 * ERROR constants
24 */
25define('PEAR_ERROR_RETURN',     1);
26define('PEAR_ERROR_PRINT',      2);
27define('PEAR_ERROR_TRIGGER',    4);
28define('PEAR_ERROR_DIE',        8);
29define('PEAR_ERROR_CALLBACK',  16);
30/**
31 * WARNING: obsolete
32 * @deprecated
33 */
34define('PEAR_ERROR_EXCEPTION', 32);
35/**#@-*/
36define('PEAR_ZE2', (function_exists('version_compare') &&
37                    version_compare(zend_version(), "2-dev", "ge")));
38
39if (substr(PHP_OS, 0, 3) == 'WIN') {
40    define('OS_WINDOWS', true);
41    define('OS_UNIX',    false);
42    define('PEAR_OS',    'Windows');
43} else {
44    define('OS_WINDOWS', false);
45    define('OS_UNIX',    true);
46    define('PEAR_OS',    'Unix'); // blatant assumption
47}
48
49$GLOBALS['_PEAR_default_error_mode']     = PEAR_ERROR_RETURN;
50$GLOBALS['_PEAR_default_error_options']  = E_USER_NOTICE;
51$GLOBALS['_PEAR_destructor_object_list'] = array();
52$GLOBALS['_PEAR_shutdown_funcs']         = array();
53$GLOBALS['_PEAR_error_handler_stack']    = array();
54
55@ini_set('track_errors', true);
56
57/**
58 * Base class for other PEAR classes.  Provides rudimentary
59 * emulation of destructors.
60 *
61 * If you want a destructor in your class, inherit PEAR and make a
62 * destructor method called _yourclassname (same name as the
63 * constructor, but with a "_" prefix).  Also, in your constructor you
64 * have to call the PEAR constructor: $this->PEAR();.
65 * The destructor method will be called without parameters.  Note that
66 * at in some SAPI implementations (such as Apache), any output during
67 * the request shutdown (in which destructors are called) seems to be
68 * discarded.  If you need to get any debug information from your
69 * destructor, use error_log(), syslog() or something similar.
70 *
71 * IMPORTANT! To use the emulated destructors you need to create the
72 * objects by reference: $obj =& new PEAR_child;
73 *
74 * @category   pear
75 * @package    PEAR
76 * @author     Stig Bakken <ssb@php.net>
77 * @author     Tomas V.V. Cox <cox@idecnet.com>
78 * @author     Greg Beaver <cellog@php.net>
79 * @copyright  1997-2006 The PHP Group
80 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
81 * @version    Release: 1.9.0
82 * @link       http://pear.php.net/package/PEAR
83 * @see        PEAR_Error
84 * @since      Class available since PHP 4.0.2
85 * @link        http://pear.php.net/manual/en/core.pear.php#core.pear.pear
86 */
87class PEAR
88{
89    // {{{ properties
90
91    /**
92     * Whether to enable internal debug messages.
93     *
94     * @var     bool
95     * @access  private
96     */
97    var $_debug = false;
98
99    /**
100     * Default error mode for this object.
101     *
102     * @var     int
103     * @access  private
104     */
105    var $_default_error_mode = null;
106
107    /**
108     * Default error options used for this object when error mode
109     * is PEAR_ERROR_TRIGGER.
110     *
111     * @var     int
112     * @access  private
113     */
114    var $_default_error_options = null;
115
116    /**
117     * Default error handler (callback) for this object, if error mode is
118     * PEAR_ERROR_CALLBACK.
119     *
120     * @var     string
121     * @access  private
122     */
123    var $_default_error_handler = '';
124
125    /**
126     * Which class to use for error objects.
127     *
128     * @var     string
129     * @access  private
130     */
131    var $_error_class = 'PEAR_Error';
132
133    /**
134     * An array of expected errors.
135     *
136     * @var     array
137     * @access  private
138     */
139    var $_expected_errors = array();
140
141    // }}}
142
143    // {{{ constructor
144
145    /**
146     * Constructor.  Registers this object in
147     * $_PEAR_destructor_object_list for destructor emulation if a
148     * destructor object exists.
149     *
150     * @param string $error_class  (optional) which class to use for
151     *        error objects, defaults to PEAR_Error.
152     * @access public
153     * @return void
154     */
155    function PEAR($error_class = null)
156    {
157        $classname = strtolower(get_class($this));
158        if ($this->_debug) {
159            print "PEAR constructor called, class=$classname\n";
160        }
161        if ($error_class !== null) {
162            $this->_error_class = $error_class;
163        }
164        while ($classname && strcasecmp($classname, "pear")) {
165            $destructor = "_$classname";
166            if (method_exists($this, $destructor)) {
167                global $_PEAR_destructor_object_list;
168                $_PEAR_destructor_object_list[] = &$this;
169                if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
170                    register_shutdown_function("_PEAR_call_destructors");
171                    $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
172                }
173                break;
174            } else {
175                $classname = get_parent_class($classname);
176            }
177        }
178    }
179
180    // }}}
181    // {{{ destructor
182
183    /**
184     * Destructor (the emulated type of...).  Does nothing right now,
185     * but is included for forward compatibility, so subclass
186     * destructors should always call it.
187     *
188     * See the note in the class desciption about output from
189     * destructors.
190     *
191     * @access public
192     * @return void
193     */
194    function _PEAR() {
195        if ($this->_debug) {
196            printf("PEAR destructor called, class=%s\n", strtolower(get_class($this)));
197        }
198    }
199
200    // }}}
201    // {{{ getStaticProperty()
202
203    /**
204    * If you have a class that's mostly/entirely static, and you need static
205    * properties, you can use this method to simulate them. Eg. in your method(s)
206    * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar');
207    * You MUST use a reference, or they will not persist!
208    *
209    * @access public
210    * @param  string $class  The calling classname, to prevent clashes
211    * @param  string $var    The variable to retrieve.
212    * @return mixed   A reference to the variable. If not set it will be
213    *                 auto initialised to NULL.
214    */
215    function &getStaticProperty($class, $var)
216    {
217        static $properties;
218        if (!isset($properties[$class])) {
219            $properties[$class] = array();
220        }
221
222        if (!array_key_exists($var, $properties[$class])) {
223            $properties[$class][$var] = null;
224        }
225
226        return $properties[$class][$var];
227    }
228
229    // }}}
230    // {{{ registerShutdownFunc()
231
232    /**
233    * Use this function to register a shutdown method for static
234    * classes.
235    *
236    * @access public
237    * @param  mixed $func  The function name (or array of class/method) to call
238    * @param  mixed $args  The arguments to pass to the function
239    * @return void
240    */
241    function registerShutdownFunc($func, $args = array())
242    {
243        // if we are called statically, there is a potential
244        // that no shutdown func is registered.  Bug #6445
245        if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
246            register_shutdown_function("_PEAR_call_destructors");
247            $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
248        }
249        $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args);
250    }
251
252    // }}}
253    // {{{ isError()
254
255    /**
256     * Tell whether a value is a PEAR error.
257     *
258     * @param   mixed $data   the value to test
259     * @param   int   $code   if $data is an error object, return true
260     *                        only if $code is a string and
261     *                        $obj->getMessage() == $code or
262     *                        $code is an integer and $obj->getCode() == $code
263     * @access  public
264     * @return  bool    true if parameter is an error
265     */
266    function isError($data, $code = null)
267    {
268        if (!is_object($data) || !is_a($data, 'PEAR_Error')) {
269            return false;
270        }
271
272        if (is_null($code)) {
273            return true;
274        } elseif (is_string($code)) {
275            return $data->getMessage() == $code;
276        }
277
278        return $data->getCode() == $code;
279    }
280
281    // }}}
282    // {{{ setErrorHandling()
283
284    /**
285     * Sets how errors generated by this object should be handled.
286     * Can be invoked both in objects and statically.  If called
287     * statically, setErrorHandling sets the default behaviour for all
288     * PEAR objects.  If called in an object, setErrorHandling sets
289     * the default behaviour for that object.
290     *
291     * @param int $mode
292     *        One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
293     *        PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
294     *        PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION.
295     *
296     * @param mixed $options
297     *        When $mode is PEAR_ERROR_TRIGGER, this is the error level (one
298     *        of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
299     *
300     *        When $mode is PEAR_ERROR_CALLBACK, this parameter is expected
301     *        to be the callback function or method.  A callback
302     *        function is a string with the name of the function, a
303     *        callback method is an array of two elements: the element
304     *        at index 0 is the object, and the element at index 1 is
305     *        the name of the method to call in the object.
306     *
307     *        When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is
308     *        a printf format string used when printing the error
309     *        message.
310     *
311     * @access public
312     * @return void
313     * @see PEAR_ERROR_RETURN
314     * @see PEAR_ERROR_PRINT
315     * @see PEAR_ERROR_TRIGGER
316     * @see PEAR_ERROR_DIE
317     * @see PEAR_ERROR_CALLBACK
318     * @see PEAR_ERROR_EXCEPTION
319     *
320     * @since PHP 4.0.5
321     */
322
323    function setErrorHandling($mode = null, $options = null)
324    {
325        if (isset($this) && is_a($this, 'PEAR')) {
326            $setmode     = &$this->_default_error_mode;
327            $setoptions  = &$this->_default_error_options;
328        } else {
329            $setmode     = &$GLOBALS['_PEAR_default_error_mode'];
330            $setoptions  = &$GLOBALS['_PEAR_default_error_options'];
331        }
332
333        switch ($mode) {
334            case PEAR_ERROR_EXCEPTION:
335            case PEAR_ERROR_RETURN:
336            case PEAR_ERROR_PRINT:
337            case PEAR_ERROR_TRIGGER:
338            case PEAR_ERROR_DIE:
339            case null:
340                $setmode = $mode;
341                $setoptions = $options;
342                break;
343
344            case PEAR_ERROR_CALLBACK:
345                $setmode = $mode;
346                // class/object method callback
347                if (is_callable($options)) {
348                    $setoptions = $options;
349                } else {
350                    trigger_error("invalid error callback", E_USER_WARNING);
351                }
352                break;
353
354            default:
355                trigger_error("invalid error mode", E_USER_WARNING);
356                break;
357        }
358    }
359
360    // }}}
361    // {{{ expectError()
362
363    /**
364     * This method is used to tell which errors you expect to get.
365     * Expected errors are always returned with error mode
366     * PEAR_ERROR_RETURN.  Expected error codes are stored in a stack,
367     * and this method pushes a new element onto it.  The list of
368     * expected errors are in effect until they are popped off the
369     * stack with the popExpect() method.
370     *
371     * Note that this method can not be called statically
372     *
373     * @param mixed $code a single error code or an array of error codes to expect
374     *
375     * @return int     the new depth of the "expected errors" stack
376     * @access public
377     */
378    function expectError($code = '*')
379    {
380        if (is_array($code)) {
381            array_push($this->_expected_errors, $code);
382        } else {
383            array_push($this->_expected_errors, array($code));
384        }
385        return sizeof($this->_expected_errors);
386    }
387
388    // }}}
389    // {{{ popExpect()
390
391    /**
392     * This method pops one element off the expected error codes
393     * stack.
394     *
395     * @return array   the list of error codes that were popped
396     */
397    function popExpect()
398    {
399        return array_pop($this->_expected_errors);
400    }
401
402    // }}}
403    // {{{ _checkDelExpect()
404
405    /**
406     * This method checks unsets an error code if available
407     *
408     * @param mixed error code
409     * @return bool true if the error code was unset, false otherwise
410     * @access private
411     * @since PHP 4.3.0
412     */
413    function _checkDelExpect($error_code)
414    {
415        $deleted = false;
416
417        foreach ($this->_expected_errors AS $key => $error_array) {
418            if (in_array($error_code, $error_array)) {
419                unset($this->_expected_errors[$key][array_search($error_code, $error_array)]);
420                $deleted = true;
421            }
422
423            // clean up empty arrays
424            if (0 == count($this->_expected_errors[$key])) {
425                unset($this->_expected_errors[$key]);
426            }
427        }
428        return $deleted;
429    }
430
431    // }}}
432    // {{{ delExpect()
433
434    /**
435     * This method deletes all occurences of the specified element from
436     * the expected error codes stack.
437     *
438     * @param  mixed $error_code error code that should be deleted
439     * @return mixed list of error codes that were deleted or error
440     * @access public
441     * @since PHP 4.3.0
442     */
443    function delExpect($error_code)
444    {
445        $deleted = false;
446        if ((is_array($error_code) && (0 != count($error_code)))) {
447            // $error_code is a non-empty array here;
448            // we walk through it trying to unset all
449            // values
450            foreach($error_code as $key => $error) {
451                if ($this->_checkDelExpect($error)) {
452                    $deleted =  true;
453                } else {
454                    $deleted = false;
455                }
456            }
457            return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
458        } elseif (!empty($error_code)) {
459            // $error_code comes alone, trying to unset it
460            if ($this->_checkDelExpect($error_code)) {
461                return true;
462            } else {
463                return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
464            }
465        }
466
467        // $error_code is empty
468        return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME
469    }
470
471    // }}}
472    // {{{ raiseError()
473
474    /**
475     * This method is a wrapper that returns an instance of the
476     * configured error class with this object's default error
477     * handling applied.  If the $mode and $options parameters are not
478     * specified, the object's defaults are used.
479     *
480     * @param mixed $message a text error message or a PEAR error object
481     *
482     * @param int $code      a numeric error code (it is up to your class
483     *                  to define these if you want to use codes)
484     *
485     * @param int $mode      One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
486     *                  PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
487     *                  PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION.
488     *
489     * @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter
490     *                  specifies the PHP-internal error level (one of
491     *                  E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
492     *                  If $mode is PEAR_ERROR_CALLBACK, this
493     *                  parameter specifies the callback function or
494     *                  method.  In other error modes this parameter
495     *                  is ignored.
496     *
497     * @param string $userinfo If you need to pass along for example debug
498     *                  information, this parameter is meant for that.
499     *
500     * @param string $error_class The returned error object will be
501     *                  instantiated from this class, if specified.
502     *
503     * @param bool $skipmsg If true, raiseError will only pass error codes,
504     *                  the error message parameter will be dropped.
505     *
506     * @access public
507     * @return object   a PEAR error object
508     * @see PEAR::setErrorHandling
509     * @since PHP 4.0.5
510     */
511    function &raiseError($message = null,
512                         $code = null,
513                         $mode = null,
514                         $options = null,
515                         $userinfo = null,
516                         $error_class = null,
517                         $skipmsg = false)
518    {
519        // The error is yet a PEAR error object
520        if (is_object($message)) {
521            $code        = $message->getCode();
522            $userinfo    = $message->getUserInfo();
523            $error_class = $message->getType();
524            $message->error_message_prefix = '';
525            $message     = $message->getMessage();
526        }
527
528        if (isset($this) && isset($this->_expected_errors) && sizeof($this->_expected_errors) > 0 && sizeof($exp = end($this->_expected_errors))) {
529            if ($exp[0] == "*" ||
530                (is_int(reset($exp)) && in_array($code, $exp)) ||
531                (is_string(reset($exp)) && in_array($message, $exp))) {
532                $mode = PEAR_ERROR_RETURN;
533            }
534        }
535
536        // No mode given, try global ones
537        if ($mode === null) {
538            // Class error handler
539            if (isset($this) && isset($this->_default_error_mode)) {
540                $mode    = $this->_default_error_mode;
541                $options = $this->_default_error_options;
542            // Global error handler
543            } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) {
544                $mode    = $GLOBALS['_PEAR_default_error_mode'];
545                $options = $GLOBALS['_PEAR_default_error_options'];
546            }
547        }
548
549        if ($error_class !== null) {
550            $ec = $error_class;
551        } elseif (isset($this) && isset($this->_error_class)) {
552            $ec = $this->_error_class;
553        } else {
554            $ec = 'PEAR_Error';
555        }
556
557        if (intval(PHP_VERSION) < 5) {
558            // little non-eval hack to fix bug #12147
559            include 'PEAR/FixPHP5PEARWarnings.php';
560            return $a;
561        }
562
563        if ($skipmsg) {
564            $a = new $ec($code, $mode, $options, $userinfo);
565        } else {
566            $a = new $ec($message, $code, $mode, $options, $userinfo);
567        }
568
569        return $a;
570    }
571
572    // }}}
573    // {{{ throwError()
574
575    /**
576     * Simpler form of raiseError with fewer options.  In most cases
577     * message, code and userinfo are enough.
578     *
579     * @param string $message
580     *
581     */
582    function &throwError($message = null,
583                         $code = null,
584                         $userinfo = null)
585    {
586        if (isset($this) && is_a($this, 'PEAR')) {
587            $a = &$this->raiseError($message, $code, null, null, $userinfo);
588            return $a;
589        }
590
591        $a = &PEAR::raiseError($message, $code, null, null, $userinfo);
592        return $a;
593    }
594
595    // }}}
596    function staticPushErrorHandling($mode, $options = null)
597    {
598        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
599        $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
600        $def_options = &$GLOBALS['_PEAR_default_error_options'];
601        $stack[] = array($def_mode, $def_options);
602        switch ($mode) {
603            case PEAR_ERROR_EXCEPTION:
604            case PEAR_ERROR_RETURN:
605            case PEAR_ERROR_PRINT:
606            case PEAR_ERROR_TRIGGER:
607            case PEAR_ERROR_DIE:
608            case null:
609                $def_mode = $mode;
610                $def_options = $options;
611                break;
612
613            case PEAR_ERROR_CALLBACK:
614                $def_mode = $mode;
615                // class/object method callback
616                if (is_callable($options)) {
617                    $def_options = $options;
618                } else {
619                    trigger_error("invalid error callback", E_USER_WARNING);
620                }
621                break;
622
623            default:
624                trigger_error("invalid error mode", E_USER_WARNING);
625                break;
626        }
627        $stack[] = array($mode, $options);
628        return true;
629    }
630
631    function staticPopErrorHandling()
632    {
633        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
634        $setmode     = &$GLOBALS['_PEAR_default_error_mode'];
635        $setoptions  = &$GLOBALS['_PEAR_default_error_options'];
636        array_pop($stack);
637        list($mode, $options) = $stack[sizeof($stack) - 1];
638        array_pop($stack);
639        switch ($mode) {
640            case PEAR_ERROR_EXCEPTION:
641            case PEAR_ERROR_RETURN:
642            case PEAR_ERROR_PRINT:
643            case PEAR_ERROR_TRIGGER:
644            case PEAR_ERROR_DIE:
645            case null:
646                $setmode = $mode;
647                $setoptions = $options;
648                break;
649
650            case PEAR_ERROR_CALLBACK:
651                $setmode = $mode;
652                // class/object method callback
653                if (is_callable($options)) {
654                    $setoptions = $options;
655                } else {
656                    trigger_error("invalid error callback", E_USER_WARNING);
657                }
658                break;
659
660            default:
661                trigger_error("invalid error mode", E_USER_WARNING);
662                break;
663        }
664        return true;
665    }
666
667    // {{{ pushErrorHandling()
668
669    /**
670     * Push a new error handler on top of the error handler options stack. With this
671     * you can easily override the actual error handler for some code and restore
672     * it later with popErrorHandling.
673     *
674     * @param mixed $mode (same as setErrorHandling)
675     * @param mixed $options (same as setErrorHandling)
676     *
677     * @return bool Always true
678     *
679     * @see PEAR::setErrorHandling
680     */
681    function pushErrorHandling($mode, $options = null)
682    {
683        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
684        if (isset($this) && is_a($this, 'PEAR')) {
685            $def_mode    = &$this->_default_error_mode;
686            $def_options = &$this->_default_error_options;
687        } else {
688            $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
689            $def_options = &$GLOBALS['_PEAR_default_error_options'];
690        }
691        $stack[] = array($def_mode, $def_options);
692
693        if (isset($this) && is_a($this, 'PEAR')) {
694            $this->setErrorHandling($mode, $options);
695        } else {
696            PEAR::setErrorHandling($mode, $options);
697        }
698        $stack[] = array($mode, $options);
699        return true;
700    }
701
702    // }}}
703    // {{{ popErrorHandling()
704
705    /**
706    * Pop the last error handler used
707    *
708    * @return bool Always true
709    *
710    * @see PEAR::pushErrorHandling
711    */
712    function popErrorHandling()
713    {
714        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
715        array_pop($stack);
716        list($mode, $options) = $stack[sizeof($stack) - 1];
717        array_pop($stack);
718        if (isset($this) && is_a($this, 'PEAR')) {
719            $this->setErrorHandling($mode, $options);
720        } else {
721            PEAR::setErrorHandling($mode, $options);
722        }
723        return true;
724    }
725
726    // }}}
727    // {{{ loadExtension()
728
729    /**
730    * OS independant PHP extension load. Remember to take care
731    * on the correct extension name for case sensitive OSes.
732    *
733    * @param string $ext The extension name
734    * @return bool Success or not on the dl() call
735    */
736    function loadExtension($ext)
737    {
738        if (!extension_loaded($ext)) {
739            // if either returns true dl() will produce a FATAL error, stop that
740            if ((ini_get('enable_dl') != 1) || (ini_get('safe_mode') == 1)) {
741                return false;
742            }
743
744            if (OS_WINDOWS) {
745                $suffix = '.dll';
746            } elseif (PHP_OS == 'HP-UX') {
747                $suffix = '.sl';
748            } elseif (PHP_OS == 'AIX') {
749                $suffix = '.a';
750            } elseif (PHP_OS == 'OSX') {
751                $suffix = '.bundle';
752            } else {
753                $suffix = '.so';
754            }
755
756            return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix);
757        }
758
759        return true;
760    }
761
762    // }}}
763}
764
765if (PEAR_ZE2) {
766    include_once 'PEAR5.php';
767}
768
769// {{{ _PEAR_call_destructors()
770
771function _PEAR_call_destructors()
772{
773    global $_PEAR_destructor_object_list;
774    if (is_array($_PEAR_destructor_object_list) &&
775        sizeof($_PEAR_destructor_object_list))
776    {
777        reset($_PEAR_destructor_object_list);
778        if (PEAR_ZE2) {
779            $destructLifoExists = PEAR5::getStaticProperty('PEAR', 'destructlifo');
780        } else {
781            $destructLifoExists = PEAR::getStaticProperty('PEAR', 'destructlifo');
782        }
783
784        if ($destructLifoExists) {
785            $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list);
786        }
787
788        while (list($k, $objref) = each($_PEAR_destructor_object_list)) {
789            $classname = get_class($objref);
790            while ($classname) {
791                $destructor = "_$classname";
792                if (method_exists($objref, $destructor)) {
793                    $objref->$destructor();
794                    break;
795                } else {
796                    $classname = get_parent_class($classname);
797                }
798            }
799        }
800        // Empty the object list to ensure that destructors are
801        // not called more than once.
802        $_PEAR_destructor_object_list = array();
803    }
804
805    // Now call the shutdown functions
806    if (isset($GLOBALS['_PEAR_shutdown_funcs']) AND is_array($GLOBALS['_PEAR_shutdown_funcs']) AND !empty($GLOBALS['_PEAR_shutdown_funcs'])) {
807        foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) {
808            call_user_func_array($value[0], $value[1]);
809        }
810    }
811}
812
813// }}}
814/**
815 * Standard PEAR error class for PHP 4
816 *
817 * This class is supserseded by {@link PEAR_Exception} in PHP 5
818 *
819 * @category   pear
820 * @package    PEAR
821 * @author     Stig Bakken <ssb@php.net>
822 * @author     Tomas V.V. Cox <cox@idecnet.com>
823 * @author     Gregory Beaver <cellog@php.net>
824 * @copyright  1997-2006 The PHP Group
825 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
826 * @version    Release: 1.9.0
827 * @link       http://pear.php.net/manual/en/core.pear.pear-error.php
828 * @see        PEAR::raiseError(), PEAR::throwError()
829 * @since      Class available since PHP 4.0.2
830 */
831class PEAR_Error
832{
833    // {{{ properties
834
835    var $error_message_prefix = '';
836    var $mode                 = PEAR_ERROR_RETURN;
837    var $level                = E_USER_NOTICE;
838    var $code                 = -1;
839    var $message              = '';
840    var $userinfo             = '';
841    var $backtrace            = null;
842
843    // }}}
844    // {{{ constructor
845
846    /**
847     * PEAR_Error constructor
848     *
849     * @param string $message  message
850     *
851     * @param int $code     (optional) error code
852     *
853     * @param int $mode     (optional) error mode, one of: PEAR_ERROR_RETURN,
854     * PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER,
855     * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION
856     *
857     * @param mixed $options   (optional) error level, _OR_ in the case of
858     * PEAR_ERROR_CALLBACK, the callback function or object/method
859     * tuple.
860     *
861     * @param string $userinfo (optional) additional user/debug info
862     *
863     * @access public
864     *
865     */
866    function PEAR_Error($message = 'unknown error', $code = null,
867                        $mode = null, $options = null, $userinfo = null)
868    {
869        if ($mode === null) {
870            $mode = PEAR_ERROR_RETURN;
871        }
872        $this->message   = $message;
873        $this->code      = $code;
874        $this->mode      = $mode;
875        $this->userinfo  = $userinfo;
876
877        if (PEAR_ZE2) {
878            $skiptrace = PEAR5::getStaticProperty('PEAR_Error', 'skiptrace');
879        } else {
880            $skiptrace = PEAR::getStaticProperty('PEAR_Error', 'skiptrace');
881        }
882
883        if (!$skiptrace) {
884            $this->backtrace = debug_backtrace();
885            if (isset($this->backtrace[0]) && isset($this->backtrace[0]['object'])) {
886                unset($this->backtrace[0]['object']);
887            }
888        }
889
890        if ($mode & PEAR_ERROR_CALLBACK) {
891            $this->level = E_USER_NOTICE;
892            $this->callback = $options;
893        } else {
894            if ($options === null) {
895                $options = E_USER_NOTICE;
896            }
897
898            $this->level = $options;
899            $this->callback = null;
900        }
901
902        if ($this->mode & PEAR_ERROR_PRINT) {
903            if (is_null($options) || is_int($options)) {
904                $format = "%s";
905            } else {
906                $format = $options;
907            }
908
909            printf($format, $this->getMessage());
910        }
911
912        if ($this->mode & PEAR_ERROR_TRIGGER) {
913            trigger_error($this->getMessage(), $this->level);
914        }
915
916        if ($this->mode & PEAR_ERROR_DIE) {
917            $msg = $this->getMessage();
918            if (is_null($options) || is_int($options)) {
919                $format = "%s";
920                if (substr($msg, -1) != "\n") {
921                    $msg .= "\n";
922                }
923            } else {
924                $format = $options;
925            }
926            die(sprintf($format, $msg));
927        }
928
929        if ($this->mode & PEAR_ERROR_CALLBACK) {
930            if (is_callable($this->callback)) {
931                call_user_func($this->callback, $this);
932            }
933        }
934
935        if ($this->mode & PEAR_ERROR_EXCEPTION) {
936            trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions", E_USER_WARNING);
937            eval('$e = new Exception($this->message, $this->code);throw($e);');
938        }
939    }
940
941    // }}}
942    // {{{ getMode()
943
944    /**
945     * Get the error mode from an error object.
946     *
947     * @return int error mode
948     * @access public
949     */
950    function getMode() {
951        return $this->mode;
952    }
953
954    // }}}
955    // {{{ getCallback()
956
957    /**
958     * Get the callback function/method from an error object.
959     *
960     * @return mixed callback function or object/method array
961     * @access public
962     */
963    function getCallback() {
964        return $this->callback;
965    }
966
967    // }}}
968    // {{{ getMessage()
969
970
971    /**
972     * Get the error message from an error object.
973     *
974     * @return  string  full error message
975     * @access public
976     */
977    function getMessage()
978    {
979        return ($this->error_message_prefix . $this->message);
980    }
981
982
983    // }}}
984    // {{{ getCode()
985
986    /**
987     * Get error code from an error object
988     *
989     * @return int error code
990     * @access public
991     */
992     function getCode()
993     {
994        return $this->code;
995     }
996
997    // }}}
998    // {{{ getType()
999
1000    /**
1001     * Get the name of this error/exception.
1002     *
1003     * @return string error/exception name (type)
1004     * @access public
1005     */
1006    function getType()
1007    {
1008        return get_class($this);
1009    }
1010
1011    // }}}
1012    // {{{ getUserInfo()
1013
1014    /**
1015     * Get additional user-supplied information.
1016     *
1017     * @return string user-supplied information
1018     * @access public
1019     */
1020    function getUserInfo()
1021    {
1022        return $this->userinfo;
1023    }
1024
1025    // }}}
1026    // {{{ getDebugInfo()
1027
1028    /**
1029     * Get additional debug information supplied by the application.
1030     *
1031     * @return string debug information
1032     * @access public
1033     */
1034    function getDebugInfo()
1035    {
1036        return $this->getUserInfo();
1037    }
1038
1039    // }}}
1040    // {{{ getBacktrace()
1041
1042    /**
1043     * Get the call backtrace from where the error was generated.
1044     * Supported with PHP 4.3.0 or newer.
1045     *
1046     * @param int $frame (optional) what frame to fetch
1047     * @return array Backtrace, or NULL if not available.
1048     * @access public
1049     */
1050    function getBacktrace($frame = null)
1051    {
1052        if (defined('PEAR_IGNORE_BACKTRACE')) {
1053            return null;
1054        }
1055        if ($frame === null) {
1056            return $this->backtrace;
1057        }
1058        return $this->backtrace[$frame];
1059    }
1060
1061    // }}}
1062    // {{{ addUserInfo()
1063
1064    function addUserInfo($info)
1065    {
1066        if (empty($this->userinfo)) {
1067            $this->userinfo = $info;
1068        } else {
1069            $this->userinfo .= " ** $info";
1070        }
1071    }
1072
1073    // }}}
1074    // {{{ toString()
1075    function __toString()
1076    {
1077        return $this->getMessage();
1078    }
1079    // }}}
1080    // {{{ toString()
1081
1082    /**
1083     * Make a string representation of this object.
1084     *
1085     * @return string a string with an object summary
1086     * @access public
1087     */
1088    function toString() {
1089        $modes = array();
1090        $levels = array(E_USER_NOTICE  => 'notice',
1091                        E_USER_WARNING => 'warning',
1092                        E_USER_ERROR   => 'error');
1093        if ($this->mode & PEAR_ERROR_CALLBACK) {
1094            if (is_array($this->callback)) {
1095                $callback = (is_object($this->callback[0]) ?
1096                    strtolower(get_class($this->callback[0])) :
1097                    $this->callback[0]) . '::' .
1098                    $this->callback[1];
1099            } else {
1100                $callback = $this->callback;
1101            }
1102            return sprintf('[%s: message="%s" code=%d mode=callback '.
1103                           'callback=%s prefix="%s" info="%s"]',
1104                           strtolower(get_class($this)), $this->message, $this->code,
1105                           $callback, $this->error_message_prefix,
1106                           $this->userinfo);
1107        }
1108        if ($this->mode & PEAR_ERROR_PRINT) {
1109            $modes[] = 'print';
1110        }
1111        if ($this->mode & PEAR_ERROR_TRIGGER) {
1112            $modes[] = 'trigger';
1113        }
1114        if ($this->mode & PEAR_ERROR_DIE) {
1115            $modes[] = 'die';
1116        }
1117        if ($this->mode & PEAR_ERROR_RETURN) {
1118            $modes[] = 'return';
1119        }
1120        return sprintf('[%s: message="%s" code=%d mode=%s level=%s '.
1121                       'prefix="%s" info="%s"]',
1122                       strtolower(get_class($this)), $this->message, $this->code,
1123                       implode("|", $modes), $levels[$this->level],
1124                       $this->error_message_prefix,
1125                       $this->userinfo);
1126    }
1127
1128    // }}}
1129}
1130
1131/*
1132 * Local Variables:
1133 * mode: php
1134 * tab-width: 4
1135 * c-basic-offset: 4
1136 * End:
1137 */
Note: See TracBrowser for help on using the repository browser.