Skip to content

Commit

Permalink
Add new classes and tests for input elements. (#169)
Browse files Browse the repository at this point in the history
  • Loading branch information
terabytesoftw committed Dec 21, 2023
1 parent 77cfd82 commit 3c97f05
Show file tree
Hide file tree
Showing 16 changed files with 313 additions and 327 deletions.
30 changes: 4 additions & 26 deletions src/Input/Base/AbstractButton.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,17 @@

use InvalidArgumentException;
use PHPForge\Html\Attribute;
use PHPForge\Html\Input\Input;
use PHPForge\Html\Label;
use PHPForge\Html\Tag;
use PHPForge\Widget\Element;

use function array_key_exists;
use function is_string;

abstract class AbstractButton extends Element
abstract class AbstractButton extends AbstractInput
{
use Attribute\Aria\HasAriaDescribedBy;
use Attribute\Aria\HasAriaLabel;
use Attribute\CanBeHidden;
use Attribute\Custom\HasAttributes;
use Attribute\Custom\HasContainer;
use Attribute\Custom\HasLabel;
use Attribute\HasClass;
use Attribute\HasId;
use Attribute\HasStyle;
use Attribute\HasTabindex;
use Attribute\HasTitle;
use Attribute\Input\CanBeDisabled;
use Attribute\Input\HasForm;
use Attribute\Input\HasName;
use Attribute\Input\HasType;
use Attribute\Input\HasValue;

protected array $attributes = [];
protected bool $container = true;
Expand All @@ -40,6 +25,7 @@ abstract class AbstractButton extends Element
protected function run(): string
{
$attributes = $this->attributes;
/** @var string $type */
$type = $this->attributes['type'] ?? 'button';
$value = $this->attributes['value'] ?? null;

Expand All @@ -52,16 +38,8 @@ protected function run(): string
);
}

$id = $this->generateId("$type-");

$ariaDescribedBy = $this->attributes['aria-describedby'] ?? null;

if ($ariaDescribedBy === true) {
$attributes['aria-describedby'] = "$id-help";
}

$buttonInput = Input::widget()->attributes($attributes)->id($id)->type($type)->value($value);
$labelFor = $id;
$buttonInput = $this->buildInputTag($attributes, $type);
$labelFor = $buttonInput->getId();

if (array_key_exists('for', $this->labelAttributes)) {
$labelFor = (string) $this->labelAttributes['for'];
Expand Down
56 changes: 4 additions & 52 deletions src/Input/Base/AbstractChoice.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,48 +7,26 @@
use InvalidArgumentException;
use PHPForge\Html\Attribute;
use PHPForge\Html\Input\Hidden;
use PHPForge\Html\Input\InputInterface;
use PHPForge\Html\Input\LabelInterface;
use PHPForge\Html\Label;
use PHPForge\Html\Tag;
use PHPForge\Widget\Element;

use function is_bool;
use function is_iterable;
use function is_object;

abstract class AbstractChoice extends Element implements InputInterface, LabelInterface
abstract class AbstractChoice extends AbstractInput implements LabelInterface
{
use Attribute\Aria\HasAriaDescribedBy;
use Attribute\Aria\HasAriaLabel;
use Attribute\CanBeAutofocus;
use Attribute\CanBeHidden;
use Attribute\Custom\HasAttributes;
use Attribute\Custom\HasCheckedValue;
use Attribute\Custom\HasContainer;
use Attribute\Custom\HasLabel;
use Attribute\Custom\HasPrefixAndSuffix;
use Attribute\Custom\HasTemplate;
use Attribute\Custom\HasUnchecked;
use Attribute\HasClass;
use Attribute\HasData;
use Attribute\HasId;
use Attribute\HasLang;
use Attribute\HasStyle;
use Attribute\HasTabindex;
use Attribute\HasTitle;
use Attribute\Input\CanBeChecked;
use Attribute\Input\CanBeDisabled;
use Attribute\Input\CanBeReadonly;
use Attribute\Input\CanBeRequired;
use Attribute\Input\HasForm;
use Attribute\Input\HasName;
use Attribute\Input\HasValue;

protected array $attributes = [];
protected bool $container = false;
protected string $containerTag = 'div';
protected string $template = '{prefix}{tag}{suffix}';
protected string $type = '';

protected function run(): string
Expand All @@ -65,21 +43,14 @@ protected function run(): string
);
}

$value = is_bool($value) ? (int) $value : $value;
$id = $this->generateId("$this->type-");
$attributes['value'] = is_bool($value) ? (int) $value : $value;

$attributes['checked'] = match (empty($this->checkedValue)) {
true => $this->checked,
default => $value === $this->checkedValue,
default => $attributes['value'] === $this->checkedValue,
};

$ariaDescribedBy = $this->attributes['aria-describedby'] ?? null;

if ($ariaDescribedBy === true) {
$attributes['aria-describedby'] = "$id-help";
}

$inputCheckboxTag = $this->renderInputCheckboxTag($attributes, $id, $this->generateUncheckTag(), $value);
$inputCheckboxTag = $this->buildInputTag($attributes, $this->type, $this->generateUncheckTag());

if ($this->isNotLabel() === false) {
$inputCheckboxTag = $this->renderLabelTag($inputCheckboxTag);
Expand Down Expand Up @@ -124,23 +95,4 @@ private function renderLabelTag(Tag $inputCheckboxTag): Label|Tag
->content(PHP_EOL, $inputCheckboxTag, PHP_EOL, $this->labelContent, PHP_EOL)
->for($inputCheckboxTag->getId());
}

private function renderInputCheckboxTag(array $attributes, string|null $id, string $uncheckTag, mixed $value): Tag
{
return Tag::widget()
->attributes($attributes)
->id($id)
->prefix($this->prefix, $uncheckTag)
->prefixContainer($this->prefixContainer)
->prefixContainerAttributes($this->prefixContainerAttributes)
->prefixContainerTag($this->prefixContainerTag)
->suffix($this->suffix)
->suffixContainer($this->suffixContainer)
->suffixContainerAttributes($this->suffixContainerAttributes)
->suffixContainerTag($this->suffixContainerTag)
->tagName('input')
->template($this->template)
->type($this->type)
->value($value);
}
}
5 changes: 3 additions & 2 deletions src/Input/Base/AbstractColor.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
namespace PHPForge\Html\Input\Base;

use InvalidArgumentException;
use PHPForge\Html\Attribute;

use function is_string;

abstract class AbstractColor extends AbstractInput
{
protected string $type = 'color';
use Attribute\Input\CanBeRequired;

/**
* @return string the generated input tag.
Expand All @@ -29,6 +30,6 @@ protected function run(): string
);
}

return parent::run();
return $this->buildInputTag($attributes, 'color')->render();
}
}
61 changes: 32 additions & 29 deletions src/Input/Base/AbstractHidden.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,42 +5,30 @@
namespace PHPForge\Html\Input\Base;

use InvalidArgumentException;
use PHPForge\Html\Attribute;
use PHPForge\Html\Input\HiddenInterface;
use PHPForge\Html\Tag;
use PHPForge\Widget\Element;

use function array_key_exists;
use function is_string;
use function sprintf;

abstract class AbstractHidden extends AbstractInput
abstract class AbstractHidden extends Element implements HiddenInterface
{
/**
* @var array<string>
*/
protected const NOT_ALLOWED_ATTRIBUTES = [
'aria-describedby',
'aria-label',
'autofocus',
'disabled',
'hidden',
'placeholder',
'required',
'readonly',
'tabindex',
'title',
];

protected string $type = 'hidden';
use Attribute\Custom\HasAttributes;
use Attribute\Custom\HasPrefixAndSuffix;
use Attribute\Custom\HasTemplate;
use Attribute\HasId;
use Attribute\HasStyle;
use Attribute\Input\HasName;
use Attribute\Input\HasValue;

protected array $attributes = [];
protected string $template = '{prefix}{tag}{suffix}';

protected function run(): string
{
$attributes = $this->attributes;

foreach (static::NOT_ALLOWED_ATTRIBUTES as $attribute) {
if (array_key_exists($attribute, $attributes)) {
throw new InvalidArgumentException(
sprintf('%s::class widget must not be "%s" attribute.', static::class, $attribute)
);
}
}

$value = $attributes['value'] ?? null;

/**
Expand All @@ -52,6 +40,21 @@ protected function run(): string
);
}

return parent::run();
return Tag::widget()
->attributes($attributes)
->id($this->generateId('hidden-'))
->prefix($this->prefix)
->prefixContainer($this->prefixContainer)
->prefixContainerAttributes($this->prefixContainerAttributes)
->prefixContainerTag($this->prefixContainerTag)
->suffix($this->suffix)
->suffixContainer($this->suffixContainer)
->suffixContainerAttributes($this->suffixContainerAttributes)
->suffixContainerTag($this->suffixContainerTag)
->tagName('input')
->template($this->template)
->type('hidden')
->value($value)
->render();
}
}
20 changes: 6 additions & 14 deletions src/Input/Base/AbstractInput.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,13 @@

use PHPForge\Html\Attribute;
use PHPForge\Html\Input\InputInterface;
use PHPForge\Html\Input\PlaceholderInterface;
use PHPForge\Html\Input\RuleHtmlByAttribute;
use PHPForge\Html\Tag;
use PHPForge\Widget\Element;

/**
* Provides a foundation for creating HTML `input` custom elements with various attributes and content.
*/
abstract class AbstractInput extends Element implements InputInterface, PlaceholderInterface, RuleHtmlByAttribute
abstract class AbstractInput extends Element implements InputInterface
{
use Attribute\Aria\HasAriaDescribedBy;
use Attribute\Aria\HasAriaLabel;
Expand All @@ -32,24 +30,19 @@ abstract class AbstractInput extends Element implements InputInterface, Placehol
use Attribute\HasTitle;
use Attribute\Input\CanBeDisabled;
use Attribute\Input\CanBeReadonly;
use Attribute\Input\CanBeRequired;
use Attribute\Input\HasForm;
use Attribute\Input\HasName;
use Attribute\Input\HasPlaceholder;
use Attribute\Input\HasType;
use Attribute\Input\HasValue;

protected array $attributes = [];
protected string $template = '{prefix}{tag}{suffix}';
protected string $type = 'text';

protected function run(): string
protected function buildInputTag(array $attributes, string $type, string $prefixWidget = ''): Tag
{
$attributes = $this->attributes;
$type = $this->attributes['type'] ?? $this->type;
$type = $attributes['type'] ?? $type;

$ariaDescribedBy = $attributes['aria-describedby'] ?? null;
$id = $this->generateId("$this->type-");
$id = $this->generateId("$type-");

if ($ariaDescribedBy === true) {
$attributes['aria-describedby'] = "$id-help";
Expand All @@ -58,7 +51,7 @@ protected function run(): string
return Tag::widget()
->attributes($attributes)
->id($id)
->prefix($this->prefix)
->prefix($this->prefix, $prefixWidget)
->prefixContainer($this->prefixContainer)
->prefixContainerAttributes($this->prefixContainerAttributes)
->prefixContainerTag($this->prefixContainerTag)
Expand All @@ -68,7 +61,6 @@ protected function run(): string
->suffixContainerTag($this->suffixContainerTag)
->tagName('input')
->template($this->template)
->type($type)
->render();
->type($type);
}
}
41 changes: 41 additions & 0 deletions src/Input/Base/AbstractText.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

namespace PHPForge\Html\Input\Base;

use InvalidArgumentException;
use PHPForge\Html\Attribute;
use PHPForge\Html\Input\PlaceholderInterface;
use PHPForge\Html\Input\RuleHtmlByAttributeInterface;

use function is_string;
use function sprintf;

abstract class AbstractText extends AbstractInput implements PlaceholderInterface, RuleHtmlByAttributeInterface
{
use Attribute\Input\CanBeRequired;
use Attribute\Input\HasDirname;
use Attribute\Input\HasMaxLength;
use Attribute\Input\HasMinLength;
use Attribute\Input\HasPattern;
use Attribute\Input\HasPlaceholder;
use Attribute\Input\HasSize;

protected function run(): string
{
$attributes = $this->attributes;
$value = $attributes['value'] ?? null;

/**
* @link https://www.w3.org/TR/2012/WD-html-markup-20120329/input.text.html#input.text.attrs.value
*/
if ($value !== null && is_string($value) === false) {
throw new InvalidArgumentException(
sprintf('%s::class widget must be a string or null value.', static::class)
);
}

return $this->buildInputTag($attributes, 'text')->render();
}
}

0 comments on commit 3c97f05

Please sign in to comment.