Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add badges #118

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## 3.2.2 under development

- Enh #117: Show arguments table by click (@xepozz)
- Enh #116: Remove @anonymous postfix (@xepozz)
- Bug #114: Stop `click` event on text selection (@xepozz)
- Enh #114: Show full argument by click (@xepozz)
Expand Down
11 changes: 10 additions & 1 deletion src/Middleware/ErrorCatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
*/
final class ErrorCatcher implements MiddlewareInterface
{
public const REQUEST_ATTRIBUTE_NAME_TIMER = self::class . 'timer';

private HeadersProvider $headersProvider;

/**
Expand Down Expand Up @@ -129,6 +131,7 @@ public function forceContentType(string $contentType): self

public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$startTime = microtime(true);
try {
return $handler->handle($request);
} catch (Throwable $t) {
Expand All @@ -137,7 +140,13 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface
} catch (Throwable $e) {
$t = new CompositeException($e, $t);
}
return $this->generateErrorResponse($t, $request);
return $this->generateErrorResponse(
$t,
$request->withAttribute(
self::REQUEST_ATTRIBUTE_NAME_TIMER,
microtime(true) - $startTime,
),
);
}
}

Expand Down
48 changes: 40 additions & 8 deletions src/Renderer/HtmlRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,16 @@ public function renderPreviousExceptions(Throwable $t): string
public function renderCallStack(Throwable $t, array $trace = []): string
{
$application = $vendor = [];
$application[1] = $this->renderCallStackItem($t->getFile(), $t->getLine(), null, null, [], 1, false);
$application[1] = $this->renderCallStackItem(
$t->getFile(),
$t->getLine(),
null,
null,
[],
1,
false,
[],
);

$length = count($trace);
for ($i = 0; $i < $length; ++$i) {
Expand All @@ -254,18 +263,39 @@ public function renderCallStack(Throwable $t, array $trace = []): string
$class = !empty($trace[$i]['class']) ? $trace[$i]['class'] : null;
$args = !empty($trace[$i]['args']) ? $trace[$i]['args'] : [];

$parameters = [];
$function = null;
if (!empty($trace[$i]['function']) && $trace[$i]['function'] !== 'unknown') {
$function = $trace[$i]['function'];
if ($class !== null) {
$parameters = (new \ReflectionMethod($class, $function))->getParameters();
}
}
$index = $i + 2;

if ($isVendor = $this->isVendorFile($file)) {
$vendor[$index] = $this->renderCallStackItem($file, $line, $class, $function, $args, $index, $isVendor);
continue;
if ($this->isVendorFile($file)) {
$vendor[$index] = $this->renderCallStackItem(
$file,
$line,
$class,
$function,
$args,
$index,
true,
$parameters,
);
} else {
$application[$index] = $this->renderCallStackItem(
$file,
$line,
$class,
$function,
$args,
$index,
false,
$parameters,
);
}

$application[$index] = $this->renderCallStackItem($file, $line, $class, $function, $args, $index, $isVendor);
}

return $this->renderTemplate($this->defaultTemplatePath . '/_call-stack-items.php', [
Expand Down Expand Up @@ -302,7 +332,7 @@ public function argumentsToString(array $args, bool $truncate = true): string
}

if (is_object($value)) {
$args[$key] = '<span class="title">' . $this->htmlEncode($this->removeAnonymous($value::class)) . '</span>';
$args[$key] = '<span class="title">' . $this->htmlEncode($this->removeAnonymous($value::class) . '#' . spl_object_id($value)) . '</span>';
} elseif (is_bool($value)) {
$args[$key] = '<span class="keyword">' . ($value ? 'true' : 'false') . '</span>';
} elseif (is_string($value)) {
Expand Down Expand Up @@ -498,7 +528,8 @@ private function renderCallStackItem(
?string $function,
array $args,
int $index,
bool $isVendorFile
bool $isVendorFile,
array $reflectionParameters,
): string {
$lines = [];
$begin = $end = 0;
Expand All @@ -525,6 +556,7 @@ private function renderCallStackItem(
'end' => $end,
'args' => $args,
'isVendorFile' => $isVendorFile,
'reflectionParameters' => $reflectionParameters,
]);
}

Expand Down
63 changes: 50 additions & 13 deletions templates/_call-stack-item.php
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
<?php
/* @var $file string|null */
/* @var $line int|null */
/* @var $class string|null */
/* @var $function string|null */
/* @var $index int */
/* @var $lines string[] */
/* @var $begin int */
/* @var $end int */
/* @var $args array */
/* @var $isVendorFile bool */
/* @var $this \Yiisoft\ErrorHandler\Renderer\HtmlRenderer */

use Yiisoft\ErrorHandler\Renderer\HtmlRenderer;

/**
* @var $file string|null
* @var $line int|null
* @var $class string|null
* @var $function string|null
* @var $index int
* @var $lines string[]
* @var $begin int
* @var $end int
* @var $args array
* @var $isVendorFile bool
* @var $reflectionParameters ReflectionMethod[]
* @var $this HtmlRenderer
*/


$icon = <<<HTML
<svg class="external-link" width="20" height="20" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<title>Open the target page</title>
Expand All @@ -32,7 +40,7 @@
<?php endif ?>

<?php if ($function !== null): ?>
<span class="function-info">
<span class="function-info word-break">
<?php
echo $file === null ? "{$index}." : '&mdash;&nbsp;';
$function = $class === null ? $function : "{$this->removeAnonymous($class)}::$function";
Expand All @@ -48,9 +56,38 @@
</div>

<?php if ($line !== null): ?>
<div><?= sprintf('at line %d', $line + 1) ?></div>
<div class="flex flex-column">
<?= sprintf('at line %d', $line + 1) ?>
<?php if (!empty($args)): ?>
<button class="show-arguments-toggle">arguments</button>
<?php endif ?>
</div>
<?php endif ?>
</div>
<div class="function-arguments-wrap hidden">
<?php
if ($function !== null) {
echo '<table class="table w-100">';
foreach ($args as $key => $argument) {
echo '<tr class="argument">';
$key = is_int($key) && isset($reflectionParameters[$key]) ? $reflectionParameters[$key]->getName() : $key;
echo '<td>';
echo '<span class="argument-key bold">$' . $this->htmlEncode($key) . '</span>';
echo '</td>';
echo '<td>';
echo '<span class="argument-value word-break">';
echo $this->argumentsToString(is_array($argument) ? $argument : [$argument]);
echo '</span>';
echo '<span class="argument-type">';
echo gettype($argument);
echo '</span>';
echo '</td>';
echo '</tr>';
}
echo '</table>';
}
?>
</div>
<?php if (!empty($lines)): ?>
<div class="element-code-wrap">
<div class="code-wrap">
Expand Down
Loading
Loading