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