Skip to content

Commit 04cc409

Browse files
committed
Merge branch 'develop' into 3.x
2 parents a35ca04 + a5d2a66 commit 04cc409

File tree

3 files changed

+114
-7
lines changed

3 files changed

+114
-7
lines changed

CHANGELOG.md

+8
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@
33
All notable changes to this project will be documented in this file. This project adheres to
44
[Semantic Versioning](http://semver.org/) and [this changelog format](http://keepachangelog.com/).
55

6+
## Unreleased
7+
8+
## [2.1.0] - 2023-11-08
9+
10+
### Added
11+
12+
- Debug exception output now includes any previous exceptions.
13+
614
## [2.0.1] - 2023-07-29
715

816
### Fixed

src/ExceptionParser.php

+25-6
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
use Illuminate\Support\Collection;
2929
use Illuminate\Support\Enumerable;
3030
use LaravelJsonApi\Core\Document\Error;
31+
use LaravelJsonApi\Core\Document\ErrorList;
3132
use LaravelJsonApi\Core\Exceptions\JsonApiException;
3233
use LaravelJsonApi\Core\Responses\ErrorResponse;
3334
use Throwable;
@@ -297,20 +298,38 @@ private function mustAccept(Throwable $ex, $request): bool
297298
* Get the default JSON API error.
298299
*
299300
* @param Throwable $ex
300-
* @return Error
301+
* @return Error|ErrorList
301302
*/
302-
private function getDefaultError(Throwable $ex): Error
303+
private function getDefaultError(Throwable $ex): Error|ErrorList
303304
{
304305
if ($this->default) {
305306
return $this->default;
306307
}
307308

309+
$errors = [];
310+
$debug = config('app.debug');
311+
312+
do {
313+
$errors[] = $this->convertExceptionToError($ex, $debug);
314+
} while ($ex = $ex->getPrevious());
315+
316+
return new ErrorList(...$errors);
317+
}
318+
319+
/**
320+
* @param Throwable $ex
321+
* @param bool $debug
322+
* @return Error
323+
*/
324+
private function convertExceptionToError(Throwable $ex, bool $debug): Error
325+
{
308326
$error = Error::make()
309327
->setStatus(500)
310328
->setTitle(__(Response::$statusTexts[500]));
311329

312-
if (config('app.debug')) {
313-
$error->setCode($ex->getCode())
330+
if ($debug) {
331+
$error
332+
->setCode($ex->getCode())
314333
->setDetail($ex->getMessage())
315334
->setMeta($this->convertExceptionToMeta($ex));
316335
}
@@ -325,13 +344,13 @@ private function getDefaultError(Throwable $ex): Error
325344
* puts into its JSON representation of an exception when in debug mode.
326345
*
327346
* @param Throwable $ex
328-
* @return array
347+
* @return array<string, mixed>
329348
* @see \Illuminate\Foundation\Exceptions\Handler::convertExceptionToArray()
330349
*/
331350
private function convertExceptionToMeta(Throwable $ex): array
332351
{
333352
return [
334-
'exception' => get_class($ex),
353+
'exception' => $ex::class,
335354
'file' => $ex->getFile(),
336355
'line' => $ex->getLine(),
337356
'trace' => Collection::make($ex->getTrace())

tests/Integration/ExceptionsTest.php

+81-1
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,9 @@ public function testDefaultExceptionWithoutDebug(): void
541541
->assertExactJson($expected);
542542
}
543543

544+
/**
545+
* @return void
546+
*/
544547
public function testDefaultExceptionWithDebug(): void
545548
{
546549
config()->set('app.debug', true);
@@ -569,10 +572,87 @@ public function testDefaultExceptionWithDebug(): void
569572
],
570573
];
571574

572-
$this->get('/test', ['Accept' => 'application/vnd.api+json'])
575+
$this
576+
->get('/test', ['Accept' => 'application/vnd.api+json'])
573577
->assertStatus(500)
574578
->assertHeader('Content-Type', 'application/vnd.api+json')
575579
->assertExactJson($expected);
576580
}
577581

582+
/**
583+
* @return void
584+
*/
585+
public function testDefaultExceptionWithPreviousExceptionAndWithDebug(): void
586+
{
587+
config()->set('app.debug', true);
588+
589+
$this->ex = $ex = new \LogicException(
590+
message: 'Boom.',
591+
code: 99,
592+
previous: $previous1 = new \RuntimeException(
593+
message: 'Blah!',
594+
code: 98,
595+
previous: $previous2 = new \Exception(
596+
message: 'Baz!',
597+
code: 97
598+
),
599+
),
600+
);
601+
602+
$expected = [
603+
'errors' => [
604+
[
605+
'code' => (string) $ex->getCode(),
606+
'detail' => $ex->getMessage(),
607+
'meta' => [
608+
'exception' => $ex::class,
609+
'file' => $ex->getFile(),
610+
'line' => $ex->getLine(),
611+
'trace' => Collection::make($ex->getTrace())
612+
->map(fn($trace) => Arr::except($trace, ['args']))
613+
->all(),
614+
],
615+
'status' => '500',
616+
'title' => 'Internal Server Error',
617+
],
618+
[
619+
'code' => (string) $previous1->getCode(),
620+
'detail' => $previous1->getMessage(),
621+
'meta' => [
622+
'exception' => $previous1::class,
623+
'file' => $previous1->getFile(),
624+
'line' => $previous1->getLine(),
625+
'trace' => Collection::make($previous1->getTrace())
626+
->map(fn($trace) => Arr::except($trace, ['args']))
627+
->all(),
628+
],
629+
'status' => '500',
630+
'title' => 'Internal Server Error',
631+
],
632+
[
633+
'code' => (string) $previous2->getCode(),
634+
'detail' => $previous2->getMessage(),
635+
'meta' => [
636+
'exception' => $previous2::class,
637+
'file' => $previous2->getFile(),
638+
'line' => $previous2->getLine(),
639+
'trace' => Collection::make($previous2->getTrace())
640+
->map(fn($trace) => Arr::except($trace, ['args']))
641+
->all(),
642+
],
643+
'status' => '500',
644+
'title' => 'Internal Server Error',
645+
],
646+
],
647+
'jsonapi' => [
648+
'version' => '1.0',
649+
],
650+
];
651+
652+
$this
653+
->get('/test', ['Accept' => 'application/vnd.api+json'])
654+
->assertStatus(500)
655+
->assertHeader('Content-Type', 'application/vnd.api+json')
656+
->assertExactJson($expected);
657+
}
578658
}

0 commit comments

Comments
 (0)