Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
69.23% covered (warning)
69.23%
9 / 13
7.69% covered (danger)
7.69%
1 / 13
12.50% covered (danger)
12.50%
1 / 8
33.33% covered (danger)
33.33%
1 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
ExceptionSubscriber
69.23% covered (warning)
69.23%
9 / 13
7.69% covered (danger)
7.69%
1 / 13
12.50% covered (danger)
12.50%
1 / 8
33.33% covered (danger)
33.33%
1 / 3
39.83
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 onExceptionEvent
88.89% covered (warning)
88.89%
8 / 9
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
5.03
 getSubscribedEvents
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace App\EventSubscriber;
4
5use App\Normalizer\ExceptionNormalizer;
6use Symfony\Component\DependencyInjection\Attribute\AutowireIterator;
7use Symfony\Component\EventDispatcher\EventSubscriberInterface;
8use Symfony\Component\HttpFoundation\JsonResponse;
9use Symfony\Component\HttpKernel\Event\ExceptionEvent;
10use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
11use Symfony\Component\HttpKernel\KernelEvents;
12use Symfony\Component\Serializer\Exception\ExceptionInterface;
13
14/**
15 * Handles exceptions to generate Json responses using custom normalizers
16 * This allows more control on the error response format with no dependency to symfony internals.
17 *
18 * @author Wilhelm Zwertvaegher
19 */
20readonly class ExceptionSubscriber implements EventSubscriberInterface
21{
22    /**
23     * @param iterable<ExceptionNormalizer> $normalizers
24     */
25    public function __construct(
26        #[AutowireIterator('app.exception_normalizer')]
27        private iterable $normalizers,
28    ) {
29    }
30
31    /**
32     * @throws ExceptionInterface
33     */
34    public function onExceptionEvent(ExceptionEvent $event): void
35    {
36        $request = $event->getRequest();
37        if ('json' !== $request->getRequestFormat()) {
38            return;
39        }
40        $throwable = $event->getThrowable();
41        foreach ($this->normalizers as $normalizer) {
42            if ($normalizer->supportsNormalization($throwable)) {
43                $data = $normalizer->normalize($throwable);
44                $status = $data['status'] ?? ($throwable instanceof HttpExceptionInterface ? $throwable->getStatusCode() : 500);
45                $event->setResponse(new JsonResponse($data, $status));
46            }
47        }
48    }
49
50    public static function getSubscribedEvents(): array
51    {
52        return [
53            KernelEvents::EXCEPTION => 'onExceptionEvent',
54        ];
55    }
56}