Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions src/Renderer/HtmlRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
use Yiisoft\ErrorHandler\Exception\ErrorException;
use Yiisoft\ErrorHandler\ThrowableRendererInterface;
use Yiisoft\FriendlyException\FriendlyExceptionInterface;
use Yiisoft\FriendlyException\Attribute\FriendlyException;
use Yiisoft\Http\Header;
use ReflectionClass;

use function array_values;
use function dirname;
Expand Down Expand Up @@ -491,16 +493,33 @@
}

/**
* Returns the name of the throwable instance.
* Returns string representation of the throwable name.
*
* @return string The name of the throwable instance.
* @param Throwable $throwable The throwable.
*
* @return string The throwable name.
*/
public function getThrowableName(Throwable $throwable): string
{
$name = $throwable::class;

if ($throwable instanceof FriendlyExceptionInterface) {
$name = $throwable->getName() . ' (' . $name . ')';
} else {
// Check if the exception class has FriendlyException attribute
try {
$reflectionClass = new ReflectionClass($throwable);
if (class_exists('Yiisoft\FriendlyException\Attribute\FriendlyException')) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use full class name notation without quotes

Suggested change
if (class_exists('Yiisoft\FriendlyException\Attribute\FriendlyException')) {
if (class_exists(\Yiisoft\FriendlyException\Attribute\FriendlyException::class)) {

$attributes = $reflectionClass->getAttributes('Yiisoft\FriendlyException\Attribute\FriendlyException');

Check failure on line 513 in src/Renderer/HtmlRenderer.php

View workflow job for this annotation

GitHub Actions / psalm / PHP 8.3-ubuntu-latest

ArgumentTypeCoercion

src/Renderer/HtmlRenderer.php:513:67: ArgumentTypeCoercion: Argument 1 of ReflectionClass::getAttributes expects class-string|null, but parent type 'Yiisoft\\FriendlyException\\Attribute\\FriendlyException' provided (see https://psalm.dev/193)

Check warning on line 513 in src/Renderer/HtmlRenderer.php

View check run for this annotation

Codecov / codecov/patch

src/Renderer/HtmlRenderer.php#L513

Added line #L513 was not covered by tests
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same


if (!empty($attributes)) {
$friendlyExceptionAttribute = $attributes[0]->newInstance();

Check warning on line 516 in src/Renderer/HtmlRenderer.php

View check run for this annotation

Codecov / codecov/patch

src/Renderer/HtmlRenderer.php#L515-L516

Added lines #L515 - L516 were not covered by tests
$name = $friendlyExceptionAttribute->name . ' (' . $name . ')';

Check failure on line 517 in src/Renderer/HtmlRenderer.php

View workflow job for this annotation

GitHub Actions / psalm / PHP 8.3-ubuntu-latest

MixedOperand

src/Renderer/HtmlRenderer.php:517:33: MixedOperand: Left operand cannot be mixed (see https://psalm.dev/059)
}
}
} catch (\Throwable) {

Check warning on line 520 in src/Renderer/HtmlRenderer.php

View check run for this annotation

Codecov / codecov/patch

src/Renderer/HtmlRenderer.php#L520

Added line #L520 was not covered by tests
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where do you expect an exception? I'd remove try/catch

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, the try/catch block isn't necessary here. When checking for the FriendlyException attribute, it would be better to let any exceptions propagate normally, making potential issues easier to discover. I'll remove the try/catch block. Thank you for the suggestion!

// Ignore exception and keep default name
}
}

return $name;
Expand Down
64 changes: 58 additions & 6 deletions templates/development.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
<?php

declare(strict_types=1);

use Psr\Http\Message\ServerRequestInterface;
use ReflectionClass;
use Throwable;
use Yiisoft\ErrorHandler\CompositeException;
use Yiisoft\ErrorHandler\Exception\ErrorException;
use Yiisoft\ErrorHandler\HeadersProvider;
use Yiisoft\ErrorHandler\Renderer\HtmlRenderer;
use Yiisoft\FriendlyException\FriendlyExceptionInterface;

Expand All @@ -20,6 +25,22 @@
}
$isFriendlyException = $throwable instanceof FriendlyExceptionInterface;
$solution = $isFriendlyException ? $throwable->getSolution() : null;

// Check if the exception class has FriendlyException attribute
if ($solution === null && class_exists('Yiisoft\FriendlyException\Attribute\FriendlyException')) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same

try {
$reflectionClass = new ReflectionClass($throwable);
$attributes = $reflectionClass->getAttributes('Yiisoft\FriendlyException\Attribute\FriendlyException');

if (!empty($attributes)) {
$friendlyExceptionAttribute = $attributes[0]->newInstance();
$solution = $friendlyExceptionAttribute->solution;
}
} catch (\Throwable $e) {
// Ignore exception
}
}

$exceptionClass = get_class($throwable);
$exceptionMessage = $throwable->getMessage();

Expand Down Expand Up @@ -78,13 +99,44 @@
<div class="exception-card">
<div class="exception-class">
<?php
if ($isFriendlyException): ?>
$hasFriendlyName = false;
if ($isFriendlyException) {
$hasFriendlyName = true;
?>
<span><?= $this->htmlEncode($throwable->getName())?></span>
&mdash;
<?= $exceptionClass ?>
<?php else: ?>
<span><?= $exceptionClass ?></span>
<?php endif ?>
<?php
} else {
// Check if the exception class has FriendlyException attribute
$hasFriendlyNameFromAttribute = false;

if (class_exists('Yiisoft\FriendlyException\Attribute\FriendlyException')) {
try {
$reflectionClass = new ReflectionClass($throwable);
$attributes = $reflectionClass->getAttributes('Yiisoft\FriendlyException\Attribute\FriendlyException');

if (!empty($attributes)) {
$friendlyExceptionAttribute = $attributes[0]->newInstance();
$hasFriendlyNameFromAttribute = true;
?>
<span><?= $this->htmlEncode($friendlyExceptionAttribute->name) ?></span>
&mdash;
<?= $exceptionClass ?>
<?php
}
} catch (\Throwable $e) {
// Ignore exception
}
}

if (!$hasFriendlyName && !$hasFriendlyNameFromAttribute) {
?>
<span><?= $exceptionClass ?></span>
<?php
}
}
?>
(Code #<?= $throwable->getCode() ?>)
</div>

Expand All @@ -98,12 +150,12 @@

<?= $this->renderPreviousExceptions($originalException) ?>

<textarea id="clipboard"><?= $this->htmlEncode($throwable) ?></textarea>
<textarea id="clipboard"><?= $this->htmlEncode((string)$throwable) ?></textarea>
<span id="copied">Copied!</span>

<a href="#"
class="copy-clipboard"
data-clipboard="<?= $this->htmlEncode($throwable) ?>"
data-clipboard="<?= $this->htmlEncode((string)$throwable) ?>"
title="Copy the stacktrace for use in a bug report or pastebin"
>
<svg width="26" height="30" fill="none" xmlns="http://www.w3.org/2000/svg">
Expand Down
25 changes: 25 additions & 0 deletions tests/Renderer/Attribute/HtmlRendererWithAttributeTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace Yiisoft\ErrorHandler\Tests\Renderer\Attribute;

use PHPUnit\Framework\TestCase;
use Yiisoft\ErrorHandler\Renderer\HtmlRenderer;
use Yiisoft\ErrorHandler\Tests\Support\TestExceptionWithAttribute;

final class HtmlRendererWithAttributeTest extends TestCase
{
public function testGetThrowableNameWithAttribute(): void
{
$this->markTestSkipped('The attribute feature is not available in the current version of friendly-exception package');

$renderer = new HtmlRenderer();
$exception = new TestExceptionWithAttribute();

$name = $renderer->getThrowableName($exception);

$this->assertStringContainsString('Test Exception Name', $name);
$this->assertStringContainsString($exception::class, $name);
}
}
17 changes: 17 additions & 0 deletions tests/Support/TestExceptionWithAttribute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace Yiisoft\ErrorHandler\Tests\Support;

use Exception;
use Yiisoft\FriendlyException\Attribute\FriendlyException;

#[FriendlyException(name: 'Test Exception Name', solution: 'This is a test solution for an exception.')]
final class TestExceptionWithAttribute extends Exception
{
public function __construct()
{
parent::__construct('This is a test exception with attribute.');
}
}
Loading