references_PEAR::__construct()   B
last analyzed

Complexity

Conditions 7
Paths 16

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
nc 16
nop 1
dl 0
loc 24
rs 8.6026
c 0
b 0
f 0
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
 * LICENSE: This source file is subject to version 3.0 of the PHP license
10
 * that is available through the world-wide-web at the following URI:
11
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
12
 * the PHP License and are unable to obtain it through the web, please
13
 * send a note to [email protected] so we can mail you a copy immediately.
14
 *
15
 * @category   pear
16
 * @package    PEAR
17
 * @author     Sterling Hughes <[email protected]>
18
 * @author     Stig Bakken <[email protected]>
19
 * @author     Tomas V.V.Cox <[email protected]>
20
 * @author     Greg Beaver <[email protected]>
21
 * @copyright  1997-2006 The PHP Group
22
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
23
 * @version    CVS: $Id: PEAR.php 2 2010-01-23 20:04:25Z hthouzard $
24
 * @link       http://pear.php.net/package/PEAR
25
 * @since      File available since Release 0.1
26
 */
27
28
/**#@+
29
 * ERROR constants
30
 */
31
define('references_PEAR_ERROR_RETURN', 1);
32
define('references_PEAR_ERROR_PRINT', 2);
33
define('references_PEAR_ERROR_TRIGGER', 4);
34
define('references_PEAR_ERROR_DIE', 8);
35
define('references_PEAR_ERROR_CALLBACK', 16);
36
/**
37
 * WARNING: obsolete
38
 * @deprecated
39
 */
40
define('references_PEAR_ERROR_EXCEPTION', 32);
41
/**#@-*/
42
define('references_PEAR_ZE2', function_exists('version_compare')
43
                              && version_compare(zend_version(), '2-dev', 'ge'));
44
45
if (substr(PHP_OS, 0, 3) == 'WIN') {
46
    define('references_OS_WINDOWS', true);
47
    define('references_OS_UNIX', false);
48
    define('references_PEAR_OS', 'Windows');
49
} else {
50
    define('references_OS_WINDOWS', false);
51
    define('references_OS_UNIX', true);
52
    define('references_PEAR_OS', 'Unix'); // blatant assumption
53
}
54
55
// instant backwards compatibility
56
if (!defined('PATH_SEPARATOR')) {
57
    if (references_OS_WINDOWS) {
58
        define('PATH_SEPARATOR', ';');
59
    } else {
60
        define('PATH_SEPARATOR', ':');
61
    }
62
}
63
64
$GLOBALS['_PEAR_default_error_mode']     = references_PEAR_ERROR_RETURN;
65
$GLOBALS['_PEAR_default_error_options']  = E_USER_NOTICE;
66
$GLOBALS['_PEAR_destructor_object_list'] = array();
67
$GLOBALS['_PEAR_shutdown_funcs']         = array();
68
$GLOBALS['_PEAR_error_handler_stack']    = array();
69
70
@ini_set('track_errors', true);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
71
72
/**
73
 * Base class for other PEAR classes.  Provides rudimentary
74
 * emulation of destructors.
75
 *
76
 * If you want a destructor in your class, inherit PEAR and make a
77
 * destructor method called _yourclassname (same name as the
78
 * constructor, but with a "_" prefix).  Also, in your constructor you
79
 * have to call the PEAR constructor: $this->PEAR();.
80
 * The destructor method will be called without parameters.  Note that
81
 * at in some SAPI implementations (such as Apache), any output during
82
 * the request shutdown (in which destructors are called) seems to be
83
 * discarded.  If you need to get any debug information from your
84
 * destructor, use error_log(), syslog() or something similar.
85
 *
86
 * IMPORTANT! To use the emulated destructors you need to create the
87
 * objects by reference: $obj =& new PEAR_child;
88
 *
89
 * @category    pear
90
 * @package     PEAR
91
 * @author      Stig Bakken <[email protected]>
92
 * @author      Tomas V.V. Cox <[email protected]>
93
 * @author      Greg Beaver <[email protected]>
94
 * @copyright   1997-2006 The PHP Group
95
 * @license     http://www.php.net/license/3_0.txt  PHP License 3.0
96
 * @version     Release: 1.5.4
97
 * @link        http://pear.php.net/package/PEAR
98
 * @see         PEAR_Error
99
 * @since       Class available since PHP 4.0.2
100
 * @link        http://pear.php.net/manual/en/core.pear.php#core.pear.pear
101
 */
102
class references_PEAR
103
{
104
    // {{{ properties
105
106
    /**
107
     * Whether to enable internal debug messages.
108
     *
109
     * @var bool
110
     * @access  private
111
     */
112
    public $_debug = false;
113
114
    /**
115
     * Default error mode for this object.
116
     *
117
     * @var int
118
     * @access  private
119
     */
120
    public $_default_error_mode = null;
121
122
    /**
123
     * Default error options used for this object when error mode
124
     * is references_PEAR_ERROR_TRIGGER.
125
     *
126
     * @var int
127
     * @access  private
128
     */
129
    public $_default_error_options = null;
130
131
    /**
132
     * Default error handler (callback) for this object, if error mode is
133
     * references_PEAR_ERROR_CALLBACK.
134
     *
135
     * @var string
136
     * @access  private
137
     */
138
    public $_default_error_handler = '';
139
140
    /**
141
     * Which class to use for error objects.
142
     *
143
     * @var string
144
     * @access  private
145
     */
146
    public $_error_class = 'PEAR_Error';
147
148
    /**
149
     * An array of expected errors.
150
     *
151
     * @var array
152
     * @access  private
153
     */
154
    public $_expected_errors = array();
155
156
    // }}}
157
158
    // {{{ constructor
159
160
    /**
161
     * Constructor.  Registers this object in
162
     * $_PEAR_destructor_object_list for destructor emulation if a
163
     * destructor object exists.
164
     *
165
     * @param  string $error_class (optional) which class to use for
0 ignored issues
show
Documentation introduced by
Should the type for parameter $error_class not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
166
     *                             error objects, defaults to PEAR_Error.
167
     * @access public
168
     */
169
    public function __construct($error_class = null)
170
    {
171
        $classname = strtolower(get_class($this));
172
        if ($this->_debug) {
173
            print "PEAR constructor called, class=$classname\n";
174
        }
175
        if ($error_class !== null) {
176
            $this->_error_class = $error_class;
177
        }
178
        while ($classname && strcasecmp($classname, 'pear')) {
179
            $destructor = "_$classname";
180
            if (method_exists($this, $destructor)) {
181
                global $_PEAR_destructor_object_list;
182
                $_PEAR_destructor_object_list[] = &$this;
183
                if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
184
                    register_shutdown_function('references_PEAR_call_destructors');
185
                    $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
186
                }
187
                break;
188
            } else {
189
                $classname = get_parent_class($classname);
190
            }
191
        }
192
    }
193
194
    // }}}
195
    // {{{ destructor
196
197
    /**
198
     * Destructor (the emulated type of...).  Does nothing right now,
199
     * but is included for forward compatibility, so subclass
200
     * destructors should always call it.
201
     *
202
     * See the note in the class desciption about output from
203
     * destructors.
204
     *
205
     * @access public
206
     * @return void
207
     */
208
    public function _PEAR()
209
    {
210
        if ($this->_debug) {
211
            printf("PEAR destructor called, class=%s\n", strtolower(get_class($this)));
212
        }
213
    }
214
215
    // }}}
216
    // {{{ getStaticProperty()
217
218
    /**
219
     * If you have a class that's mostly/entirely static, and you need static
220
     * properties, you can use this method to simulate them. Eg. in your method(s)
221
     * do this: $myVar = &references_PEAR::getStaticProperty('myclass', 'myVar');
222
     * You MUST use a reference, or they will not persist!
223
     *
224
     * @access public
225
     * @param  string $class The calling classname, to prevent clashes
226
     * @param  string $var   The variable to retrieve.
227
     * @return mixed   A reference to the variable. If not set it will be
228
     *                       auto initialised to NULL.
229
     */
230
    public function &getStaticProperty($class, $var)
231
    {
232
        static $properties;
233
        if (!isset($properties[$class])) {
234
            $properties[$class] = array();
235
        }
236
        if (!array_key_exists($var, $properties[$class])) {
237
            $properties[$class][$var] = null;
238
        }
239
240
        return $properties[$class][$var];
241
    }
242
243
    // }}}
244
    // {{{ registerShutdownFunc()
245
246
    /**
247
     * Use this function to register a shutdown method for static
248
     * classes.
249
     *
250
     * @access public
251
     * @param  mixed $func The function name (or array of class/method) to call
252
     * @param  mixed $args The arguments to pass to the function
253
     * @return void
254
     */
255
    public function registerShutdownFunc($func, $args = array())
256
    {
257
        // if we are called statically, there is a potential
258
        // that no shutdown func is registered.  Bug #6445
259
        if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
260
            register_shutdown_function('references__PEAR_call_destructors');
261
            $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
262
        }
263
        $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args);
264
    }
265
266
    // }}}
267
    // {{{ isError()
268
269
    /**
270
     * Tell whether a value is a PEAR error.
271
     *
272
     * @param  mixed $data the value to test
273
     * @param  int   $code if $data is an error object, return true
0 ignored issues
show
Documentation introduced by
Should the type for parameter $code not be integer|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
274
     *                     only if $code is a string and
275
     *                     $obj->getMessage() == $code or
276
     *                     $code is an integer and $obj->getCode() == $code
277
     * @access  public
278
     * @return bool  true if parameter is an error
279
     */
280
    public function isError($data, $code = null)
281
    {
282
        if (is_a($data, 'PEAR_Error')) {
283
            if (is_null($code)) {
284
                return true;
285
            } elseif (is_string($code)) {
286
                return $data->getMessage() == $code;
287
            } else {
288
                return $data->getCode() == $code;
289
            }
290
        }
291
292
        return false;
293
    }
294
295
    // }}}
296
    // {{{ setErrorHandling()
297
298
    /**
299
     * Sets how errors generated by this object should be handled.
300
     * Can be invoked both in objects and statically.  If called
301
     * statically, setErrorHandling sets the default behaviour for all
302
     * PEAR objects.  If called in an object, setErrorHandling sets
303
     * the default behaviour for that object.
304
     *
305
     * @param int   $mode
306
     *                       One of references_PEAR_ERROR_RETURN, references_PEAR_ERROR_PRINT,
0 ignored issues
show
Documentation introduced by
Should the type for parameter $mode not be integer|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
307
     *                       references_PEAR_ERROR_TRIGGER, references_PEAR_ERROR_DIE,
308
     *                       references_PEAR_ERROR_CALLBACK or references_PEAR_ERROR_EXCEPTION.
309
     *
310
     * @param mixed $options
311
     *                       When $mode is references_PEAR_ERROR_TRIGGER, this is the error level (one
312
     *                       of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
313
     *
314
     *        When $mode is references_PEAR_ERROR_CALLBACK, this parameter is expected
315
     *        to be the callback function or method.  A callback
316
     *        function is a string with the name of the function, a
317
     *        callback method is an array of two elements: the element
318
     *        at index 0 is the object, and the element at index 1 is
319
     *        the name of the method to call in the object.
320
     *
321
     *        When $mode is references_PEAR_ERROR_PRINT or references_PEAR_ERROR_DIE, this is
322
     *        a printf format string used when printing the error
323
     *        message.
324
     *
325
     * @access public
326
     * @return void
327
     * @see    references_PEAR_ERROR_RETURN
328
     * @see    references_PEAR_ERROR_PRINT
329
     * @see    references_PEAR_ERROR_TRIGGER
330
     * @see    references_PEAR_ERROR_DIE
331
     * @see    references_PEAR_ERROR_CALLBACK
332
     * @see    references_PEAR_ERROR_EXCEPTION
333
     *
334
     */
335
336
    public function setErrorHandling($mode = null, $options = null)
337
    {
338 View Code Duplication
        if (isset($this) && is_a($this, 'PEAR')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
339
            $setmode    = &$this->_default_error_mode;
340
            $setoptions = &$this->_default_error_options;
341
        } else {
342
            $setmode    = &$GLOBALS['_PEAR_default_error_mode'];
343
            $setoptions = &$GLOBALS['_PEAR_default_error_options'];
344
        }
345
346 View Code Duplication
        switch ($mode) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
347
            case references_PEAR_ERROR_EXCEPTION:
0 ignored issues
show
Deprecated Code introduced by
The constant references_PEAR_ERROR_EXCEPTION has been deprecated.

This constant has been deprecated.

Loading history...
348
            case references_PEAR_ERROR_RETURN:
349
            case references_PEAR_ERROR_PRINT:
350
            case references_PEAR_ERROR_TRIGGER:
351
            case references_PEAR_ERROR_DIE:
352
            case null:
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $mode of type integer|null against null; this is ambiguous if the integer can be zero. Consider using a strict comparison === instead.
Loading history...
353
                $setmode    = $mode;
354
                $setoptions = $options;
355
                break;
356
357
            case references_PEAR_ERROR_CALLBACK:
358
                $setmode = $mode;
359
                // class/object method callback
360
                if (is_callable($options)) {
361
                    $setoptions = $options;
362
                } else {
363
                    trigger_error('invalid error callback', E_USER_WARNING);
364
                }
365
                break;
366
367
            default:
368
                trigger_error('invalid error mode', E_USER_WARNING);
369
                break;
370
        }
371
    }
372
373
    // }}}
374
    // {{{ expectError()
375
376
    /**
377
     * This method is used to tell which errors you expect to get.
378
     * Expected errors are always returned with error mode
379
     * references_PEAR_ERROR_RETURN.  Expected error codes are stored in a stack,
380
     * and this method pushes a new element onto it.  The list of
381
     * expected errors are in effect until they are popped off the
382
     * stack with the popExpect() method.
383
     *
384
     * Note that this method can not be called statically
385
     *
386
     * @param mixed $code a single error code or an array of error codes to expect
387
     *
388
     * @return int the new depth of the "expected errors" stack
389
     * @access public
390
     */
391
    public function expectError($code = '*')
392
    {
393
        if (is_array($code)) {
394
            array_push($this->_expected_errors, $code);
395
        } else {
396
            array_push($this->_expected_errors, array($code));
397
        }
398
399
        return count($this->_expected_errors);
400
    }
401
402
    // }}}
403
    // {{{ popExpect()
404
405
    /**
406
     * This method pops one element off the expected error codes
407
     * stack.
408
     *
409
     * @return array the list of error codes that were popped
410
     */
411
    public function popExpect()
412
    {
413
        return array_pop($this->_expected_errors);
414
    }
415
416
    // }}}
417
    // {{{ _checkDelExpect()
418
419
    /**
420
     * This method checks unsets an error code if available
421
     *
422
     * @param mixed error code
423
     * @return bool true if the error code was unset, false otherwise
424
     * @access private
425
     */
426
    public function _checkDelExpect($error_code)
427
    {
428
        $deleted = false;
429
430
        foreach ($this->_expected_errors as $key => $error_array) {
431
            if (in_array($error_code, $error_array)) {
432
                unset($this->_expected_errors[$key][array_search($error_code, $error_array)]);
433
                $deleted = true;
434
            }
435
436
            // clean up empty arrays
437
            if (0 == count($this->_expected_errors[$key])) {
438
                unset($this->_expected_errors[$key]);
439
            }
440
        }
441
442
        return $deleted;
443
    }
444
445
    // }}}
446
    // {{{ delExpect()
447
448
    /**
449
     * This method deletes all occurences of the specified element from
450
     * the expected error codes stack.
451
     *
452
     * @param  mixed $error_code error code that should be deleted
453
     * @return mixed list of error codes that were deleted or error
454
     * @access public
455
     */
456
    public function delExpect($error_code)
457
    {
458
        $deleted = false;
459
460
        if (is_array($error_code) && (0 != count($error_code))) {
461
            // $error_code is a non-empty array here;
462
            // we walk through it trying to unset all
463
            // values
464
            foreach ($error_code as $key => $error) {
465
                if ($this->_checkDelExpect($error)) {
466
                    $deleted = true;
467
                } else {
468
                    $deleted = false;
469
                }
470
            }
471
472
            return $deleted ? true : references_PEAR::raiseError('The expected error you submitted does not exist'); // IMPROVE ME
473
        } elseif (!empty($error_code)) {
474
            // $error_code comes alone, trying to unset it
475
            if ($this->_checkDelExpect($error_code)) {
476
                return true;
477
            } else {
478
                return references_PEAR::raiseError('The expected error you submitted does not exist'); // IMPROVE ME
479
            }
480
        } else {
481
            // $error_code is empty
482
            return references_PEAR::raiseError('The expected error you submitted is empty'); // IMPROVE ME
483
        }
484
    }
485
486
    // }}}
487
    // {{{ raiseError()
488
489
    /**
490
     * This method is a wrapper that returns an instance of the
491
     * configured error class with this object's default error
492
     * handling applied.  If the $mode and $options parameters are not
493
     * specified, the object's defaults are used.
494
     *
495
     * @param mixed  $message     a text error message or a PEAR error object
496
     *
497
     * @param int    $code        a numeric error code (it is up to your class
0 ignored issues
show
Documentation introduced by
Should the type for parameter $code not be integer|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
498
     *                            to define these if you want to use codes)
499
     *
500
     * @param int    $mode        One of references_PEAR_ERROR_RETURN, references_PEAR_ERROR_PRINT,
0 ignored issues
show
Documentation introduced by
Should the type for parameter $mode not be integer|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
501
     *                            references_PEAR_ERROR_TRIGGER, references_PEAR_ERROR_DIE,
502
     *                            references_PEAR_ERROR_CALLBACK, references_PEAR_ERROR_EXCEPTION.
503
     *
504
     * @param mixed  $options     If $mode is references_PEAR_ERROR_TRIGGER, this parameter
505
     *                            specifies the PHP-internal error level (one of
506
     *                            E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
507
     *                            If $mode is references_PEAR_ERROR_CALLBACK, this
508
     *                            parameter specifies the callback function or
509
     *                            method.  In other error modes this parameter
510
     *                            is ignored.
511
     *
512
     * @param string $userinfo    If you need to pass along for example debug
0 ignored issues
show
Documentation introduced by
Should the type for parameter $userinfo not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
513
     *                            information, this parameter is meant for that.
514
     *
515
     * @param string $error_class The returned error object will be
0 ignored issues
show
Documentation introduced by
Should the type for parameter $error_class not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
516
     *                            instantiated from this class, if specified.
517
     *
518
     * @param bool   $skipmsg     If true, raiseError will only pass error codes,
519
     *                            the error message parameter will be dropped.
520
     *
521
     * @access public
522
     * @return object a PEAR error object
523
     * @see    references_PEAR::setErrorHandling
524
     * @since  PHP 4.0.5
525
     */
526
    public function &raiseError($message = null, $code = null, $mode = null, $options = null, $userinfo = null, $error_class = null, $skipmsg = false)
527
    {
528
        // The error is yet a PEAR error object
529
        if (is_object($message)) {
530
            $code                          = $message->getCode();
531
            $userinfo                      = $message->getUserInfo();
532
            $error_class                   = $message->getType();
533
            $message->error_message_prefix = '';
534
            $message                       = $message->getMessage();
535
        }
536
537
        if (isset($this) && isset($this->_expected_errors) && count($this->_expected_errors) > 0 && count($exp = end($this->_expected_errors))) {
538
            if ($exp[0] === '*'
539
                || (is_int(reset($exp)) && in_array($code, $exp))
540
                || (is_string(reset($exp)) && in_array($message, $exp))
541
            ) {
542
                $mode = references_PEAR_ERROR_RETURN;
543
            }
544
        }
545
        // No mode given, try global ones
546
        if ($mode === null) {
547
            // Class error handler
548
            if (isset($this) && isset($this->_default_error_mode)) {
549
                $mode    = $this->_default_error_mode;
550
                $options = $this->_default_error_options;
551
                // Global error handler
552
            } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) {
553
                $mode    = $GLOBALS['_PEAR_default_error_mode'];
554
                $options = $GLOBALS['_PEAR_default_error_options'];
555
            }
556
        }
557
558
        if ($error_class !== null) {
559
            $ec = $error_class;
560
        } elseif (isset($this) && isset($this->_error_class)) {
561
            $ec = $this->_error_class;
562
        } else {
563
            $ec = 'references_PEAR_Error';
564
        }
565
        if ($skipmsg) {
566
            $a = new $ec($code, $mode, $options, $userinfo);
567
568
            return $a;
569
        } else {
570
            $a = new $ec($message, $code, $mode, $options, $userinfo);
571
572
            return $a;
573
        }
574
    }
575
576
    // }}}
577
    // {{{ throwError()
578
579
    /**
580
     * Simpler form of raiseError with fewer options.  In most cases
581
     * message, code and userinfo are enough.
582
     *
583
     * @param string $message
0 ignored issues
show
Documentation introduced by
Should the type for parameter $message not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
584
     *
585
     * @param null   $code
586
     * @param null   $userinfo
587
     * @return object
588
     */
589
    public function &throwError($message = null, $code = null, $userinfo = null)
590
    {
591
        if (isset($this) && is_a($this, 'PEAR')) {
592
            $a = &$this->raiseError($message, $code, null, null, $userinfo);
593
594
            return $a;
595
        } else {
596
            $a = &references_PEAR::raiseError($message, $code, null, null, $userinfo);
597
598
            return $a;
599
        }
600
    }
601
602
    // }}}
603
    public function staticPushErrorHandling($mode, $options = null)
604
    {
605
        $stack       = &$GLOBALS['_PEAR_error_handler_stack'];
606
        $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
607
        $def_options = &$GLOBALS['_PEAR_default_error_options'];
608
        $stack[]     = array($def_mode, $def_options);
609 View Code Duplication
        switch ($mode) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
610
            case references_PEAR_ERROR_EXCEPTION:
0 ignored issues
show
Deprecated Code introduced by
The constant references_PEAR_ERROR_EXCEPTION has been deprecated.

This constant has been deprecated.

Loading history...
611
            case references_PEAR_ERROR_RETURN:
612
            case references_PEAR_ERROR_PRINT:
613
            case references_PEAR_ERROR_TRIGGER:
614
            case references_PEAR_ERROR_DIE:
615
            case null:
616
                $def_mode    = $mode;
617
                $def_options = $options;
618
                break;
619
620
            case references_PEAR_ERROR_CALLBACK:
621
                $def_mode = $mode;
622
                // class/object method callback
623
                if (is_callable($options)) {
624
                    $def_options = $options;
625
                } else {
626
                    trigger_error('invalid error callback', E_USER_WARNING);
627
                }
628
                break;
629
630
            default:
631
                trigger_error('invalid error mode', E_USER_WARNING);
632
                break;
633
        }
634
        $stack[] = array($mode, $options);
635
636
        return true;
637
    }
638
639
    public function staticPopErrorHandling()
640
    {
641
        $stack      = &$GLOBALS['_PEAR_error_handler_stack'];
642
        $setmode    = &$GLOBALS['_PEAR_default_error_mode'];
643
        $setoptions = &$GLOBALS['_PEAR_default_error_options'];
644
        array_pop($stack);
645
        list($mode, $options) = $stack[count($stack) - 1];
646
        array_pop($stack);
647 View Code Duplication
        switch ($mode) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
648
            case references_PEAR_ERROR_EXCEPTION:
0 ignored issues
show
Deprecated Code introduced by
The constant references_PEAR_ERROR_EXCEPTION has been deprecated.

This constant has been deprecated.

Loading history...
649
            case references_PEAR_ERROR_RETURN:
650
            case references_PEAR_ERROR_PRINT:
651
            case references_PEAR_ERROR_TRIGGER:
652
            case references_PEAR_ERROR_DIE:
653
            case null:
654
                $setmode    = $mode;
655
                $setoptions = $options;
656
                break;
657
658
            case references_PEAR_ERROR_CALLBACK:
659
                $setmode = $mode;
660
                // class/object method callback
661
                if (is_callable($options)) {
662
                    $setoptions = $options;
663
                } else {
664
                    trigger_error('invalid error callback', E_USER_WARNING);
665
                }
666
                break;
667
668
            default:
669
                trigger_error('invalid error mode', E_USER_WARNING);
670
                break;
671
        }
672
673
        return true;
674
    }
675
676
    // {{{ pushErrorHandling()
677
678
    /**
679
     * Push a new error handler on top of the error handler options stack. With this
680
     * you can easily override the actual error handler for some code and restore
681
     * it later with popErrorHandling.
682
     *
683
     * @param mixed $mode    (same as setErrorHandling)
684
     * @param mixed $options (same as setErrorHandling)
685
     *
686
     * @return bool Always true
687
     *
688
     * @see references_PEAR::setErrorHandling
689
     */
690
    public function pushErrorHandling($mode, $options = null)
691
    {
692
        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
693 View Code Duplication
        if (isset($this) && is_a($this, 'PEAR')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
694
            $def_mode    = &$this->_default_error_mode;
695
            $def_options = &$this->_default_error_options;
696
        } else {
697
            $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
698
            $def_options = &$GLOBALS['_PEAR_default_error_options'];
699
        }
700
        $stack[] = array($def_mode, $def_options);
701
702 View Code Duplication
        if (isset($this) && is_a($this, 'PEAR')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
703
            $this->setErrorHandling($mode, $options);
704
        } else {
705
            references_PEAR::setErrorHandling($mode, $options);
706
        }
707
        $stack[] = array($mode, $options);
708
709
        return true;
710
    }
711
712
    // }}}
713
    // {{{ popErrorHandling()
714
715
    /**
716
     * Pop the last error handler used
717
     *
718
     * @return bool Always true
719
     *
720
     * @see references_PEAR::pushErrorHandling
721
     */
722
    public function popErrorHandling()
723
    {
724
        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
725
        array_pop($stack);
726
        list($mode, $options) = $stack[count($stack) - 1];
727
        array_pop($stack);
728 View Code Duplication
        if (isset($this) && is_a($this, 'PEAR')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
729
            $this->setErrorHandling($mode, $options);
730
        } else {
731
            references_PEAR::setErrorHandling($mode, $options);
732
        }
733
734
        return true;
735
    }
736
737
    // }}}
738
    // {{{ loadExtension()
739
740
    /**
741
     * OS independant PHP extension load. Remember to take care
742
     * on the correct extension name for case sensitive OSes.
743
     *
744
     * @param string $ext The extension name
745
     * @return bool Success or not on the dl() call
746
     */
747
    public function loadExtension($ext)
748
    {
749
        if (!extension_loaded($ext)) {
750
            // if either returns true dl() will produce a FATAL error, stop that
751
            if ((ini_get('enable_dl') != 1) || (ini_get('safe_mode') == 1)) {
752
                return false;
753
            }
754
            if (references_OS_WINDOWS) {
755
                $suffix = '.dll';
756
            } elseif (PHP_OS === 'HP-UX') {
757
                $suffix = '.sl';
758
            } elseif (PHP_OS === 'AIX') {
759
                $suffix = '.a';
760
            } elseif (PHP_OS === 'OSX') {
761
                $suffix = '.bundle';
762
            } else {
763
                $suffix = '.so';
764
            }
765
766
            return @dl('php_' . $ext . $suffix) || @dl($ext . $suffix);
767
        }
768
769
        return true;
770
    }
771
772
    // }}}
773
}
774
775
// {{{ _PEAR_call_destructors()
776
777
function references_PEAR_call_destructors()
778
{
779
    global $_PEAR_destructor_object_list;
780
    if (is_array($_PEAR_destructor_object_list)
781
        && count($_PEAR_destructor_object_list)
782
    ) {
783
        reset($_PEAR_destructor_object_list);
784
        if (references_PEAR::getStaticProperty('PEAR', 'destructlifo')) {
785
            $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list);
786
        }
787
        while (list($k, $objref) = each($_PEAR_destructor_object_list)) {
0 ignored issues
show
Unused Code introduced by
The assignment to $k is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
788
            $classname = get_class($objref);
789
            while ($classname) {
790
                $destructor = "_$classname";
791
                if (method_exists($objref, $destructor)) {
792
                    $objref->$destructor();
793
                    break;
794
                } else {
795
                    $classname = get_parent_class($classname);
796
                }
797
            }
798
        }
799
        // Empty the object list to ensure that destructors are
800
        // not called more than once.
801
        $_PEAR_destructor_object_list = array();
802
    }
803
804
    // Now call the shutdown functions
805
    if (is_array($GLOBALS['_PEAR_shutdown_funcs']) and !empty($GLOBALS['_PEAR_shutdown_funcs'])) {
806
        foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) {
807
            call_user_func_array($value[0], $value[1]);
808
        }
809
    }
810
}
811
812
// }}}
813
/**
814
 * Standard PEAR error class for PHP 4
815
 *
816
 * This class is supserseded by {@link PEAR_Exception} in PHP 5
817
 *
818
 * @category   pear
819
 * @package    PEAR
820
 * @author     Stig Bakken <[email protected]>
821
 * @author     Tomas V.V. Cox <[email protected]>
822
 * @author     Gregory Beaver <[email protected]>
823
 * @copyright  1997-2006 The PHP Group
824
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
825
 * @version    Release: 1.5.4
826
 * @link       http://pear.php.net/manual/en/core.pear.pear-error.php
827
 * @see        references_PEAR::raiseError(), PEAR::throwError()
828
 * @since      Class available since PHP 4.0.2
829
 */
830
class references_PEAR_Error
831
{
832
    // {{{ properties
833
834
    public $error_message_prefix = '';
835
    public $mode                 = references_PEAR_ERROR_RETURN;
836
    public $level                = E_USER_NOTICE;
837
    public $code                 = -1;
838
    public $message              = '';
839
    public $userinfo             = '';
840
    public $backtrace            = null;
841
842
    // }}}
843
    // {{{ constructor
844
845
    /**
846
     * PEAR_Error constructor
847
     *
848
     * @param string $message  message
849
     *
850
     * @param int    $code     (optional) error code
0 ignored issues
show
Documentation introduced by
Should the type for parameter $code not be integer|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
851
     *
852
     * @param int    $mode     (optional) error mode, one of: references_PEAR_ERROR_RETURN,
0 ignored issues
show
Documentation introduced by
Should the type for parameter $mode not be integer|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
853
     *                         references_PEAR_ERROR_PRINT, references_PEAR_ERROR_DIE, references_PEAR_ERROR_TRIGGER,
854
     *                         references_PEAR_ERROR_CALLBACK or references_PEAR_ERROR_EXCEPTION
855
     *
856
     * @param mixed  $options  (optional) error level, _OR_ in the case of
857
     *                         references_PEAR_ERROR_CALLBACK, the callback function or object/method
858
     *                         tuple.
859
     *
860
     * @param string $userinfo (optional) additional user/debug info
0 ignored issues
show
Documentation introduced by
Should the type for parameter $userinfo not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
861
     *
862
     * @access public
863
     *
864
     */
865
    public function __construct($message = 'unknown error', $code = null, $mode = null, $options = null, $userinfo = null)
866
    {
867
        if ($mode === null) {
868
            $mode = references_PEAR_ERROR_RETURN;
869
        }
870
        $this->message  = $message;
871
        $this->code     = $code;
872
        $this->mode     = $mode;
873
        $this->userinfo = $userinfo;
874
        if (!references_PEAR::getStaticProperty('PEAR_Error', 'skiptrace')) {
875
            $this->backtrace = debug_backtrace();
876
            if (isset($this->backtrace[0]) && isset($this->backtrace[0]['object'])) {
877
                unset($this->backtrace[0]['object']);
878
            }
879
        }
880
        if ($mode & references_PEAR_ERROR_CALLBACK) {
881
            $this->level    = E_USER_NOTICE;
882
            $this->callback = $options;
0 ignored issues
show
Bug introduced by
The property callback does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
883
        } else {
884
            if ($options === null) {
885
                $options = E_USER_NOTICE;
886
            }
887
            $this->level    = $options;
888
            $this->callback = null;
889
        }
890
        if ($this->mode & references_PEAR_ERROR_PRINT) {
891
            if (is_null($options) || is_int($options)) {
892
                $format = '%s';
893
            } else {
894
                $format = $options;
895
            }
896
            printf($format, $this->getMessage());
897
        }
898
        if ($this->mode & references_PEAR_ERROR_TRIGGER) {
899
            trigger_error($this->getMessage(), $this->level);
900
        }
901
        if ($this->mode & references_PEAR_ERROR_DIE) {
902
            $msg = $this->getMessage();
903
            if (is_null($options) || is_int($options)) {
904
                $format = '%s';
905
                if (substr($msg, -1) !== "\n") {
906
                    $msg .= "\n";
907
                }
908
            } else {
909
                $format = $options;
910
            }
911
            die(sprintf($format, $msg));
912
        }
913
        if ($this->mode & references_PEAR_ERROR_CALLBACK) {
914
            if (is_callable($this->callback)) {
915
                call_user_func($this->callback, $this);
916
            }
917
        }
918
        if ($this->mode & references_PEAR_ERROR_EXCEPTION) {
0 ignored issues
show
Deprecated Code introduced by
The constant references_PEAR_ERROR_EXCEPTION has been deprecated.

This constant has been deprecated.

Loading history...
919
            trigger_error('references_PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions', E_USER_WARNING);
920
            eval('$e = new Exception($this->message, $this->code);throw($e);');
921
        }
922
    }
923
924
    // }}}
925
    // {{{ getMode()
926
927
    /**
928
     * Get the error mode from an error object.
929
     *
930
     * @return int error mode
931
     * @access public
932
     */
933
    public function getMode()
934
    {
935
        return $this->mode;
936
    }
937
938
    // }}}
939
    // {{{ getCallback()
940
941
    /**
942
     * Get the callback function/method from an error object.
943
     *
944
     * @return mixed callback function or object/method array
945
     * @access public
946
     */
947
    public function getCallback()
948
    {
949
        return $this->callback;
950
    }
951
952
    // }}}
953
    // {{{ getMessage()
954
955
    /**
956
     * Get the error message from an error object.
957
     *
958
     * @return string full error message
959
     * @access public
960
     */
961
    public function getMessage()
962
    {
963
        return ($this->error_message_prefix . $this->message);
964
    }
965
966
    // }}}
967
    // {{{ getCode()
968
969
    /**
970
     * Get error code from an error object
971
     *
972
     * @return int error code
973
     * @access public
974
     */
975
    public function getCode()
976
    {
977
        return $this->code;
978
    }
979
980
    // }}}
981
    // {{{ getType()
982
983
    /**
984
     * Get the name of this error/exception.
985
     *
986
     * @return string error/exception name (type)
987
     * @access public
988
     */
989
    public function getType()
990
    {
991
        return get_class($this);
992
    }
993
994
    // }}}
995
    // {{{ getUserInfo()
996
997
    /**
998
     * Get additional user-supplied information.
999
     *
1000
     * @return string user-supplied information
1001
     * @access public
1002
     */
1003
    public function getUserInfo()
1004
    {
1005
        return $this->userinfo;
1006
    }
1007
1008
    // }}}
1009
    // {{{ getDebugInfo()
1010
1011
    /**
1012
     * Get additional debug information supplied by the application.
1013
     *
1014
     * @return string debug information
1015
     * @access public
1016
     */
1017
    public function getDebugInfo()
1018
    {
1019
        return $this->getUserInfo();
1020
    }
1021
1022
    // }}}
1023
    // {{{ getBacktrace()
1024
1025
    /**
1026
     * Get the call backtrace from where the error was generated.
1027
     * Supported with PHP 4.3.0 or newer.
1028
     *
1029
     * @param  int $frame (optional) what frame to fetch
0 ignored issues
show
Documentation introduced by
Should the type for parameter $frame not be integer|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1030
     * @return array Backtrace, or NULL if not available.
1031
     * @access public
1032
     */
1033
    public function getBacktrace($frame = null)
1034
    {
1035
        if (defined('PEAR_IGNORE_BACKTRACE')) {
1036
            return null;
1037
        }
1038
        if ($frame === null) {
1039
            return $this->backtrace;
1040
        }
1041
1042
        return $this->backtrace[$frame];
1043
    }
1044
1045
    // }}}
1046
    // {{{ addUserInfo()
1047
1048
    public function addUserInfo($info)
1049
    {
1050
        if (empty($this->userinfo)) {
1051
            $this->userinfo = $info;
1052
        } else {
1053
            $this->userinfo .= " ** $info";
1054
        }
1055
    }
1056
1057
    // }}}
1058
    // {{{ toString()
1059
1060
    /**
1061
     * Make a string representation of this object.
1062
     *
1063
     * @return string a string with an object summary
1064
     * @access public
1065
     */
1066
    public function toString()
1067
    {
1068
        $modes  = array();
1069
        $levels = array(
1070
            E_USER_NOTICE  => 'notice',
1071
            E_USER_WARNING => 'warning',
1072
            E_USER_ERROR   => 'error'
1073
        );
1074
        if ($this->mode & references_PEAR_ERROR_CALLBACK) {
1075
            if (is_array($this->callback)) {
1076
                $callback = (is_object($this->callback[0]) ? strtolower(get_class($this->callback[0])) : $this->callback[0]) . '::' . $this->callback[1];
1077
            } else {
1078
                $callback = $this->callback;
1079
            }
1080
1081
            return sprintf('[%s: message="%s" code=%d mode=callback ' . 'callback=%s prefix="%s" info="%s"]', strtolower(get_class($this)), $this->message, $this->code, $callback, $this->error_message_prefix, $this->userinfo);
1082
        }
1083
        if ($this->mode & references_PEAR_ERROR_PRINT) {
1084
            $modes[] = 'print';
1085
        }
1086
        if ($this->mode & references_PEAR_ERROR_TRIGGER) {
1087
            $modes[] = 'trigger';
1088
        }
1089
        if ($this->mode & references_PEAR_ERROR_DIE) {
1090
            $modes[] = 'die';
1091
        }
1092
        if ($this->mode & references_PEAR_ERROR_RETURN) {
1093
            $modes[] = 'return';
1094
        }
1095
1096
        return sprintf('[%s: message="%s" code=%d mode=%s level=%s ' . 'prefix="%s" info="%s"]', strtolower(get_class($this)), $this->message, $this->code, implode('|', $modes), $levels[$this->level], $this->error_message_prefix, $this->userinfo);
1097
    }
1098
1099
    // }}}
1100
}
1101
1102
/*
1103
 * Local Variables:
1104
 * mode: php
1105
 * tab-width: 4
1106
 * c-basic-offset: 4
1107
 * End:
1108
 */
1109