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::onKernelException()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 5
nc 3
nop 1
dl 0
loc 10
ccs 6
cts 6
cp 1
crap 4
rs 9.2
c 0
b 0
f 0
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