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.
Passed
Pull Request — master (#1)
by Pascal
02:13
created

ExceptionResponseListener   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 114
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
dl 0
loc 114
ccs 48
cts 48
cp 1
rs 10
c 0
b 0
f 0
wmc 16

8 Methods

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