From f0f156b60e7d2352d99ae6c26c0a63fd82722164 Mon Sep 17 00:00:00 2001 From: ignace nyamagana butera Date: Fri, 27 Dec 2024 16:22:21 +0100 Subject: [PATCH] Adding new mwthods to UriString --- Uri.php | 84 ++++----------------------------------------------- UriTest.php | 2 -- composer.json | 3 +- 3 files changed, 7 insertions(+), 82 deletions(-) diff --git a/Uri.php b/Uri.php index e7c9baabe..3d94a13f2 100644 --- a/Uri.php +++ b/Uri.php @@ -43,7 +43,6 @@ use function array_keys; use function array_map; use function array_pop; -use function array_reduce; use function base64_decode; use function base64_encode; use function count; @@ -64,7 +63,6 @@ use function ltrim; use function preg_match; use function preg_replace_callback; -use function preg_split; use function rawurldecode; use function rawurlencode; use function restore_error_handler; @@ -74,13 +72,11 @@ use function str_repeat; use function str_replace; use function str_starts_with; -use function strcmp; use function strlen; use function strpos; use function strspn; use function strtolower; use function substr; -use function uksort; use const FILEINFO_MIME; use const FILEINFO_MIME_TYPE; @@ -91,7 +87,6 @@ use const FILTER_VALIDATE_IP; use const JSON_PRESERVE_ZERO_FRACTION; use const PHP_ROUND_HALF_EVEN; -use const PREG_SPLIT_NO_EMPTY; /** * @phpstan-import-type ComponentMap from UriString @@ -244,9 +239,6 @@ final class Uri implements Conditionable, UriInterface, UriRenderer, UriInspecto /** @var array */ private const WHATWG_SPECIAL_SCHEMES = ['ftp' => 1, 'http' => 1, 'https' => 1, 'ws' => 1, 'wss' => 1]; - /** @var array */ - private const DOT_SEGMENTS = ['.' => 1, '..' => 1]; - private readonly ?string $scheme; private readonly ?string $user; private readonly ?string $pass; @@ -1686,9 +1678,10 @@ public function equals(UriInterface|Stringable|string $uri, bool $excludeFragmen public function normalize(): UriInterface { return $this + ->withUserInfo($this->decodeUnreservedCharacters($this->user), $this->decodeUnreservedCharacters($this->pass)) ->withHost($this->normalizeHost()) ->withPath($this->normalizePath()) - ->withQuery($this->decodeUnreservedCharacters($this->sortQuery($this->query))) + ->withQuery($this->decodeUnreservedCharacters($this->query)) ->withFragment($this->decodeUnreservedCharacters($this->fragment)); } @@ -1696,7 +1689,7 @@ private function normalizePath(): string { $path = $this->path; if ('/' === ($path[0] ?? '') || '' !== $this->scheme.$this->authority) { - $path = self::removeDotSegments($path); + $path = UriString::removeDotSegments($path); } $path = (string) $this->decodeUnreservedCharacters($path); @@ -1720,71 +1713,6 @@ private function decodeUnreservedCharacters(?string $str): ?string }; } - private function sortQuery(?string $query): ?string - { - $codepoints = fn (?string $str): string => in_array($str, ['', null], true) ? '' : implode('.', array_map( - mb_ord(...), /* @phpstan-ignore-line */ - (array) preg_split(pattern:'//u', subject: $str, flags: PREG_SPLIT_NO_EMPTY) - )); - - $compare = fn (string $name1, string $name2): int => match (1) { - preg_match('/[^\x20-\x7f]/', $name1.$name2) => strcmp($codepoints($name1), $codepoints($name2)), - default => strcmp($name1, $name2), - }; - - $pairs = QueryString::parseFromValue($query); - $parameters = array_reduce($pairs, function (array $carry, array $pair) { - $carry[$pair[0]] ??= []; - $carry[$pair[0]][] = $pair[1]; - - return $carry; - }, []); - - uksort($parameters, $compare); - - $newPairs = []; - foreach ($parameters as $key => $values) { - $newPairs = [...$newPairs, ...array_map(fn ($value) => [$key, $value], $values)]; - } - - return match ($newPairs) { - $pairs => $query, - default => QueryString::buildFromPairs($newPairs), - }; - } - - /** - * Remove dot segments from the URI path as per RFC specification. - */ - private static function removeDotSegments(string $path): string - { - if (!str_contains($path, '.')) { - return $path; - } - - $reducer = function (array $carry, string $segment): array { - if ('..' === $segment) { - array_pop($carry); - - return $carry; - } - - if (!isset(static::DOT_SEGMENTS[$segment])) { - $carry[] = $segment; - } - - return $carry; - }; - - $oldSegments = explode('/', $path); - $newPath = implode('/', array_reduce($oldSegments, $reducer(...), [])); - if (isset(static::DOT_SEGMENTS[end($oldSegments)])) { - $newPath .= '/'; - } - - return $newPath; - } - /** * Resolves a URI against a base URI using RFC3986 rules. * @@ -1804,17 +1732,17 @@ public function resolve(Stringable|string $uri): UriInterface if (null !== $uri->getScheme()) { return $uri - ->withPath(self::removeDotSegments($uri->getPath())); + ->withPath(UriString::removeDotSegments($uri->getPath())); } if (null !== $uri->getAuthority()) { return $uri - ->withPath(self::removeDotSegments($uri->getPath())) + ->withPath(UriString::removeDotSegments($uri->getPath())) ->withScheme($this->scheme); } [$path, $query] = $this->resolvePathAndQuery($uri); - $path = self::removeDotSegments($path); + $path = UriString::removeDotSegments($path); if ('' !== $path && '/' !== $path[0] && null !== $this->getAuthority()) { $path = '/'.$path; } diff --git a/UriTest.php b/UriTest.php index 3dbbf615c..93df2bf65 100644 --- a/UriTest.php +++ b/UriTest.php @@ -529,8 +529,6 @@ public static function resolveProvider(): array ]; } - - public function testRelativizeIsNotMade(): void { $uri = '//path#fragment'; diff --git a/composer.json b/composer.json index 62162a1a2..d88b63436 100644 --- a/composer.json +++ b/composer.json @@ -64,8 +64,7 @@ "jeremykendall/php-domain-parser": "to resolve Public Suffix and Top Level Domain", "league/uri-components" : "Needed to easily manipulate URI objects components", "php-64bit": "to improve IPV4 host parsing", - "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present", - "symfony/polyfill-mbstring": "to handle URI normalization if the ext-mbstring is not present" + "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" }, "extra": { "branch-alias": {