Passed
Push — master ( 585219...1d1cc0 )
by Divine Niiquaye
02:46
created

PathMiddleware::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of Flight Routing.
7
 *
8
 * PHP version 7.1 and above required
9
 *
10
 * @author    Divine Niiquaye Ibok <[email protected]>
11
 * @copyright 2019 Biurad Group (https://biurad.com/)
12
 * @license   https://opensource.org/licenses/BSD-3-Clause License
13
 *
14
 * For the full copyright and license information, please view the LICENSE
15
 * file that was distributed with this source code.
16
 */
17
18
namespace Flight\Routing\Middlewares;
19
20
use Flight\Routing\Interfaces\RouteInterface;
21
use Flight\Routing\Route;
22
use Psr\Http\Message\ResponseInterface;
23
use Psr\Http\Message\ServerRequestInterface;
24
use Psr\Http\Server\MiddlewareInterface;
25
use Psr\Http\Server\RequestHandlerInterface;
26
27
class PathMiddleware implements MiddlewareInterface
28
{
29
    /** @var bool */
30
    private $permanent;
31
32
    /**
33
     * @param bool $permanent
34
     */
35 4
    public function __construct(bool $permanent = true)
36
    {
37 4
        $this->permanent = $permanent;
38 4
    }
39
40
    /**
41
     * {@inheritdoc}
42
     */
43 4
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
44
    {
45 4
        $route    = $request->getAttribute(Route::class);
46 4
        $response = $handler->handle($request);
47 4
        $path     = $this->comparePath($route->getPath(), $request->getUri()->getPath());
48
49
        // Allow Redirection if exists and avoid static request.
50 4
        if ($route instanceof RouteInterface && null !== $path) {
51
            $response = $response
52 3
                ->withAddedHeader('Location', $path)
53 3
                ->withStatus($this->determineResponseCode($request));
54
        }
55
56 4
        return $response;
57
    }
58
59
    /**
60
     * Check if the user is on the right uri which was matched.
61
     * If matched returns null, else returns the path the user should be in.
62
     *
63
     * @param string $routeUri
64
     * @param string $requestUri
65
     *
66
     * @return null|string
67
     */
68 4
    private function comparePath(string $routeUri, string $requestUri): ?string
69
    {
70
        // Resolve Request Uri.
71 4
        $newRequestUri = '/' === $requestUri ? '/' : \rtrim($requestUri, '/');
72 4
        $newRouteUri   = '/' === $routeUri ? $routeUri : \rtrim($routeUri, '/');
73
74
        $paths = [
75 4
            'path'      => \substr($requestUri, \strlen($newRequestUri)),
76 4
            'route'     => \substr($routeUri, \strlen($newRouteUri)),
77
        ];
78
79 4
        if (!empty($paths['route']) && $paths['route'] !== $paths['path']) {
80 1
            return $newRequestUri . $paths['route'];
81
        }
82
83 3
        if (empty($paths['route']) && $paths['route'] !== $paths['path']) {
84 2
            return $newRequestUri;
85
        }
86
87 1
        return null;
88
    }
89
90
    /**
91
     * Determine the response code according with the method and the permanent config.
92
     *
93
     * @param ServerRequestInterface $request
94
     *
95
     * @return int
96
     */
97 3
    private function determineResponseCode(ServerRequestInterface $request): int
98
    {
99 3
        if (\in_array($request->getMethod(), ['GET', 'HEAD', 'CONNECT', 'TRACE', 'OPTIONS'], true)) {
100 3
            return $this->permanent ? 301 : 302;
101
        }
102
103 3
        return $this->permanent ? 308 : 307;
104
    }
105
}
106