Test Failed
Push — master ( 08de7a...d45f24 )
by Divine Niiquaye
11:57
created

PathMiddleware::process()   C

Complexity

Conditions 12
Paths 33

Size

Total Lines 30
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 12

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 12
eloc 15
c 3
b 0
f 0
nc 33
nop 2
dl 0
loc 30
rs 6.9666
ccs 10
cts 10
cp 1
crap 12

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of Flight Routing.
7
 *
8
 * PHP version 7.4 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\Routes\{FastRoute as Route, Route as BaseRoute};
21
use Psr\Http\Message\{ResponseInterface, ServerRequestInterface, UriInterface};
22
use Psr\Http\Server\{MiddlewareInterface, RequestHandlerInterface};
23
24
/**
25
 * This middleware increases SEO (search engine optimization) by preventing duplication
26
 * of content at different URLs including resolving sub-directory paths.
27
 *
28
 * The response status code is 302 if the permanent parameter is false (default),
29
 * and 301 if the redirection is permanent on redirection. If keep request method
30
 * parameter is true, response code 307, and if permanent is true status code is 308.
31
 *
32
 * @author Divine Niiquaye Ibok <[email protected]>
33
 */
34 3
final class PathMiddleware implements MiddlewareInterface
35
{
36 3
    public const SUB_FOLDER = __CLASS__ . '::subFolder';
37 3
38
    private bool $permanent;
39
40
    private bool $keepRequestMethod;
41
42 3
    /**
43
     * @param bool $permanent         Whether the redirection is permanent
44 3
     * @param bool $keepRequestMethod Whether redirect action should keep HTTP request method
45 3
     */
46
    public function __construct(bool $permanent = false, bool $keepRequestMethod = false)
47 3
    {
48 3
        $this->permanent = $permanent;
49
        $this->keepRequestMethod = $keepRequestMethod;
50
    }
51 3
52 2
    /**
53 2
     * {@inheritdoc}
54
     */
55
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
56
    {
57 1
        $requestPath = ($requestUri = self::resolveUri($request))->getPath(); // Determine right request uri path.
58
59
        $response = $handler->handle($request);
60
        $route = $request->getAttribute(Route::class);
61
62
        if ($route instanceof Route) {
63
            // Determine the response code should keep HTTP request method ...
64
            $statusCode = $this->keepRequestMethod ? ($this->permanent ? 308 : 307) : ($this->permanent ? 301 : 302);
65
66
            $routeEndTail = BaseRoute::URL_PREFIX_SLASHES[$route->getPath()[-1]] ?? null;
67
            $requestEndTail = BaseRoute::URL_PREFIX_SLASHES[$requestPath[-1]] ?? null;
68
69 3
            if ($requestEndTail === $requestPath || $routeEndTail === $requestEndTail) {
70
                return $response;
71
            }
72 3
73 3
            // Resolve request tail end to avoid conflicts and infinite redirection looping ...
74
            if (null === $requestEndTail && null !== $routeEndTail) {
75 3
                $requestPath .= $routeEndTail;
76 3
            } elseif (null === $routeEndTail && null !== $requestEndTail) {
77 3
                $requestPath = \substr($requestPath, 0, -1) ?: $requestEndTail;
78
            }
79
80 3
            // Allow Redirection if exists and avoid static request.
81 1
            return $response->withHeader('Location', (string) $requestUri->withPath($requestPath))->withStatus($statusCode);
82
        }
83
84 2
        return $response;
85 1
    }
86
87
    public static function resolveUri(ServerRequestInterface &$request): UriInterface
88 1
    {
89
        $requestUri = $request->getUri();
90
        $pathInfo = $request->getServerParams()['PATH_INFO'] ?? '';
91
92
        // Checks if the project is in a sub-directory, expect PATH_INFO in $_SERVER.
93
        if ('' !== $pathInfo && $pathInfo !== $requestUri->getPath()) {
94
            $request = $request->withAttribute(self::SUB_FOLDER, \substr($requestUri->getPath(), 0, -(\strlen($pathInfo))));
95
96
            return $requestUri->withPath($pathInfo);
97
        }
98 2
99
        return $requestUri;
100 2
    }
101
}
102