Subversion-Projekte lars-tiefland.laravel_shop

Revision

Zur aktuellen Revision | Details | 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) {
200
            //
201
        }
202
 
203
        if (static::$app->runningInConsole()) {
204
            $this->renderForConsole($e);
205
        } else {
206
            $this->renderHttpResponse($e);
207
        }
208
    }
209
 
210
    /**
211
     * Render an exception to the console.
212
     *
213
     * @param  \Throwable  $e
214
     * @return void
215
     */
216
    protected function renderForConsole(Throwable $e)
217
    {
218
        $this->getExceptionHandler()->renderForConsole(new ConsoleOutput, $e);
219
    }
220
 
221
    /**
222
     * Render an exception as an HTTP response and send it.
223
     *
224
     * @param  \Throwable  $e
225
     * @return void
226
     */
227
    protected function renderHttpResponse(Throwable $e)
228
    {
229
        $this->getExceptionHandler()->render(static::$app['request'], $e)->send();
230
    }
231
 
232
    /**
233
     * Handle the PHP shutdown event.
234
     *
235
     * @return void
236
     */
237
    public function handleShutdown()
238
    {
239
        self::$reservedMemory = null;
240
 
241
        if (! is_null($error = error_get_last()) && $this->isFatal($error['type'])) {
242
            $this->handleException($this->fatalErrorFromPhpError($error, 0));
243
        }
244
    }
245
 
246
    /**
247
     * Create a new fatal error instance from an error array.
248
     *
249
     * @param  array  $error
250
     * @param  int|null  $traceOffset
251
     * @return \Symfony\Component\ErrorHandler\Error\FatalError
252
     */
253
    protected function fatalErrorFromPhpError(array $error, $traceOffset = null)
254
    {
255
        return new FatalError($error['message'], 0, $error, $traceOffset);
256
    }
257
 
258
    /**
259
     * Forward a method call to the given method if an application instance exists.
260
     *
261
     * @return callable
262
     */
263
    protected function forwardsTo($method)
264
    {
265
        return fn (...$arguments) => static::$app
266
            ? $this->{$method}(...$arguments)
267
            : false;
268
    }
269
 
270
    /**
271
     * Determine if the error level is a deprecation.
272
     *
273
     * @param  int  $level
274
     * @return bool
275
     */
276
    protected function isDeprecation($level)
277
    {
278
        return in_array($level, [E_DEPRECATED, E_USER_DEPRECATED]);
279
    }
280
 
281
    /**
282
     * Determine if the error type is fatal.
283
     *
284
     * @param  int  $type
285
     * @return bool
286
     */
287
    protected function isFatal($type)
288
    {
289
        return in_array($type, [E_COMPILE_ERROR, E_CORE_ERROR, E_ERROR, E_PARSE]);
290
    }
291
 
292
    /**
293
     * Get an instance of the exception handler.
294
     *
295
     * @return \Illuminate\Contracts\Debug\ExceptionHandler
296
     */
297
    protected function getExceptionHandler()
298
    {
299
        return static::$app->make(ExceptionHandler::class);
300
    }
301
 
302
    /**
303
     * Clear the local application instance from memory.
304
     *
305
     * @return void
306
     */
307
    public static function forgetApp()
308
    {
309
        static::$app = null;
310
    }
311
}