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: 
 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:             return $this->controller->appError($exception);
 96:         }
 97:         $method = $template = Inflector::variable(str_replace('Exception', '', get_class($exception)));
 98:         $code = $exception->getCode();
 99: 
100:         $methodExists = method_exists($this, $method);
101: 
102:         if ($exception instanceof CakeException && !$methodExists) {
103:             $method = '_cakeError';
104:             if (empty($template)) {
105:                 $template = 'error500';
106:             }
107:             if ($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:         if (Configure::read('debug') == 0) {
122:             if ($method == '_cakeError') {
123:                 $method = 'error400';
124:             }
125:             if ($code == 500) {
126:                 $method = 'error500';
127:             }
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('CakeErrorController', 'Controller');
145:         if (!$request = Router::getRequest(false)) {
146:             $request = new CakeRequest();
147:         }
148:         $response = new CakeResponse(array('charset' => Configure::read('App.encoding')));
149:         try {
150:             $controller = new CakeErrorController($request, $response);
151:         } catch (Exception $e) {
152:             $controller = new Controller($request, $response);
153:             $controller->viewPath = 'Errors';
154:         }
155:         return $controller;
156:     }
157: 
158: 159: 160: 161: 162: 
163:     public function render() {
164:         if ($this->method) {
165:             call_user_func_array(array($this, $this->method), array($this->error));
166:         }
167:     }
168: 
169: 170: 171: 172: 173: 174: 
175:     protected function _cakeError(CakeException $error) {
176:         $url = $this->controller->request->here();
177:         $code = ($error->getCode() >= 400 && $error->getCode() < 506) ? $error->getCode() : 500;
178:         $this->controller->response->statusCode($code);
179:         $this->controller->set(array(
180:             'code' => $code,
181:             'url' => h($url),
182:             'name' => $error->getMessage(),
183:             'error' => $error,
184:         ));
185:         try {
186:             $this->controller->set($error->getAttributes());
187:             $this->_outputMessage($this->template);
188:         } catch (MissingViewException $e) {
189:             $this->_outputMessage('error500');
190:         } catch (Exception $e) {
191:             $this->_outputMessageSafe('error500');
192:         }
193:     }
194: 
195: 196: 197: 198: 199: 200: 
201:     public function error400($error) {
202:         $message = $error->getMessage();
203:         if (Configure::read('debug') == 0 && $error instanceof CakeException) {
204:             $message = __d('cake', 'Not Found');
205:         }
206:         $url = $this->controller->request->here();
207:         $this->controller->response->statusCode($error->getCode());
208:         $this->controller->set(array(
209:             'name' => $message,
210:             'url' => h($url),
211:             'error' => $error,
212:         ));
213:         $this->_outputMessage('error400');
214:     }
215: 
216: 217: 218: 219: 220: 221: 
222:     public function error500($error) {
223:         $message = $error->getMessage();
224:         if (Configure::read('debug') == 0) {
225:             $message = __d('cake', 'An Internal Error Has Occurred.');
226:         }
227:         $url = $this->controller->request->here();
228:         $code = ($error->getCode() > 500 && $error->getCode() < 506) ? $error->getCode() : 500;
229:         $this->controller->response->statusCode($code);
230:         $this->controller->set(array(
231:             'name' => $message,
232:             'message' => h($url),
233:             'error' => $error,
234:         ));
235:         $this->_outputMessage('error500');
236:     }
237: 
238: 239: 240: 241: 242: 243: 
244:     public function pdoError(PDOException $error) {
245:         $url = $this->controller->request->here();
246:         $code = 500;
247:         $this->controller->response->statusCode($code);
248:         $this->controller->set(array(
249:             'code' => $code,
250:             'url' => h($url),
251:             'name' => $error->getMessage(),
252:             'error' => $error,
253:         ));
254:         try {
255:             $this->_outputMessage($this->template);
256:         } catch (Exception $e) {
257:             $this->_outputMessageSafe('error500');
258:         }
259:     }
260: 
261: 262: 263: 264: 265: 266: 
267:     protected function _outputMessage($template) {
268:         $this->controller->render($template);
269:         $this->controller->afterFilter();
270:         $this->controller->response->send();
271:     }
272: 
273: 274: 275: 276: 277: 278: 279: 
280:     protected function _outputMessageSafe($template) {
281:         $this->controller->helpers = array('Form', 'Html', 'Session');
282:         $this->controller->render($template);
283:         $this->controller->response->send();
284:     }
285: }
286: