|
20 | 20 | use Stringable; |
21 | 21 | use Throwable; |
22 | 22 |
|
| 23 | +use function array_map; |
23 | 24 | use function array_merge; |
24 | 25 | use function array_pop; |
25 | 26 | use function array_reduce; |
|
33 | 34 | use function preg_match; |
34 | 35 | use function rawurldecode; |
35 | 36 | use function sprintf; |
| 37 | +use function str_replace; |
36 | 38 | use function strpos; |
37 | 39 | use function strtolower; |
38 | 40 | use function substr; |
@@ -194,6 +196,45 @@ final class UriString |
194 | 196 | */ |
195 | 197 | private const MAXIMUM_HOST_CACHED = 100; |
196 | 198 |
|
| 199 | + /** |
| 200 | + * Generate an IRI string representation (RFC3987) from its parsed representation |
| 201 | + * returned by League\UriString::parse() or PHP's parse_url. |
| 202 | + * |
| 203 | + * If you supply your own array, you are responsible for providing |
| 204 | + * valid components without their URI delimiters. |
| 205 | + * |
| 206 | + * @link https://tools.ietf.org/html/rfc3986#section-5.3 |
| 207 | + * @link https://tools.ietf.org/html/rfc3986#section-7.5 |
| 208 | + */ |
| 209 | + public static function toIriString(Stringable|string $uri): string |
| 210 | + { |
| 211 | + $components = UriString::parse($uri); |
| 212 | + $port = null; |
| 213 | + if (isset($components['port'])) { |
| 214 | + $port = (int) $components['port']; |
| 215 | + unset($components['port']); |
| 216 | + } |
| 217 | + |
| 218 | + if (null !== $components['host']) { |
| 219 | + $components['host'] = IdnaConverter::toUnicode($components['host'])->domain(); |
| 220 | + } |
| 221 | + |
| 222 | + $components['path'] = Encoder::decodePath($components['path']); |
| 223 | + $components['user'] = Encoder::decodeNecessary($components['user']); |
| 224 | + $components['pass'] = Encoder::decodeNecessary($components['pass']); |
| 225 | + $components['query'] = Encoder::decodeQuery($components['query']); |
| 226 | + $components['fragment'] = Encoder::decodeFragment($components['fragment']); |
| 227 | + |
| 228 | + return self::build([ |
| 229 | + ...array_map(fn (?string $value) => match (true) { |
| 230 | + null === $value, |
| 231 | + !str_contains($value, '%20') => $value, |
| 232 | + default => str_replace('%20', ' ', $value), |
| 233 | + }, $components), |
| 234 | + ...['port' => $port], |
| 235 | + ]); |
| 236 | + } |
| 237 | + |
197 | 238 | /** |
198 | 239 | * Generate a URI string representation from its parsed representation |
199 | 240 | * returned by League\UriString::parse() or PHP's parse_url. |
|
0 commit comments