GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — master (#1)
by Pascal
03:33
created

ExceptionResponseListener   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 98
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
dl 0
loc 98
ccs 41
cts 41
cp 1
rs 10
c 0
b 0
f 0
wmc 14

7 Methods

Rating   Name   Duplication   Size   Complexity  
A getResponseHeadersByException() 0 9 2
A getResponseStatusCodeByException() 0 7 2
A onKernelException() 0 10 4
A getResponse() 0 13 1
A getSerializer() 0 11 2
A __construct() 0 4 1
A getRequestAcceptableContentTypes() 0 9 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Saikootau\ApiBundle\Event\Listener;
6
7
use Saikootau\ApiBundle\MediaType\Exception\NonNegotiableMediaTypeException;
8
use Saikootau\ApiBundle\MediaType\MediaTypeNegotiator;
9
use Saikootau\ApiBundle\MediaType\MediaTypes;
10
use Saikootau\ApiBundle\Resource\Builder\ErrorResourceBuilder;
11
use Saikootau\ApiBundle\Resource\Builder\ServiceResourceBuilder;
12
use Saikootau\ApiBundle\Serializer\Serializer;
13
use Symfony\Component\HttpFoundation\Response;
14
use Symfony\Component\HttpFoundation\Request;
15
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
16
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
17
use Throwable;
18
19
class ExceptionResponseListener
20
{
21
    private $defaultContentType;
22
    private $mediaTypeNegotiator;
23
24 9
    public function __construct(MediaTypeNegotiator $mediaTypeNegotiator, string $defaultContentType)
25
    {
26 9
        $this->mediaTypeNegotiator = $mediaTypeNegotiator;
27 9
        $this->defaultContentType = $defaultContentType;
28 9
    }
29
30 9
    public function onKernelException(GetResponseForExceptionEvent $event): void
31
    {
32 9
        if ($event->getResponse()) {
33
            // Another listener already added a response, skip
34 1
            return;
35
        }
36
37 8
        if (($request = $event->getRequest()) && $request instanceof Request) {
38 7
            $response = $this->getResponse($request, $event->getException());
39 7
            $event->setResponse($response);
40
        }
41 8
    }
42
43 7
    private function getResponse(Request $request, Throwable $exception): Response
44
    {
45 7
        $errors = (new ErrorResourceBuilder())->build($exception);
46 7
        $service = (new ServiceResourceBuilder($request))
47 7
            ->addError(...$errors)
48 7
            ->build();
49
50 7
        $serializer = $this->getSerializer($request);
51
52 7
        return new Response(
53 7
            $serializer->serialize($service),
54 7
            $this->getResponseStatusCodeByException($exception),
55 7
            $this->getResponseHeadersByException($serializer->getContentType(), $exception)
56
        );
57
    }
58
59 7
    private function getResponseStatusCodeByException(Throwable $exception): int
60
    {
61 7
        if ($exception instanceof HttpExceptionInterface) {
62 3
            return $exception->getStatusCode();
63
        }
64
65 4
        return Response::HTTP_INTERNAL_SERVER_ERROR;
66
    }
67
68 7
    private function getResponseHeadersByException(string $contentType, Throwable $exception): array
69
    {
70 7
        $headers = [];
71 7
        if ($exception instanceof HttpExceptionInterface) {
72 3
            $headers = array_merge($headers, $exception->getHeaders());
73
        }
74 7
        $headers['Content-Type'] = $contentType;
75
76 7
        return $headers;
77
    }
78
79
    /**
80
     * Get a matching serializer for the given request's acceptable content types.
81
     *
82
     * @param Request $request
83
     *
84
     * @return Serializer
85
     *
86
     * @throws NonNegotiableMediaTypeException
87
     */
88 7
    protected function getSerializer(Request $request): Serializer
89
    {
90
        try {
91
            /** @var Serializer $serializer */
92 7
            $serializer = $this->mediaTypeNegotiator->negotiate(...$this->getRequestAcceptableContentTypes($request));
93 1
        } catch (NonNegotiableMediaTypeException $exception) {
94
            /** @var Serializer $serializer */
95 1
            $serializer = $this->mediaTypeNegotiator->negotiate($this->defaultContentType);
96
        }
97
98 7
        return $serializer;
99
    }
100
101
    /**
102
     * Returns an array of acceptable content types for the given request.
103
     *
104
     * @param Request $request
105
     *
106
     * @return string[]
107
     */
108 7
    private function getRequestAcceptableContentTypes(Request $request): array
109
    {
110 7
        $acceptableContentTypes = $request->getAcceptableContentTypes();
111
112 7
        if (false !== ($anyIndex = array_search(MediaTypes::TYPE_APPLICATION_ANY, $acceptableContentTypes))) {
113 1
            $acceptableContentTypes[$anyIndex] = $this->defaultContentType;
114
        }
115
116 7
        return $acceptableContentTypes;
117
    }
118
}
119