Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 47 |
|
0.00% |
0 / 4 |
CRAP | |
0.00% |
0 / 1 |
HttpErrorHandler | |
0.00% |
0 / 47 |
|
0.00% |
0 / 4 |
156 | |
0.00% |
0 / 1 |
getFileContents | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
30 | |||
getSuppressionStatusList | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
getHttpStatus | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
catchError | |
0.00% |
0 / 30 |
|
0.00% |
0 / 1 |
20 |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace PeServer\Core\Errors; |
6 | |
7 | use PeServer\Core\DI\Inject; |
8 | use PeServer\Core\Http\HttpRequest; |
9 | use PeServer\Core\Http\HttpResponse; |
10 | use PeServer\Core\Http\HttpStatus; |
11 | use PeServer\Core\Http\IResponsePrinterFactory; |
12 | use PeServer\Core\IO\Directory; |
13 | use PeServer\Core\IO\File; |
14 | use PeServer\Core\IO\Path; |
15 | use PeServer\Core\Mvc\Template\ITemplateFactory; |
16 | use PeServer\Core\Mvc\Template\TemplateFactory; |
17 | use PeServer\Core\Mvc\Template\TemplateOptions; |
18 | use PeServer\Core\Mvc\Template\TemplateParameter; |
19 | use PeServer\Core\ProgramContext; |
20 | use PeServer\Core\Throws\HttpStatusException; |
21 | use PeServer\Core\Web\UrlHelper; |
22 | use PeServer\Core\Web\WebSecurity; |
23 | use Throwable; |
24 | |
25 | class HttpErrorHandler extends ErrorHandler |
26 | { |
27 | #region variable |
28 | |
29 | #[Inject(TemplateFactory::class)] //@phpstan-ignore-next-line [INJECT] |
30 | private ITemplateFactory $templateFactory; |
31 | |
32 | #[Inject] //@phpstan-ignore-next-line [INJECT] |
33 | private IResponsePrinterFactory $responsePrinterFactory; |
34 | |
35 | #[Inject] //@phpstan-ignore-next-line [INJECT] |
36 | private WebSecurity $webSecurity; |
37 | |
38 | #[Inject] //@phpstan-ignore-next-line [INJECT] |
39 | private ProgramContext $programContext; |
40 | |
41 | #endregion |
42 | |
43 | #region function |
44 | |
45 | /** |
46 | * 検出できるソースファイル内容をすべて取得。 |
47 | * |
48 | * @param string $file |
49 | * @param Throwable|null $throwable |
50 | * @return array<string,string> |
51 | */ |
52 | private function getFileContents(string $file, ?Throwable $throwable): array |
53 | { |
54 | $files = [ |
55 | "$file" => File::readContent($file)->raw, |
56 | ]; |
57 | |
58 | if ($throwable !== null) { |
59 | foreach ($throwable->getTrace() as $item) { |
60 | if (isset($item['file'])) { |
61 | $f = $item['file']; |
62 | if (!isset($files[$f])) { |
63 | $files[$f] = File::readContent($f)->raw; |
64 | } |
65 | } |
66 | } |
67 | } |
68 | |
69 | return $files; |
70 | } |
71 | |
72 | /** |
73 | * 抑制エラーコード指定。 |
74 | * |
75 | * @return HttpStatus[] |
76 | */ |
77 | protected function getSuppressionStatusList(): array |
78 | { |
79 | return [ |
80 | HttpStatus::NotFound, |
81 | ]; |
82 | } |
83 | |
84 | |
85 | /** |
86 | * 例外からHTTP応答ステータスコードを取得する。 |
87 | * |
88 | * @param Throwable|null $throwable |
89 | * @return HttpStatus 設定されたHTTPステータスコード。 |
90 | */ |
91 | final protected function getHttpStatus(?Throwable $throwable): HttpStatus |
92 | { |
93 | $status = $throwable instanceof HttpStatusException |
94 | ? $throwable->status |
95 | : HttpStatus::ServiceUnavailable; |
96 | |
97 | return $status; |
98 | } |
99 | |
100 | protected function catchError(int $errorNumber, string $message, string $file, int $lineNumber, ?Throwable $throwable): void |
101 | { |
102 | $response = new HttpResponse(); |
103 | $response->status = $this->getHttpStatus($throwable); |
104 | |
105 | $values = [ |
106 | 'error_number' => $errorNumber, |
107 | 'message' => $message, |
108 | 'file' => $file, |
109 | 'line_number' => $lineNumber, |
110 | 'throwable' => $throwable, |
111 | 'cache' => $this->getFileContents($file, $throwable) |
112 | ]; |
113 | |
114 | $isSuppressionStatus = false; |
115 | foreach ($this->getSuppressionStatusList() as $suppressionStatus) { |
116 | if ($response->status === $suppressionStatus) { |
117 | $isSuppressionStatus = true; |
118 | $this->logger->info('HTTP {0}: {1}', $suppressionStatus->value, $suppressionStatus->name); |
119 | break; |
120 | } |
121 | } |
122 | if (!$isSuppressionStatus) { |
123 | $this->logger->error($values); |
124 | } |
125 | |
126 | $options = new TemplateOptions( |
127 | Path::combine(__DIR__, '..'), |
128 | 'template', |
129 | $this->programContext, |
130 | UrlHelper::none(), |
131 | $this->webSecurity, |
132 | Path::combine(Directory::getTemporaryDirectory(), 'PeServer-Core') |
133 | ); |
134 | $template = $this->templateFactory->createTemplate($options); |
135 | |
136 | $response->content = $template->build('error-display.tpl', new TemplateParameter($response->status, $values, [])); |
137 | |
138 | $printer = $this->responsePrinterFactory->createResponsePrinter(HttpRequest::none(), $response); |
139 | |
140 | $printer->execute(); |
141 | } |
142 | |
143 | #endregion |
144 | } |