Passed
Push — master ( 8d8e58...047d50 )
by Michael
02:21
created

PEAR::__call()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 7
nc 2
nop 2
dl 0
loc 11
rs 9.4285
c 0
b 0
f 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 24 and the first side effect is on line 46.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
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 <[email protected]>
12
 * @author     Stig Bakken <[email protected]>
13
 * @author     Tomas V.V.Cox <[email protected]>
14
 * @author     Greg Beaver <[email protected]>
15
 * @copyright  1997-2010 The Authors
16
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
17
 * @link       http://pear.php.net/package/PEAR
18
 * @since      File available since Release 0.1
19
 */
20
21
/**#@+
22
 * ERROR constants
23
 */
24
define('PEAR_ERROR_RETURN', 1);
25
define('PEAR_ERROR_PRINT', 2);
26
define('PEAR_ERROR_TRIGGER', 4);
27
define('PEAR_ERROR_DIE', 8);
28
define('PEAR_ERROR_CALLBACK', 16);
29
/**
30
 * WARNING: obsolete
31
 * @deprecated
32
 */
33
define('PEAR_ERROR_EXCEPTION', 32);
34
/**#@-*/
35
36
if (substr(PHP_OS, 0, 3) == 'WIN') {
37
    define('OS_WINDOWS', true);
38
    define('OS_UNIX', false);
39
    define('PEAR_OS', 'Windows');
40
} else {
41
    define('OS_WINDOWS', false);
42
    define('OS_UNIX', true);
43
    define('PEAR_OS', 'Unix'); // blatant assumption
44
}
45
46
$GLOBALS['_PEAR_default_error_mode']     = PEAR_ERROR_RETURN;
47
$GLOBALS['_PEAR_default_error_options']  = E_USER_NOTICE;
48
$GLOBALS['_PEAR_destructor_object_list'] = array();
49
$GLOBALS['_PEAR_shutdown_funcs']         = array();
50
$GLOBALS['_PEAR_error_handler_stack']    = array();
51
52
@ini_set('track_errors', true);
0 ignored issues
show
Bug introduced by
true of type true is incompatible with the type string expected by parameter $newvalue of ini_set(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

52
@ini_set('track_errors', /** @scrutinizer ignore-type */ true);
Loading history...
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
 * IMPORTANT! To use the emulated destructors you need to create the
69
 * objects by reference: $obj =& new PEAR_child;
70
 *
71
 * @category   pear
72
 * @package    PEAR
73
 * @author     Stig Bakken <[email protected]>
74
 * @author     Tomas V.V. Cox <[email protected]>
75
 * @author     Greg Beaver <[email protected]>
76
 * @copyright  1997-2006 The PHP Group
77
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
78
 * @version    Release: 1.10.5
79
 * @link       http://pear.php.net/package/PEAR
80
 * @see        PEAR_Error
81
 * @since      Class available since PHP 4.0.2
82
 * @link        http://pear.php.net/manual/en/core.pear.php#core.pear.pear
83
 */
84
class PEAR
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
85
{
86
    /**
87
     * Whether to enable internal debug messages.
88
     *
89
     * @var     bool
90
     * @access  private
91
     */
92
    public $_debug = false;
93
94
    /**
95
     * Default error mode for this object.
96
     *
97
     * @var     int
98
     * @access  private
99
     */
100
    public $_default_error_mode = null;
101
102
    /**
103
     * Default error options used for this object when error mode
104
     * is PEAR_ERROR_TRIGGER.
105
     *
106
     * @var     int
107
     * @access  private
108
     */
109
    public $_default_error_options = null;
110
111
    /**
112
     * Default error handler (callback) for this object, if error mode is
113
     * PEAR_ERROR_CALLBACK.
114
     *
115
     * @var     string
116
     * @access  private
117
     */
118
    public $_default_error_handler = '';
119
120
    /**
121
     * Which class to use for error objects.
122
     *
123
     * @var     string
124
     * @access  private
125
     */
126
    public $_error_class = 'PEAR_Error';
127
128
    /**
129
     * An array of expected errors.
130
     *
131
     * @var     array
132
     * @access  private
133
     */
134
    public $_expected_errors = array();
135
136
    /**
137
     * List of methods that can be called both statically and non-statically.
138
     * @var array
139
     */
140
    protected static $bivalentMethods = array(
141
        'setErrorHandling' => true,
142
        'raiseError' => true,
143
        'throwError' => true,
144
        'pushErrorHandling' => true,
145
        'popErrorHandling' => true,
146
    );
147
148
    /**
149
     * Constructor.  Registers this object in
150
     * $_PEAR_destructor_object_list for destructor emulation if a
151
     * destructor object exists.
152
     *
153
     * @param string $error_class  (optional) which class to use for
154
     *        error objects, defaults to PEAR_Error.
155
     * @access public
156
     * @return void
157
     */
158
    public function __construct($error_class = null)
159
    {
160
        $classname = strtolower(get_class($this));
161
        if ($this->_debug) {
162
            print "PEAR constructor called, class=$classname\n";
163
        }
164
165
        if ($error_class !== null) {
166
            $this->_error_class = $error_class;
167
        }
168
169
        while ($classname && strcasecmp($classname, "pear")) {
170
            $destructor = "_$classname";
171
            if (method_exists($this, $destructor)) {
172
                global $_PEAR_destructor_object_list;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
173
                $_PEAR_destructor_object_list[] = $this;
174
                if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
175
                    register_shutdown_function("_PEAR_call_destructors");
176
                    $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
177
                }
178
                break;
179
            } else {
180
                $classname = get_parent_class($classname);
181
            }
182
        }
183
    }
184
185
    /**
186
     * Only here for backwards compatibility.
187
     * E.g. Archive_Tar calls $this->PEAR() in its constructor.
188
     *
189
     * @param string $error_class Which class to use for error objects,
190
     *                            defaults to PEAR_Error.
191
     */
192
    public function PEAR($error_class = null)
193
    {
194
        self::__construct($error_class);
0 ignored issues
show
Bug Best Practice introduced by
The method PEAR::__construct() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

194
        self::/** @scrutinizer ignore-call */ 
195
              __construct($error_class);
Loading history...
195
    }
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
    public function __call($method, $arguments)
216
    {
217
        if (!isset(self::$bivalentMethods[$method])) {
218
            trigger_error(
219
                'Call to undefined method PEAR::' . $method . '()',
220
                E_USER_ERROR
221
            );
222
        }
223
        return call_user_func_array(
224
            array(get_class(), '_' . $method),
225
            array_merge(array($this), $arguments)
226
        );
227
    }
228
229
    public static function __callStatic($method, $arguments)
230
    {
231
        if (!isset(self::$bivalentMethods[$method])) {
232
            trigger_error(
233
                'Call to undefined method PEAR::' . $method . '()',
234
                E_USER_ERROR
235
            );
236
        }
237
        return call_user_func_array(
238
            array(get_class(), '_' . $method),
239
            array_merge(array(null), $arguments)
240
        );
241
    }
242
243
    /**
244
    * If you have a class that's mostly/entirely static, and you need static
245
    * properties, you can use this method to simulate them. Eg. in your method(s)
246
    * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar');
247
    * You MUST use a reference, or they will not persist!
248
    *
249
    * @param  string $class  The calling classname, to prevent clashes
250
    * @param  string $var    The variable to retrieve.
251
    * @return mixed   A reference to the variable. If not set it will be
252
    *                 auto initialised to NULL.
253
    */
254
    public static function &getStaticProperty($class, $var)
255
    {
256
        static $properties;
257
        if (!isset($properties[$class])) {
258
            $properties[$class] = array();
259
        }
260
261
        if (!array_key_exists($var, $properties[$class])) {
262
            $properties[$class][$var] = null;
263
        }
264
265
        return $properties[$class][$var];
266
    }
267
268
    /**
269
    * Use this function to register a shutdown method for static
270
    * classes.
271
    *
272
    * @param  mixed $func  The function name (or array of class/method) to call
273
    * @param  mixed $args  The arguments to pass to the function
274
    *
275
    * @return void
276
    */
277
    public static function registerShutdownFunc($func, $args = array())
278
    {
279
        // if we are called statically, there is a potential
280
        // that no shutdown func is registered.  Bug #6445
281
        if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
282
            register_shutdown_function("_PEAR_call_destructors");
283
            $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
284
        }
285
        $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args);
286
    }
287
288
    /**
289
     * Tell whether a value is a PEAR error.
290
     *
291
     * @param   mixed $data   the value to test
292
     * @param   int   $code   if $data is an error object, return true
293
     *                        only if $code is a string and
294
     *                        $obj->getMessage() == $code or
295
     *                        $code is an integer and $obj->getCode() == $code
296
     *
297
     * @return  bool    true if parameter is an error
298
     */
299
    public static function isError($data, $code = null)
300
    {
301
        if (!is_a($data, 'PEAR_Error')) {
302
            return false;
303
        }
304
305
        if (is_null($code)) {
306
            return true;
307
        } elseif (is_string($code)) {
0 ignored issues
show
introduced by
The condition is_string($code) is always false.
Loading history...
308
            return $data->getMessage() == $code;
309
        }
310
311
        return $data->getCode() == $code;
312
    }
313
314
    /**
315
     * Sets how errors generated by this object should be handled.
316
     * Can be invoked both in objects and statically.  If called
317
     * statically, setErrorHandling sets the default behaviour for all
318
     * PEAR objects.  If called in an object, setErrorHandling sets
319
     * the default behaviour for that object.
320
     *
321
     * @param object $object
322
     *        Object the method was called on (non-static mode)
323
     *
324
     * @param int $mode
325
     *        One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
326
     *        PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
327
     *        PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION.
328
     *
329
     * @param mixed $options
330
     *        When $mode is PEAR_ERROR_TRIGGER, this is the error level (one
331
     *        of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
332
     *
333
     *        When $mode is PEAR_ERROR_CALLBACK, this parameter is expected
334
     *        to be the callback function or method.  A callback
335
     *        function is a string with the name of the function, a
336
     *        callback method is an array of two elements: the element
337
     *        at index 0 is the object, and the element at index 1 is
338
     *        the name of the method to call in the object.
339
     *
340
     *        When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is
341
     *        a printf format string used when printing the error
342
     *        message.
343
     *
344
     * @access public
345
     * @return void
346
     * @see PEAR_ERROR_RETURN
347
     * @see PEAR_ERROR_PRINT
348
     * @see PEAR_ERROR_TRIGGER
349
     * @see PEAR_ERROR_DIE
350
     * @see PEAR_ERROR_CALLBACK
351
     * @see PEAR_ERROR_EXCEPTION
352
     *
353
     * @since PHP 4.0.5
354
     */
355
    protected static function _setErrorHandling(
356
        $object,
357
        $mode = null,
358
        $options = null
359
    ) {
360
        if ($object !== null) {
361
            $setmode     = &$object->_default_error_mode;
362
            $setoptions  = &$object->_default_error_options;
363
        } else {
364
            $setmode     = &$GLOBALS['_PEAR_default_error_mode'];
365
            $setoptions  = &$GLOBALS['_PEAR_default_error_options'];
366
        }
367
368
        switch ($mode) {
369
            case PEAR_ERROR_EXCEPTION:
0 ignored issues
show
Deprecated Code introduced by
The constant PEAR_ERROR_EXCEPTION has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

369
            case /** @scrutinizer ignore-deprecated */ PEAR_ERROR_EXCEPTION:
Loading history...
370
            case PEAR_ERROR_RETURN:
371
            case PEAR_ERROR_PRINT:
372
            case PEAR_ERROR_TRIGGER:
373
            case PEAR_ERROR_DIE:
374
            case null:
375
                $setmode = $mode;
376
                $setoptions = $options;
377
                break;
378
379
            case PEAR_ERROR_CALLBACK:
380
                $setmode = $mode;
381
                // class/object method callback
382
                if (is_callable($options)) {
383
                    $setoptions = $options;
384
                } else {
385
                    trigger_error("invalid error callback", E_USER_WARNING);
386
                }
387
                break;
388
389
            default:
390
                trigger_error("invalid error mode", E_USER_WARNING);
391
                break;
392
        }
393
    }
394
395
    /**
396
     * This method is used to tell which errors you expect to get.
397
     * Expected errors are always returned with error mode
398
     * PEAR_ERROR_RETURN.  Expected error codes are stored in a stack,
399
     * and this method pushes a new element onto it.  The list of
400
     * expected errors are in effect until they are popped off the
401
     * stack with the popExpect() method.
402
     *
403
     * Note that this method can not be called statically
404
     *
405
     * @param mixed $code a single error code or an array of error codes to expect
406
     *
407
     * @return int     the new depth of the "expected errors" stack
408
     * @access public
409
     */
410
    public function expectError($code = '*')
411
    {
412
        if (is_array($code)) {
413
            array_push($this->_expected_errors, $code);
414
        } else {
415
            array_push($this->_expected_errors, array($code));
416
        }
417
        return count($this->_expected_errors);
418
    }
419
420
    /**
421
     * This method pops one element off the expected error codes
422
     * stack.
423
     *
424
     * @return array   the list of error codes that were popped
425
     */
426
    public function popExpect()
427
    {
428
        return array_pop($this->_expected_errors);
429
    }
430
431
    /**
432
     * This method checks unsets an error code if available
433
     *
434
     * @param mixed error code
435
     * @return bool true if the error code was unset, false otherwise
436
     * @access private
437
     * @since PHP 4.3.0
438
     */
439
    public function _checkDelExpect($error_code)
440
    {
441
        $deleted = false;
442
        foreach ($this->_expected_errors as $key => $error_array) {
443
            if (in_array($error_code, $error_array)) {
444
                unset($this->_expected_errors[$key][array_search($error_code, $error_array)]);
445
                $deleted = true;
446
            }
447
448
            // clean up empty arrays
449
            if (0 == count($this->_expected_errors[$key])) {
450
                unset($this->_expected_errors[$key]);
451
            }
452
        }
453
454
        return $deleted;
455
    }
456
457
    /**
458
     * This method deletes all occurrences of the specified element from
459
     * the expected error codes stack.
460
     *
461
     * @param  mixed $error_code error code that should be deleted
462
     * @return mixed list of error codes that were deleted or error
463
     * @access public
464
     * @since PHP 4.3.0
465
     */
466
    public function delExpect($error_code)
467
    {
468
        $deleted = false;
469
        if ((is_array($error_code) && (0 != count($error_code)))) {
470
            // $error_code is a non-empty array here; we walk through it trying
471
            // to unset all values
472
            foreach ($error_code as $key => $error) {
473
                $deleted =  $this->_checkDelExpect($error) ? true : false;
474
            }
475
476
            return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
0 ignored issues
show
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
Bug introduced by
The method raiseError() does not exist on PEAR. Since you implemented __callStatic, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

476
            return $deleted ? true : PEAR::/** @scrutinizer ignore-call */ raiseError("The expected error you submitted does not exist"); // IMPROVE ME
Loading history...
477
        } elseif (!empty($error_code)) {
478
            // $error_code comes alone, trying to unset it
479
            if ($this->_checkDelExpect($error_code)) {
480
                return true;
481
            }
482
483
            return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
0 ignored issues
show
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
484
        }
485
486
        // $error_code is empty
487
        return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME
0 ignored issues
show
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
488
    }
489
490
    /**
491
     * This method is a wrapper that returns an instance of the
492
     * configured error class with this object's default error
493
     * handling applied.  If the $mode and $options parameters are not
494
     * specified, the object's defaults are used.
495
     *
496
     * @param mixed $message a text error message or a PEAR error object
497
     *
498
     * @param int $code      a numeric error code (it is up to your class
499
     *                  to define these if you want to use codes)
500
     *
501
     * @param int $mode      One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
502
     *                  PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
503
     *                  PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION.
504
     *
505
     * @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter
506
     *                  specifies the PHP-internal error level (one of
507
     *                  E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
508
     *                  If $mode is PEAR_ERROR_CALLBACK, this
509
     *                  parameter specifies the callback function or
510
     *                  method.  In other error modes this parameter
511
     *                  is ignored.
512
     *
513
     * @param string $userinfo If you need to pass along for example debug
514
     *                  information, this parameter is meant for that.
515
     *
516
     * @param string $error_class The returned error object will be
517
     *                  instantiated from this class, if specified.
518
     *
519
     * @param bool $skipmsg If true, raiseError will only pass error codes,
520
     *                  the error message parameter will be dropped.
521
     *
522
     * @return object   a PEAR error object
523
     * @see PEAR::setErrorHandling
524
     * @since PHP 4.0.5
525
     */
526
    protected static function _raiseError(
527
        $object,
528
                         $message = null,
529
                         $code = null,
530
                         $mode = null,
531
                         $options = null,
532
                         $userinfo = null,
533
                         $error_class = null,
534
                         $skipmsg = false
535
    ) {
536
        // The error is yet a PEAR error object
537
        if (is_object($message)) {
538
            $code        = $message->getCode();
539
            $userinfo    = $message->getUserInfo();
540
            $error_class = $message->getType();
541
            $message->error_message_prefix = '';
542
            $message     = $message->getMessage();
543
        }
544
545
        if (
546
            $object !== null &&
547
            isset($object->_expected_errors) &&
548
            count($object->_expected_errors) > 0 &&
549
            count($exp = end($object->_expected_errors))
550
        ) {
551
            if ($exp[0] == "*" ||
552
                (is_int(reset($exp)) && in_array($code, $exp)) ||
553
                (is_string(reset($exp)) && in_array($message, $exp))
554
            ) {
555
                $mode = PEAR_ERROR_RETURN;
556
            }
557
        }
558
559
        // No mode given, try global ones
560
        if ($mode === null) {
561
            // Class error handler
562
            if ($object !== null && isset($object->_default_error_mode)) {
563
                $mode    = $object->_default_error_mode;
564
                $options = $object->_default_error_options;
565
                // Global error handler
566
            } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) {
567
                $mode    = $GLOBALS['_PEAR_default_error_mode'];
568
                $options = $GLOBALS['_PEAR_default_error_options'];
569
            }
570
        }
571
572
        if ($error_class !== null) {
573
            $ec = $error_class;
574
        } elseif ($object !== null && isset($object->_error_class)) {
575
            $ec = $object->_error_class;
576
        } else {
577
            $ec = 'PEAR_Error';
578
        }
579
580
        if ($skipmsg) {
581
            $a = new $ec($code, $mode, $options, $userinfo);
582
        } else {
583
            $a = new $ec($message, $code, $mode, $options, $userinfo);
584
        }
585
586
        return $a;
587
    }
588
589
    /**
590
     * Simpler form of raiseError with fewer options.  In most cases
591
     * message, code and userinfo are enough.
592
     *
593
     * @param mixed $message a text error message or a PEAR error object
594
     *
595
     * @param int $code      a numeric error code (it is up to your class
596
     *                  to define these if you want to use codes)
597
     *
598
     * @param string $userinfo If you need to pass along for example debug
599
     *                  information, this parameter is meant for that.
600
     *
601
     * @return object   a PEAR error object
602
     * @see PEAR::raiseError
603
     */
604
    protected static function _throwError($object, $message = null, $code = null, $userinfo = null)
605
    {
606
        if ($object !== null) {
607
            $a = $object->raiseError($message, $code, null, null, $userinfo);
608
            return $a;
609
        }
610
611
        $a = PEAR::raiseError($message, $code, null, null, $userinfo);
0 ignored issues
show
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
612
        return $a;
613
    }
614
615
    public static function staticPushErrorHandling($mode, $options = null)
616
    {
617
        $stack       = &$GLOBALS['_PEAR_error_handler_stack'];
618
        $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
619
        $def_options = &$GLOBALS['_PEAR_default_error_options'];
620
        $stack[] = array($def_mode, $def_options);
621
        switch ($mode) {
622
            case PEAR_ERROR_EXCEPTION:
0 ignored issues
show
Deprecated Code introduced by
The constant PEAR_ERROR_EXCEPTION has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

622
            case /** @scrutinizer ignore-deprecated */ PEAR_ERROR_EXCEPTION:
Loading history...
623
            case PEAR_ERROR_RETURN:
624
            case PEAR_ERROR_PRINT:
625
            case PEAR_ERROR_TRIGGER:
626
            case PEAR_ERROR_DIE:
627
            case null:
628
                $def_mode = $mode;
629
                $def_options = $options;
630
                break;
631
632
            case PEAR_ERROR_CALLBACK:
633
                $def_mode = $mode;
634
                // class/object method callback
635
                if (is_callable($options)) {
636
                    $def_options = $options;
637
                } else {
638
                    trigger_error("invalid error callback", E_USER_WARNING);
639
                }
640
                break;
641
642
            default:
643
                trigger_error("invalid error mode", E_USER_WARNING);
644
                break;
645
        }
646
        $stack[] = array($mode, $options);
647
        return true;
648
    }
649
650
    public static function staticPopErrorHandling()
651
    {
652
        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
653
        $setmode     = &$GLOBALS['_PEAR_default_error_mode'];
654
        $setoptions  = &$GLOBALS['_PEAR_default_error_options'];
655
        array_pop($stack);
656
        list($mode, $options) = $stack[sizeof($stack) - 1];
657
        array_pop($stack);
658
        switch ($mode) {
659
            case PEAR_ERROR_EXCEPTION:
0 ignored issues
show
Deprecated Code introduced by
The constant PEAR_ERROR_EXCEPTION has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

659
            case /** @scrutinizer ignore-deprecated */ PEAR_ERROR_EXCEPTION:
Loading history...
660
            case PEAR_ERROR_RETURN:
661
            case PEAR_ERROR_PRINT:
662
            case PEAR_ERROR_TRIGGER:
663
            case PEAR_ERROR_DIE:
664
            case null:
665
                $setmode = $mode;
666
                $setoptions = $options;
667
                break;
668
669
            case PEAR_ERROR_CALLBACK:
670
                $setmode = $mode;
671
                // class/object method callback
672
                if (is_callable($options)) {
673
                    $setoptions = $options;
674
                } else {
675
                    trigger_error("invalid error callback", E_USER_WARNING);
676
                }
677
                break;
678
679
            default:
680
                trigger_error("invalid error mode", E_USER_WARNING);
681
                break;
682
        }
683
        return true;
684
    }
685
686
    /**
687
     * Push a new error handler on top of the error handler options stack. With this
688
     * you can easily override the actual error handler for some code and restore
689
     * it later with popErrorHandling.
690
     *
691
     * @param mixed $mode (same as setErrorHandling)
692
     * @param mixed $options (same as setErrorHandling)
693
     *
694
     * @return bool Always true
695
     *
696
     * @see PEAR::setErrorHandling
697
     */
698
    protected static function _pushErrorHandling($object, $mode, $options = null)
699
    {
700
        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
701
        if ($object !== null) {
702
            $def_mode    = &$object->_default_error_mode;
703
            $def_options = &$object->_default_error_options;
704
        } else {
705
            $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
706
            $def_options = &$GLOBALS['_PEAR_default_error_options'];
707
        }
708
        $stack[] = array($def_mode, $def_options);
709
710
        if ($object !== null) {
711
            $object->setErrorHandling($mode, $options);
712
        } else {
713
            PEAR::setErrorHandling($mode, $options);
0 ignored issues
show
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
Bug introduced by
The method setErrorHandling() does not exist on PEAR. Since you implemented __callStatic, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

713
            PEAR::/** @scrutinizer ignore-call */ 
714
                  setErrorHandling($mode, $options);
Loading history...
714
        }
715
        $stack[] = array($mode, $options);
716
        return true;
717
    }
718
719
    /**
720
    * Pop the last error handler used
721
    *
722
    * @return bool Always true
723
    *
724
    * @see PEAR::pushErrorHandling
725
    */
726
    protected static function _popErrorHandling($object)
727
    {
728
        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
729
        array_pop($stack);
730
        list($mode, $options) = $stack[sizeof($stack) - 1];
731
        array_pop($stack);
732
        if ($object !== null) {
733
            $object->setErrorHandling($mode, $options);
734
        } else {
735
            PEAR::setErrorHandling($mode, $options);
0 ignored issues
show
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
736
        }
737
        return true;
738
    }
739
740
    /**
741
    * OS independent 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 static function loadExtension($ext)
748
    {
749
        if (extension_loaded($ext)) {
750
            return true;
751
        }
752
753
        // if either returns true dl() will produce a FATAL error, stop that
754
        if (
755
            function_exists('dl') === false ||
756
            ini_get('enable_dl') != 1
757
        ) {
758
            return false;
759
        }
760
761
        if (OS_WINDOWS) {
762
            $suffix = '.dll';
763
        } elseif (PHP_OS == 'HP-UX') {
764
            $suffix = '.sl';
765
        } elseif (PHP_OS == 'AIX') {
766
            $suffix = '.a';
767
        } elseif (PHP_OS == 'OSX') {
768
            $suffix = '.bundle';
769
        } else {
770
            $suffix = '.so';
771
        }
772
773
        return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix);
0 ignored issues
show
Deprecated Code introduced by
The function dl() has been deprecated: 5.3.0 since 5.3.0 Loads a PHP extension at runtime ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

773
        return @dl('php_'.$ext.$suffix) || @/** @scrutinizer ignore-deprecated */ dl($ext.$suffix);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
774
    }
775
}
776
777
function _PEAR_call_destructors()
778
{
779
    global $_PEAR_destructor_object_list;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
780
    if (is_array($_PEAR_destructor_object_list) &&
781
        sizeof($_PEAR_destructor_object_list)) {
782
        reset($_PEAR_destructor_object_list);
783
784
        $destructLifoExists = PEAR::getStaticProperty('PEAR', 'destructlifo');
785
786
        if ($destructLifoExists) {
787
            $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list);
788
        }
789
790
        while (list($k, $objref) = each($_PEAR_destructor_object_list)) {
0 ignored issues
show
Deprecated Code introduced by
The function each() has been deprecated: 7.2 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

790
        while (list($k, $objref) = /** @scrutinizer ignore-deprecated */ each($_PEAR_destructor_object_list)) {

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
791
            $classname = get_class($objref);
792
            while ($classname) {
793
                $destructor = "_$classname";
794
                if (method_exists($objref, $destructor)) {
795
                    $objref->$destructor();
796
                    break;
797
                } else {
798
                    $classname = get_parent_class($classname);
799
                }
800
            }
801
        }
802
        // Empty the object list to ensure that destructors are
803
        // not called more than once.
804
        $_PEAR_destructor_object_list = array();
805
    }
806
807
    // Now call the shutdown functions
808
    if (
809
        isset($GLOBALS['_PEAR_shutdown_funcs']) &&
810
        is_array($GLOBALS['_PEAR_shutdown_funcs']) &&
811
        !empty($GLOBALS['_PEAR_shutdown_funcs'])
812
    ) {
813
        foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) {
814
            call_user_func_array($value[0], $value[1]);
815
        }
816
    }
817
}
818
819
/**
820
 * Standard PEAR error class for PHP 4
821
 *
822
 * This class is supserseded by {@link PEAR_Exception} in PHP 5
823
 *
824
 * @category   pear
825
 * @package    PEAR
826
 * @author     Stig Bakken <[email protected]>
827
 * @author     Tomas V.V. Cox <[email protected]>
828
 * @author     Gregory Beaver <[email protected]>
829
 * @copyright  1997-2006 The PHP Group
830
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
831
 * @version    Release: 1.10.5
832
 * @link       http://pear.php.net/manual/en/core.pear.pear-error.php
833
 * @see        PEAR::raiseError(), PEAR::throwError()
834
 * @since      Class available since PHP 4.0.2
835
 */
836
class PEAR_Error
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
837
{
838
    public $error_message_prefix = '';
839
    public $mode                 = PEAR_ERROR_RETURN;
840
    public $level                = E_USER_NOTICE;
841
    public $code                 = -1;
842
    public $message              = '';
843
    public $userinfo             = '';
844
    public $backtrace            = null;
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
    public function __construct(
867
        $message = 'unknown error',
868
        $code = null,
869
                        $mode = null,
870
        $options = null,
871
        $userinfo = null
872
    ) {
873
        if ($mode === null) {
874
            $mode = PEAR_ERROR_RETURN;
875
        }
876
        $this->message   = $message;
877
        $this->code      = $code;
878
        $this->mode      = $mode;
879
        $this->userinfo  = $userinfo;
880
881
        $skiptrace = PEAR::getStaticProperty('PEAR_Error', 'skiptrace');
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;
0 ignored issues
show
Bug Best Practice introduced by
The property callback does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
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
            printf($format, $msg);
927
            exit($code);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
928
        }
929
930
        if ($this->mode & PEAR_ERROR_CALLBACK && is_callable($this->callback)) {
931
            call_user_func($this->callback, $this);
932
        }
933
934
        if ($this->mode & PEAR_ERROR_EXCEPTION) {
0 ignored issues
show
Deprecated Code introduced by
The constant PEAR_ERROR_EXCEPTION has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

934
        if ($this->mode & /** @scrutinizer ignore-deprecated */ PEAR_ERROR_EXCEPTION) {
Loading history...
935
            trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions", E_USER_WARNING);
936
            eval('$e = new Exception($this->message, $this->code);throw($e);');
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
937
        }
938
    }
939
940
    /**
941
     * Only here for backwards compatibility.
942
     *
943
     * Class "Cache_Error" still uses it, among others.
944
     *
945
     * @param string $message  Message
946
     * @param int    $code     Error code
947
     * @param int    $mode     Error mode
948
     * @param mixed  $options  See __construct()
949
     * @param string $userinfo Additional user/debug info
950
     */
951
    public function PEAR_Error(
952
        $message = 'unknown error',
953
        $code = null,
954
        $mode = null,
955
        $options = null,
956
        $userinfo = null
957
    ) {
958
        self::__construct($message, $code, $mode, $options, $userinfo);
0 ignored issues
show
Bug Best Practice introduced by
The method PEAR_Error::__construct() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

958
        self::/** @scrutinizer ignore-call */ 
959
              __construct($message, $code, $mode, $options, $userinfo);
Loading history...
959
    }
960
961
    /**
962
     * Get the error mode from an error object.
963
     *
964
     * @return int error mode
965
     * @access public
966
     */
967
    public function getMode()
968
    {
969
        return $this->mode;
970
    }
971
972
    /**
973
     * Get the callback function/method from an error object.
974
     *
975
     * @return mixed callback function or object/method array
976
     * @access public
977
     */
978
    public function getCallback()
979
    {
980
        return $this->callback;
981
    }
982
983
    /**
984
     * Get the error message from an error object.
985
     *
986
     * @return  string  full error message
987
     * @access public
988
     */
989
    public function getMessage()
990
    {
991
        return ($this->error_message_prefix . $this->message);
992
    }
993
994
    /**
995
     * Get error code from an error object
996
     *
997
     * @return int error code
998
     * @access public
999
     */
1000
    public function getCode()
1001
    {
1002
        return $this->code;
1003
    }
1004
1005
    /**
1006
     * Get the name of this error/exception.
1007
     *
1008
     * @return string error/exception name (type)
1009
     * @access public
1010
     */
1011
    public function getType()
1012
    {
1013
        return get_class($this);
1014
    }
1015
1016
    /**
1017
     * Get additional user-supplied information.
1018
     *
1019
     * @return string user-supplied information
1020
     * @access public
1021
     */
1022
    public function getUserInfo()
1023
    {
1024
        return $this->userinfo;
1025
    }
1026
1027
    /**
1028
     * Get additional debug information supplied by the application.
1029
     *
1030
     * @return string debug information
1031
     * @access public
1032
     */
1033
    public function getDebugInfo()
1034
    {
1035
        return $this->getUserInfo();
1036
    }
1037
1038
    /**
1039
     * Get the call backtrace from where the error was generated.
1040
     * Supported with PHP 4.3.0 or newer.
1041
     *
1042
     * @param int $frame (optional) what frame to fetch
1043
     * @return array Backtrace, or NULL if not available.
1044
     * @access public
1045
     */
1046
    public function getBacktrace($frame = null)
1047
    {
1048
        if (defined('PEAR_IGNORE_BACKTRACE')) {
1049
            return null;
1050
        }
1051
        if ($frame === null) {
1052
            return $this->backtrace;
1053
        }
1054
        return $this->backtrace[$frame];
1055
    }
1056
1057
    public function addUserInfo($info)
1058
    {
1059
        if (empty($this->userinfo)) {
1060
            $this->userinfo = $info;
1061
        } else {
1062
            $this->userinfo .= " ** $info";
1063
        }
1064
    }
1065
1066
    public function __toString()
1067
    {
1068
        return $this->getMessage();
1069
    }
1070
1071
    /**
1072
     * Make a string representation of this object.
1073
     *
1074
     * @return string a string with an object summary
1075
     * @access public
1076
     */
1077
    public function toString()
1078
    {
1079
        $modes = array();
1080
        $levels = array(E_USER_NOTICE  => 'notice',
1081
                        E_USER_WARNING => 'warning',
1082
                        E_USER_ERROR   => 'error');
1083
        if ($this->mode & PEAR_ERROR_CALLBACK) {
1084
            if (is_array($this->callback)) {
1085
                $callback = (is_object($this->callback[0]) ?
1086
                    strtolower(get_class($this->callback[0])) :
1087
                    $this->callback[0]) . '::' .
1088
                    $this->callback[1];
1089
            } else {
1090
                $callback = $this->callback;
1091
            }
1092
            return sprintf(
1093
                '[%s: message="%s" code=%d mode=callback '.
1094
                           'callback=%s prefix="%s" info="%s"]',
1095
                           strtolower(get_class($this)),
1096
                $this->message,
1097
                $this->code,
1098
                           $callback,
1099
                $this->error_message_prefix,
1100
                           $this->userinfo
1101
            );
1102
        }
1103
        if ($this->mode & PEAR_ERROR_PRINT) {
1104
            $modes[] = 'print';
1105
        }
1106
        if ($this->mode & PEAR_ERROR_TRIGGER) {
1107
            $modes[] = 'trigger';
1108
        }
1109
        if ($this->mode & PEAR_ERROR_DIE) {
1110
            $modes[] = 'die';
1111
        }
1112
        if ($this->mode & PEAR_ERROR_RETURN) {
1113
            $modes[] = 'return';
1114
        }
1115
        return sprintf(
1116
            '[%s: message="%s" code=%d mode=%s level=%s '.
1117
                       'prefix="%s" info="%s"]',
1118
                       strtolower(get_class($this)),
1119
            $this->message,
1120
            $this->code,
1121
                       implode("|", $modes),
1122
            $levels[$this->level],
1123
                       $this->error_message_prefix,
1124
                       $this->userinfo
1125
        );
1126
    }
1127
}
1128
1129
/*
1130
 * Local Variables:
1131
 * mode: php
1132
 * tab-width: 4
1133
 * c-basic-offset: 4
1134
 * End:
1135
 */
1136