BasePath::__toString()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 2
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 4
rs 10
1
<?php
2
/**
3
 * Webino™ (http://webino.sk)
4
 *
5
 * @link        https://github.com/webino/request
6
 * @copyright   Copyright (c) 2019 Webino, s.r.o. (http://webino.sk)
7
 * @author      Peter Bačinský <[email protected]>
8
 * @license     BSD-3-Clause
9
 */
10
11
namespace Webino;
12
13
/**
14
 * Class BasePath
15
 * @package request
16
 */
17
class BasePath implements BasePathInterface
18
{
19
    /**
20
     * @var string
21
     */
22
    private $basePath;
23
24
    /**
25
     * @var HttpRequestInterface
26
     */
27
    private $request;
28
29
    /**
30
     * @var RequestUriInterface
31
     */
32
    private $requestUri;
33
34
    /**
35
     * @param CreateInstanceEventInterface $event
36
     * @return BasePath
37
     */
38
    public static function create(CreateInstanceEventInterface $event): BasePath
39
    {
40
        $params = $event->getParameters();
41
        return new static(...$params);
42
    }
43
44
    /**
45
     * @param HttpRequestInterface $request
46
     * @param RequestUriInterface $requestUri
47
     */
48
    public function __construct(HttpRequestInterface $request, RequestUriInterface $requestUri)
49
    {
50
        $this->request = $request;
51
        $this->requestUri = $requestUri;
52
    }
53
54
    /**
55
     * @return string
56
     */
57
    public function __toString(): string
58
    {
59
        $this->basePath or $this->basePath = $this->createHttpBasePath();
60
        return $this->basePath;
61
    }
62
63
    /**
64
     * @see https://github.com/zendframework/zend-http/blob/master/src/PhpEnvironment/Request.php
65
     * @return string
66
     */
67
    protected function createHttpBasePath(): string
68
    {
69
        $request = $this->request;
70
71
        $filename = $request[$request::SCRIPT_FILENAME] ?? '';
72
        $scriptName = $request[$request::SCRIPT_NAME] ?? '';
73
        $phpSelf = $request['PHP_SELF'] ?? $scriptName;
74
        $origScriptName = $request['ORIG_SCRIPT_NAME'] ?? '';
75
76
        if ($scriptName !== null && basename($scriptName) === $filename) {
77
            $basePath = $scriptName;
78
        } elseif ($phpSelf !== null && basename($phpSelf) === $filename) {
79
            $basePath = $phpSelf;
80
        } elseif ($origScriptName !== null && basename($origScriptName) === $filename) {
81
            // 1and1 shared hosting compatibility.
82
            $basePath = $origScriptName;
83
        } else {
84
            // Backtrack up the SCRIPT_FILENAME to find the portion
85
            // matching PHP_SELF.
86
            $basePath = '';
87
            $basename = basename($filename);
88
89
            if ($basename) {
90
                $path = ($phpSelf ? trim($phpSelf, '/') : '');
91
                $basePos = strpos($path, $basename) ?: 0;
92
                $basePath .= substr($path, 0, $basePos) . $basename;
93
            }
94
        }
95
96
        // If the basePath is empty, then simply return it.
97
        if (empty($basePath)) {
98
            return '';
99
        }
100
101
        // Does the base URL have anything in common with the request URI?
102
        $requestUri = (string) $this->requestUri;
103
104
        // Full base URL matches.
105
        if (0 === strpos($requestUri, $basePath)) {
106
            return $basePath;
107
        }
108
109
        // Directory portion of base path matches.
110
        $baseDir = '/' . str_replace('\\', '/', dirname($basePath));
111
        if (0 === strpos($requestUri, $baseDir)) {
112
            return $baseDir;
113
        }
114
115
        $truncatedRequestUri = $requestUri;
116
        if (false !== ($pos = strpos($requestUri, '?'))) {
117
            $truncatedRequestUri = substr($requestUri, 0, $pos);
118
        }
119
120
        // No match whatsoever
121
        $basename = basename($basePath);
122
        if (empty($basename) || false === strpos($truncatedRequestUri, $basename)) {
123
            return '';
124
        }
125
126
        // If using mod_rewrite or ISAPI_Rewrite strip the script filename
127
        // out of the base path. $pos !== 0 makes sure it is not matching a
128
        // value from PATH_INFO or QUERY_STRING.
129
        if (strlen($requestUri) >= strlen($basePath)
130
            && (false !== ($pos = strpos($requestUri, $basePath)) && $pos !== 0)
131
        ) {
132
            $basePath = substr($requestUri, 0, $pos + strlen($basePath));
133
        }
134
135
        return $basePath;
136
    }
137
}
138