Skip to content

Commit

Permalink
Refactor NavLink class to use constructor property promotion and ad…
Browse files Browse the repository at this point in the history
…d immutable methods.
  • Loading branch information
terabytesoftw committed Jan 21, 2025
1 parent 3dc4609 commit 725fbb2
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 41 deletions.
149 changes: 110 additions & 39 deletions src/NavLink.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,64 @@
*/
final class NavLink
{
private bool $active = false;
private array $attributes = [];
private bool $encodeLabel = true;
private bool $disabled = false;
private string|Stringable $label = '';
private string|null $url = '';
private array $urlAttributes = [];

/**
* Use {@see NavLink::to()} to create an instance.
*/
private function __construct()
private function __construct(
private bool $active = false,
private array $attributes = [],
private bool $encodeLabel = true,
private bool $disabled = false,
private string|Stringable $label = '',
private string|null $url = '',
private array $urlAttributes = [],
) {
}

/**
* Creates a nav {@see NavLink} instance.
*
* @param string|Stringable $label The label of the link.
* @param string|null $url The URL of the link.
* @param bool $active Whether the link is active.
* @param bool $disabled Whether the link is disabled.
* @param bool $encodeLabel Whether the label should be encoded.
* @param array $attributes The HTML attributes for the nav item.
* @param array $urlAttributes The HTML attributes for the nav item link.
*
* @throws InvalidArgumentException If the link is both active and disabled.
*
* @return self A new instance with the specified attributes.
*/
public static function to(
string|Stringable $label = '',
string|null $url = null,
bool $active = false,
bool $disabled = false,
bool $encodeLabel = true,
array $attributes = [],
array $urlAttributes = [],
): self {
if ($active === true && $disabled === true) {
throw new InvalidArgumentException('A nav link cannot be both active and disabled.');
}

return new self($active, $attributes, $encodeLabel, $disabled, $label, $url, $urlAttributes);
}

/**
* Sets the active state of the nav item.
*
* @param bool $value Whether the nav item is active.
*
* @return self A new instance with the specified active state.
*/
public function active(bool $value): self
{
$new = clone $this;
$new->active = $value;

return $new;
}

/**
Expand All @@ -60,54 +105,80 @@ public function attributes(array $values): self
}

/**
* Sets the HTML attributes for the nav item link.
* Sets the disabled state of the nav item.
*
* @param array $values Attribute values indexed by attribute names.
* @param bool $value Whether the nav item is disabled.
*
* @return self A new instance with the specified attributes.
* @return self A new instance with the specified disabled state.
*/
public function disabled(bool $value): self
{
$new = clone $this;
$new->disabled = $value;

return $new;
}

/**
* Sets whether to HTML-encode the label.
*
* @see {\Yiisoft\Html\Html::renderTagAttributes()} for details on how attributes are being rendered.
* @param bool $value Whether to encode the label
*
* @return self New instance with the specified encode setting.
*/
public function urlAttributes(array $values): self
public function encodeLabel(bool $value): self
{
$new = clone $this;
$new->urlAttributes = $values;
$new->encodeLabel = $value;

return $new;
}

/**
* Creates a nav item.
* Sets the label text for the nav item.
*
* @param string|Stringable $label The label of the link.
* @param string|null $url The URL of the link.
* @param bool $active Whether the link is active.
* @param bool $disabled Whether the link is disabled.
* @param string|Stringable $value The label text or Stringable object
*
* @throws InvalidArgumentException If the link is both active and disabled.
* @return self New instance with the specified label text.
*/
public function label(string|Stringable $value): self
{
$new = clone $this;
$new->label = $value;

return $new;
}

/**
* Sets the URL for the nav item.
*
* @return self A new instance with the specified attributes.
* @param string|null $value The URL or `null` for no URL.
*
* @return self New instance with the specified URL.
*/
public static function to(
string|Stringable $label = '',
string|null $url = null,
bool $active = false,
bool $disabled = false,
bool $encodeLabel = true
): self {
$navlink = new self();
public function url(string|null $value): self
{
$new = clone $this;
$new->url = $value;

if ($active === true && $disabled === true) {
throw new InvalidArgumentException('A nav link cannot be both active and disabled.');
}
return $new;
}

$navlink->active = $active;
$navlink->disabled = $disabled;
$navlink->encodeLabel = $encodeLabel;
$navlink->label = $label;
$navlink->url = $url;
/**
* Sets HTML attributes for the nav item link.
*
* @param array $values Attribute values indexed by attribute names
*
* @return self New instance with the specified link attributes
*
* @see \Yiisoft\Html\Html::renderTagAttributes() for details on how attributes are rendered
*/
public function urlAttributes(array $values): self
{
$new = clone $this;
$new->urlAttributes = $values;

return $navlink;
return $new;
}

/**
Expand Down
5 changes: 5 additions & 0 deletions tests/NavLinkTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ public function testImmutability(): void
{
$navLink = NavLink::to('Home', '/', true);

$this->assertNotSame($navLink, $navLink->active(false));
$this->assertNotSame($navLink, $navLink->attributes([]));
$this->assertNotSame($navLink, $navLink->disabled(false));
$this->assertNotSame($navLink, $navLink->encodeLabel(false));
$this->assertNotSame($navLink, $navLink->label(''));
$this->assertNotSame($navLink, $navLink->url(''));
$this->assertNotSame($navLink, $navLink->urlAttributes([]));
}

Expand Down
4 changes: 2 additions & 2 deletions tests/NavTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,7 @@ public function testNavLinkWithAttributes(): void
</ul>
HTML,
Nav::widget()
->items(NavLink::to('Active', '#', active: true)->attributes(['data-test' => 'test']))
->items(NavLink::to('Active', '#', active: true, attributes: ['data-test' => 'test']))
->render(),
);
}
Expand All @@ -665,7 +665,7 @@ public function testNavLinkWithUrlAttributes(): void
</ul>
HTML,
Nav::widget()
->items(NavLink::to('Active', '#', active: true)->urlAttributes(['data-test' => 'test']))
->items(NavLink::to('Active', '#', active: true, urlAttributes: ['data-test' => 'test']))
->render(),
);
}
Expand Down

0 comments on commit 725fbb2

Please sign in to comment.