Passed
Push — master ( 0e5f33...6b937f )
by Rustam
03:20
created

SubFolder::getBaseUrl()   B

Complexity

Conditions 9
Paths 5

Size

Total Lines 26
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 9

Importance

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