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