Test Failed
Pull Request — master (#334)
by Alexander
02:54
created

ErrorException::getName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Web\ErrorHandler;
6
7
use Yiisoft\FriendlyException\FriendlyExceptionInterface;
8
9
/**
10
 * ErrorException represents a PHP error.
11
 */
12
class ErrorException extends \ErrorException implements FriendlyExceptionInterface
13
{
14
    private const ERROR_NAMES = [
15
        E_ERROR => 'PHP Fatal Error',
16
        E_WARNING => 'PHP Warning',
17
        E_PARSE => 'PHP Parse Error',
18
        E_NOTICE => 'PHP Notice',
19
        E_CORE_ERROR => 'PHP Core Error',
20
        E_CORE_WARNING => 'PHP Core Warning',
21
        E_COMPILE_ERROR => 'PHP Compile Error',
22
        E_COMPILE_WARNING => 'PHP Compile Warning',
23
        E_USER_ERROR => 'PHP User Error',
24
        E_USER_WARNING => 'PHP User Warning',
25
        E_USER_NOTICE => 'PHP User Notice',
26
        E_STRICT => 'PHP Strict Warning',
27
        E_RECOVERABLE_ERROR => 'PHP Recoverable Error',
28
        E_DEPRECATED => 'PHP Deprecated Warning',
29
        E_USER_DEPRECATED => 'PHP User Deprecated Warning',
30
    ];
31
32
    public function __construct($message = '', $code = 0, $severity = 1, $filename = __FILE__, $lineno = __LINE__, \Exception $previous = null)
33
    {
34
        parent::__construct($message, $code, $severity, $filename, $lineno, $previous);
35
        $this->addXDebugTraceToFatalIfAvailable();
36
    }
37
38
    /**
39
     * Returns if error is one of fatal type.
40
     *
41
     * @param array $error error got from error_get_last()
42
     *
43
     * @return bool if error is one of fatal type
44
     */
45
    public static function isFatalError(array $error): bool
46
    {
47
        return isset($error['type']) && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING], true);
48
    }
49
50
    /**
51
     * @return string the user-friendly name of this exception
52
     */
53
    public function getName(): string
54
    {
55
        return self::ERROR_NAMES[$this->getCode()] ?? 'Error';
56
    }
57
58
    /**
59
     * Fatal errors normally do not provide any trace making it harder to debug. In case XDebug is installed, we
60
     * can get a trace using xdebug_get_function_stack().
61
     *
62
     * @suppress PhanUndeclaredFunction
63
     */
64
    private function addXDebugTraceToFatalIfAvailable(): void
65
    {
66
        if (function_exists('xdebug_get_function_stack')) {
67
            // XDebug trace can't be modified and used directly with PHP 7
68
            // @see https://github.com/yiisoft/yii2/pull/11723
69
            $xDebugTrace = array_slice(array_reverse(xdebug_get_function_stack()), 1, -1);
70
            $trace = [];
71
            foreach ($xDebugTrace as $frame) {
72
                if (!isset($frame['function'])) {
73
                    $frame['function'] = 'unknown';
74
                }
75
76
                // XDebug < 2.1.1: http://bugs.xdebug.org/view.php?id=695
77
                if (!isset($frame['type']) || $frame['type'] === 'static') {
78
                    $frame['type'] = '::';
79
                } elseif ($frame['type'] === 'dynamic') {
80
                    $frame['type'] = '->';
81
                }
82
83
                // XDebug has a different key name
84
                if (isset($frame['params']) && !isset($frame['args'])) {
85
                    $frame['args'] = $frame['params'];
86
                }
87
                $trace[] = $frame;
88
            }
89
90
            $ref = new \ReflectionProperty('Exception', 'trace');
91
            $ref->setAccessible(true);
92
            $ref->setValue($this, $trace);
93
        }
94
    }
95
96
    public function getSolution(): ?string
97
    {
98
        return null;
99
    }
100
}
101