Test Failed
Push — master ( 2160b1...e71542 )
by Anatoly
09:43 queued 10s
created

ErrorHandlingMiddleware::handleInvalidEntity()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 1
nc 1
nop 2
dl 0
loc 5
c 0
b 0
f 0
cc 1
rs 10
ccs 0
cts 0
cp 0
crap 2
1
<?php declare(strict_types=1);
2
3
namespace App\Middleware;
4
5
/**
6
 * Import classes
7
 */
8
use App\ContainerAwareTrait;
9
use App\Exception\InvalidEntityException;
10
use Arus\Http\Response\ResponseFactoryAwareTrait;
11
use Psr\Http\Message\ResponseInterface;
12
use Psr\Http\Message\ServerRequestInterface;
13
use Psr\Http\Server\MiddlewareInterface;
14
use Psr\Http\Server\RequestHandlerInterface;
15
use Sunrise\Http\Router\Exception\BadRequestException;
16
use Sunrise\Http\Router\Exception\MethodNotAllowedException;
17
use Sunrise\Http\Router\Exception\RouteNotFoundException;
18
use Sunrise\Http\Router\Exception\UnsupportedMediaTypeException;
19
use Symfony\Component\Validator\ConstraintViolation;
20
use Symfony\Component\Validator\ConstraintViolationList;
21
use Whoops\Run as Whoops;
22
use Whoops\Handler\PrettyPageHandler;
23
use Throwable;
24
25
/**
26
 * Import functions
27
 */
28
use function get_class;
29
use function implode;
30
use function preg_quote;
31
use function preg_replace;
32
use function sprintf;
33
34
/**
35
 * ErrorHandlingMiddleware
36
 */
37
final class ErrorHandlingMiddleware implements MiddlewareInterface
38
{
39
    use ContainerAwareTrait;
40
    use ResponseFactoryAwareTrait;
41
42
    /**
43
     * {@inheritDoc}
44
     *
45
     * @param ServerRequestInterface $request
46
     * @param RequestHandlerInterface $handler
47
     *
48
     * @return ResponseInterface
49
     */
50
    public function process(
51
        ServerRequestInterface $request,
52
        RequestHandlerInterface $handler
53
    ) : ResponseInterface {
54
        try {
55
            return $handler->handle($request);
56
        } catch (BadRequestException $e) {
57
            return $this->handleBadRequest($request, $e);
58
        } catch (MethodNotAllowedException $e) {
59
            return $this->handleMethodNotAllowed($request, $e);
60
        } catch (RouteNotFoundException $e) {
61
            return $this->handleRouteNotFound($request, $e);
62
        } catch (UnsupportedMediaTypeException $e) {
63
            return $this->handleUnsupportedMediaType($request, $e);
64
        } catch (InvalidEntityException $e) {
65
            return $this->handleInvalidEntity($request, $e);
66
        } catch (Throwable $e) {
67
            return $this->handleException($request, $e);
68
        }
69
    }
70
71
    /**
72
     * Returns a response with the given processed exception
73
     *
74
     * @param ServerRequestInterface $request
75
     * @param BadRequestException $exception
76
     *
77
     * @return ResponseInterface
78
     */
79
    private function handleBadRequest(
80
        ServerRequestInterface $request,
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

80
        /** @scrutinizer ignore-unused */ ServerRequestInterface $request,

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
81
        BadRequestException $exception
82
    ) : ResponseInterface {
83
        $violations = new ConstraintViolationList();
84
85
        foreach ($exception->getViolations() as $v) {
86
            $violations->add(new ConstraintViolation(
87
                $v['message'],
88
                null,
89
                [],
90
                null,
91
                $v['property'],
92
                null,
93
                null,
94
                'b187c971-810b-455a-baf3-06dc6a1591f4',
95
                null,
96
                null
97
            ));
98
        }
99
100
        return $this->violations($violations, 400);
101
    }
102
103
    /**
104
     * Returns a response with the given processed exception
105
     *
106
     * @param ServerRequestInterface $request
107
     * @param MethodNotAllowedException $exception
108
     *
109
     * @return ResponseInterface
110
     */
111
    private function handleMethodNotAllowed(
112
        ServerRequestInterface $request,
113
        MethodNotAllowedException $exception
114
    ) : ResponseInterface {
115
        return $this->error(
116
            $exception->getMessage(),
117
            $request->getUri()->getPath(),
118
            '7d8f78d7-c689-409b-8031-8401ab5836b6',
119
            405
120
        )->withHeader('Allow', implode(',', $exception->getAllowedMethods()));
121
    }
122
123
    /**
124
     * Returns a response with the given processed exception
125
     *
126
     * @param ServerRequestInterface $request
127
     * @param RouteNotFoundException $exception
128
     *
129
     * @return ResponseInterface
130
     */
131
    private function handleRouteNotFound(
132
        ServerRequestInterface $request,
133
        RouteNotFoundException $exception
134
    ) : ResponseInterface {
135
        return $this->error(
136
            $exception->getMessage(),
137
            $request->getUri()->getPath(),
138
            '979775e6-a43b-414f-bb72-cbe0133f621e',
139
            404
140
        );
141
    }
142
143
    /**
144
     * Returns a response with the given processed exception
145
     *
146
     * @param ServerRequestInterface $request
147
     * @param UnsupportedMediaTypeException $exception
148
     *
149
     * @return ResponseInterface
150
     */
151
    private function handleUnsupportedMediaType(
152
        ServerRequestInterface $request,
153
        UnsupportedMediaTypeException $exception
154
    ) : ResponseInterface {
155
        return $this->error(
156
            $exception->getMessage(),
157
            $request->getUri()->getPath(),
158
            '87255179-5041-4f1b-a469-b891ad5dc623',
159
            415
160
        )->withHeader('Accept', implode(',', $exception->getSupportedTypes()));
161
    }
162
163
    /**
164
     * Returns a response with the given processed exception
165
     *
166
     * @param ServerRequestInterface $request
167
     * @param InvalidEntityException $exception
168
     *
169
     * @return ResponseInterface
170
     */
171
    private function handleInvalidEntity(
172
        ServerRequestInterface $request,
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

172
        /** @scrutinizer ignore-unused */ ServerRequestInterface $request,

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
173
        InvalidEntityException $exception
174
    ) : ResponseInterface {
175
        return $this->violations($exception->getEntityViolations(), 400);
176
    }
177
178
    /**
179
     * Returns a response with the given processed exception
180
     *
181
     * @param ServerRequestInterface $request
182
     * @param Throwable $exception
183
     *
184
     * @return ResponseInterface
185
     *
186
     * @link https://github.com/filp/whoops
187
     */
188
    private function handleException(
189
        ServerRequestInterface $request,
190
        Throwable $exception
191
    ) : ResponseInterface {
192
        $this->container->get('logger')->error($exception->getMessage(), [
193
            'exception' => $exception,
194
        ]);
195
196
        if (!$this->container->get('app.display_errors')) {
197
            return $this->error(
198
                sprintf(
199
                    'Caught the exception %s in the file %s on line %d.',
200
                    get_class($exception),
201
                    $this->hideRoot($exception->getFile()),
202
                    $exception->getLine()
203
                ),
204
                $request->getUri()->getPath(),
205
                '594358d2-b5f1-4cfc-8c60-df43cfd720b3',
206
                500
207
            );
208
        }
209
210
        $whoops = new Whoops();
211
        $whoops->allowQuit(false);
212
        $whoops->sendHttpCode(false);
213
        $whoops->writeToOutput(false);
214
        $whoops->pushHandler(new PrettyPageHandler());
215
216
        return $this->html($whoops->handleException($exception), 500);
217
    }
218
219
    /**
220
     * Hides the application root from the given path
221
     *
222
     * @param string $path
223
     *
224
     * @return string
225
     */
226
    private function hideRoot(string $path) : string
227
    {
228
        $root = preg_quote($this->container->get('app.root'), '/');
229
        $path = preg_replace('/^' . $root . '/ui', '', $path);
230
231
        return $path;
232
    }
233
}
234