Passed
Push — master ( 650988...cc92ec )
by
unknown
02:35
created

Subfolder   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 93
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
eloc 41
dl 0
loc 93
ccs 42
cts 42
cp 1
rs 10
c 0
b 0
f 0
wmc 21

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
B process() 0 40 11
B getBaseUrl() 0 34 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 dirname;
16
use function strlen;
17
18
/**
19
 * This middleware supports routing when the entry point of the application isn't directly at the webroot.
20
 * By default, it determines webroot based on server parameters.
21
 *
22
 * You should place this middleware before `Route` middleware in the middleware list.
23
 */
24
final class Subfolder implements MiddlewareInterface
25
{
26
    /**
27
     * @param UrlGeneratorInterface $uriGenerator The URI generator instance.
28
     * @param Aliases $aliases The aliases instance.
29
     * @param string|null $prefix URI prefix that goes immediately after the domain part.
30
     * The prefix value usually begins with a slash and mustn't end with a slash.
31
     * @param string|null $baseUrlAlias The base URL alias {@see Aliases::get()}. Defaults to `@baseUrl`.
32
     */
33 18
    public function __construct(
34
        private UrlGeneratorInterface $uriGenerator,
35
        private Aliases $aliases,
36
        private ?string $prefix = null,
37
        private ?string $baseUrlAlias = '@baseUrl',
38
    ) {
39 18
    }
40
41 18
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
42
    {
43 18
        $uri = $request->getUri();
44 18
        $path = $uri->getPath();
45 18
        $baseUrl = $this->prefix ?? $this->getBaseUrl($request);
46 18
        $length = strlen($baseUrl);
47
48 18
        if ($this->prefix !== null) {
49 6
            if (empty($this->prefix)) {
50 1
                throw new BadUriPrefixException('URI prefix can\'t be empty.');
51
            }
52
53 5
            if ($baseUrl[-1] === '/') {
54 1
                throw new BadUriPrefixException('Wrong URI prefix value.');
55
            }
56
57 4
            if (!str_starts_with($path, $baseUrl)) {
58 2
                throw new BadUriPrefixException('URI prefix doesn\'t match.');
59
            }
60
        }
61
62 14
        if ($length > 0) {
63 13
            $newPath = substr($path, $length);
64
65 13
            if ($newPath === '') {
66 1
                $newPath = '/';
67
            }
68
69 13
            if ($newPath[0] === '/') {
70 10
                $request = $request->withUri($uri->withPath($newPath));
71 10
                $this->uriGenerator->setUriPrefix($baseUrl);
72 10
                if ($this->baseUrlAlias !== null && $this->prefix === null) {
73 10
                    $this->aliases->set($this->baseUrlAlias, $baseUrl);
74
                }
75 3
            } elseif ($this->prefix !== null) {
76 1
                throw new BadUriPrefixException('URI prefix doesn\'t match completely.');
77
            }
78
        }
79
80 13
        return $handler->handle($request);
81
    }
82
83 12
    private function getBaseUrl(ServerRequestInterface $request): string
84
    {
85
        /**
86
         * @var array{
87
         *     SCRIPT_FILENAME?:string,
88
         *     PHP_SELF?:string,
89
         *     ORIG_SCRIPT_NAME?:string,
90
         *     DOCUMENT_ROOT?:string
91
         * } $serverParams
92
         */
93 12
        $serverParams = $request->getServerParams();
94 12
        $scriptUrl = $serverParams['SCRIPT_FILENAME'] ?? '/index.php';
95 12
        $scriptName = basename($scriptUrl);
96
97 12
        if (isset($serverParams['PHP_SELF']) && basename($serverParams['PHP_SELF']) === $scriptName) {
98 1
            $scriptUrl = $serverParams['PHP_SELF'];
99
        } elseif (
100 11
            isset($serverParams['ORIG_SCRIPT_NAME']) &&
101 11
            basename($serverParams['ORIG_SCRIPT_NAME']) === $scriptName
102
        ) {
103 2
            $scriptUrl = $serverParams['ORIG_SCRIPT_NAME'];
104
        } elseif (
105 9
            isset($serverParams['PHP_SELF']) &&
106 9
            ($pos = strpos($serverParams['PHP_SELF'], $scriptName)) !== false
107
        ) {
108 1
            $scriptUrl = substr($serverParams['PHP_SELF'], 0, $pos + strlen($scriptName));
109
        } elseif (
110 8
            !empty($serverParams['DOCUMENT_ROOT']) &&
111 8
            str_starts_with($scriptUrl, $serverParams['DOCUMENT_ROOT'])
112
        ) {
113 1
            $scriptUrl = str_replace([$serverParams['DOCUMENT_ROOT'], '\\'], ['', '/'], $scriptUrl);
114
        }
115
116 12
        return rtrim(dirname($scriptUrl), '\\/');
117
    }
118
}
119