From 689080519e10aefdb015dfffe57160f4ce08b9d7 Mon Sep 17 00:00:00 2001 From: Carsten Brandt Date: Sun, 26 May 2013 04:38:13 +0200 Subject: [PATCH] Added support for previous exceptions PHP supports exception stacks since 5.3 so we should use it. Also Errorhandler is now able to display the stack: #297 --- framework/yii/base/ErrorHandler.php | 22 +++++++++++++ framework/yii/base/HttpException.php | 2 +- framework/yii/console/Application.php | 2 +- framework/yii/db/ActiveRecord.php | 2 +- framework/yii/db/Command.php | 6 ++-- framework/yii/db/Connection.php | 2 +- framework/yii/views/errorHandler/callStackItem.php | 1 - framework/yii/views/errorHandler/main.php | 36 ++++++++++++++++++++-- .../yii/views/errorHandler/previousException.php | 20 ++++++++++++ 9 files changed, 82 insertions(+), 11 deletions(-) create mode 100644 framework/yii/views/errorHandler/previousException.php diff --git a/framework/yii/base/ErrorHandler.php b/framework/yii/base/ErrorHandler.php index 8997b9e..6077af6 100644 --- a/framework/yii/base/ErrorHandler.php +++ b/framework/yii/base/ErrorHandler.php @@ -49,6 +49,10 @@ class ErrorHandler extends Component */ public $callStackItemView = '@yii/views/errorHandler/callStackItem.php'; /** + * @var string the path of the view file for rendering previous exceptions. + */ + public $previousExceptionView = '@yii/views/errorHandler/previousException.php'; + /** * @var \Exception the exception that is being handled currently. */ public $exception; @@ -161,6 +165,24 @@ class ErrorHandler extends Component } /** + * Renders the previous exception stack for a given Exception. + * @param \Exception $exception the exception whose precursors should be rendered. + * @return string HTML content of the rendered previous exceptions. + * Empty string if there are none. + */ + public function renderPreviousExceptions($exception) + { + if (($previous = $exception->getPrevious()) === null) { + return ''; + } + $view = new View(); + return $view->renderFile($this->previousExceptionView, array( + 'exception' => $previous, + 'previousHtml' => $this->renderPreviousExceptions($previous), + ), $this); + } + + /** * Renders a single call stack element. * @param string $file name where call has happened. * @param integer $line number on which call has happened. diff --git a/framework/yii/base/HttpException.php b/framework/yii/base/HttpException.php index 2b014f7..4d63764 100644 --- a/framework/yii/base/HttpException.php +++ b/framework/yii/base/HttpException.php @@ -103,7 +103,7 @@ class HttpException extends UserException if (isset($httpCodes[$this->statusCode])) { return $httpCodes[$this->statusCode]; } else { - return \Yii::t('yii', 'Error'); + return 'Error'; } } } diff --git a/framework/yii/console/Application.php b/framework/yii/console/Application.php index 58c2de4..6cc114a 100644 --- a/framework/yii/console/Application.php +++ b/framework/yii/console/Application.php @@ -113,7 +113,7 @@ class Application extends \yii\base\Application try { return parent::runAction($route, $params); } catch (InvalidRouteException $e) { - throw new Exception(\Yii::t('yii', 'Unknown command "{command}".', array('{command}' => $route))); + throw new Exception(\Yii::t('yii', 'Unknown command "{command}".', array('{command}' => $route)), 0, $e); } } diff --git a/framework/yii/db/ActiveRecord.php b/framework/yii/db/ActiveRecord.php index dd90782..a58ac4d 100644 --- a/framework/yii/db/ActiveRecord.php +++ b/framework/yii/db/ActiveRecord.php @@ -1215,7 +1215,7 @@ class ActiveRecord extends Model return $relation; } } catch (UnknownMethodException $e) { - throw new InvalidParamException(get_class($this) . ' has no relation named "' . $name . '".'); + throw new InvalidParamException(get_class($this) . ' has no relation named "' . $name . '".', 0, $e); } } diff --git a/framework/yii/db/Command.php b/framework/yii/db/Command.php index e05bde7..657ef8d 100644 --- a/framework/yii/db/Command.php +++ b/framework/yii/db/Command.php @@ -148,7 +148,7 @@ class Command extends \yii\base\Component } catch (\Exception $e) { Yii::error($e->getMessage() . "\nFailed to prepare SQL: $sql", __METHOD__); $errorInfo = $e instanceof \PDOException ? $e->errorInfo : null; - throw new Exception($e->getMessage(), $errorInfo, (int)$e->getCode()); + throw new Exception($e->getMessage(), $errorInfo, (int)$e->getCode(), $e); } } } @@ -298,7 +298,7 @@ class Command extends \yii\base\Component Yii::error("$message\nFailed to execute SQL: $rawSql", __METHOD__); $errorInfo = $e instanceof \PDOException ? $e->errorInfo : null; - throw new Exception($message, $errorInfo, (int)$e->getCode()); + throw new Exception($message, $errorInfo, (int)$e->getCode(), $e); } } @@ -433,7 +433,7 @@ class Command extends \yii\base\Component $message = $e->getMessage(); Yii::error("$message\nCommand::$method() failed: $rawSql", __METHOD__); $errorInfo = $e instanceof \PDOException ? $e->errorInfo : null; - throw new Exception($message, $errorInfo, (int)$e->getCode()); + throw new Exception($message, $errorInfo, (int)$e->getCode(), $e); } } diff --git a/framework/yii/db/Connection.php b/framework/yii/db/Connection.php index d956691..e14eeb7 100644 --- a/framework/yii/db/Connection.php +++ b/framework/yii/db/Connection.php @@ -319,7 +319,7 @@ class Connection extends Component Yii::endProfile($token, __METHOD__); Yii::error("Failed to open DB connection ({$this->dsn}): " . $e->getMessage(), __METHOD__); $message = YII_DEBUG ? 'Failed to open DB connection: ' . $e->getMessage() : 'Failed to open DB connection.'; - throw new Exception($message, $e->errorInfo, (int)$e->getCode()); + throw new Exception($message, $e->errorInfo, (int)$e->getCode(), $e); } } } diff --git a/framework/yii/views/errorHandler/callStackItem.php b/framework/yii/views/errorHandler/callStackItem.php index 3854ea4..2139c46 100644 --- a/framework/yii/views/errorHandler/callStackItem.php +++ b/framework/yii/views/errorHandler/callStackItem.php @@ -11,7 +11,6 @@ */ $context = $this->context; ?> -
  • diff --git a/framework/yii/views/errorHandler/main.php b/framework/yii/views/errorHandler/main.php index 93fa589..b92e29b 100644 --- a/framework/yii/views/errorHandler/main.php +++ b/framework/yii/views/errorHandler/main.php @@ -93,6 +93,35 @@ html,body{ font-size: 20px; text-shadow: 0 1px 0 #cacaca; } +/* previous exceptions */ +.header div.previous{ + margin: 20px 20px 0 0; +} +.header div.previous div{ + margin: 15px 20px 0 25px; +} +.header div.previous h1{ + font-size: 20px; + margin-bottom: 10px; +} +h1 span.arrow{ + display: inline-block; + -moz-transform: scale(-1, 1); + -webkit-transform: scale(-1, 1); + -o-transform: scale(-1, 1); + transform: scale(-1, 1); + filter: progid:DXImageTransform.Microsoft.BasicImage(mirror=1); + width: 30px; + text-align: center; +} +.header div.previous h2{ + font-size: 15px; + margin-left: 30px; +} +.header div.previous p{ + margin: 10px 0 0 30px; + color: #aaa; +} /* call stack */ .call-stack{ @@ -131,7 +160,7 @@ html,body{ display: inline-block; } .call-stack ul li .text{ - color: #bbb; + color: #aaa; } .call-stack ul li.application .text{ color: #505050; @@ -139,7 +168,7 @@ html,body{ .call-stack ul li .at{ position: absolute; right: 110px; /* 50px + 60px */ - color: #bbb; + color: #aaa; } .call-stack ul li.application .at{ color: #505050; @@ -185,7 +214,7 @@ html,body{ line-height: 18px; font-size: 14px; font-family: Consolas, Courier New, monospace; - color: #bbb; + color: #aaa; } .call-stack ul li .code pre{ position: relative; @@ -335,6 +364,7 @@ pre .diff .change{ ?>

    htmlEncode($exception->getMessage()); ?>

    + renderPreviousExceptions($exception); ?>
    diff --git a/framework/yii/views/errorHandler/previousException.php b/framework/yii/views/errorHandler/previousException.php new file mode 100644 index 0000000..4a3d9c6 --- /dev/null +++ b/framework/yii/views/errorHandler/previousException.php @@ -0,0 +1,20 @@ + \ No newline at end of file