PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / trunk
Tutor LMS – eLearning and online course solution vtrunk
4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 4.0.0 3.9.15 3.9.14 3.9.13 3.9.12 3.9.11 trunk 1.0.0 1.0.0-alpha 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.2.0 1.2.1 1.2.11 1.2.12 1.2.13 1.2.20 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 1.8.10 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.15 1.9.16 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.1.1 2.1.10 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.3.0 2.4.0 2.5.0 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 3.0.0 3.0.1 3.0.2 3.1.0 3.2.0 3.2.1 3.2.2 3.2.3 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.7.0 3.7.1 3.7.2 3.7.3 3.7.4 3.8.0 3.8.1 3.8.2 3.8.3 3.9.0 3.9.1 3.9.10 3.9.2 3.9.3 3.9.4 3.9.5 3.9.6 3.9.7 3.9.8 3.9.9
tutor / ecommerce / PaymentGateways / Paypal / vendor / guzzlehttp / psr7 / src / UriResolver.php
tutor / ecommerce / PaymentGateways / Paypal / vendor / guzzlehttp / psr7 / src Last commit date
Exception 1 year ago AppendStream.php 2 months ago BufferStream.php 2 months ago CachingStream.php 2 months ago DroppingStream.php 2 months ago FnStream.php 2 months ago Header.php 2 months ago HttpFactory.php 1 year ago InflateStream.php 1 year ago LazyOpenStream.php 1 year ago LimitStream.php 2 months ago Message.php 2 months ago MessageTrait.php 2 months ago MimeType.php 2 months ago MultipartStream.php 2 months ago NoSeekStream.php 2 months ago PumpStream.php 2 months ago Query.php 1 year ago Request.php 2 months ago Response.php 2 months ago Rfc3986.php 2 months ago Rfc7230.php 2 months ago ServerRequest.php 2 months ago Stream.php 2 months ago StreamDecoratorTrait.php 2 months ago StreamWrapper.php 2 months ago UploadedFile.php 2 months ago Uri.php 2 months ago UriComparator.php 2 months ago UriNormalizer.php 2 months ago UriResolver.php 2 months ago Utils.php 2 months ago
UriResolver.php
208 lines
1 <?php
2
3 declare(strict_types=1);
4
5 namespace GuzzleHttp\Psr7;
6
7 use Psr\Http\Message\UriInterface;
8
9 /**
10 * Resolves a URI reference in the context of a base URI and the opposite way.
11 *
12 * @author Tobias Schultze
13 *
14 * @see https://datatracker.ietf.org/doc/html/rfc3986#section-5
15 */
16 final class UriResolver
17 {
18 /**
19 * Removes dot segments from a path and returns the new path.
20 *
21 * @see https://datatracker.ietf.org/doc/html/rfc3986#section-5.2.4
22 */
23 public static function removeDotSegments(string $path): string
24 {
25 if ($path === '' || $path === '/') {
26 return $path;
27 }
28
29 $results = [];
30 $segments = explode('/', $path);
31 foreach ($segments as $segment) {
32 if ($segment === '..') {
33 array_pop($results);
34 } elseif ($segment !== '.') {
35 $results[] = $segment;
36 }
37 }
38
39 $newPath = implode('/', $results);
40
41 if ($path[0] === '/' && (!isset($newPath[0]) || $newPath[0] !== '/')) {
42 // Re-add the leading slash if necessary for cases like "/.."
43 $newPath = '/'.$newPath;
44 } elseif ($newPath !== '' && ($segment === '.' || $segment === '..')) {
45 // Add the trailing slash if necessary
46 // If newPath is not empty, then $segment must be set and is the last segment from the foreach
47 $newPath .= '/';
48 }
49
50 return $newPath;
51 }
52
53 /**
54 * Converts the relative URI into a new URI that is resolved against the base URI.
55 *
56 * @see https://datatracker.ietf.org/doc/html/rfc3986#section-5.2
57 */
58 public static function resolve(UriInterface $base, UriInterface $rel): UriInterface
59 {
60 if ((string) $rel === '') {
61 // we can simply return the same base URI instance for this same-document reference
62 return $base;
63 }
64
65 if ($rel->getScheme() != '') {
66 return $rel->withPath(self::removeDotSegments($rel->getPath()));
67 }
68
69 if ($rel->getAuthority() != '') {
70 return $rel
71 ->withScheme($base->getScheme())
72 ->withPath(self::removeDotSegments($rel->getPath()));
73 }
74
75 if ($rel->getPath() === '') {
76 $targetPath = $base->getPath();
77 $targetQuery = $rel->getQuery() != '' ? $rel->getQuery() : $base->getQuery();
78 } else {
79 if ($rel->getPath()[0] === '/') {
80 $targetPath = $rel->getPath();
81 } else {
82 if ($base->getAuthority() != '' && $base->getPath() === '') {
83 $targetPath = '/'.$rel->getPath();
84 } else {
85 $lastSlashPos = strrpos($base->getPath(), '/');
86 if ($lastSlashPos === false) {
87 $targetPath = $rel->getPath();
88 } else {
89 $targetPath = substr($base->getPath(), 0, $lastSlashPos + 1).$rel->getPath();
90 }
91 }
92 }
93 $targetPath = self::removeDotSegments($targetPath);
94 $targetQuery = $rel->getQuery();
95 }
96
97 return $base
98 ->withPath($targetPath)
99 ->withQuery($targetQuery)
100 ->withFragment($rel->getFragment());
101 }
102
103 /**
104 * Returns the target URI as a relative reference from the base URI.
105 *
106 * This method is the counterpart to resolve():
107 *
108 * (string) $target === (string) UriResolver::resolve($base, UriResolver::relativize($base, $target))
109 *
110 * One use-case is to use the current request URI as base URI and then generate relative links in your documents
111 * to reduce the document size or offer self-contained downloadable document archives.
112 *
113 * $base = new Uri('http://example.com/a/b/');
114 * echo UriResolver::relativize($base, new Uri('http://example.com/a/b/c')); // prints 'c'.
115 * echo UriResolver::relativize($base, new Uri('http://example.com/a/x/y')); // prints '../x/y'.
116 * echo UriResolver::relativize($base, new Uri('http://example.com/a/b/?q')); // prints '?q'.
117 * echo UriResolver::relativize($base, new Uri('http://example.org/a/b/')); // prints '//example.org/a/b/'.
118 *
119 * This method also accepts a target that is already relative and will try to relativize it further. Only a
120 * relative-path reference will be returned as-is.
121 *
122 * echo UriResolver::relativize($base, new Uri('/a/b/c')); // prints 'c' as well
123 */
124 public static function relativize(UriInterface $base, UriInterface $target): UriInterface
125 {
126 if ($target->getScheme() !== ''
127 && ($base->getScheme() !== $target->getScheme() || $target->getAuthority() === '' && $base->getAuthority() !== '')
128 ) {
129 return $target;
130 }
131
132 if (Uri::isRelativePathReference($target)) {
133 // As the target is already highly relative we return it as-is. It would be possible to resolve
134 // the target with `$target = self::resolve($base, $target);` and then try make it more relative
135 // by removing a duplicate query. But let's not do that automatically.
136 return $target;
137 }
138
139 if ($target->getAuthority() !== '' && $base->getAuthority() !== $target->getAuthority()) {
140 return $target->withScheme('');
141 }
142
143 // We must remove the path before removing the authority because if the path starts with two slashes, the URI
144 // would turn invalid. And we also cannot set a relative path before removing the authority, as that is also
145 // invalid.
146 $emptyPathUri = $target->withScheme('')->withPath('')->withUserInfo('')->withPort(null)->withHost('');
147
148 if ($base->getPath() !== $target->getPath()) {
149 return $emptyPathUri->withPath(self::getRelativePath($base, $target));
150 }
151
152 if ($base->getQuery() === $target->getQuery()) {
153 // Only the target fragment is left. And it must be returned even if base and target fragment are the same.
154 return $emptyPathUri->withQuery('');
155 }
156
157 // If the base URI has a query but the target has none, we cannot return an empty path reference as it would
158 // inherit the base query component when resolving.
159 if ($target->getQuery() === '') {
160 $segments = explode('/', $target->getPath());
161 /** @var string $lastSegment */
162 $lastSegment = end($segments);
163
164 return $emptyPathUri->withPath($lastSegment === '' ? './' : $lastSegment);
165 }
166
167 return $emptyPathUri;
168 }
169
170 private static function getRelativePath(UriInterface $base, UriInterface $target): string
171 {
172 $sourceSegments = explode('/', $base->getPath());
173 $targetSegments = explode('/', $target->getPath());
174 array_pop($sourceSegments);
175 $targetLastSegment = array_pop($targetSegments);
176 foreach ($sourceSegments as $i => $segment) {
177 if (isset($targetSegments[$i]) && $segment === $targetSegments[$i]) {
178 unset($sourceSegments[$i], $targetSegments[$i]);
179 } else {
180 break;
181 }
182 }
183 $targetSegments[] = $targetLastSegment;
184 $relativePath = str_repeat('../', count($sourceSegments)).implode('/', $targetSegments);
185
186 // A reference to am empty last segment or an empty first sub-segment must be prefixed with "./".
187 // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used
188 // as the first segment of a relative-path reference, as it would be mistaken for a scheme name.
189 if ('' === $relativePath || false !== strpos(explode('/', $relativePath, 2)[0], ':')) {
190 $relativePath = "./$relativePath";
191 } elseif ('/' === $relativePath[0]) {
192 if ($base->getAuthority() != '' && $base->getPath() === '') {
193 // In this case an extra slash is added by resolve() automatically. So we must not add one here.
194 $relativePath = ".$relativePath";
195 } else {
196 $relativePath = "./$relativePath";
197 }
198 }
199
200 return $relativePath;
201 }
202
203 private function __construct()
204 {
205 // cannot be instantiated
206 }
207 }
208