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