Commit 2d600bc6 by Alexander Makarov

Merge pull request #3157 from yiisoft/exception-display-arguments

Fixes #2837: Error page now shows arguments in stack trace method calls
parents 9470faf2 1170e027
...@@ -11,6 +11,7 @@ Yii Framework 2 Change Log ...@@ -11,6 +11,7 @@ Yii Framework 2 Change Log
- Bug #3125: `yii\console\controllers\AssetController` now respects data URL resources (klimov-paul) - Bug #3125: `yii\console\controllers\AssetController` now respects data URL resources (klimov-paul)
- Bug #3128: Fixed the bug that `defaultRoles` set in RBAC manager was not working as specified (qiangxue) - Bug #3128: Fixed the bug that `defaultRoles` set in RBAC manager was not working as specified (qiangxue)
- Bug #3153: Fixed the bug that using "between" operator to build a SQL query will cause a PHP notice (gonimar) - Bug #3153: Fixed the bug that using "between" operator to build a SQL query will cause a PHP notice (gonimar)
- Enh #2837: Error page now shows arguments in stack trace method calls (samdark)
- Enh #3088: The debug and gii modules will manage their own URL rules now (hiltonjanfield, qiangxue) - Enh #3088: The debug and gii modules will manage their own URL rules now (hiltonjanfield, qiangxue)
- Enh #3103: debugger panel is now not displayed when printing a page (githubjeka) - Enh #3103: debugger panel is now not displayed when printing a page (githubjeka)
- Enh #3108: Added `yii\debug\Module::enableDebugLogs` to disable logging debug logs by default (qiangxue) - Enh #3108: Added `yii\debug\Module::enableDebugLogs` to disable logging debug logs by default (qiangxue)
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
<?php if ($method !== null): ?> <?php if ($method !== null): ?>
<span class="call"> <span class="call">
<?php if ($file !== null) echo '&ndash;' ?> <?php if ($file !== null) echo '&ndash;' ?>
<?= $class !== null ? $handler->addTypeLinks("$class::$method()") : $method . '()' ?> <?= $class !== null ? $handler->addTypeLinks("$class::$method(" . $handler->argumentsToString($args) . ")") : $handler->htmlEncode($method) . '(' . $handler->argumentsToString($args) . ')' ?>
</span> </span>
<?php endif; ?> <?php endif; ?>
<span class="at"><?php if ($line !== null) echo 'at line'; ?></span> <span class="at"><?php if ($line !== null) echo 'at line'; ?></span>
......
...@@ -150,6 +150,7 @@ html,body{ ...@@ -150,6 +150,7 @@ html,body{
margin: 0 auto; margin: 0 auto;
padding: 0 50px; padding: 0 50px;
position: relative; position: relative;
white-space: nowrap;
} }
.call-stack ul li a{ .call-stack ul li a{
color: #505050; color: #505050;
...@@ -286,55 +287,33 @@ html,body{ ...@@ -286,55 +287,33 @@ html,body{
} }
/* highlight.js */ /* highlight.js */
pre .subst,pre .title{ .comment{
font-weight: normal;
color: #505050;
}
pre .comment,pre .template_comment,pre .javadoc,pre .diff .header{
color: #808080; color: #808080;
font-style: italic; font-style: italic;
} }
pre .annotation,pre .decorator,pre .preprocessor,pre .doctype,pre .pi,pre .chunk,pre .shebang,pre .apache .cbracket, .keyword{
pre .prompt,pre .http .title{
color: #808000;
}
pre .tag,pre .pi{
background: #efefef;
}
pre .tag .title,pre .id,pre .attr_selector,pre .pseudo,pre .literal,pre .keyword,pre .hexcolor,pre .css .function,
pre .ini .title,pre .css .class,pre .list .title,pre .clojure .title,pre .nginx .title,pre .tex .command,
pre .request,pre .status{
color: #000080; color: #000080;
} }
pre .attribute,pre .rules .keyword,pre .number,pre .date,pre .regexp,pre .tex .special{ .number{
color: #00a; color: #00a;
} }
pre .number,pre .regexp{ .number{
font-weight: normal; font-weight: normal;
} }
pre .string,pre .value,pre .filter .argument,pre .css .function .params,pre .apache .tag{ .string, .value{
color: #0a0; color: #0a0;
} }
pre .symbol,pre .ruby .symbol .string,pre .char,pre .tex .formula{ .symbol, .char {
color: #505050; color: #505050;
background: #d0eded; background: #d0eded;
font-style: italic; font-style: italic;
} }
pre .phpdoc,pre .yardoctag,pre .javadoctag{ .phpdoc{
text-decoration: underline; text-decoration: underline;
} }
pre .variable,pre .envvar,pre .apache .sqbracket,pre .nginx .built_in{ .variable{
color: #a00; color: #a00;
} }
pre .addition{
background: #baeeba;
}
pre .deletion{
background: #ffc8bd;
}
pre .diff .change{
background: #bccff9;
}
</style> </style>
</head> </head>
...@@ -367,10 +346,10 @@ pre .diff .change{ ...@@ -367,10 +346,10 @@ pre .diff .change{
<div class="call-stack"> <div class="call-stack">
<ul> <ul>
<?= $handler->renderCallStackItem($exception->getFile(), $exception->getLine(), null, null, 1) ?> <?= $handler->renderCallStackItem($exception->getFile(), $exception->getLine(), null, null, [], 1) ?>
<?php for ($i = 0, $trace = $exception->getTrace(), $length = count($trace); $i < $length; ++$i): ?> <?php for ($i = 0, $trace = $exception->getTrace(), $length = count($trace); $i < $length; ++$i): ?>
<?= $handler->renderCallStackItem(@$trace[$i]['file'] ?: null, @$trace[$i]['line'] ?: null, <?= $handler->renderCallStackItem(@$trace[$i]['file'] ?: null, @$trace[$i]['line'] ?: null,
@$trace[$i]['class'] ?: null, @$trace[$i]['function'] ?: null, $i + 2) ?> @$trace[$i]['class'] ?: null, @$trace[$i]['function'] ?: null, $trace[$i]['args'], $i + 2) ?>
<?php endfor; ?> <?php endfor; ?>
</ul> </ul>
</div> </div>
......
...@@ -152,15 +152,18 @@ class ErrorHandler extends \yii\base\ErrorHandler ...@@ -152,15 +152,18 @@ class ErrorHandler extends \yii\base\ErrorHandler
*/ */
public function addTypeLinks($code) public function addTypeLinks($code)
{ {
if (strpos($code, 'yii\\') !== 0) { if (preg_match('/(.*?)::([^(]+)\((.*)\)/', $code, $matches)) {
return $this->htmlEncode($code); $class = $matches[1];
} $method = $matches[2];
$args = $matches[3];
if (($pos = strpos($code, '::')) !== false) { $text = $this->htmlEncode($class) . '::' . $this->htmlEncode($method) . '(' . $args . ')';
$class = substr($code, 0, $pos);
$method = substr($code, $pos + 2);
} else { } else {
$class = $code; $class = $code;
$text = $this->htmlEncode($class);
}
if (strpos($code, 'yii\\') !== 0) {
return $text;
} }
$page = $this->htmlEncode(strtolower(str_replace('\\', '-', $class))); $page = $this->htmlEncode(strtolower(str_replace('\\', '-', $class)));
...@@ -169,7 +172,7 @@ class ErrorHandler extends \yii\base\ErrorHandler ...@@ -169,7 +172,7 @@ class ErrorHandler extends \yii\base\ErrorHandler
$url .= "#$method-detail"; $url .= "#$method-detail";
} }
return '<a href="' . $url . '" target="_blank">' . $this->htmlEncode($code) . '</a>'; return '<a href="' . $url . '" target="_blank">' . $text . '</a>';
} }
/** /**
...@@ -215,9 +218,10 @@ class ErrorHandler extends \yii\base\ErrorHandler ...@@ -215,9 +218,10 @@ class ErrorHandler extends \yii\base\ErrorHandler
* @param string|null $class called class name. * @param string|null $class called class name.
* @param string|null $method called function/method name. * @param string|null $method called function/method name.
* @param integer $index number of the call stack element. * @param integer $index number of the call stack element.
* @param array $args array of method arguments.
* @return string HTML content of the rendered call stack element. * @return string HTML content of the rendered call stack element.
*/ */
public function renderCallStackItem($file, $line, $class, $method, $index) public function renderCallStackItem($file, $line, $class, $method, $args, $index)
{ {
$lines = []; $lines = [];
$begin = $end = 0; $begin = $end = 0;
...@@ -242,6 +246,7 @@ class ErrorHandler extends \yii\base\ErrorHandler ...@@ -242,6 +246,7 @@ class ErrorHandler extends \yii\base\ErrorHandler
'lines' => $lines, 'lines' => $lines,
'begin' => $begin, 'begin' => $begin,
'end' => $end, 'end' => $end,
'args' => $args,
]); ]);
} }
...@@ -319,4 +324,59 @@ class ErrorHandler extends \yii\base\ErrorHandler ...@@ -319,4 +324,59 @@ class ErrorHandler extends \yii\base\ErrorHandler
{ {
return '<a href="http://github.com/yiisoft/yii2/" target="_blank">' . $this->htmlEncode(Yii::getVersion()) . '</a>'; return '<a href="http://github.com/yiisoft/yii2/" target="_blank">' . $this->htmlEncode(Yii::getVersion()) . '</a>';
} }
/**
* Converts arguments array to its string representation
*
* @param array $args arguments array to be converted
* @return string string representation of the arguments array
*/
public function argumentsToString($args)
{
$count = 0;
$isAssoc = $args !== array_values($args);
foreach ($args as $key => $value) {
$count++;
if($count>=5) {
if($count>5) {
unset($args[$key]);
} else {
$args[$key] = '...';
}
continue;
}
if (is_object($value)) {
$args[$key] = '<span class="title">' . $this->htmlEncode(get_class($value)) . '</span>';
} elseif (is_bool($value)) {
$args[$key] = '<span class="keyword">' . ($value ? 'true' : 'false') . '</span>';
} elseif (is_string($value)) {
$fullValue = $this->htmlEncode($value);
if (mb_strlen($value, 'utf8') > 32) {
$displayValue = $this->htmlEncode(mb_substr($value, 0, 32, 'utf8')) . '...';
$args[$key] = "<span class=\"string\" title=\"$fullValue\">'$displayValue'</span>";
} else {
$args[$key] = "<span class=\"string\">'$fullValue'</span>";
}
} elseif (is_array($value)) {
$args[$key] = '[' . $this->argumentsToString($value) . ']';
} elseif ($value === null) {
$args[$key] = '<span class="keyword">null</span>';
} elseif(is_resource($value)) {
$args[$key] = '<span class="keyword">resource</span>';
} else {
$args[$key] = '<span class="number">' . $value . '</span>';
}
if (is_string($key)) {
$args[$key] = '<span class="string">\'' . $this->htmlEncode($key) . "'</span> => $args[$key]";
} elseif ($isAssoc) {
$args[$key] = "<span class=\"number\">$key</span> => $args[$key]";
}
}
$out = implode(", ", $args);
return $out;
}
} }
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