<?php /** * Controller is the customized base controller class. * All controller classes for this application should extend from this base class. */ class Controller extends /*WRestController*/ CController { /** * */ private $_error = array(); /** * Initializes the controller. This method is called by the application * before the controller starts to execute. */ public function init() { parent::init(); // Let completely bypass Yii's default error displaying mechanism // by registering onError and onException event listeners Yii::app()->attachEventHandler('onError',array($this,'handleError')); Yii::app()->attachEventHandler('onException',array($this,'handleError')); } /** * Handling all errors and exceptions for all controllers * To check if there was error or exception need use construction like * * if ($event instanceof CExceptionEvent) { ... } * elseif($event instanceof CErrorEvent) { ... } * * @param {object} event */ public function handleError(CEvent $event) { $error = ($event instanceof CExceptionEvent) ? $event->exception : $event; if($event instanceof CExceptionEvent) { if(($trace = $this->getExactTrace($error)) === null) { $fileName = $error->getFile(); $errorLine = $error->getLine(); } else { $fileName = $trace['file']; $errorLine = $trace['line']; } $trace = $error->getTrace(); foreach($trace as $i => $t) { if(!isset($t['file'])) { $trace[$i]['file']='unknown'; } if(!isset($t['line'])) { $trace[$i]['line']=0; } if(!isset($t['function'])) { $trace[$i]['function']='unknown'; } unset($trace[$i]['object']); } } elseif($event instanceof CErrorEvent) { $trace = debug_backtrace(); // skip the first 3 stacks as they do not tell the error position if(count($trace) > 3) { $trace = array_slice($trace,3); } $traceString = ''; foreach($trace as $i=>$t) { if(!isset($t['file'])) { $trace[$i]['file']='unknown'; } if(!isset($t['line'])) { $trace[$i]['line']=0; } if(!isset($t['function'])) { $trace[$i]['function']='unknown'; } $traceString .= "#$i {$trace[$i]['file']}({$trace[$i]['line']}): "; if(isset($t['object']) && is_object($t['object'])) { $traceString.=get_class($t['object']).'->'; } $traceString.="{$trace[$i]['function']}()\n"; unset($trace[$i]['object']); } switch($error->code) { case E_WARNING: $type = 'PHP warning'; break; case E_NOTICE: $type = 'PHP notice'; break; case E_USER_ERROR: $type = 'User error'; break; case E_USER_WARNING: $type = 'User warning'; break; case E_USER_NOTICE: $type = 'User notice'; break; case E_RECOVERABLE_ERROR: $type = 'Recoverable error'; break; default: $type = 'PHP error'; } } else { return; } $this->_error =array( 'code' => ($error instanceof CHttpException) ? $error->statusCode : 500, 'type' => $type ? $type : get_class($error), 'message' => ($error instanceof CException) ? $error->getMessage() : $error->message, 'file' => $fileName ? $fileName : $error->file, 'line' => $errorLine ? $errorLine : $error->line, 'trace' => ($error instanceof CException) ? $error->getTraceAsString() : $traceString, 'traces' => $trace ); if(YII_DEBUG) { $this->sendResponse($this->_error['code'], array( 'success' => false, 'error' => $this->_error )); } else { if(Yii::app()->user->isGuest) { $this->sendResponse(401, array( 'success' => false )); } else { $this->sendResponse($this->_error['code'], array( 'success' => false, 'error' => array( 'message' => $this->_error['message'] )) ); } } // Stop rising error / exception $event->handled = true; } /** * Returns the exact trace where the problem occurs. * @param Exception $exception the uncaught exception * @return array the exact trace where the problem occurs */ protected function getExactTrace($exception) { $traces = $exception->getTrace(); foreach($traces as $trace) { // property access exception if(isset($trace['function']) && ($trace['function']==='__get' || $trace['function']==='__set')) return $trace; } return null; } /** * Access filter control */ public function filters() { return array( array( 'application.filters.AccessControl - index,authorize,error' ) ); } public function showJSON($params) { $params = !is_array($params) || empty($params) ? array() : $params; echo "(" . CJSON::encode($params) . ")"; Yii::app()->end(); } /** * This is the action to handle external exceptions. */ public function actionError() { if($error=Yii::app()->errorHandler->error) { if(Yii::app()->request->isAjaxRequest) { $this->showJSON(array( "success" => false, "error" => $error['code'], "message" => $error['message'] )); } else { $this->render('error', $error); } } } }