Skip to content

Commit

Permalink
Adding UriAccess::getIdnUriString method
Browse files Browse the repository at this point in the history
  • Loading branch information
nyamsprod committed May 28, 2024
1 parent 9e9aac7 commit eb54fa3
Show file tree
Hide file tree
Showing 10 changed files with 157 additions and 3 deletions.
1 change: 1 addition & 0 deletions components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ All Notable changes to `League\Uri\Components` will be documented in this file
### Added

- `UrlSearchParams::uniqueKeyCount`
- `Modifier::getIdnUriString`

### Fixed

Expand Down
18 changes: 18 additions & 0 deletions components/Modifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,24 @@ public function getUri(): Psr7UriInterface|UriInterface
return $this->uri;
}

public function getIdnUriString(): string
{
$currentHost = $this->uri->getHost();
if (null === $currentHost || '' === $currentHost) {
return $this->getUriString();
}

$host = IdnConverter::toUnicode($currentHost)->domain();
if ($host === $currentHost) {
return $this->getUriString();
}

$components = $this->uri instanceof UriInterface ? $this->uri->getComponents() : UriString::parse($this->uri);
$components['host'] = $host;

return UriString::build($components);
}

public function getUriString(): string
{
return $this->uri->__toString();
Expand Down
32 changes: 31 additions & 1 deletion components/ModifierTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@
use League\Uri\Components\DataPath;
use League\Uri\Exceptions\SyntaxError;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\TestCase;

use const PHP_QUERY_RFC3986;

#[CoversClass(UriModifier::class)] /** @phpstan-ignore-line */
#[CoversClass(Modifier::class)]
#[Group('host')]
#[Group('resolution')]
final class ModifierTest extends TestCase
Expand Down Expand Up @@ -829,4 +830,33 @@ public function testItCanSlicePathSegments(): void

self::assertSame('http://www.localhost.com/the/sky/', Modifier::from($uri)->sliceSegments(2, 2)->getUriString());
}

#[DataProvider('idnUriProvider')]
public function testItReturnsTheCorrectUriString(string $expected, string $input): void
{
self::assertSame($expected, Modifier::from($input)->getIdnUriString());
}

public static function idnUriProvider(): iterable
{
yield 'basic uri stays the same' => [
'expected' => 'http://example.com/foo/bar',
'input' => 'http://example.com/foo/bar',
];

yield 'idn host are changed' => [
'expected' => "http://bébé.be",
'input' => "http://xn--bb-bjab.be",
];

yield 'idn host are the same' => [
'expected' => "http://bébé.be",
'input' => "http://bébé.be",
];

yield 'the rest of the URI is not affected and uses RFC3986 rules' => [
'expected' => "http://bébé.be?q=toto%20le%20h%C3%A9ros",
'input' => "http://bébé.be:80?q=toto le héros",
];
}
}
7 changes: 5 additions & 2 deletions docs/components/7.0/modifiers.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,13 @@ echo $uri, PHP_EOL; // returns http://shop.bébé.be./toto?foo=toto&foo=tata
<p class="message-warning">While the class does manipulate URI it does not implement any URI related interface.</p>
<p class="message-notice">If a PSR-7 or a League <code>UriInterface</code> implementing instance is given
then the return value will also be a PSR-7 <code>UriInterface</code> implementing instance.</p>
<p class="message-notice"><code>getIdnUriString</code> was added in version <code>7.5.0</code>.</p>

The `Modifier::getUri` method returns either a `PSR-7` or a League URI `UriInterface`, conversely,
the `Modifier::getUriString` method returns the URI as a string. Last but not least, the class implements
the `Stringable` and the `JsonSerializable` interface to improve developer experience.
the `Modifier::getUriString` method returns the RFC3986 string representation for the URI and
the `Modifier::getIdnUriString` method returns the RFC3986 string representation for the URI
with a Internationalized Domain Name (IDNA) if applicable. Last but not least, the class
implements the `Stringable` and the `JsonSerializable` interface to improve developer experience.

Under the hood the `Modifier` class intensively uses the [URI components objects](/components/7.0/)
to apply changes to the submitted URI object.
Expand Down
13 changes: 13 additions & 0 deletions docs/uri/7.0/base-uri.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,19 @@ echo $baseUri; // display 'http://www.example.com'

The instance also implements PHP's `Stringable` and `JsonSerializable` interface.

Since version `7.5` it is possible to use the `getIdnUriString` to get the URI with its host in its
internationalized string format.

~~~php
<?php

use League\Uri\BaseUri;

$baseUri = BaseUri::from('http://www.bébé.be');
$baseUri->getUriString(); // return 'http://xn--bb-bjab.be'
$baseUri->getIdnUriString(); // display 'http://www.bébé.be'
~~~

## URI resolution

The `BaseUri::resolve` resolves a URI as a browser would for a relative URI while
Expand Down
18 changes: 18 additions & 0 deletions interfaces/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,24 @@

All Notable changes to `League\Uri\Interfaces` will be documented in this file

## [Next](https://github.com/thephpleague/uri-interfaces/compare/7.3.1...master) - TBD

### Added

- `UriAccess::getIdnUriString`

### Fixed

- None

### Deprecated

- None

### Removed

- None

## [7.3.1](https://github.com/thephpleague/uri-interfaces/compare/7.3.0...7.3.1) - 2024-02-23

### Added
Expand Down
6 changes: 6 additions & 0 deletions interfaces/Contracts/UriAccess.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,15 @@

use Psr\Http\Message\UriInterface as Psr7UriInterface;

/**
* @method string getIdnUriString() returns the RFC3986 string representation of the complete URI with its host in IDNA form
*/
interface UriAccess
{
public function getUri(): UriInterface|Psr7UriInterface;

/**
* Returns the RFC3986 string representation of the complete URI.
*/
public function getUriString(): string;
}
18 changes: 18 additions & 0 deletions uri/BaseUri.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,24 @@ public function getUri(): Psr7UriInterface|UriInterface
return $this->uri;
}

public function getIdnUriString(): string
{
$currentHost = $this->uri->getHost();
if (null === $currentHost || '' === $currentHost) {
return $this->getUriString();
}

$host = Converter::toUnicode($currentHost)->domain();
if ($host === $currentHost) {
return $this->getUriString();
}

$components = $this->uri instanceof UriInterface ? $this->uri->getComponents() : UriString::parse($this->uri);
$components['host'] = $host;

return UriString::build($components);
}

public function getUriString(): string
{
return $this->uri->__toString();
Expand Down
29 changes: 29 additions & 0 deletions uri/BaseUriTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -583,4 +583,33 @@ public static function rfc8089UriProvider(): iterable
],
];
}

#[DataProvider('idnUriProvider')]
public function testItReturnsTheCorrectUriString(string $expected, string $input): void
{
self::assertSame($expected, BaseUri::from($input)->getIdnUriString());
}

public static function idnUriProvider(): iterable
{
yield 'basic uri stays the same' => [
'expected' => 'http://example.com/foo/bar',
'input' => 'http://example.com/foo/bar',
];

yield 'idn host are changed' => [
'expected' => "http://bébé.be",
'input' => "http://xn--bb-bjab.be",
];

yield 'idn host are the same' => [
'expected' => "http://bébé.be",
'input' => "http://bébé.be",
];

yield 'the rest of the URI is not affected and uses RFC3986 rules' => [
'expected' => "http://bébé.be?q=toto%20le%20h%C3%A9ros",
'input' => "http://bébé.be:80?q=toto le héros",
];
}
}
18 changes: 18 additions & 0 deletions uri/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,24 @@

All Notable changes to `League\Uri` will be documented in this file

## [Next](https://github.com/thephpleague/uri/compare/7.4.1...master) - TBD

### Added

- Adding `BaseUri::getIdnUriString`

### Fixed

- None

### Deprecated

- None

### Removed

- None

## [7.4.1](https://github.com/thephpleague/uri/compare/7.4.0...7.4.1) - 2024-02-23

### Added
Expand Down

0 comments on commit eb54fa3

Please sign in to comment.