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

SubFolder::getBaseUrl()   B

Complexity

Conditions 9
Paths 5

Size

Total Lines 26
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 10.2655

Importance

Changes 0
Metric Value
cc 9
eloc 18
c 0
b 0
f 0
nc 5
nop 1
dl 0
loc 26
ccs 12
cts 16
cp 0.75
crap 10.2655
rs 8.0555
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