Error::handleException()   B
last analyzed

Complexity

Conditions 9
Paths 9

Size

Total Lines 43
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 90

Importance

Changes 7
Bugs 0 Features 0
Metric Value
cc 9
eloc 30
c 7
b 0
f 0
nc 9
nop 2
dl 0
loc 43
ccs 0
cts 29
cp 0
crap 90
rs 8.0555
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Suricate;
6
7
use ErrorException;
8
9
/**
10
 * @property bool $report
11
 * @property bool $dumpContext
12
 * @property mixed $httpHandler Handler (object/closure/string) in charge of the error
13
 */
14
class Error extends Service
15
{
16
    protected $parametersList = ['report', 'dumpContext', 'httpHandler'];
17
18
    public static function handleException($e, $context = null)
19
    {
20
        if ($e instanceof Exception\HttpException) {
21
            $httpHandler = Suricate::Error()->httpHandler;
22
            if (is_object($httpHandler) && $httpHandler instanceof \Closure) {
23
                $httpHandler($e);
24
                return;
25
            } elseif ($httpHandler != '') {
26
                $httpHandler = explode('::', $httpHandler);
27
28
                if (count($httpHandler) > 1) {
29
                    $userFunc = $httpHandler;
30
                } else {
31
                    $userFunc = head($httpHandler);
32
                }
33
                if (is_callable($userFunc)) {
34
                    call_user_func($userFunc, $e);
35
                }
36
                return;
37
            }
38
39
            Suricate::Error()->displayGenericHttpExceptionPage($e);
40
        }
41
42
        while (ob_get_level() > 1) {
43
            ob_end_clean();
44
        }
45
46
        $json = [];
47
        $error = $e;
48
        do {
49
            $json[] = [
50
                'type' => get_class($error),
51
                'code' => $error->getCode(),
52
                'message' => $error->getMessage(),
53
                'file' => $error->getFile(),
54
                'line' => $error->getLine(),
55
                'trace' => explode("\n", $error->getTraceAsString())
56
            ];
57
        } while (($error = $error->getPrevious()));
58
        Suricate::Logger()->error(json_encode($json));
59
60
        Suricate::Error()->displayExceptionPage($e, $context);
61
    }
62
63
    public static function handleError($code, $message, $file, $line, $context)
64
    {
65
        static::handleException(
66
            new ErrorException($message, $code, 0, $file, $line),
67
            $context
68
        );
69
    }
70
71
    public static function handleShutdownError()
72
    {
73
        if (($error = error_get_last())) {
74
            static::handleException(
75
                new ErrorException(
76
                    $error['message'],
77
                    $error['type'],
78
                    0,
79
                    $error['file'],
80
                    $error['line']
81
                )
82
            );
83
        }
84
    }
85
86
    private function displayExceptionPage($e, $context = null)
87
    {
88
        if ($this->report || $this->report === null) {
89
            echo '<html>' . "\n";
90
            echo '  <head>' . "\n";
91
            echo '      <title>Oops, Uncaught Exception</title>' . "\n";
92
            echo '      <style>' . "\n";
93
            echo '          body{font-family: "Open Sans",arial,sans-serif; background: #FFF; color:#333; margin:2em}' .
94
                "\n";
95
            echo '          code{background:#E0941B;border-radius:4px;padding:2px 6px}' .
96
                "\n";
97
            echo '      </style>' . "\n";
98
            echo '  </head>' . "\n";
99
            echo '  <body>' . "\n";
100
            echo '      <h1>Oops, uncaught exception !</h1>' . "\n";
101
            echo '      <h2>This is embarrassing, but server made a booboo</h2>' .
102
                "\n";
103
            echo '      <p><code>' . $e->getMessage() . '</code></p>' . "\n";
104
            echo '      <h3>From:</h3>' . "\n";
105
            echo '      <p><code>' .
106
                $e->getFile() .
107
                ' on line ' .
108
                $e->getLine() .
109
                '</code></p>' .
110
                "\n";
111
            echo '      <h3>Call stack</h3>' . "\n";
112
            echo '      <pre>' . $e->getTraceAsString() . '</pre>' . "\n";
113
            if ($this->dumpContext) {
114
                echo '<h3>Context:</h3>';
115
                _p($context);
116
            }
117
            echo '  </body>' . "\n";
118
            echo '</html>';
119
        } else {
120
            if ($e->getCode() <= 1) {
121
                $err = new Exception\HttpException('500');
122
                $this->displayGenericHttpExceptionPage($err);
123
            }
124
        }
125
        exit(1);
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...
126
    }
127
128
    private function displayGenericHttpExceptionPage($e)
129
    {
130
        $response = Suricate::Request();
131
132
        if (
133
            is_readable(
134
                app_path() . '/views/Errors/' . $e->getStatusCode() . '.php'
135
            )
136
        ) {
137
            ob_start();
138
            include app_path() .
139
                '/views/Errors/' .
140
                $e->getStatusCode() .
141
                '.php';
142
            $body = ob_get_clean();
143
        } else {
144
            $innerHtml = '<h1>' . $e->getStatusCode() . '</h1>';
145
146
            $page = new Page();
147
            $body = $page->setTitle($e->getStatusCode())->render($innerHtml);
148
        }
149
150
        $response->setBody($body)->setHttpCode($e->getStatusCode());
151
        foreach ($e->getHeaders() as $header => $value) {
152
            $response->addHeader($header, $value);
153
        }
154
155
        $response->write();
156
        die();
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...
157
    }
158
}
159