Passed
Push — 5.2 ( 94f706...1b9ee1 )
by liu
03:53
created

Handle::getCode()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 4
nc 2
nop 1
dl 0
loc 9
rs 10
c 0
b 0
f 0
1
<?php
2
// +----------------------------------------------------------------------
1 ignored issue
show
Coding Style introduced by
You must use "/**" style comments for a file comment
Loading history...
3
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: yunwuxin <[email protected]>
10
// +----------------------------------------------------------------------
11
12
namespace think\exception;
13
14
use Exception;
15
use think\App;
16
use think\console\Output;
17
use think\db\exception\DataNotFoundException;
18
use think\db\exception\ModelNotFoundException;
19
use think\Request;
20
use think\Response;
21
use think\response\Json;
22
use Throwable;
23
24
class Handle
1 ignored issue
show
Coding Style introduced by
Missing class doc comment
Loading history...
25
{
26
    /** @var App */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
27
    protected $app;
28
29
    protected $ignoreReport = [
30
        HttpException::class,
31
        HttpResponseException::class,
32
        ModelNotFoundException::class,
33
        DataNotFoundException::class,
34
        ValidateException::class,
35
    ];
36
37
    protected $isJson = false;
38
39
    public function __construct(App $app)
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
40
    {
41
        $this->app = $app;
42
    }
43
44
    /**
45
     * Report or log an exception.
46
     *
47
     * @access public
48
     * @param  Throwable $exception
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
49
     * @return void
50
     */
51
    public function report(Throwable $exception)
52
    {
53
        if (!$this->isIgnoreReport($exception)) {
54
            // 收集异常数据
55
            if ($this->app->isDebug()) {
56
                $data = [
57
                    'file'    => $exception->getFile(),
58
                    'line'    => $exception->getLine(),
59
                    'message' => $this->getMessage($exception),
60
                    'code'    => $this->getCode($exception),
61
                ];
62
                $log  = "[{$data['code']}]{$data['message']}[{$data['file']}:{$data['line']}]";
63
            } else {
64
                $data = [
65
                    'code'    => $this->getCode($exception),
66
                    'message' => $this->getMessage($exception),
67
                ];
68
                $log  = "[{$data['code']}]{$data['message']}";
69
            }
70
71
            if ($this->app->config->get('log.record_trace')) {
72
                $log .= "\r\n" . $exception->getTraceAsString();
73
            }
74
75
            $this->app->log->record($log, 'error');
76
        }
77
    }
78
79
    protected function isIgnoreReport(Throwable $exception)
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
80
    {
81
        foreach ($this->ignoreReport as $class) {
82
            if ($exception instanceof $class) {
83
                return true;
84
            }
85
        }
86
87
        return false;
88
    }
89
90
    /**
91
     * Render an exception into an HTTP response.
92
     *
93
     * @access public
94
     * @param Request   $request
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
95
     * @param Throwable $e
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
96
     * @return Response
97
     */
98
    public function render($request, Throwable $e)
99
    {
100
        $this->isJson = $request->isJson();
101
        if ($e instanceof HttpException) {
102
            return $this->renderHttpException($e);
103
        } else {
104
            return $this->convertExceptionToResponse($e);
105
        }
106
    }
107
108
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
109
     * @access public
110
     * @param  Output    $output
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
111
     * @param  Throwable $e
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
112
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
113
    public function renderForConsole(Output $output, Throwable $e)
114
    {
115
        if ($this->app->isDebug()) {
116
            $output->setVerbosity(Output::VERBOSITY_DEBUG);
117
        }
118
119
        $output->renderException($e);
120
    }
121
122
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
123
     * @access protected
124
     * @param  HttpException $e
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
125
     * @return Response
126
     */
127
    protected function renderHttpException(HttpException $e)
128
    {
129
        $status   = $e->getStatusCode();
130
        $template = $this->app->config->get('app.http_exception_template');
131
132
        if (!$this->app->isDebug() && !empty($template[$status])) {
133
            return Response::create($template[$status], 'view', $status)->assign(['e' => $e]);
0 ignored issues
show
Bug introduced by
The method assign() does not exist on think\Response. It seems like you code against a sub-type of think\Response such as think\response\View. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

133
            return Response::create($template[$status], 'view', $status)->/** @scrutinizer ignore-call */ assign(['e' => $e]);
Loading history...
134
        } else {
135
            return $this->convertExceptionToResponse($e);
136
        }
137
    }
138
139
    /**
140
     * 收集异常数据
141
     * @param Throwable $exception
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
142
     * @return array
143
     */
144
    protected function convertExceptionToArray(Throwable $exception)
145
    {
146
        if ($this->app->isDebug()) {
147
            // 调试模式,获取详细的错误信息
148
            $data = [
149
                'name'    => get_class($exception),
150
                'file'    => $exception->getFile(),
151
                'line'    => $exception->getLine(),
152
                'message' => $this->getMessage($exception),
153
                'trace'   => $exception->getTrace(),
154
                'code'    => $this->getCode($exception),
155
                'source'  => $this->getSourceCode($exception),
156
                'datas'   => $this->getExtendData($exception),
157
                'tables'  => [
158
                    'GET Data'              => $_GET,
159
                    'POST Data'             => $_POST,
160
                    'Files'                 => $_FILES,
161
                    'Cookies'               => $_COOKIE,
162
                    'Session'               => $_SESSION ?? [],
163
                    'Server/Request Data'   => $_SERVER,
164
                    'Environment Variables' => $_ENV,
165
                    'ThinkPHP Constants'    => $this->getConst(),
166
                ],
167
            ];
168
        } else {
169
            // 部署模式仅显示 Code 和 Message
170
            $data = [
171
                'code'    => $this->getCode($exception),
172
                'message' => $this->getMessage($exception),
173
            ];
174
175
            if (!$this->app->config->get('app.show_error_msg')) {
176
                // 不显示详细错误信息
177
                $data['message'] = $this->app->config->get('app.error_message');
178
            }
179
        }
180
181
        return $data;
182
    }
183
184
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
185
     * @access protected
186
     * @param  Throwable $exception
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
187
     * @return Response
188
     */
189
    protected function convertExceptionToResponse(Throwable $exception)
190
    {
191
        $data = $this->convertExceptionToArray($exception);
192
193
        if (!$this->isJson) {
194
            //保留一层
195
            while (ob_get_level() > 1) {
196
                ob_end_clean();
197
            }
198
199
            $data['echo'] = ob_get_clean();
200
201
            ob_start();
202
            extract($data);
203
            include $this->app->config->get('app.exception_tmpl') ?: __DIR__ . '/../../tpl/think_exception.tpl';
204
205
            // 获取并清空缓存
206
            $data     = ob_get_clean();
207
            $response = new Response($data);
208
        } else {
209
            $response = new Json($data);
210
        }
211
212
        if ($exception instanceof HttpException) {
213
            $statusCode = $exception->getStatusCode();
214
            $response->header($exception->getHeaders());
215
        }
216
217
        return $response->code($statusCode ?? 500);
218
    }
219
220
    /**
221
     * 获取错误编码
222
     * ErrorException则使用错误级别作为错误编码
223
     * @access protected
224
     * @param  Throwable $exception
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
225
     * @return integer                错误编码
226
     */
227
    protected function getCode(Throwable $exception)
228
    {
229
        $code = $exception->getCode();
230
231
        if (!$code && $exception instanceof ErrorException) {
232
            $code = $exception->getSeverity();
233
        }
234
235
        return $code;
236
    }
237
238
    /**
239
     * 获取错误信息
240
     * ErrorException则使用错误级别作为错误编码
241
     * @access protected
242
     * @param  Throwable $exception
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
243
     * @return string                错误信息
244
     */
245
    protected function getMessage(Throwable $exception)
246
    {
247
        $message = $exception->getMessage();
248
249
        if ($this->app->runningInConsole()) {
250
            return $message;
251
        }
252
253
        $lang = $this->app->lang;
254
255
        if (strpos($message, ':')) {
256
            $name    = strstr($message, ':', true);
257
            $message = $lang->has($name) ? $lang->get($name) . strstr($message, ':') : $message;
258
        } elseif (strpos($message, ',')) {
259
            $name    = strstr($message, ',', true);
260
            $message = $lang->has($name) ? $lang->get($name) . ':' . substr(strstr($message, ','), 1) : $message;
261
        } elseif ($lang->has($message)) {
262
            $message = $lang->get($message);
263
        }
264
265
        return $message;
266
    }
267
268
    /**
269
     * 获取出错文件内容
270
     * 获取错误的前9行和后9行
271
     * @access protected
272
     * @param  Throwable $exception
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
273
     * @return array                 错误文件内容
274
     */
275
    protected function getSourceCode(Throwable $exception)
276
    {
277
        // 读取前9行和后9行
278
        $line  = $exception->getLine();
279
        $first = ($line - 9 > 0) ? $line - 9 : 1;
280
281
        try {
282
            $contents = file($exception->getFile()) ?: [];
283
            $source   = [
284
                'first'  => $first,
285
                'source' => array_slice($contents, $first - 1, 19),
286
            ];
287
        } catch (Exception $e) {
288
            $source = [];
289
        }
290
291
        return $source;
292
    }
293
294
    /**
295
     * 获取异常扩展信息
296
     * 用于非调试模式html返回类型显示
297
     * @access protected
298
     * @param  Throwable $exception
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
299
     * @return array                 异常类定义的扩展数据
300
     */
301
    protected function getExtendData(Throwable $exception)
302
    {
303
        $data = [];
304
305
        if ($exception instanceof \think\Exception) {
306
            $data = $exception->getData();
307
        }
308
309
        return $data;
310
    }
311
312
    /**
313
     * 获取常量列表
314
     * @access private
315
     * @return array 常量列表
316
     */
317
    private static function getConst()
0 ignored issues
show
Coding Style introduced by
Private method name "Handle::getConst" must be prefixed with an underscore
Loading history...
318
    {
319
        $const = get_defined_constants(true);
320
321
        return $const['user'] ?? [];
322
    }
323
}
324