Skip to content

Commit

Permalink
Improve components interactions
Browse files Browse the repository at this point in the history
  • Loading branch information
nyamsprod committed Jul 7, 2024
1 parent dbfab96 commit ebccd24
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 6 deletions.
4 changes: 4 additions & 0 deletions components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ All Notable changes to `League\Uri\Components` will be documented in this file
- `Modifier::getIdnUriString`
- `Modifier::hostToIpv6Compressed`
- `Modifier::hostToIpv6Expanded`
- `Scheme::isHttp`
- `Scheme::isWebsocket`
- `Scheme::isSsl`
- `Scheme::isSpecial`

### Fixed

Expand Down
2 changes: 1 addition & 1 deletion components/Components/FragmentTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ public static function getURIProvider(): iterable
],
'PSR-7 URI object with empty string fragment' => [
'uri' => Http::new('http://example.com#'),
'expected' => '',
'expected' => null,
],
'League URI object' => [
'uri' => Uri::new('http://example.com#foobar'),
Expand Down
2 changes: 1 addition & 1 deletion components/Components/QueryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -753,7 +753,7 @@ public static function getURIProvider(): iterable
],
'PSR-7 URI object with empty string query' => [
'uri' => Http::new('http://example.com?'),
'expected' => '',
'expected' => null,
],
'League URI object' => [
'uri' => Uri::new('http://example.com?foo=bar'),
Expand Down
50 changes: 47 additions & 3 deletions components/Components/Scheme.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,30 @@
use Psr\Http\Message\UriInterface as Psr7UriInterface;
use Stringable;

use function array_key_exists;
use function in_array;
use function preg_match;
use function sprintf;
use function strtolower;

final class Scheme extends Component
{
/**
* Supported schemes and corresponding default port.
*
* @var array<string, int|null>
*/
private const SCHEME_DEFAULT_PORT = [
'data' => null,
'file' => null,
'ftp' => 21,
'gopher' => 70,
'http' => 80,
'https' => 443,
'ws' => 80,
'wss' => 443,
];

private const REGEXP_SCHEME = ',^[a-z]([-a-z0-9+.]+)?$,i';

private readonly ?string $scheme;
Expand All @@ -34,6 +52,32 @@ private function __construct(Stringable|string|null $scheme)
$this->scheme = $this->validate($scheme);
}

public function isWebsocket(): bool
{
return in_array($this->scheme, ['ws', 'wss'], true);
}

public function isHttp(): bool
{
return in_array($this->scheme, ['http', 'https'], true);
}

public function isSsl(): bool
{
return in_array($this->scheme, ['https', 'wss'], true);
}

public function isSpecial(): bool
{
return null !== $this->scheme
&& array_key_exists($this->scheme, self::SCHEME_DEFAULT_PORT);
}

public function defaultPort(): Port
{
return Port::new(self::SCHEME_DEFAULT_PORT[$this->scheme] ?? null);
}

/**
* Validate a scheme.
*
Expand All @@ -50,7 +94,7 @@ private function validate(Stringable|string|null $scheme): ?string

static $inMemoryCache = [];
if (isset($inMemoryCache[$fScheme])) {
return $inMemoryCache[$fScheme];
return $fScheme;
}

if (1 !== preg_match(self::REGEXP_SCHEME, $fScheme)) {
Expand All @@ -60,8 +104,9 @@ private function validate(Stringable|string|null $scheme): ?string
if (100 < count($inMemoryCache)) {
unset($inMemoryCache[array_key_first($inMemoryCache)]);
}
$inMemoryCache[$fScheme] = 1;

return $inMemoryCache[$fScheme] = $fScheme;
return $fScheme;
}

public static function new(Stringable|string|null $value = null): self
Expand Down Expand Up @@ -92,7 +137,6 @@ public function getUriComponent(): string
return $this->value().(null === $this->scheme ? '' : ':');
}


/**
* DEPRECATION WARNING! This method will be removed in the next major point release.
*
Expand Down
44 changes: 44 additions & 0 deletions components/Components/SchemeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,48 @@ public static function getURIProvider(): iterable
],
];
}

#[DataProvider('getSchemeInfoProvider')]
public function it_can_detect_information_about_special_schemes(
?string $scheme,
bool $isHttp,
bool $isSsl,
bool $isSpecial,
Port $defaultPort,
): void {
self::assertSame($isHttp, Scheme::new($scheme)->isHttp());
self::assertSame($isSsl, Scheme::new($scheme)->isSsl());
self::assertSame($isSpecial, Scheme::new($scheme)->isSpecial());
self::assertSame($defaultPort, Scheme::new($scheme)->defaultPort());
}

public static function getSchemeInfoProvider(): \Generator
{
yield 'detect an HTTP URL' => [
'scheme' => 'http',
'isHttp' => true,
'isWebsocket' => false,
'isSsl' => false,
'isSpecial' => true,
Port::new(80),
];

yield 'detect an WSS URL' => [
'scheme' => 'wss',
'isHttp' => false,
'isWebsocket' => false,
'isSsl' => true,
'isSpecial' => true,
Port::new(443),
];

yield 'detect an email URL' => [
'scheme' => 'email',
'isHttp' => false,
'isWebsocket' => false,
'isSsl' => false,
'isSpecial' => false,
Port::new(null),
];
}
}
2 changes: 1 addition & 1 deletion components/Components/UserInfoTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ public static function getURIProvider(): iterable
],
'PSR-7 URI object with empty string user info' => [
'uri' => Http::new('http://@example.com?foo=bar'),
'expected' => '',
'expected' => null,
],
'League URI object' => [
'uri' => Uri::new('http://foo:bar@example.com?foo=bar'),
Expand Down

0 comments on commit ebccd24

Please sign in to comment.