Commit 68908051 by Carsten Brandt

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
parent 0ef40b28
...@@ -49,6 +49,10 @@ class ErrorHandler extends Component ...@@ -49,6 +49,10 @@ class ErrorHandler extends Component
*/ */
public $callStackItemView = '@yii/views/errorHandler/callStackItem.php'; 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. * @var \Exception the exception that is being handled currently.
*/ */
public $exception; public $exception;
...@@ -161,6 +165,24 @@ class ErrorHandler extends Component ...@@ -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. * Renders a single call stack element.
* @param string $file name where call has happened. * @param string $file name where call has happened.
* @param integer $line number on which call has happened. * @param integer $line number on which call has happened.
......
...@@ -103,7 +103,7 @@ class HttpException extends UserException ...@@ -103,7 +103,7 @@ class HttpException extends UserException
if (isset($httpCodes[$this->statusCode])) { if (isset($httpCodes[$this->statusCode])) {
return $httpCodes[$this->statusCode]; return $httpCodes[$this->statusCode];
} else { } else {
return \Yii::t('yii', 'Error'); return 'Error';
} }
} }
} }
...@@ -113,7 +113,7 @@ class Application extends \yii\base\Application ...@@ -113,7 +113,7 @@ class Application extends \yii\base\Application
try { try {
return parent::runAction($route, $params); return parent::runAction($route, $params);
} catch (InvalidRouteException $e) { } 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);
} }
} }
......
...@@ -1215,7 +1215,7 @@ class ActiveRecord extends Model ...@@ -1215,7 +1215,7 @@ class ActiveRecord extends Model
return $relation; return $relation;
} }
} catch (UnknownMethodException $e) { } 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);
} }
} }
......
...@@ -148,7 +148,7 @@ class Command extends \yii\base\Component ...@@ -148,7 +148,7 @@ class Command extends \yii\base\Component
} catch (\Exception $e) { } catch (\Exception $e) {
Yii::error($e->getMessage() . "\nFailed to prepare SQL: $sql", __METHOD__); Yii::error($e->getMessage() . "\nFailed to prepare SQL: $sql", __METHOD__);
$errorInfo = $e instanceof \PDOException ? $e->errorInfo : null; $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 ...@@ -298,7 +298,7 @@ class Command extends \yii\base\Component
Yii::error("$message\nFailed to execute SQL: $rawSql", __METHOD__); Yii::error("$message\nFailed to execute SQL: $rawSql", __METHOD__);
$errorInfo = $e instanceof \PDOException ? $e->errorInfo : null; $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 ...@@ -433,7 +433,7 @@ class Command extends \yii\base\Component
$message = $e->getMessage(); $message = $e->getMessage();
Yii::error("$message\nCommand::$method() failed: $rawSql", __METHOD__); Yii::error("$message\nCommand::$method() failed: $rawSql", __METHOD__);
$errorInfo = $e instanceof \PDOException ? $e->errorInfo : null; $errorInfo = $e instanceof \PDOException ? $e->errorInfo : null;
throw new Exception($message, $errorInfo, (int)$e->getCode()); throw new Exception($message, $errorInfo, (int)$e->getCode(), $e);
} }
} }
......
...@@ -319,7 +319,7 @@ class Connection extends Component ...@@ -319,7 +319,7 @@ class Connection extends Component
Yii::endProfile($token, __METHOD__); Yii::endProfile($token, __METHOD__);
Yii::error("Failed to open DB connection ({$this->dsn}): " . $e->getMessage(), __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.'; $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);
} }
} }
} }
......
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
*/ */
$context = $this->context; $context = $this->context;
?> ?>
<li class="<?php if (!$context->isCoreFile($file)) echo 'application'; ?> call-stack-item"> <li class="<?php if (!$context->isCoreFile($file)) echo 'application'; ?> call-stack-item">
<div class="element-wrap"> <div class="element-wrap">
<div class="element"> <div class="element">
......
...@@ -93,6 +93,35 @@ html,body{ ...@@ -93,6 +93,35 @@ html,body{
font-size: 20px; font-size: 20px;
text-shadow: 0 1px 0 #cacaca; 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 */
.call-stack{ .call-stack{
...@@ -131,7 +160,7 @@ html,body{ ...@@ -131,7 +160,7 @@ html,body{
display: inline-block; display: inline-block;
} }
.call-stack ul li .text{ .call-stack ul li .text{
color: #bbb; color: #aaa;
} }
.call-stack ul li.application .text{ .call-stack ul li.application .text{
color: #505050; color: #505050;
...@@ -139,7 +168,7 @@ html,body{ ...@@ -139,7 +168,7 @@ html,body{
.call-stack ul li .at{ .call-stack ul li .at{
position: absolute; position: absolute;
right: 110px; /* 50px + 60px */ right: 110px; /* 50px + 60px */
color: #bbb; color: #aaa;
} }
.call-stack ul li.application .at{ .call-stack ul li.application .at{
color: #505050; color: #505050;
...@@ -185,7 +214,7 @@ html,body{ ...@@ -185,7 +214,7 @@ html,body{
line-height: 18px; line-height: 18px;
font-size: 14px; font-size: 14px;
font-family: Consolas, Courier New, monospace; font-family: Consolas, Courier New, monospace;
color: #bbb; color: #aaa;
} }
.call-stack ul li .code pre{ .call-stack ul li .code pre{
position: relative; position: relative;
...@@ -335,6 +364,7 @@ pre .diff .change{ ...@@ -335,6 +364,7 @@ pre .diff .change{
?></h1> ?></h1>
<?php endif; ?> <?php endif; ?>
<h2><?php echo $context->htmlEncode($exception->getMessage()); ?></h2> <h2><?php echo $context->htmlEncode($exception->getMessage()); ?></h2>
<?php echo $context->renderPreviousExceptions($exception); ?>
</div> </div>
<div class="call-stack"> <div class="call-stack">
......
<div class="previous">
<h1><span class="arrow">&crarr;</span><span>Caused by: </span><?php
/**
* @var \yii\base\View $this
* @var \yii\base\Exception $exception
* @var string $previousHtml
* @var \yii\base\ErrorHandler $context
*/
$context = $this->context;
if ($exception instanceof \yii\base\Exception) {
echo '<span>' . $context->htmlEncode($exception->getName()) . '</span>';
echo ' &ndash; ' . $context->addTypeLinks(get_class($exception));
} else {
echo '<span>' . $context->htmlEncode(get_class($exception)) . '</span>';
}
?></h1>
<h2><?php echo $context->htmlEncode($exception->getMessage()); ?></h2>
<p>In <span class="file"><?php echo $exception->getFile(); ?></span> at line <span class="line"><?php echo $exception->getLine(); ?></span></p>
<?php echo $previousHtml; ?>
</div>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment