Completed
Push — master ( 72613d...069c91 )
by Michael
02:16
created

PEAR_Error::toString()   C

Complexity

Conditions 8
Paths 19

Size

Total Lines 32
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 21
nc 19
nop 0
dl 0
loc 32
rs 5.3846
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 ('WIN' == substr(PHP_OS, 0, 3)) {
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
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...
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.3
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
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...
154
     *                            error objects, defaults to PEAR_Error.
155
     * @access public
156
     * @return void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
157
     */
158
    public function __construct($error_class = null)
0 ignored issues
show
Coding Style introduced by
__construct uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
159
    {
160
        $classname = strtolower(get_class($this));
161
        if ($this->_debug) {
162
            print "PEAR constructor called, class=$classname\n";
163
        }
164
165
        if (null !== $error_class) {
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,
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...
190
     *                            defaults to PEAR_Error.
191
     */
192
    public function PEAR($error_class = null)
193
    {
194
        self::__construct($error_class);
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 View Code Duplication
    public function __call($method, $arguments)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
216
    {
217
        if (!isset(self::$bivalentMethods[$method])) {
218
            trigger_error('Call to undefined method PEAR::' . $method . '()', E_USER_ERROR);
219
        }
220
221
        return call_user_func_array(array(get_class(), '_' . $method), array_merge(array($this), $arguments));
222
    }
223
224 View Code Duplication
    public static function __callStatic($method, $arguments)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
225
    {
226
        if (!isset(self::$bivalentMethods[$method])) {
227
            trigger_error('Call to undefined method PEAR::' . $method . '()', E_USER_ERROR);
228
        }
229
230
        return call_user_func_array(array(get_class(), '_' . $method), array_merge(array(null), $arguments));
231
    }
232
233
    /**
234
     * If you have a class that's mostly/entirely static, and you need static
235
     * properties, you can use this method to simulate them. Eg. in your method(s)
236
     * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar');
237
     * You MUST use a reference, or they will not persist!
238
     *
239
     * @param  string $class The calling classname, to prevent clashes
240
     * @param  string $var   The variable to retrieve.
241
     * @return mixed   A reference to the variable. If not set it will be
242
     *                       auto initialised to NULL.
243
     */
244
    public static function &getStaticProperty($class, $var)
245
    {
246
        static $properties;
247
        if (!isset($properties[$class])) {
248
            $properties[$class] = array();
249
        }
250
251
        if (!array_key_exists($var, $properties[$class])) {
252
            $properties[$class][$var] = null;
253
        }
254
255
        return $properties[$class][$var];
256
    }
257
258
    /**
259
     * Use this function to register a shutdown method for static
260
     * classes.
261
     *
262
     * @param  mixed $func The function name (or array of class/method) to call
263
     * @param  mixed $args The arguments to pass to the function
264
     *
265
     * @return void
266
     */
267
    public static function registerShutdownFunc($func, $args = array())
0 ignored issues
show
Coding Style introduced by
registerShutdownFunc uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
268
    {
269
        // if we are called statically, there is a potential
270
        // that no shutdown func is registered.  Bug #6445
271
        if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
272
            register_shutdown_function("_PEAR_call_destructors");
273
            $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
274
        }
275
        $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args);
276
    }
277
278
    /**
279
     * Tell whether a value is a PEAR error.
280
     *
281
     * @param   mixed $data   the value to test
282
     * @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...
283
     *                        only if $code is a string and
284
     *                        $obj->getMessage() == $code or
285
     *                        $code is an integer and $obj->getCode() == $code
286
     *
287
     * @return  bool    true if parameter is an error
288
     */
289
    public static function isError($data, $code = null)
290
    {
291
        if (!is_a($data, 'PEAR_Error')) {
292
            return false;
293
        }
294
295
        if (is_null($code)) {
296
            return true;
297
        } elseif (is_string($code)) {
298
            return $data->getMessage() == $code;
299
        }
300
301
        return $data->getCode() == $code;
302
    }
303
304
    /**
305
     * Sets how errors generated by this object should be handled.
306
     * Can be invoked both in objects and statically.  If called
307
     * statically, setErrorHandling sets the default behaviour for all
308
     * PEAR objects.  If called in an object, setErrorHandling sets
309
     * the default behaviour for that object.
310
     *
311
     * @param object $object
312
     *        Object the method was called on (non-static mode)
313
     *
314
     * @param int    $mode
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...
315
     *        One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
316
     *        PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
317
     *        PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION.
318
     *
319
     * @param mixed  $options
320
     *        When $mode is PEAR_ERROR_TRIGGER, this is the error level (one
321
     *        of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
322
     *
323
     *        When $mode is PEAR_ERROR_CALLBACK, this parameter is expected
324
     *        to be the callback function or method.  A callback
325
     *        function is a string with the name of the function, a
326
     *        callback method is an array of two elements: the element
327
     *        at index 0 is the object, and the element at index 1 is
328
     *        the name of the method to call in the object.
329
     *
330
     *        When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is
331
     *        a printf format string used when printing the error
332
     *        message.
333
     *
334
     * @access public
335
     * @return void
336
     * @see    PEAR_ERROR_RETURN
337
     * @see    PEAR_ERROR_PRINT
338
     * @see    PEAR_ERROR_TRIGGER
339
     * @see    PEAR_ERROR_DIE
340
     * @see    PEAR_ERROR_CALLBACK
341
     * @see    PEAR_ERROR_EXCEPTION
342
     *
343
     * @since  PHP 4.0.5
344
     */
345
    protected static function _setErrorHandling(
0 ignored issues
show
Coding Style introduced by
_setErrorHandling uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
346
        $object,
347
        $mode = null,
348
        $options = null
349
    ) {
350 View Code Duplication
        if (null !== $object) {
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...
351
            $setmode    = &$object->_default_error_mode;
352
            $setoptions = &$object->_default_error_options;
353
        } else {
354
            $setmode    = &$GLOBALS['_PEAR_default_error_mode'];
355
            $setoptions = &$GLOBALS['_PEAR_default_error_options'];
356
        }
357
358 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...
359
            case PEAR_ERROR_EXCEPTION:
0 ignored issues
show
Deprecated Code introduced by
The constant PEAR_ERROR_EXCEPTION has been deprecated.

This constant has been deprecated.

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

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
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...
468
        } elseif (!empty($error_code)) {
469
            // $error_code comes alone, trying to unset it
470
            if ($this->_checkDelExpect($error_code)) {
471
                return true;
472
            }
473
474
            return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Did you maybe mean _raiseError()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
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...
475
        }
476
477
        // $error_code is empty
478
        return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Did you maybe mean _raiseError()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
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...
479
    }
480
481
    /**
482
     * This method is a wrapper that returns an instance of the
483
     * configured error class with this object's default error
484
     * handling applied.  If the $mode and $options parameters are not
485
     * specified, the object's defaults are used.
486
     *
487
     * @param mixed  $message     a text error message or a PEAR error object
488
     *
489
     * @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...
490
     *                            to define these if you want to use codes)
491
     *
492
     * @param int    $mode        One of PEAR_ERROR_RETURN, 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...
493
     *                            PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
494
     *                            PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION.
495
     *
496
     * @param mixed  $options     If $mode is PEAR_ERROR_TRIGGER, this parameter
497
     *                            specifies the PHP-internal error level (one of
498
     *                            E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
499
     *                            If $mode is PEAR_ERROR_CALLBACK, this
500
     *                            parameter specifies the callback function or
501
     *                            method.  In other error modes this parameter
502
     *                            is ignored.
503
     *
504
     * @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...
505
     *                            information, this parameter is meant for that.
506
     *
507
     * @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...
508
     *                            instantiated from this class, if specified.
509
     *
510
     * @param bool   $skipmsg     If true, raiseError will only pass error codes,
511
     *                            the error message parameter will be dropped.
512
     *
513
     * @return object   a PEAR error object
514
     * @see   PEAR::setErrorHandling
515
     * @since PHP 4.0.5
516
     */
517
    protected static function _raiseError(
0 ignored issues
show
Coding Style introduced by
_raiseError uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
518
        $object,
519
        $message = null,
520
        $code = null,
521
        $mode = null,
522
        $options = null,
523
        $userinfo = null,
524
        $error_class = null,
525
        $skipmsg = false
526
    ) {
527
        // The error is yet a PEAR error object
528
        if (is_object($message)) {
529
            $code                          = $message->getCode();
530
            $userinfo                      = $message->getUserInfo();
531
            $error_class                   = $message->getType();
532
            $message->error_message_prefix = '';
533
            $message                       = $message->getMessage();
534
        }
535
536
        if (null !== $object
537
            && isset($object->_expected_errors)
538
            && count($object->_expected_errors) > 0
539
            && count($exp = end($object->_expected_errors))) {
540
            if ("*" == $exp[0]
541
                || (is_int(reset($exp)) && in_array($code, $exp))
542
                || (is_string(reset($exp)) && in_array($message, $exp))) {
543
                $mode = PEAR_ERROR_RETURN;
544
            }
545
        }
546
547
        // No mode given, try global ones
548
        if (null === $mode) {
549
            // Class error handler
550
            if (null !== $object && isset($object->_default_error_mode)) {
551
                $mode    = $object->_default_error_mode;
552
                $options = $object->_default_error_options;
553
                // Global error handler
554
            } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) {
555
                $mode    = $GLOBALS['_PEAR_default_error_mode'];
556
                $options = $GLOBALS['_PEAR_default_error_options'];
557
            }
558
        }
559
560
        if (null !== $error_class) {
561
            $ec = $error_class;
562
        } elseif (null !== $object && isset($object->_error_class)) {
563
            $ec = $object->_error_class;
564
        } else {
565
            $ec = 'PEAR_Error';
566
        }
567
568
        if ($skipmsg) {
569
            $a = new $ec($code, $mode, $options, $userinfo);
570
        } else {
571
            $a = new $ec($message, $code, $mode, $options, $userinfo);
572
        }
573
574
        return $a;
575
    }
576
577
    /**
578
     * Simpler form of raiseError with fewer options.  In most cases
579
     * message, code and userinfo are enough.
580
     *
581
     * @param mixed  $message  a text error message or a PEAR error object
582
     *
583
     * @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...
584
     *                         to define these if you want to use codes)
585
     *
586
     * @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...
587
     *                         information, this parameter is meant for that.
588
     *
589
     * @return object   a PEAR error object
590
     * @see PEAR::raiseError
591
     */
592
    protected static function _throwError($object, $message = null, $code = null, $userinfo = null)
593
    {
594
        if (null !== $object) {
595
            $a = &$object->raiseError($message, $code, null, null, $userinfo);
596
597
            return $a;
598
        }
599
600
        $a = &PEAR::raiseError($message, $code, null, null, $userinfo);
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Did you maybe mean _raiseError()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
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...
601
602
        return $a;
603
    }
604
605
    public static function staticPushErrorHandling($mode, $options = null)
0 ignored issues
show
Coding Style introduced by
staticPushErrorHandling uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
606
    {
607
        $stack       = &$GLOBALS['_PEAR_error_handler_stack'];
608
        $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
609
        $def_options = &$GLOBALS['_PEAR_default_error_options'];
610
        $stack[]     = array($def_mode, $def_options);
611 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...
612
            case PEAR_ERROR_EXCEPTION:
0 ignored issues
show
Deprecated Code introduced by
The constant PEAR_ERROR_EXCEPTION has been deprecated.

This constant has been deprecated.

Loading history...
613
            case PEAR_ERROR_RETURN:
614
            case PEAR_ERROR_PRINT:
615
            case PEAR_ERROR_TRIGGER:
616
            case PEAR_ERROR_DIE:
617
            case null:
618
                $def_mode    = $mode;
619
                $def_options = $options;
620
                break;
621
622
            case PEAR_ERROR_CALLBACK:
623
                $def_mode = $mode;
624
                // class/object method callback
625
                if (is_callable($options)) {
626
                    $def_options = $options;
627
                } else {
628
                    trigger_error("invalid error callback", E_USER_WARNING);
629
                }
630
                break;
631
632
            default:
633
                trigger_error("invalid error mode", E_USER_WARNING);
634
                break;
635
        }
636
        $stack[] = array($mode, $options);
637
638
        return true;
639
    }
640
641
    public static function staticPopErrorHandling()
0 ignored issues
show
Coding Style introduced by
staticPopErrorHandling uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
642
    {
643
        $stack      = &$GLOBALS['_PEAR_error_handler_stack'];
644
        $setmode    = &$GLOBALS['_PEAR_default_error_mode'];
645
        $setoptions = &$GLOBALS['_PEAR_default_error_options'];
646
        array_pop($stack);
647
        list($mode, $options) = $stack[sizeof($stack) - 1];
648
        array_pop($stack);
649 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...
650
            case PEAR_ERROR_EXCEPTION:
0 ignored issues
show
Deprecated Code introduced by
The constant PEAR_ERROR_EXCEPTION has been deprecated.

This constant has been deprecated.

Loading history...
651
            case PEAR_ERROR_RETURN:
652
            case PEAR_ERROR_PRINT:
653
            case PEAR_ERROR_TRIGGER:
654
            case PEAR_ERROR_DIE:
655
            case null:
656
                $setmode    = $mode;
657
                $setoptions = $options;
658
                break;
659
660
            case PEAR_ERROR_CALLBACK:
661
                $setmode = $mode;
662
                // class/object method callback
663
                if (is_callable($options)) {
664
                    $setoptions = $options;
665
                } else {
666
                    trigger_error("invalid error callback", E_USER_WARNING);
667
                }
668
                break;
669
670
            default:
671
                trigger_error("invalid error mode", E_USER_WARNING);
672
                break;
673
        }
674
675
        return true;
676
    }
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 PEAR::setErrorHandling
689
     */
690
    protected static function _pushErrorHandling($object, $mode, $options = null)
0 ignored issues
show
Coding Style introduced by
_pushErrorHandling uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
691
    {
692
        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
693 View Code Duplication
        if (null !== $object) {
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    = &$object->_default_error_mode;
695
            $def_options = &$object->_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
        if (null !== $object) {
703
            $object->setErrorHandling($mode, $options);
704
        } else {
705
            PEAR::setErrorHandling($mode, $options);
0 ignored issues
show
Bug introduced by
The method setErrorHandling() does not exist on PEAR. Did you maybe mean _setErrorHandling()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
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...
706
        }
707
        $stack[] = array($mode, $options);
708
709
        return true;
710
    }
711
712
    /**
713
     * Pop the last error handler used
714
     *
715
     * @return bool Always true
716
     *
717
     * @see PEAR::pushErrorHandling
718
     */
719
    protected static function _popErrorHandling($object)
0 ignored issues
show
Coding Style introduced by
_popErrorHandling uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
720
    {
721
        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
722
        array_pop($stack);
723
        list($mode, $options) = $stack[sizeof($stack) - 1];
724
        array_pop($stack);
725
        if (null !== $object) {
726
            $object->setErrorHandling($mode, $options);
727
        } else {
728
            PEAR::setErrorHandling($mode, $options);
0 ignored issues
show
Bug introduced by
The method setErrorHandling() does not exist on PEAR. Did you maybe mean _setErrorHandling()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
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...
729
        }
730
731
        return true;
732
    }
733
734
    /**
735
     * OS independent PHP extension load. Remember to take care
736
     * on the correct extension name for case sensitive OSes.
737
     *
738
     * @param string $ext The extension name
739
     * @return bool Success or not on the dl() call
740
     */
741
    public static function loadExtension($ext)
742
    {
743
        if (extension_loaded($ext)) {
744
            return true;
745
        }
746
747
        // if either returns true dl() will produce a FATAL error, stop that
748
        if (false === function_exists('dl')
749
            || 1 != ini_get('enable_dl')) {
750
            return false;
751
        }
752
753
        if (OS_WINDOWS) {
754
            $suffix = '.dll';
755
        } elseif (PHP_OS == 'HP-UX') {
756
            $suffix = '.sl';
757
        } elseif (PHP_OS == 'AIX') {
758
            $suffix = '.a';
759
        } elseif (PHP_OS == 'OSX') {
760
            $suffix = '.bundle';
761
        } else {
762
            $suffix = '.so';
763
        }
764
765
        return @dl('php_' . $ext . $suffix) || @dl($ext . $suffix);
766
    }
767
}
768
769
function _PEAR_call_destructors()
0 ignored issues
show
Coding Style introduced by
_PEAR_call_destructors uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
770
{
771
    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...
772
    if (is_array($_PEAR_destructor_object_list)
773
        && sizeof($_PEAR_destructor_object_list)) {
774
        reset($_PEAR_destructor_object_list);
775
776
        $destructLifoExists = PEAR::getStaticProperty('PEAR', 'destructlifo');
777
778
        if ($destructLifoExists) {
779
            $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list);
780
        }
781
782
        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...
783
            $classname = get_class($objref);
784
            while ($classname) {
785
                $destructor = "_$classname";
786
                if (method_exists($objref, $destructor)) {
787
                    $objref->$destructor();
788
                    break;
789
                } else {
790
                    $classname = get_parent_class($classname);
791
                }
792
            }
793
        }
794
        // Empty the object list to ensure that destructors are
795
        // not called more than once.
796
        $_PEAR_destructor_object_list = array();
797
    }
798
799
    // Now call the shutdown functions
800
    if (isset($GLOBALS['_PEAR_shutdown_funcs'])
801
        && is_array($GLOBALS['_PEAR_shutdown_funcs'])
802
        && !empty($GLOBALS['_PEAR_shutdown_funcs'])) {
803
        foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) {
804
            call_user_func_array($value[0], $value[1]);
805
        }
806
    }
807
}
808
809
/**
810
 * Standard PEAR error class for PHP 4
811
 *
812
 * This class is supserseded by {@link PEAR_Exception} in PHP 5
813
 *
814
 * @category   pear
815
 * @package    PEAR
816
 * @author     Stig Bakken <[email protected]>
817
 * @author     Tomas V.V. Cox <[email protected]>
818
 * @author     Gregory Beaver <[email protected]>
819
 * @copyright  1997-2006 The PHP Group
820
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
821
 * @version    Release: 1.10.3
822
 * @link       http://pear.php.net/manual/en/core.pear.pear-error.php
823
 * @see        PEAR::raiseError(), PEAR::throwError()
824
 * @since      Class available since PHP 4.0.2
825
 */
826
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...
827
{
828
    public $error_message_prefix = '';
829
    public $mode                 = PEAR_ERROR_RETURN;
830
    public $level                = E_USER_NOTICE;
831
    public $code                 = -1;
832
    public $message              = '';
833
    public $userinfo             = '';
834
    public $backtrace            = null;
835
836
    /**
837
     * PEAR_Error constructor
838
     *
839
     * @param string $message  message
840
     *
841
     * @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...
842
     *
843
     * @param int    $mode     (optional) error mode, one of: 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...
844
     *                         PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER,
845
     *                         PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION
846
     *
847
     * @param mixed  $options  (optional) error level, _OR_ in the case of
848
     *                         PEAR_ERROR_CALLBACK, the callback function or object/method
849
     *                         tuple.
850
     *
851
     * @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...
852
     *
853
     * @access public
854
     *
855
     */
856
    public function __construct(
857
        $message = 'unknown error',
858
        $code = null,
859
        $mode = null,
860
        $options = null,
861
        $userinfo = null
862
    ) {
863
        if (null === $mode) {
864
            $mode = PEAR_ERROR_RETURN;
865
        }
866
        $this->message  = $message;
867
        $this->code     = $code;
868
        $this->mode     = $mode;
869
        $this->userinfo = $userinfo;
870
871
        $skiptrace = PEAR::getStaticProperty('PEAR_Error', 'skiptrace');
872
873
        if (!$skiptrace) {
874
            $this->backtrace = debug_backtrace();
875
            if (isset($this->backtrace[0]) && isset($this->backtrace[0]['object'])) {
876
                unset($this->backtrace[0]['object']);
877
            }
878
        }
879
880
        if ($mode & 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 (null === $options) {
885
                $options = E_USER_NOTICE;
886
            }
887
888
            $this->level    = $options;
889
            $this->callback = null;
890
        }
891
892
        if ($this->mode & PEAR_ERROR_PRINT) {
893
            if (is_null($options) || is_int($options)) {
894
                $format = "%s";
895
            } else {
896
                $format = $options;
897
            }
898
899
            printf($format, $this->getMessage());
900
        }
901
902
        if ($this->mode & PEAR_ERROR_TRIGGER) {
903
            trigger_error($this->getMessage(), $this->level);
904
        }
905
906
        if ($this->mode & PEAR_ERROR_DIE) {
907
            $msg = $this->getMessage();
908
            if (is_null($options) || is_int($options)) {
909
                $format = "%s";
910
                if ("\n" != substr($msg, -1)) {
911
                    $msg .= "\n";
912
                }
913
            } else {
914
                $format = $options;
915
            }
916
            printf($format, $msg);
917
            exit($code);
0 ignored issues
show
Coding Style Compatibility introduced by
The method __construct() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
918
        }
919
920
        if ($this->mode & PEAR_ERROR_CALLBACK && is_callable($this->callback)) {
921
            call_user_func($this->callback, $this);
922
        }
923
924
        if ($this->mode & PEAR_ERROR_EXCEPTION) {
0 ignored issues
show
Deprecated Code introduced by
The constant PEAR_ERROR_EXCEPTION has been deprecated.

This constant has been deprecated.

Loading history...
925
            trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions", E_USER_WARNING);
926
            eval('$e = new Exception($this->message, $this->code);throw($e);');
0 ignored issues
show
Coding Style introduced by
It is generally not recommended to use eval unless absolutely required.

On one hand, eval might be exploited by malicious users if they somehow manage to inject dynamic content. On the other hand, with the emergence of faster PHP runtimes like the HHVM, eval prevents some optimization that they perform.

Loading history...
927
        }
928
    }
929
930
    /**
931
     * Only here for backwards compatibility.
932
     *
933
     * Class "Cache_Error" still uses it, among others.
934
     *
935
     * @param string $message  Message
936
     * @param int    $code     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...
937
     * @param int    $mode     Error mode
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...
938
     * @param mixed  $options  See __construct()
939
     * @param string $userinfo 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...
940
     */
941
    public function PEAR_Error(
942
        $message = 'unknown error',
943
        $code = null,
944
        $mode = null,
945
        $options = null,
946
        $userinfo = null
947
    ) {
948
        self::__construct($message, $code, $mode, $options, $userinfo);
949
    }
950
951
    /**
952
     * Get the error mode from an error object.
953
     *
954
     * @return int error mode
955
     * @access public
956
     */
957
    public function getMode()
958
    {
959
        return $this->mode;
960
    }
961
962
    /**
963
     * Get the callback function/method from an error object.
964
     *
965
     * @return mixed callback function or object/method array
966
     * @access public
967
     */
968
    public function getCallback()
969
    {
970
        return $this->callback;
971
    }
972
973
    /**
974
     * Get the error message from an error object.
975
     *
976
     * @return  string  full error message
977
     * @access public
978
     */
979
    public function getMessage()
980
    {
981
        return ($this->error_message_prefix . $this->message);
982
    }
983
984
    /**
985
     * Get error code from an error object
986
     *
987
     * @return int error code
988
     * @access public
989
     */
990
    public function getCode()
991
    {
992
        return $this->code;
993
    }
994
995
    /**
996
     * Get the name of this error/exception.
997
     *
998
     * @return string error/exception name (type)
999
     * @access public
1000
     */
1001
    public function getType()
1002
    {
1003
        return get_class($this);
1004
    }
1005
1006
    /**
1007
     * Get additional user-supplied information.
1008
     *
1009
     * @return string user-supplied information
1010
     * @access public
1011
     */
1012
    public function getUserInfo()
1013
    {
1014
        return $this->userinfo;
1015
    }
1016
1017
    /**
1018
     * Get additional debug information supplied by the application.
1019
     *
1020
     * @return string debug information
1021
     * @access public
1022
     */
1023
    public function getDebugInfo()
1024
    {
1025
        return $this->getUserInfo();
1026
    }
1027
1028
    /**
1029
     * Get the call backtrace from where the error was generated.
1030
     * Supported with PHP 4.3.0 or newer.
1031
     *
1032
     * @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...
1033
     * @return array Backtrace, or NULL if not available.
1034
     * @access public
1035
     */
1036
    public function getBacktrace($frame = null)
1037
    {
1038
        if (defined('PEAR_IGNORE_BACKTRACE')) {
1039
            return null;
1040
        }
1041
        if (null === $frame) {
1042
            return $this->backtrace;
1043
        }
1044
1045
        return $this->backtrace[$frame];
1046
    }
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
    public function __toString()
1058
    {
1059
        return $this->getMessage();
1060
    }
1061
1062
    /**
1063
     * Make a string representation of this object.
1064
     *
1065
     * @return string a string with an object summary
1066
     * @access public
1067
     */
1068
    public function toString()
1069
    {
1070
        $modes  = array();
1071
        $levels = array(
1072
            E_USER_NOTICE  => 'notice',
1073
            E_USER_WARNING => 'warning',
1074
            E_USER_ERROR   => 'error'
1075
        );
1076
        if ($this->mode & PEAR_ERROR_CALLBACK) {
1077
            if (is_array($this->callback)) {
1078
                $callback = (is_object($this->callback[0]) ? strtolower(get_class($this->callback[0])) : $this->callback[0]) . '::' . $this->callback[1];
1079
            } else {
1080
                $callback = $this->callback;
1081
            }
1082
1083
            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);
1084
        }
1085
        if ($this->mode & PEAR_ERROR_PRINT) {
1086
            $modes[] = 'print';
1087
        }
1088
        if ($this->mode & PEAR_ERROR_TRIGGER) {
1089
            $modes[] = 'trigger';
1090
        }
1091
        if ($this->mode & PEAR_ERROR_DIE) {
1092
            $modes[] = 'die';
1093
        }
1094
        if ($this->mode & PEAR_ERROR_RETURN) {
1095
            $modes[] = 'return';
1096
        }
1097
1098
        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);
1099
    }
1100
}
1101
1102
/*
1103
 * Local Variables:
1104
 * mode: php
1105
 * tab-width: 4
1106
 * c-basic-offset: 4
1107
 * End:
1108
 */
1109