Skip to content

Commit

Permalink
Adding UriStringProvider interface
Browse files Browse the repository at this point in the history
  • Loading branch information
nyamsprod committed Dec 25, 2024
1 parent d74c6b3 commit c722aba
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 5 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ All Notable changes to `League\Uri` will be documented in this file
- `Uri::toUnixPath` returns the URI path as a Unix Path or `null`
- `Uri::toWindowsPath` returns the URI path as a Windows Path or `null`
- `Uri::toRfc8089` return the URI in a RFC8089 formator `null`
- `Uri::toAnchor` returns the HTML anchor string using the instance as the href attribute value
- `Uri::toMarkdown` returns the markdown link construct using the instance as the href attribute value

### Fixed

Expand Down
47 changes: 43 additions & 4 deletions Uri.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@
namespace League\Uri;

use Deprecated;
use DOMDocument;
use DOMException;
use finfo;
use League\Uri\Contracts\Conditionable;
use League\Uri\Contracts\UriComponentInterface;
use League\Uri\Contracts\UriException;
use League\Uri\Contracts\UriInterface;
use League\Uri\Contracts\UriStringProvider;
use League\Uri\Exceptions\ConversionFailed;
use League\Uri\Exceptions\MissingFeature;
use League\Uri\Exceptions\SyntaxError;
Expand Down Expand Up @@ -75,7 +78,7 @@
* @phpstan-import-type ComponentMap from UriString
* @phpstan-import-type InputComponentMap from UriString
*/
final class Uri implements UriInterface, Conditionable
final class Uri implements UriInterface, Conditionable, UriStringProvider
{
/**
* RFC3986 invalid characters.
Expand Down Expand Up @@ -1039,6 +1042,42 @@ public function toDisplayString(): string
return UriString::build($components);
}

/**
* Returns the HTML string representation of the anchor tag with the current instance as its href attribute.
*
* @throws DOMException
*/
public function toAnchorTag(?string $content = null, ?string $class = null, ?string $target = null): string
{
$doc = new DOMDocument('1.0', 'utf-8');
$doc->preserveWhiteSpace = false;
$doc->formatOutput = true;
$anchor = $doc->createElement('a');
$anchor->setAttribute('href', $this->toString());
if (null !== $class) {
$anchor->setAttribute('class', $class);
}
if (null !== $target) {
$anchor->setAttribute('target', $target);
}

$anchor->appendChild($doc->createTextNode($content ?? $this->toDisplayString()));
$anchor = $doc->saveHTML($anchor);
if (false === $anchor) {
throw new DOMException('The link generation failed.');
}

return $anchor;
}

/**
* Returns the markdown string representation of the anchor tag with the current instance as its href attribute.
*/
public function toMarkdown(?string $content = null): string
{
return '['.($content ?? $this->toDisplayString()).']('.$this->toString().')';
}

/**
* Returns the Unix filesystem path.
*
Expand Down Expand Up @@ -1208,9 +1247,9 @@ public function getFragment(): ?string
return $this->fragment;
}

public function getOrigin(): ?self
public function getOrigin(): ?string
{
return null === $this->origin ? null : Uri::new($this->origin);
return $this->origin;
}

public function when(callable|bool $condition, callable $onSuccess, ?callable $onFail = null): static
Expand Down Expand Up @@ -1429,7 +1468,7 @@ public function isCrossOrigin(UriInterface|Stringable|string $uri): bool
return true;
}

return $this->origin !== (string) $origin;
return $this->origin !== $origin;
}

public function isSameOrigin(Stringable|string $uri): bool
Expand Down
93 changes: 92 additions & 1 deletion UriTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -717,7 +717,7 @@ public static function sameValueAsProvider(): array
#[DataProvider('getOriginProvider')]
public function testGetOrigin(Psr7UriInterface|Uri|string $uri, ?string $expectedOrigin): void
{
self::assertSame($expectedOrigin, Uri::new($uri)->getOrigin()?->toString());
self::assertSame($expectedOrigin, Uri::new($uri)->getOrigin());
}

public static function getOriginProvider(): array
Expand Down Expand Up @@ -981,4 +981,95 @@ public static function providesUriToDisplay(): iterable
'output' => 'http://bébé.be',
];
}

#[Test]
#[DataProvider('providesUriToMarkdown')]
public function it_will_generate_the_markdown_code_for_the_instance(string $uri, ?string $content, string $expected): void
{
self::assertSame($expected, Uri::new($uri)->toMarkdown($content));
}

public static function providesUriToMarkdown(): iterable
{
yield 'empty string' => [
'uri' => '',
'content' => '',
'expected' => '[]()',
];

yield 'URI with a specific content' => [
'uri' => 'http://example.com/foo/bar',
'content' => 'this is a link',
'expected' => '[this is a link](http://example.com/foo/bar)',
];

yield 'URI without content' => [
'uri' => 'http://Bébé.be',
'content' => null,
'expected' => '[http://bébé.be](http://xn--bb-bjab.be)',
];
}

#[Test]
#[DataProvider('providesUriToHTML')]
public function it_will_generate_the_html_code_for_the_instance(
string $uri,
?string $content,
?string $class,
?string $target,
string $expected
): void {
self::assertSame($expected, Uri::new($uri)->toAnchorTag($content, $class, $target));
}

public static function providesUriToHTML(): iterable
{
yield 'empty string' => [
'uri' => '',
'content' => '',
'class' => null,
'target' => null,
'expected' => '<a href=""></a>',
];

yield 'URI with a specific content' => [
'uri' => 'http://example.com/foo/bar',
'content' => 'this is a link',
'class' => null,
'target' => null,
'expected' => '<a href="http://example.com/foo/bar">this is a link</a>',
];

yield 'URI without content' => [
'uri' => 'http://Bébé.be',
'content' => null,
'class' => null,
'target' => null,
'expected' => '<a href="http://xn--bb-bjab.be">http://bébé.be</a>',
];

yield 'URI without content and with class' => [
'uri' => 'http://Bébé.be',
'content' => null,
'class' => 'foo bar',
'target' => null,
'expected' => '<a href="http://xn--bb-bjab.be" class="foo bar">http://bébé.be</a>',
];

yield 'URI without content and with target' => [
'uri' => 'http://Bébé.be',
'content' => null,
'class' => null,
'target' => '_blank',
'expected' => '<a href="http://xn--bb-bjab.be" target="_blank">http://bébé.be</a>',
];

yield 'URI without content, with target and class' => [
'uri' => 'http://Bébé.be',
'content' => null,
'class' => 'foo bar',
'target' => '_blank',
'expected' => '<a href="http://xn--bb-bjab.be" class="foo bar" target="_blank">http://bébé.be</a>',
];
}
}
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
"league/uri-schemes": "^1.0"
},
"suggest": {
"ext-dom": "to convert the URI into an HTML anchor tag",
"ext-bcmath": "to improve IPV4 host parsing",
"ext-fileinfo": "to create Data URI from file contennts",
"ext-gmp": "to improve IPV4 host parsing",
Expand Down

0 comments on commit c722aba

Please sign in to comment.