Skip to content

Commit

Permalink
Add support for RFC8089
Browse files Browse the repository at this point in the history
  • Loading branch information
nyamsprod committed Nov 19, 2023
1 parent 84b66f0 commit 5af8aa3
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 1 deletion.
12 changes: 12 additions & 0 deletions uri/BaseUri.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,18 @@ public function windowsPath(): ?string
};
}

/**
* Returns a string representation of a File URI according to RFC8089.
*/
public function toRfc8089(): ?string
{
return match (true) {
'file' !== $this->uri->getScheme() => null,
in_array($this->uri->getAuthority(), ['', null, 'localhost'], true) => 'file:'.$this->uri->getPath(),
default => (string) $this->uri,
};
}

/**
* Tells whether two URI do not share the same origin.
*/
Expand Down
30 changes: 29 additions & 1 deletion uri/BaseUriTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,6 @@ public function testReturnsWindowsPath(?string $expected, string $input): void
{
self::assertSame($expected, BaseUri::from($input)->windowsPath());
self::assertSame($expected, BaseUri::from(Utils::uriFor($input))->windowsPath());

}

public static function windowLocalPathProvider(): array
Expand Down Expand Up @@ -575,4 +574,33 @@ public static function windowLocalPathProvider(): array
],
];
}

/** @dataProvider rfc8089UriProvider */
public function testReturnsRFC8089UriString(?string $expected, string $input): void
{
self::assertSame($expected, BaseUri::from($input)->toRfc8089());
self::assertSame($expected, BaseUri::from(Utils::uriFor($input))->toRfc8089());
}

public static function rfc8089UriProvider(): iterable
{
return [
'localhost' => [
'expected' => 'file:/etc/fstab',
'input' => 'file://localhost/etc/fstab',
],
'empty authority' => [
'expected' => 'file:/etc/fstab',
'input' => 'file:///etc/fstab',
],
'file with authority' => [
'expected' => 'file://yesman/etc/fstab',
'input' => 'file://yesman/etc/fstab',
],
'invalid scheme' => [
'expected' => null,
'input' => 'foobar://yesman/etc/fstab',
],
];
}
}
44 changes: 44 additions & 0 deletions uri/FactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,50 @@ public static function windowLocalPathProvider(): array
];
}

/** @dataProvider rfc8089UriProvider */
public function testCreateFromRfc8089(string $expected, string $uri): void
{
self::assertSame($expected, Uri::fromRfc8089($uri)->toString());
}

public static function rfc8089UriProvider(): iterable
{
return [
'empty authority' => [
'expected' => 'file:///etc/fstab',
'uri' => 'file:/etc/fstab',
],
'localhost' => [
'expected' => 'file:///etc/fstab',
'uri' => 'file://localhost/etc/fstab',
],
'file with authority' => [
'expected' => 'file://yesman/etc/fstab',
'uri' => 'file://yesman/etc/fstab',
],
];
}

/** @dataProvider invalidRfc8089UriProvider */
public function testIfFailsToGenerateAnUriFromRfc8089(string $invalidUri): void
{
$this->expectException(SyntaxError::class);

Uri::fromRfc8089($invalidUri);
}

public static function invalidRfc8089UriProvider(): iterable
{
return [
'unsupported scheme' => [
'invalidUri' => 'http://www.example.com',
],
'missing scheme' => [
'invalidUri' => '//localhost/etc/fstab',
],
];
}

public function testCreateFromUri(): void
{
$expected = 'https://login:[email protected]:443/test/query.php?kingkong=toto#doc3';
Expand Down
17 changes: 17 additions & 0 deletions uri/Uri.php
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,23 @@ public static function fromWindowsPath(Stringable|string $path): self
return Uri::fromComponents(['host' => $host, 'path' => '/'.$path, 'scheme' => 'file']);
}

/**
* Creates a new instance from a RFC8089 compatible URI.
*
* @see https://datatracker.ietf.org/doc/html/rfc8089
*/
public static function fromRfc8089(Stringable|string $uri): UriInterface
{
$fileUri = self::new((string) preg_replace(',^(file:/)([^/].*)$,i', 'file:///$2', (string) $uri));
$scheme = (string) $fileUri->getScheme();

return match (true) {
'file' !== $scheme => throw new SyntaxError('The URI scheme must be `file`; `'.$scheme.'` given.'),
'localhost' === $fileUri->getAuthority() => $fileUri->withHost(''),
default => $fileUri,
};
}

/**
* Create a new instance from the environment.
*/
Expand Down

0 comments on commit 5af8aa3

Please sign in to comment.