Passed
Pull Request — master (#36)
by Rustam
09:42 queued 07:00
created

SubFolder   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 85
Duplicated Lines 0 %

Test Coverage

Coverage 77.5%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 39
c 2
b 0
f 0
dl 0
loc 85
ccs 31
cts 40
cp 0.775
rs 10
wmc 19

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
B getBaseUrl() 0 26 9
B process() 0 37 9
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Middleware;
6
7
use Psr\Http\Message\ResponseInterface;
8
use Psr\Http\Message\ServerRequestInterface;
9
use Psr\Http\Server\MiddlewareInterface;
10
use Psr\Http\Server\RequestHandlerInterface;
11
use Yiisoft\Aliases\Aliases;
12
use Yiisoft\Router\UrlGeneratorInterface;
13
use Yiisoft\Yii\Middleware\Exception\BadUriPrefixException;
14
15
use function basename;
16
use function dirname;
17
use function rtrim;
18
use function str_replace;
19
use function str_starts_with;
20
use function strlen;
21
use function strpos;
22
use function substr;
23
24
/**
25
 * This middleware supports routing when webroot is not the same folder as public.
26
 */
27
final class SubFolder implements MiddlewareInterface
28
{
29
    /**
30
     * @param UrlGeneratorInterface $uriGenerator The URI generator instance.
31
     * @param Aliases $aliases The aliases instance.
32
     * @param string|null $prefix URI prefix the specified immediately after the domain part.
33
     * The prefix value usually begins with a slash and must not end with a slash.
34
     * @param string|null $baseUrlAlias The base url alias {@see Aliases::get()}. Default "@baseUrl".
35
     */
36 7
    public function __construct(
37
        private UrlGeneratorInterface $uriGenerator,
38
        private Aliases $aliases,
39
        private ?string $prefix = null,
40
        private ?string $baseUrlAlias = '@baseUrl',
41
    ) {
42 7
    }
43
44
    /**
45
     * @inheritDoc
46
     */
47 7
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
48
    {
49 7
        $uri = $request->getUri();
50 7
        $path = $uri->getPath();
51 7
        $baseUrl = $this->prefix ?? $this->getBaseUrl($request);
52 7
        $length = strlen($baseUrl);
53
54 7
        if ($this->prefix !== null) {
55
            if ($baseUrl[-1] === '/') {
56
                throw new BadUriPrefixException('Wrong URI prefix value.');
57
            }
58
59
            if (!str_starts_with($path, $baseUrl)) {
60
                throw new BadUriPrefixException('URI prefix does not match.');
61
            }
62
        }
63
64 7
        if ($length > 0) {
65 6
            $newPath = substr($path, $length);
66
67 6
            if ($newPath === '') {
68 1
                $newPath = '/';
69
            }
70
71 6
            if ($newPath[0] === '/') {
72 4
                $request = $request->withUri($uri->withPath($newPath));
73 2
            } elseif ($this->prefix !== null) {
74
                throw new BadUriPrefixException('URI prefix does not match completely.');
75
            }
76
77 6
            $this->uriGenerator->setUriPrefix($baseUrl);
78 6
            if ($this->baseUrlAlias !== null) {
79 6
                $this->aliases->set($this->baseUrlAlias, $baseUrl);
80
            }
81
        }
82
83 7
        return $handler->handle($request);
84
    }
85
86 7
    public function getBaseUrl(ServerRequestInterface $request): string
87
    {
88 7
        $serverParams = $request->getServerParams();
89 7
        $scriptUrl = $serverParams['SCRIPT_FILENAME'];
90 7
        $scriptName = basename($scriptUrl);
91
92 7
        if (isset($serverParams['PHP_SELF']) && basename($serverParams['PHP_SELF']) === $scriptName) {
93
            $scriptUrl = $serverParams['PHP_SELF'];
94
        } elseif (
95 7
            isset($serverParams['ORIG_SCRIPT_NAME']) &&
96 7
            basename($serverParams['ORIG_SCRIPT_NAME']) === $scriptName
97
        ) {
98
            $scriptUrl = $serverParams['ORIG_SCRIPT_NAME'];
99
        } elseif (
100 7
            isset($serverParams['PHP_SELF']) &&
101 7
            ($pos = strpos($serverParams['PHP_SELF'], '/' . $scriptName)) !== false
102
        ) {
103
            $scriptUrl = substr($serverParams['PHP_SELF'], 0, $pos) . '/' . $scriptName;
104
        } elseif (
105 7
            !empty($serverParams['DOCUMENT_ROOT']) &&
106 7
            str_starts_with($scriptUrl, $serverParams['DOCUMENT_ROOT'])
107
        ) {
108
            $scriptUrl = str_replace([$serverParams['DOCUMENT_ROOT'], '\\'], ['', '/'], $scriptUrl);
109
        }
110
111 7
        return rtrim(dirname($scriptUrl), '\\/');
112
    }
113
}
114