From def297e5666ee3525ee6a7d1e7df84a864f471d3 Mon Sep 17 00:00:00 2001 From: ignace nyamagana butera Date: Thu, 11 Jul 2024 21:06:27 +0200 Subject: [PATCH] Deprecating getComponents and adding BaseUri::isOpaque --- components/Modifier.php | 2 +- composer.json | 8 +++--- docs/uri/7.0/base-uri.md | 12 ++++++++ interfaces/CHANGELOG.md | 5 ++-- interfaces/Contracts/UriInterface.php | 1 + uri/BaseUri.php | 12 ++++++++ uri/BaseUriTest.php | 41 +++++++++++++++++++++++++++ uri/CHANGELOG.md | 1 + uri/Http.php | 28 ++++++++++++++---- uri/Uri.php | 20 +++++++++++-- uri/UriTest.php | 2 +- 11 files changed, 116 insertions(+), 16 deletions(-) diff --git a/components/Modifier.php b/components/Modifier.php index 1d04a62a..fc2e1dc5 100644 --- a/components/Modifier.php +++ b/components/Modifier.php @@ -77,7 +77,7 @@ public function getIdnUriString(): string return $this->getUriString(); } - $components = $this->uri instanceof UriInterface ? $this->uri->getComponents() : UriString::parse($this->uri); + $components = $this->uri instanceof UriInterface ? $this->uri->toComponents() : UriString::parse($this->uri); $components['host'] = $host; return UriString::build($components); diff --git a/composer.json b/composer.json index 3945ed33..3ed5c8b4 100644 --- a/composer.json +++ b/composer.json @@ -32,15 +32,15 @@ "guzzlehttp/psr7": "^2.6.2", "laminas/laminas-diactoros": "^3.3.1", "nyholm/psr7": "^1.8.1", - "phpbench/phpbench": "^1.2.15", - "phpstan/phpstan": "^1.11.5", + "phpbench/phpbench": "^1.3.1", + "phpstan/phpstan": "^1.11.7", "phpstan/phpstan-deprecation-rules": "^1.2.0", "phpstan/phpstan-phpunit": "^1.4.0", "phpstan/phpstan-strict-rules": "^1.6.0", - "phpunit/phpunit": "^10.5.17 || ^11.2.5", + "phpunit/phpunit": "^10.5.17 || ^11.2.6", "psr/http-factory": "^1.1.0", "psr/http-message": "^1.1.0 || ^2.0", - "symfony/var-dumper": "^6.4.8", + "symfony/var-dumper": "^6.4.9", "uri-templates/uritemplate-test": "dev-master" }, "repositories": [ diff --git a/docs/uri/7.0/base-uri.md b/docs/uri/7.0/base-uri.md index a0edfe7b..42a72369 100644 --- a/docs/uri/7.0/base-uri.md +++ b/docs/uri/7.0/base-uri.md @@ -104,6 +104,18 @@ BaseUri::from("//example.com/toto")->isNetworkPath(); //returns true BaseUri::from("/🍣🍺")->isNetworkPath(); //returns false ~~~ +### BaseUri::isOpaque + +

added in version 7.5.0

+ +Tells whether the given URI object represents an opaque URI. An URI is said to be +opaque if and only if it is absolute but does not have an authority + +~~~php +BaseUri::from("email:john@example.com?subject=🏳️‍🌈"))->isOpaque(); //returns true +BaseUri::from("/🍣🍺")->isOpaque(); //returns false +~~~ + ### BaseUri::isRelativePath Tells whether the given URI object represents a relative path. diff --git a/interfaces/CHANGELOG.md b/interfaces/CHANGELOG.md index 7c79d216..d181048d 100644 --- a/interfaces/CHANGELOG.md +++ b/interfaces/CHANGELOG.md @@ -6,6 +6,7 @@ All Notable changes to `League\Uri\Interfaces` will be documented in this file ### Added +- `UriInterface::toComponents` returns an associative array containing all URI components values. - `UriInterface::getUsername` returns the encoded user component of the URI. - `UriInterface::getPassword` returns the encoded scheme-specific information about how to gain authorization to access the resource. - `Uri\IPv6\Converter` allow expanding and compressing IPv6. @@ -17,7 +18,7 @@ All Notable changes to `League\Uri\Interfaces` will be documented in this file ### Deprecated -- None +- `UriInterface::getComponents` use `UriInterface::toComponents` ### Removed @@ -115,7 +116,7 @@ All Notable changes to `League\Uri\Interfaces` will be documented in this file - New method to `UserInfoInterface::withUser` - New method to `UserInfoInterface::withPass` - New method to `UriInterface::toString` -- New method to `UriInterface::toComponents` +- New method to `UriInterface::getComponents` - `League\Uri\IPv4` tools - `League\Uri\Idna` tools - `League\Uri\UriString` parser diff --git a/interfaces/Contracts/UriInterface.php b/interfaces/Contracts/UriInterface.php index eee6d89a..1fde6b96 100644 --- a/interfaces/Contracts/UriInterface.php +++ b/interfaces/Contracts/UriInterface.php @@ -24,6 +24,7 @@ * * @method string|null getUsername() returns the user component of the URI. * @method string|null getPassword() returns the scheme-specific information about how to gain authorization to access the resource. + * @method array toComponents() returns an associative array containing all the URI components. */ interface UriInterface extends JsonSerializable, Stringable { diff --git a/uri/BaseUri.php b/uri/BaseUri.php index 2b44ecaa..5de77a93 100644 --- a/uri/BaseUri.php +++ b/uri/BaseUri.php @@ -185,6 +185,18 @@ public function isLocalFile(): bool }; } + /** + * Tells whether the URI is opaque or not. + * + * A URI is opaque if and only if it is absolute + * and does not has an authority path. + */ + public function isOpaque(): bool + { + return $this->nullValue === $this->uri->getAuthority() + && $this->isAbsolute(); + } + /** * Tells whether two URI do not share the same origin. */ diff --git a/uri/BaseUriTest.php b/uri/BaseUriTest.php index be04edc8..f5b9ebb3 100644 --- a/uri/BaseUriTest.php +++ b/uri/BaseUriTest.php @@ -16,6 +16,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Psr\Http\Message\UriInterface as Psr7UriInterface; @@ -583,4 +584,44 @@ public static function rfc8089UriProvider(): iterable ], ]; } + + #[DataProvider('opaqueUriProvider')] + #[Test] + public function it_tells_if_an_uri_is_opaque(bool $expected, string $uri): void + { + self::assertSame($expected, BaseUri::from($uri)->isOpaque()); + } + + public static function opaqueUriProvider(): iterable + { + yield 'empty URI' => [ + 'expected' => false, + 'uri' => '', + ]; + + yield 'relative URI' => [ + 'expected' => false, + 'uri' => 'path?query#fragment', + ]; + + yield 'URI with authority' => [ + 'expected' => false, + 'uri' => '//authority/path?query#fragment', + ]; + + yield 'absolute HTTP URI' => [ + 'expected' => false, + 'uri' => 'https://authority/path?query#fragment', + ]; + + yield 'absolute mail URI' => [ + 'expected' => true, + 'uri' => 'mail:foo@example.com', + ]; + + yield 'data URI' => [ + 'expected' => true, + 'uri' => 'data:', + ]; + } } diff --git a/uri/CHANGELOG.md b/uri/CHANGELOG.md index 72ad2904..f9ae9ebd 100644 --- a/uri/CHANGELOG.md +++ b/uri/CHANGELOG.md @@ -8,6 +8,7 @@ All Notable changes to `League\Uri` will be documented in this file - `Uri::getUsername` returns the encoded user component of the URI. - `Uri::getPassword` returns the encoded password component of the URI. +- `BaseUri::isOpaque` tells whether a URI is opaque. ### Fixed diff --git a/uri/Http.php b/uri/Http.php index 58e5dafc..d2fce116 100644 --- a/uri/Http.php +++ b/uri/Http.php @@ -67,7 +67,7 @@ private function normalizePsr7Uri(UriInterface $uri): UriInterface return match ($components) { [] => $uri, - default => Uri::fromComponents([...$uri->getComponents(), ...$components]), /* @phpstan-ignore-line */ + default => Uri::fromComponents([...$uri->toComponents(), ...$components]), }; } @@ -76,10 +76,7 @@ private function normalizePsr7Uri(UriInterface $uri): UriInterface */ public static function new(Stringable|string $uri = ''): self { - return match (true) { - $uri instanceof UriInterface => new self($uri), - default => new self(Uri::new($uri)), - }; + return self::fromComponents(UriString::parse($uri)); } /** @@ -90,6 +87,27 @@ public static function new(Stringable|string $uri = ''): self */ public static function fromComponents(array $components): self { + $components += [ + 'scheme' => null, 'user' => null, 'pass' => null, 'host' => null, + 'port' => null, 'path' => '', 'query' => null, 'fragment' => null, + ]; + + if ($components['user'] === '') { + $components['user'] = null; + } + + if ($components['pass'] === '') { + $components['pass'] = null; + } + + if ($components['query'] === '') { + $components['query'] = null; + } + + if ($components['fragment'] === '') { + $components['fragment'] = null; + } + return new self(Uri::fromComponents($components)); } diff --git a/uri/Uri.php b/uri/Uri.php index b406ff9f..2d5a6bae 100644 --- a/uri/Uri.php +++ b/uri/Uri.php @@ -384,7 +384,7 @@ private function formatPort(?int $port = null): ?int public static function new(#[SensitiveParameter] Stringable|string $uri = ''): self { $components = match (true) { - $uri instanceof UriInterface => $uri->getComponents(), + $uri instanceof UriInterface => $uri->toComponents(), default => UriString::parse($uri), }; @@ -430,7 +430,7 @@ public static function fromBaseUri( public static function fromTemplate(UriTemplate|Stringable|string $template, iterable $variables = []): self { return match (true) { - $template instanceof UriTemplate => self::fromComponents($template->expand($variables)->getComponents()), + $template instanceof UriTemplate => self::fromComponents($template->expand($variables)->toComponents()), $template instanceof UriTemplate\Template => self::new($template->expand($variables)), default => self::new(UriTemplate\Template::new($template)->expand($variables)), }; @@ -978,7 +978,7 @@ public function jsonSerialize(): string /** * @return ComponentMap */ - public function getComponents(): array + public function toComponents(): array { return [ 'scheme' => $this->scheme, @@ -1241,6 +1241,20 @@ public function withFragment(Stringable|string|null $fragment): UriInterface }; } + /** + * DEPRECATION WARNING! This method will be removed in the next major point release. + * + * @deprecated Since version 7.5.0 + * @codeCoverageIgnore + * @see Uri::toComponents() + * + * @return ComponentMap + */ + public function getComponents(): array + { + return $this->toComponents(); + } + /** * DEPRECATION WARNING! This method will be removed in the next major point release. * diff --git a/uri/UriTest.php b/uri/UriTest.php index e5f762f5..460d027a 100644 --- a/uri/UriTest.php +++ b/uri/UriTest.php @@ -55,7 +55,7 @@ public function testAutomaticUrlNormalization(): void $uri = Uri::new($raw); self::assertSame($normalized, $uri->toString()); - self::assertSame($components, $uri->getComponents()); + self::assertSame($components, $uri->toComponents()); } public function testAutomaticUrlNormalizationBis(): void