PluginProbe
Media Cloud Sync / 1.2.3
Media Cloud Sync v1.2.3
1.4.2 1.4.1 1.4.0 1.3.12 1.3.11 1.3.10 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.2.0 1.2.10 1.2.11 1.2.12 1.2.13 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 All 36 releases
media-cloud-sync / includes / sdk / google / guzzlehttp / psr7 / src / UriResolver.php

UriResolver.php in Media Cloud Sync 1.2.3, at includes/sdk/google/guzzlehttp/psr7/src/UriResolver.php

179 lines 8.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare (strict_types=1);
4 namespace Dudlewebs\WPMCS\GuzzleHttp\Psr7;
5
6 use Dudlewebs\WPMCS\Psr\Http\Message\UriInterface;
7 /**
8 * Resolves a URI reference in the context of a base URI and the opposite way.
9 *
10 * @author Tobias Schultze
11 *
12 * @see https://datatracker.ietf.org/doc/html/rfc3986#section-5
13 */
14 final class UriResolver
15 {
16 /**
17 * Removes dot segments from a path and returns the new path.
18 *
19 * @see https://datatracker.ietf.org/doc/html/rfc3986#section-5.2.4
20 */
21 public static function removeDotSegments(string $path): string
22 {
23 if ($path === '' || $path === '/') {
24 return $path;
25 }
26 $results = [];
27 $segments = explode('/', $path);
28 foreach ($segments as $segment) {
29 if ($segment === '..') {
30 array_pop($results);
31 } elseif ($segment !== '.') {
32 $results[] = $segment;
33 }
34 }
35 $newPath = implode('/', $results);
36 if ($path[0] === '/' && (!isset($newPath[0]) || $newPath[0] !== '/')) {
37 // Re-add the leading slash if necessary for cases like "/.."
38 $newPath = '/' . $newPath;
39 } elseif ($newPath !== '' && ($segment === '.' || $segment === '..')) {
40 // Add the trailing slash if necessary
41 // If newPath is not empty, then $segment must be set and is the last segment from the foreach
42 $newPath .= '/';
43 }
44 return $newPath;
45 }
46 /**
47 * Converts the relative URI into a new URI that is resolved against the base URI.
48 *
49 * @see https://datatracker.ietf.org/doc/html/rfc3986#section-5.2
50 */
51 public static function resolve(UriInterface $base, UriInterface $rel): UriInterface
52 {
53 if ((string) $rel === '') {
54 // we can simply return the same base URI instance for this same-document reference
55 return $base;
56 }
57 if ($rel->getScheme() != '') {
58 return $rel->withPath(self::removeDotSegments($rel->getPath()));
59 }
60 if ($rel->getAuthority() != '') {
61 $targetAuthority = $rel->getAuthority();
62 $targetPath = self::removeDotSegments($rel->getPath());
63 $targetQuery = $rel->getQuery();
64 } else {
65 $targetAuthority = $base->getAuthority();
66 if ($rel->getPath() === '') {
67 $targetPath = $base->getPath();
68 $targetQuery = $rel->getQuery() != '' ? $rel->getQuery() : $base->getQuery();
69 } else {
70 if ($rel->getPath()[0] === '/') {
71 $targetPath = $rel->getPath();
72 } else if ($targetAuthority != '' && $base->getPath() === '') {
73 $targetPath = '/' . $rel->getPath();
74 } else {
75 $lastSlashPos = strrpos($base->getPath(), '/');
76 if ($lastSlashPos === \false) {
77 $targetPath = $rel->getPath();
78 } else {
79 $targetPath = substr($base->getPath(), 0, $lastSlashPos + 1) . $rel->getPath();
80 }
81 }
82 $targetPath = self::removeDotSegments($targetPath);
83 $targetQuery = $rel->getQuery();
84 }
85 }
86 return new Uri(Uri::composeComponents($base->getScheme(), $targetAuthority, $targetPath, $targetQuery, $rel->getFragment()));
87 }
88 /**
89 * Returns the target URI as a relative reference from the base URI.
90 *
91 * This method is the counterpart to resolve():
92 *
93 * (string) $target === (string) UriResolver::resolve($base, UriResolver::relativize($base, $target))
94 *
95 * One use-case is to use the current request URI as base URI and then generate relative links in your documents
96 * to reduce the document size or offer self-contained downloadable document archives.
97 *
98 * $base = new Uri('http://example.com/a/b/');
99 * echo UriResolver::relativize($base, new Uri('http://example.com/a/b/c')); // prints 'c'.
100 * echo UriResolver::relativize($base, new Uri('http://example.com/a/x/y')); // prints '../x/y'.
101 * echo UriResolver::relativize($base, new Uri('http://example.com/a/b/?q')); // prints '?q'.
102 * echo UriResolver::relativize($base, new Uri('http://example.org/a/b/')); // prints '//example.org/a/b/'.
103 *
104 * This method also accepts a target that is already relative and will try to relativize it further. Only a
105 * relative-path reference will be returned as-is.
106 *
107 * echo UriResolver::relativize($base, new Uri('/a/b/c')); // prints 'c' as well
108 */
109 public static function relativize(UriInterface $base, UriInterface $target): UriInterface
110 {
111 if ($target->getScheme() !== '' && ($base->getScheme() !== $target->getScheme() || $target->getAuthority() === '' && $base->getAuthority() !== '')) {
112 return $target;
113 }
114 if (Uri::isRelativePathReference($target)) {
115 // As the target is already highly relative we return it as-is. It would be possible to resolve
116 // the target with `$target = self::resolve($base, $target);` and then try make it more relative
117 // by removing a duplicate query. But let's not do that automatically.
118 return $target;
119 }
120 if ($target->getAuthority() !== '' && $base->getAuthority() !== $target->getAuthority()) {
121 return $target->withScheme('');
122 }
123 // We must remove the path before removing the authority because if the path starts with two slashes, the URI
124 // would turn invalid. And we also cannot set a relative path before removing the authority, as that is also
125 // invalid.
126 $emptyPathUri = $target->withScheme('')->withPath('')->withUserInfo('')->withPort(null)->withHost('');
127 if ($base->getPath() !== $target->getPath()) {
128 return $emptyPathUri->withPath(self::getRelativePath($base, $target));
129 }
130 if ($base->getQuery() === $target->getQuery()) {
131 // Only the target fragment is left. And it must be returned even if base and target fragment are the same.
132 return $emptyPathUri->withQuery('');
133 }
134 // If the base URI has a query but the target has none, we cannot return an empty path reference as it would
135 // inherit the base query component when resolving.
136 if ($target->getQuery() === '') {
137 $segments = explode('/', $target->getPath());
138 /** @var string $lastSegment */
139 $lastSegment = end($segments);
140 return $emptyPathUri->withPath($lastSegment === '' ? './' : $lastSegment);
141 }
142 return $emptyPathUri;
143 }
144 private static function getRelativePath(UriInterface $base, UriInterface $target): string
145 {
146 $sourceSegments = explode('/', $base->getPath());
147 $targetSegments = explode('/', $target->getPath());
148 array_pop($sourceSegments);
149 $targetLastSegment = array_pop($targetSegments);
150 foreach ($sourceSegments as $i => $segment) {
151 if (isset($targetSegments[$i]) && $segment === $targetSegments[$i]) {
152 unset($sourceSegments[$i], $targetSegments[$i]);
153 } else {
154 break;
155 }
156 }
157 $targetSegments[] = $targetLastSegment;
158 $relativePath = str_repeat('../', count($sourceSegments)) . implode('/', $targetSegments);
159 // A reference to am empty last segment or an empty first sub-segment must be prefixed with "./".
160 // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used
161 // as the first segment of a relative-path reference, as it would be mistaken for a scheme name.
162 if ('' === $relativePath || \false !== strpos(explode('/', $relativePath, 2)[0], ':')) {
163 $relativePath = "./{$relativePath}";
164 } elseif ('/' === $relativePath[0]) {
165 if ($base->getAuthority() != '' && $base->getPath() === '') {
166 // In this case an extra slash is added by resolve() automatically. So we must not add one here.
167 $relativePath = ".{$relativePath}";
168 } else {
169 $relativePath = "./{$relativePath}";
170 }
171 }
172 return $relativePath;
173 }
174 private function __construct()
175 {
176 // cannot be instantiated
177 }
178 }
179