File tree Expand file tree Collapse file tree 6 files changed +77
-9
lines changed
Expand file tree Collapse file tree 6 files changed +77
-9
lines changed Original file line number Diff line number Diff line change 44
55- Enh #150 : Cleanup templates, remove legacy code (@vjik )
66- New #151 : Add ` $traceLink ` parameter to ` HtmlRenderer ` to allow linking to trace files (@vjik )
7+ - New #153 : Introduce ` UserException ` attribute to mark user exceptions (@vjik )
78
89## 4.1.0 April 18, 2025
910
Original file line number Diff line number Diff line change 44
55namespace Yiisoft \ErrorHandler \Exception ;
66
7+ use Attribute ;
78use Exception ;
9+ use ReflectionClass ;
10+ use Throwable ;
11+
12+ use function count ;
813
914/**
10- * UserException is the base class for exceptions that are meant to be shown to end users.
11- * Such exceptions are often caused by mistakes of end users.
15+ * `UserException` is an exception and a class attribute that indicates
16+ * the exception message is safe to display to end users.
17+ *
18+ * Usage:
19+ * - throw directly (`throw new UserException(...)`) for explicit user-facing errors;
20+ * - annotate any exception class with the `#[UserException]` attribute
21+ * to mark its messages as user-facing without extending this class.
1222 *
1323 * @final
1424 */
25+ #[Attribute(Attribute::TARGET_CLASS )]
1526class UserException extends Exception
1627{
28+ public static function isUserException (Throwable $ throwable ): bool
29+ {
30+ if ($ throwable instanceof self) {
31+ return true ;
32+ }
33+
34+ $ attributes = (new ReflectionClass ($ throwable ))->getAttributes (self ::class);
35+ return count ($ attributes ) > 0 ;
36+ }
1737}
Original file line number Diff line number Diff line change 99 * @var HtmlRenderer $this
1010 */
1111
12- if ($ throwable instanceof UserException ) {
12+ if (UserException:: isUserException ( $ throwable) ) {
1313 $ name = $ this ->getThrowableName ($ throwable );
1414 $ message = $ throwable ->getMessage ();
1515} else {
Original file line number Diff line number Diff line change 1+ <?php
2+
3+ declare (strict_types=1 );
4+
5+ namespace Yiisoft \ErrorHandler \Tests \Exception \UserException ;
6+
7+ use Exception ;
8+ use Yiisoft \ErrorHandler \Exception \UserException ;
9+
10+ #[UserException]
11+ final class NotFoundException extends Exception
12+ {
13+ }
Original file line number Diff line number Diff line change 1+ <?php
2+
3+ declare (strict_types=1 );
4+
5+ namespace Yiisoft \ErrorHandler \Tests \Exception \UserException ;
6+
7+ use Exception ;
8+ use PHPUnit \Framework \Attributes \DataProvider ;
9+ use PHPUnit \Framework \TestCase ;
10+ use Throwable ;
11+ use Yiisoft \ErrorHandler \Exception \UserException ;
12+
13+ use function PHPUnit \Framework \assertInstanceOf ;
14+ use function PHPUnit \Framework \assertSame ;
15+
16+ final class UserExceptionTest extends TestCase
17+ {
18+ public function testUserExceptionInstance (): void
19+ {
20+ $ exception = new UserException ('User error message ' );
21+
22+ assertSame ('User error message ' , $ exception ->getMessage ());
23+ assertInstanceOf (Exception::class, $ exception );
24+ }
25+
26+ public static function dataIsUserException (): iterable
27+ {
28+ yield [true , new UserException ()];
29+ yield [false , new Exception ()];
30+ yield [true , new NotFoundException ()];
31+ }
32+
33+ #[DataProvider('dataIsUserException ' )]
34+ public function testIsUserException (bool $ expected , Throwable $ exception ): void
35+ {
36+ assertSame ($ expected , UserException::isUserException ($ exception ));
37+ }
38+ }
Original file line number Diff line number Diff line change @@ -32,12 +32,8 @@ public function testHandleWithHeadRequestMethod(): void
3232 $ this ->createThrowable (),
3333 $ this ->createServerRequest ('HEAD ' , ['Accept ' => ['test/html ' ]])
3434 );
35- $ response
36- ->getBody ()
37- ->rewind ();
38- $ content = $ response
39- ->getBody ()
40- ->getContents ();
35+ $ response ->getBody ()->rewind ();
36+ $ content = $ response ->getBody ()->getContents ();
4137
4238 $ this ->assertEmpty ($ content );
4339 $ this ->assertSame ([HeaderRenderer::DEFAULT_ERROR_MESSAGE ], $ response ->getHeader ('X-Error-Message ' ));
You can’t perform that action at this time.
0 commit comments