1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
23:
24: App::uses('Sanitize', 'Utility');
25: App::uses('Router', 'Routing');
26: App::uses('CakeResponse', 'Network');
27: App::uses('Controller', 'Controller');
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: class ExceptionRenderer {
57:
58: 59: 60: 61: 62:
63: public $controller = null;
64:
65: 66: 67: 68: 69:
70: public $template = '';
71:
72: 73: 74: 75: 76:
77: public $method = '';
78:
79: 80: 81: 82: 83:
84: public $error = null;
85:
86: 87: 88: 89: 90: 91: 92: 93:
94: public function __construct(Exception $exception) {
95: $this->controller = $this->_getController($exception);
96:
97: if (method_exists($this->controller, 'apperror')) {
98: return $this->controller->appError($exception);
99: }
100: $method = $template = Inflector::variable(str_replace('Exception', '', get_class($exception)));
101: $code = $exception->getCode();
102:
103: $methodExists = method_exists($this, $method);
104:
105: if ($exception instanceof CakeException && !$methodExists) {
106: $method = '_cakeError';
107: if (empty($template) || $template === 'internalError') {
108: $template = 'error500';
109: }
110: } elseif ($exception instanceof PDOException) {
111: $method = 'pdoError';
112: $template = 'pdo_error';
113: $code = 500;
114: } elseif (!$methodExists) {
115: $method = 'error500';
116: if ($code >= 400 && $code < 500) {
117: $method = 'error400';
118: }
119: }
120:
121: $isNotDebug = !Configure::read('debug');
122: if ($isNotDebug && $method === '_cakeError') {
123: $method = 'error400';
124: }
125: if ($isNotDebug && $code == 500) {
126: $method = 'error500';
127: }
128: $this->template = $template;
129: $this->method = $method;
130: $this->error = $exception;
131: }
132:
133: 134: 135: 136: 137: 138: 139: 140: 141:
142: protected function _getController($exception) {
143: App::uses('AppController', 'Controller');
144: App::uses('CakeErrorController', 'Controller');
145: if (!$request = Router::getRequest(true)) {
146: $request = new CakeRequest();
147: }
148: $response = new CakeResponse();
149:
150: if (method_exists($exception, 'responseHeader')) {
151: $response->header($exception->responseHeader());
152: }
153:
154: if (class_exists('AppController')) {
155: try {
156: $controller = new CakeErrorController($request, $response);
157: $controller->startupProcess();
158: } catch (Exception $e) {
159: if (!empty($controller) && $controller->Components->enabled('RequestHandler')) {
160: $controller->RequestHandler->startup($controller);
161: }
162: }
163: }
164: if (empty($controller)) {
165: $controller = new Controller($request, $response);
166: $controller->viewPath = 'Errors';
167: }
168: return $controller;
169: }
170:
171: 172: 173: 174: 175:
176: public function render() {
177: if ($this->method) {
178: call_user_func_array(array($this, $this->method), array($this->error));
179: }
180: }
181:
182: 183: 184: 185: 186: 187:
188: protected function _cakeError(CakeException $error) {
189: $url = $this->controller->request->here();
190: $code = ($error->getCode() >= 400 && $error->getCode() < 506) ? $error->getCode() : 500;
191: $this->controller->response->statusCode($code);
192: $this->controller->set(array(
193: 'code' => $code,
194: 'url' => h($url),
195: 'name' => h($error->getMessage()),
196: 'error' => $error,
197: '_serialize' => array('code', 'url', 'name')
198: ));
199: $this->controller->set($error->getAttributes());
200: $this->_outputMessage($this->template);
201: }
202:
203: 204: 205: 206: 207: 208:
209: public function error400($error) {
210: $message = $error->getMessage();
211: if (!Configure::read('debug') && $error instanceof CakeException) {
212: $message = __d('cake', 'Not Found');
213: }
214: $url = $this->controller->request->here();
215: $this->controller->response->statusCode($error->getCode());
216: $this->controller->set(array(
217: 'name' => h($message),
218: 'url' => h($url),
219: 'error' => $error,
220: '_serialize' => array('name', 'url')
221: ));
222: $this->_outputMessage('error400');
223: }
224:
225: 226: 227: 228: 229: 230:
231: public function error500($error) {
232: $message = $error->getMessage();
233: if (!Configure::read('debug')) {
234: $message = __d('cake', 'An Internal Error Has Occurred.');
235: }
236: $url = $this->controller->request->here();
237: $code = ($error->getCode() > 500 && $error->getCode() < 506) ? $error->getCode() : 500;
238: $this->controller->response->statusCode($code);
239: $this->controller->set(array(
240: 'name' => h($message),
241: 'message' => h($url),
242: 'error' => $error,
243: '_serialize' => array('name', 'message')
244: ));
245: $this->_outputMessage('error500');
246: }
247:
248: 249: 250: 251: 252: 253:
254: public function pdoError(PDOException $error) {
255: $url = $this->controller->request->here();
256: $code = 500;
257: $this->controller->response->statusCode($code);
258: $this->controller->set(array(
259: 'code' => $code,
260: 'url' => h($url),
261: 'name' => h($error->getMessage()),
262: 'error' => $error,
263: '_serialize' => array('code', 'url', 'name', 'error')
264: ));
265: $this->_outputMessage($this->template);
266: }
267:
268: 269: 270: 271: 272: 273:
274: protected function _outputMessage($template) {
275: try {
276: $this->controller->render($template);
277: $this->controller->afterFilter();
278: $this->controller->response->send();
279: } catch (MissingViewException $e) {
280: $attributes = $e->getAttributes();
281: if (isset($attributes['file']) && strpos($attributes['file'], 'error500') !== false) {
282: $this->_outputMessageSafe('error500');
283: } else {
284: $this->_outputMessage('error500');
285: }
286: } catch (Exception $e) {
287: $this->_outputMessageSafe('error500');
288: }
289: }
290:
291: 292: 293: 294: 295: 296: 297:
298: protected function _outputMessageSafe($template) {
299: $this->controller->layoutPath = null;
300: $this->controller->subDir = null;
301: $this->controller->viewPath = 'Errors/';
302: $this->controller->layout = 'error';
303: $this->controller->helpers = array('Form', 'Html', 'Session');
304:
305: $view = new View($this->controller);
306: $this->controller->response->body($view->render($template, 'error'));
307: $this->controller->response->type('html');
308: $this->controller->response->send();
309: }
310:
311: }
312: