-
Notifications
You must be signed in to change notification settings - Fork 145
/
Copy pathExceptionRenderer.php
125 lines (112 loc) · 3.85 KB
/
ExceptionRenderer.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
<?php
declare(strict_types=1);
namespace Crud\Error;
use Cake\Core\Configure;
use Cake\Error\Debugger;
use Cake\Error\Renderer\WebExceptionRenderer;
use Cake\Http\Response;
use Crud\Error\Exception\ValidationException;
use Crud\Traits\QueryLogTrait;
use Exception;
use function Cake\Core\h;
/**
* Exception renderer for ApiListener
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
*/
class ExceptionRenderer extends WebExceptionRenderer
{
use QueryLogTrait;
/**
* Renders validation errors and sends a 422 error code
*
* @param \Crud\Error\Exception\ValidationException $error Exception instance
* @return \Cake\Http\Response
*/
public function validation(ValidationException $error): Response
{
$url = $this->controller->getRequest()->getRequestTarget();
/** @var int $status */
$status = $code = $error->getCode();
try {
$this->controller->setResponse($this->controller->getResponse()->withStatus($status));
} catch (Exception $e) {
$status = 422;
$this->controller->setResponse($this->controller->getResponse()->withStatus($status));
}
$sets = [
'code' => $code,
'url' => h($url),
'message' => $error->getMessage(),
'error' => $error,
'errorCount' => $error->getValidationErrorCount(),
'errors' => $error->getValidationErrors(),
];
$this->controller->set($sets);
$this->controller->viewBuilder()->setOption(
'serialize',
['code', 'url', 'message', 'errorCount', 'errors']
);
return $this->_outputMessage('error400');
}
/**
* Generate the response using the controller object.
*
* If there is no specific template for the raised error (normally there won't be one)
* swallow the missing view exception and just use the standard
* error format. This prevents throwing an unknown Exception and seeing instead
* a MissingView exception
*
* @param string $template The template to render.
* @return \Cake\Http\Response
*/
protected function _outputMessage(string $template): Response
{
$viewVars = ['success', 'data'];
$this->controller->set('success', false);
$this->controller->set('data', $this->_getErrorData());
if (Configure::read('debug')) {
$queryLog = $this->_getQueryLog();
if ($queryLog) {
$this->controller->set(compact('queryLog'));
$viewVars[] = 'queryLog';
}
}
$this->controller->viewBuilder()->setOption(
'serialize',
$viewVars
);
return parent::_outputMessage($template);
}
/**
* Helper method used to generate extra debugging data into the error template
*
* @return array debugging data
*/
protected function _getErrorData(): array
{
$data = [];
$viewVars = $this->controller->viewBuilder()->getVars();
$serialize = $this->controller->viewBuilder()->getOption('serialize');
if (!empty($serialize)) {
foreach ($serialize as $v) {
$data[$v] = $viewVars[$v];
}
}
if (!empty($viewVars['error']) && Configure::read('debug')) {
$data['exception'] = [
'class' => get_class($viewVars['error']),
'code' => $viewVars['error']->getCode(),
'message' => $viewVars['error']->getMessage(),
];
if (!isset($data['trace'])) {
$data['trace'] = Debugger::formatTrace($viewVars['error']->getTrace(), [
'format' => 'array',
'args' => false,
]);
}
}
return $data;
}
}