Subversion-Projekte lars-tiefland.laravel_shop

Revision

Revision 148 | Details | Vergleich mit vorheriger | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
namespace Illuminate\Foundation\Bootstrap;
4
 
5
use ErrorException;
6
use Exception;
7
use Illuminate\Contracts\Debug\ExceptionHandler;
8
use Illuminate\Contracts\Foundation\Application;
9
use Illuminate\Log\LogManager;
10
use Monolog\Handler\NullHandler;
11
use Symfony\Component\Console\Output\ConsoleOutput;
12
use Symfony\Component\ErrorHandler\Error\FatalError;
13
use Throwable;
14
 
15
class HandleExceptions
16
{
17
    /**
18
     * Reserved memory so that errors can be displayed properly on memory exhaustion.
19
     *
20
     * @var string|null
21
     */
22
    public static $reservedMemory;
23
 
24
    /**
25
     * The application instance.
26
     *
27
     * @var \Illuminate\Contracts\Foundation\Application
28
     */
29
    protected static $app;
30
 
31
    /**
32
     * Bootstrap the given application.
33
     *
34
     * @param  \Illuminate\Contracts\Foundation\Application  $app
35
     * @return void
36
     */
37
    public function bootstrap(Application $app)
38
    {
39
        self::$reservedMemory = str_repeat('x', 32768);
40
 
41
        static::$app = $app;
42
 
43
        error_reporting(-1);
44
 
45
        set_error_handler($this->forwardsTo('handleError'));
46
 
47
        set_exception_handler($this->forwardsTo('handleException'));
48
 
49
        register_shutdown_function($this->forwardsTo('handleShutdown'));
50
 
51
        if (! $app->environment('testing')) {
52
            ini_set('display_errors', 'Off');
53
        }
54
    }
55
 
56
    /**
57
     * Report PHP deprecations, or convert PHP errors to ErrorException instances.
58
     *
59
     * @param  int  $level
60
     * @param  string  $message
61
     * @param  string  $file
62
     * @param  int  $line
63
     * @param  array  $context
64
     * @return void
65
     *
66
     * @throws \ErrorException
67
     */
68
    public function handleError($level, $message, $file = '', $line = 0, $context = [])
69
    {
70
        if ($this->isDeprecation($level)) {
71
            $this->handleDeprecationError($message, $file, $line, $level);
72
        } elseif (error_reporting() & $level) {
73
            throw new ErrorException($message, 0, $level, $file, $line);
74
        }
75
    }
76
 
77
    /**
78
     * Reports a deprecation to the "deprecations" logger.
79
     *
80
     * @param  string  $message
81
     * @param  string  $file
82
     * @param  int  $line
83
     * @return void
84
     *
85
     * @deprecated Use handleDeprecationError instead.
86
     */
87
    public function handleDeprecation($message, $file, $line)
88
    {
89
        $this->handleDeprecationError($message, $file, $line);
90
    }
91
 
92
    /**
93
     * Reports a deprecation to the "deprecations" logger.
94
     *
95
     * @param  string  $message
96
     * @param  string  $file
97
     * @param  int  $line
98
     * @param  int  $level
99
     * @return void
100
     */
101
    public function handleDeprecationError($message, $file, $line, $level = E_DEPRECATED)
102
    {
103
        if ($this->shouldIgnoreDeprecationErrors()) {
104
            return;
105
        }
106
 
107
        try {
108
            $logger = static::$app->make(LogManager::class);
109
        } catch (Exception $e) {
110
            return;
111
        }
112
 
113
        $this->ensureDeprecationLoggerIsConfigured();
114
 
115
        $options = static::$app['config']->get('logging.deprecations') ?? [];
116
 
117
        with($logger->channel('deprecations'), function ($log) use ($message, $file, $line, $level, $options) {
118
            if ($options['trace'] ?? false) {
119
                $log->warning((string) new ErrorException($message, 0, $level, $file, $line));
120
            } else {
121
                $log->warning(sprintf('%s in %s on line %s',
122
                    $message, $file, $line
123
                ));
124
            }
125
        });
126
    }
127
 
128
    /**
129
     * Determine if deprecation errors should be ignored.
130
     *
131
     * @return bool
132
     */
133
    protected function shouldIgnoreDeprecationErrors()
134
    {
135
        return ! class_exists(LogManager::class)
136
            || ! static::$app->hasBeenBootstrapped()
137
            || static::$app->runningUnitTests();
138
    }
139
 
140
    /**
141
     * Ensure the "deprecations" logger is configured.
142
     *
143
     * @return void
144
     */
145
    protected function ensureDeprecationLoggerIsConfigured()
146
    {
147
        with(static::$app['config'], function ($config) {
148
            if ($config->get('logging.channels.deprecations')) {
149
                return;
150
            }
151
 
152
            $this->ensureNullLogDriverIsConfigured();
153
 
154
            if (is_array($options = $config->get('logging.deprecations'))) {
155
                $driver = $options['channel'] ?? 'null';
156
            } else {
157
                $driver = $options ?? 'null';
158
            }
159
 
160
            $config->set('logging.channels.deprecations', $config->get("logging.channels.{$driver}"));
161
        });
162
    }
163
 
164
    /**
165
     * Ensure the "null" log driver is configured.
166
     *
167
     * @return void
168
     */
169
    protected function ensureNullLogDriverIsConfigured()
170
    {
171
        with(static::$app['config'], function ($config) {
172
            if ($config->get('logging.channels.null')) {
173
                return;
174
            }
175
 
176
            $config->set('logging.channels.null', [
177
                'driver' => 'monolog',
178
                'handler' => NullHandler::class,
179
            ]);
180
        });
181
    }
182
 
183
    /**
184
     * Handle an uncaught exception from the application.
185
     *
186
     * Note: Most exceptions can be handled via the try / catch block in
187
     * the HTTP and Console kernels. But, fatal error exceptions must
188
     * be handled differently since they are not normal exceptions.
189
     *
190
     * @param  \Throwable  $e
191
     * @return void
192
     */
193
    public function handleException(Throwable $e)
194
    {
195
        self::$reservedMemory = null;
196
 
197
        try {
198
            $this->getExceptionHandler()->report($e);
199
        } catch (Exception $e) {
1464 lars 200
            $exceptionHandlerFailed = true;
148 lars 201
        }
202
 
203
        if (static::$app->runningInConsole()) {
204
            $this->renderForConsole($e);
1464 lars 205
 
206
            if ($exceptionHandlerFailed ?? false) {
207
                exit(1);
208
            }
148 lars 209
        } else {
210
            $this->renderHttpResponse($e);
211
        }
212
    }
213
 
214
    /**
215
     * Render an exception to the console.
216
     *
217
     * @param  \Throwable  $e
218
     * @return void
219
     */
220
    protected function renderForConsole(Throwable $e)
221
    {
222
        $this->getExceptionHandler()->renderForConsole(new ConsoleOutput, $e);
223
    }
224
 
225
    /**
226
     * Render an exception as an HTTP response and send it.
227
     *
228
     * @param  \Throwable  $e
229
     * @return void
230
     */
231
    protected function renderHttpResponse(Throwable $e)
232
    {
233
        $this->getExceptionHandler()->render(static::$app['request'], $e)->send();
234
    }
235
 
236
    /**
237
     * Handle the PHP shutdown event.
238
     *
239
     * @return void
240
     */
241
    public function handleShutdown()
242
    {
243
        self::$reservedMemory = null;
244
 
245
        if (! is_null($error = error_get_last()) && $this->isFatal($error['type'])) {
246
            $this->handleException($this->fatalErrorFromPhpError($error, 0));
247
        }
248
    }
249
 
250
    /**
251
     * Create a new fatal error instance from an error array.
252
     *
253
     * @param  array  $error
254
     * @param  int|null  $traceOffset
255
     * @return \Symfony\Component\ErrorHandler\Error\FatalError
256
     */
257
    protected function fatalErrorFromPhpError(array $error, $traceOffset = null)
258
    {
259
        return new FatalError($error['message'], 0, $error, $traceOffset);
260
    }
261
 
262
    /**
263
     * Forward a method call to the given method if an application instance exists.
264
     *
265
     * @return callable
266
     */
267
    protected function forwardsTo($method)
268
    {
269
        return fn (...$arguments) => static::$app
270
            ? $this->{$method}(...$arguments)
271
            : false;
272
    }
273
 
274
    /**
275
     * Determine if the error level is a deprecation.
276
     *
277
     * @param  int  $level
278
     * @return bool
279
     */
280
    protected function isDeprecation($level)
281
    {
282
        return in_array($level, [E_DEPRECATED, E_USER_DEPRECATED]);
283
    }
284
 
285
    /**
286
     * Determine if the error type is fatal.
287
     *
288
     * @param  int  $type
289
     * @return bool
290
     */
291
    protected function isFatal($type)
292
    {
293
        return in_array($type, [E_COMPILE_ERROR, E_CORE_ERROR, E_ERROR, E_PARSE]);
294
    }
295
 
296
    /**
297
     * Get an instance of the exception handler.
298
     *
299
     * @return \Illuminate\Contracts\Debug\ExceptionHandler
300
     */
301
    protected function getExceptionHandler()
302
    {
303
        return static::$app->make(ExceptionHandler::class);
304
    }
305
 
306
    /**
307
     * Clear the local application instance from memory.
308
     *
309
     * @return void
310
     */
311
    public static function forgetApp()
312
    {
313
        static::$app = null;
314
    }
315
}