Passed
Pull Request — master (#36)
by Rustam
02:29
created

SubFolder::process()   B

Complexity

Conditions 9
Paths 20

Size

Total Lines 36
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 22
CRAP Score 9

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 9
eloc 21
c 2
b 0
f 0
nc 20
nop 2
dl 0
loc 36
ccs 22
cts 22
cp 1
crap 9
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 12
    public function __construct(
37
        private UrlGeneratorInterface $uriGenerator,
38
        private Aliases $aliases,
39
        private ?string $prefix = null,
40
        private ?string $baseUrlAlias = '@baseUrl',
41
    ) {
42 12
    }
43
44
    /**
45
     * @inheritDoc
46
     */
47 12
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
48
    {
49 12
        $uri = $request->getUri();
50 12
        $path = $uri->getPath();
51 12
        $baseUrl = $this->prefix ?? $this->getBaseUrl($request);
52 12
        $length = strlen($baseUrl);
53
54 12
        if ($this->prefix !== null) {
55 5
            if ($baseUrl[-1] === '/') {
56 1
                throw new BadUriPrefixException('Wrong URI prefix value.');
57
            }
58
59 4
            if (!str_starts_with($path, $baseUrl)) {
60 2
                throw new BadUriPrefixException('URI prefix does not match.');
61
            }
62
        }
63
64 9
        if ($length > 0) {
65 8
            $newPath = substr($path, $length);
66
67 8
            if ($newPath === '') {
68 1
                $newPath = '/';
69
            }
70
71 8
            if ($newPath[0] === '/') {
72 5
                $request = $request->withUri($uri->withPath($newPath));
73 5
                $this->uriGenerator->setUriPrefix($baseUrl);
74 5
                if ($this->baseUrlAlias !== null) {
75 5
                    $this->aliases->set($this->baseUrlAlias, $baseUrl);
76
                }
77 3
            } elseif ($this->prefix !== null) {
78 1
                throw new BadUriPrefixException('URI prefix does not match completely.');
79
            }
80
        }
81
82 8
        return $handler->handle($request);
83
    }
84
85 7
    public function getBaseUrl(ServerRequestInterface $request): string
86
    {
87 7
        $serverParams = $request->getServerParams();
88 7
        $scriptUrl = $serverParams['SCRIPT_FILENAME'];
89 7
        $scriptName = basename($scriptUrl);
90
91 7
        if (isset($serverParams['PHP_SELF']) && basename($serverParams['PHP_SELF']) === $scriptName) {
92
            $scriptUrl = $serverParams['PHP_SELF'];
93
        } elseif (
94 7
            isset($serverParams['ORIG_SCRIPT_NAME']) &&
95 7
            basename($serverParams['ORIG_SCRIPT_NAME']) === $scriptName
96
        ) {
97
            $scriptUrl = $serverParams['ORIG_SCRIPT_NAME'];
98
        } elseif (
99 7
            isset($serverParams['PHP_SELF']) &&
100 7
            ($pos = strpos($serverParams['PHP_SELF'], '/' . $scriptName)) !== false
101
        ) {
102
            $scriptUrl = substr($serverParams['PHP_SELF'], 0, $pos) . '/' . $scriptName;
103
        } elseif (
104 7
            !empty($serverParams['DOCUMENT_ROOT']) &&
105 7
            str_starts_with($scriptUrl, $serverParams['DOCUMENT_ROOT'])
106
        ) {
107
            $scriptUrl = str_replace([$serverParams['DOCUMENT_ROOT'], '\\'], ['', '/'], $scriptUrl);
108
        }
109
110 7
        return rtrim(dirname($scriptUrl), '\\/');
111
    }
112
}
113