Slim::process()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 8
c 1
b 0
f 0
dl 0
loc 16
rs 10
cc 3
nc 4
nop 2
1
<?php
2
3
namespace Jasny\Controller\Middleware;
4
5
use Jasny\Controller\Controller;
6
use Psr\Http\Message\ResponseInterface;
7
use Psr\Http\Message\ServerRequestInterface;
8
use Psr\Http\Server\MiddlewareInterface;
9
use Psr\Http\Server\RequestHandlerInterface;
10
use Slim\Exception\HttpBadRequestException;
11
use Slim\Exception\HttpException;
12
use Slim\Exception\HttpForbiddenException;
13
use Slim\Exception\HttpGoneException;
14
use Slim\Exception\HttpInternalServerErrorException;
15
use Slim\Exception\HttpMethodNotAllowedException;
16
use Slim\Exception\HttpNotFoundException;
17
use Slim\Exception\HttpNotImplementedException;
18
use Slim\Exception\HttpUnauthorizedException;
19
use Slim\Routing\Route;
20
21
/**
22
 * Middleware to use controller in Slim framework
23
 */
24
class Slim implements MiddlewareInterface
25
{
26
    /**
27
     * @param bool $useSlimErrors  Throw Slim exceptions for error responses.
28
     */
29
    public function __construct(public bool $useSlimErrors = false)
30
    {
31
    }
32
33
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
34
    {
35
        $route = $request->getAttribute('__route__');
36
37
        if ($route instanceof Route) {
38
            $request = $this->changeCallable($request, $route);
39
            $request = $this->setPathParameters($request, $route);
40
        }
41
42
        $response = $handler->handle($request);
43
44
        if ($this->useSlimErrors) {
45
            $this->throwOnError($request, $response);
46
        }
47
48
        return $response;
49
    }
50
51
    protected function changeCallable(ServerRequestInterface $request, Route $route): ServerRequestInterface
52
    {
53
        $callable = $route->getCallable();
54
55
        if (is_array($callable) &&
56
            is_a($callable[0], Controller::class, true) &&
57
            isset($callable[1]) &&
58
            $callable[1] !== '__invoke'
59
        ) {
60
            $request = $request
61
                ->withAttribute("route:action", $callable[1])
62
                ->withAttribute('__route__', $route->setCallable([$callable[0], '__invoke']));
63
        }
64
65
        return $request;
66
    }
67
68
    protected function setPathParameters(ServerRequestInterface $request, Route $route): ServerRequestInterface
69
    {
70
        foreach ($route->getArguments() as $key => $value) {
71
            $request = $request->withAttribute('route:{' . $key . '}', $value);
72
        }
73
74
        return $request;
75
    }
76
77
    protected function throwOnError(ServerRequestInterface $request, ResponseInterface $response): void
78
    {
79
        $status = $response->getStatusCode();
80
81
        switch ($status) {
82
            case 400:
83
                throw new HttpBadRequestException($request, $this->getBody($response));
84
            case 401:
85
                throw new HttpUnauthorizedException($request, $this->getBody($response));
86
            case 403:
87
                throw new HttpForbiddenException($request, $this->getBody($response));
88
            case 404:
89
                throw new HttpNotFoundException($request, $this->getBody($response));
90
            case 405:
91
                throw new HttpMethodNotAllowedException($request, $this->getBody($response));
92
            case 410:
93
                throw class_exists(HttpGoneException::class)
94
                    ? new HttpGoneException($request, $this->getBody($response))
95
                    : new HttpException($request, $this->getBody($response), $status);
96
            case 500:
97
                throw new HttpInternalServerErrorException($request, $this->getBody($response));
98
            case 501:
99
                throw new HttpNotImplementedException($request, $this->getBody($response));
100
        }
101
102
        if ($status >= 400) {
103
            throw new HttpException($request, $this->getBody($response), $status);
104
        }
105
    }
106
107
    protected function getBody(ResponseInterface $response): string|null
108
    {
109
        $body = (string)$response->getBody();
110
        return $body !== '' ? $body : null;
111
    }
112
}
113