diff --git a/src/CliProgram/Validation/Validators/AbstractDateTimeValidator.php b/src/CliProgram/Validation/Validators/AbstractDateTimeValidator.php index 7690ead..1460bd7 100644 --- a/src/CliProgram/Validation/Validators/AbstractDateTimeValidator.php +++ b/src/CliProgram/Validation/Validators/AbstractDateTimeValidator.php @@ -7,7 +7,7 @@ use DateTimeInterface; /** * An argument/option value validator expecting a date and/or time * - * @template-implements BasedValidator + * @extends BasedValidator */ abstract class AbstractDateTimeValidator extends BasedValidator { /** diff --git a/src/CliProgram/Validation/Validators/AssociativeListValidator.php b/src/CliProgram/Validation/Validators/AssociativeListValidator.php new file mode 100644 index 0000000..d9555d0 --- /dev/null +++ b/src/CliProgram/Validation/Validators/AssociativeListValidator.php @@ -0,0 +1,75 @@ +Value = Real value (see {@see IValidator::getValue() getValue()}) + * + * @implements IValidatorWithSuggestions + */ +class AssociativeListValidator implements IValidatorWithSuggestions { + use TIdenticalValidDefaultValidator; + + /** + * @use TInternalValueValidator + */ + use TInternalValueValidator; + + /** + * @var StringCollection The list of allowed values + */ + private StringCollection $allowedValues; + + /** + * Create a validator + * + * @param StringCollection|null $allowedValues The list of allowed values + */ + public function __construct (?StringCollection $allowedValues = null) { + $this->setAllowedValues($allowedValues ?? new StringCollection()); + } + + /** + * @inheritDoc + */ + public function validate (mixed $value): bool { + if ($this->allowedValues->keyExists($value)) { + $this->setValue($this->allowedValues->get($value)); + return true; + } + return false; + } + + /** + * The list of allowed values + * + * @return StringCollection The list of allowed values + */ + public function getAllowedValues (): StringCollection { + return $this->allowedValues; + } + /** + * Set the list of allowed values + * + * @param StringCollection $allowedValues The list of allowed values + * + * @return $this + */ + public function setAllowedValues (StringCollection $allowedValues): self { + $this->allowedValues = $allowedValues; + return $this; + } + + /** + * @inheritDoc + */ + public function getSuggestions (): Closure|array { + return $this->getAllowedValues()->getKeys()->toArray(); + } +} \ No newline at end of file diff --git a/src/CliProgram/Validation/Validators/BasedValidator.php b/src/CliProgram/Validation/Validators/BasedValidator.php index c7a5fe6..eefe133 100644 --- a/src/CliProgram/Validation/Validators/BasedValidator.php +++ b/src/CliProgram/Validation/Validators/BasedValidator.php @@ -5,7 +5,10 @@ namespace jrosset\CliProgram\Validation\Validators; /** * An argument/option value validator based on another, internal, validator * - * @template TValidator of IValidator + * @template TValue of mixed The type of the returned value + * @template TValidator of IValidator The type of the internal validator + * + * @extends IValidator */ abstract class BasedValidator implements IValidator { /** diff --git a/src/CliProgram/Validation/Validators/DateTimeValidator.php b/src/CliProgram/Validation/Validators/DateTimeValidator.php index c69d04c..aed2050 100644 --- a/src/CliProgram/Validation/Validators/DateTimeValidator.php +++ b/src/CliProgram/Validation/Validators/DateTimeValidator.php @@ -7,8 +7,6 @@ use DateTimeInterface; /** * An argument/option value validator expecting a date and time - * - * @template-implements BasedValidator */ class DateTimeValidator extends AbstractDateTimeValidator { /** diff --git a/src/CliProgram/Validation/Validators/DateValidator.php b/src/CliProgram/Validation/Validators/DateValidator.php index cc4595f..aea55a1 100644 --- a/src/CliProgram/Validation/Validators/DateValidator.php +++ b/src/CliProgram/Validation/Validators/DateValidator.php @@ -7,8 +7,6 @@ use DateTimeInterface; /** * An argument/option value validator expecting a date (without time) - * - * @template-implements BasedValidator */ class DateValidator extends AbstractDateTimeValidator { /** diff --git a/src/CliProgram/Validation/Validators/DecimalValidator.php b/src/CliProgram/Validation/Validators/DecimalValidator.php index 13f8eef..743140f 100644 --- a/src/CliProgram/Validation/Validators/DecimalValidator.php +++ b/src/CliProgram/Validation/Validators/DecimalValidator.php @@ -7,11 +7,14 @@ use InvalidArgumentException; /** * An argument/option value validator expecting a decimal * - * @template-implements BasedValidator - * @template-implements TInternalValueValidator + * @extends BasedValidator */ class DecimalValidator extends BasedValidator { use TIdenticalValidDefaultValidator; + + /** + * @use TInternalValueValidator + */ use TInternalValueValidator; /** @@ -47,8 +50,8 @@ class DecimalValidator extends BasedValidator { parent::__construct( new RegexValidator( - /** @lang PhpRegExp */ '/^(?[+-]?(?:\d{1,3}' . $this->thousandsSeparator . '?(?:\d{3}' . $this->thousandsSeparator . '?)*\d{3}|\d{1,3}))(?:' . $this->decimalSeparator - . '(?\d+))?$/' + /** @lang PhpRegExp */ + "/^(?[+-]?(?:\\d{1,3}$this->thousandsSeparator?(?:\\d{3}$this->thousandsSeparator?)*\\d{3}|\\d{1,3}))(?:$this->decimalSeparator(?\\d+))?\$/" ) ); } diff --git a/src/CliProgram/Validation/Validators/DirectoryValidator.php b/src/CliProgram/Validation/Validators/DirectoryValidator.php index 86f9d3c..cb699c1 100644 --- a/src/CliProgram/Validation/Validators/DirectoryValidator.php +++ b/src/CliProgram/Validation/Validators/DirectoryValidator.php @@ -11,8 +11,13 @@ use Symfony\Component\Console\Completion\CompletionInput; /** * An argument/option value validator for a directory path + * + * @implements IValidatorWithSuggestions */ class DirectoryValidator implements IValidatorWithSuggestions { + /** + * @use TInternalValueValidator + */ use TInternalValueValidator; /** @@ -80,7 +85,7 @@ class DirectoryValidator implements IValidatorWithSuggestions { return false; } - $this->setValue($value); + $this->setValue((string)$value); return true; } diff --git a/src/CliProgram/Validation/Validators/EmailValidator.php b/src/CliProgram/Validation/Validators/EmailValidator.php index 3b0a6bf..4b840db 100644 --- a/src/CliProgram/Validation/Validators/EmailValidator.php +++ b/src/CliProgram/Validation/Validators/EmailValidator.php @@ -4,11 +4,17 @@ namespace jrosset\CliProgram\Validation\Validators; /** * An argument/option value validator expecting an email address + * + * @implements IValidator */ class EmailValidator implements IValidator { - use TInternalValueValidator; use TIdenticalValidDefaultValidator; + /** + * @use TInternalValueValidator + */ + use TInternalValueValidator; + /** * @inheritDoc */ diff --git a/src/CliProgram/Validation/Validators/EnumValidator.php b/src/CliProgram/Validation/Validators/EnumValidator.php index 69cf04f..12c91df 100644 --- a/src/CliProgram/Validation/Validators/EnumValidator.php +++ b/src/CliProgram/Validation/Validators/EnumValidator.php @@ -13,8 +13,9 @@ use UnitEnum; * An argument/option value validator based on an enumeration * * @template TEnum of UnitEnum - * @template-implements IValidator - * @template-implements TInternalValueValidator + * + * @extends BasedValidator + * @implements IValidatorWithSuggestions */ class EnumValidator extends BasedValidator implements IValidatorWithSuggestions { /** @@ -53,10 +54,14 @@ class EnumValidator extends BasedValidator implements IValidatorWithSuggestions /** * @inheritDoc * + * @return TEnum|null The value + * * @throws ReflectionException */ - public function getValue (): UnitEnum { - $enumCase = $this->getInternalValidator()->getValue(); + public function getValue (): ?UnitEnum { + if (($enumCase = $this->getInternalValidator()->getValue()) === null) { + return null; + } return $this->enum->getCase($enumCase)->getValue(); } diff --git a/src/CliProgram/Validation/Validators/FilesystemValidationOptionsList.php b/src/CliProgram/Validation/Validators/FilesystemValidationOptionsList.php index a02a673..4fa26da 100644 --- a/src/CliProgram/Validation/Validators/FilesystemValidationOptionsList.php +++ b/src/CliProgram/Validation/Validators/FilesystemValidationOptionsList.php @@ -5,7 +5,7 @@ namespace jrosset\CliProgram\Validation\Validators; use Arrayy\Collection\AbstractCollection; /** - * A list of options of a filesystem based validator + * A list of options of a filesystem-based validator * * @extends AbstractCollection */ diff --git a/src/CliProgram/Validation/Validators/IValidator.php b/src/CliProgram/Validation/Validators/IValidator.php index 19ecb2c..97e8256 100644 --- a/src/CliProgram/Validation/Validators/IValidator.php +++ b/src/CliProgram/Validation/Validators/IValidator.php @@ -5,7 +5,7 @@ namespace jrosset\CliProgram\Validation\Validators; /** * An argument/option value validator * - * @template TValue The Type of the returned value + * @template TValue of mixed The type of the returned value */ interface IValidator { /** @@ -26,9 +26,9 @@ interface IValidator { */ public function validate (mixed $value): bool; /** - * Get the value, after it's validation + * Get the value, after the validation * * @return TValue|null The value */ - public function getValue (); + public function getValue (): mixed; } \ No newline at end of file diff --git a/src/CliProgram/Validation/Validators/IValidatorWithSuggestions.php b/src/CliProgram/Validation/Validators/IValidatorWithSuggestions.php index 256d0b7..90f0f8a 100644 --- a/src/CliProgram/Validation/Validators/IValidatorWithSuggestions.php +++ b/src/CliProgram/Validation/Validators/IValidatorWithSuggestions.php @@ -10,7 +10,8 @@ use Symfony\Component\Console\Completion\Suggestion; /** * An argument/option value validator * - * @template TValue The Type of the returned value + * @template TValue of mixed The type of the returned value + * * @extends IValidator */ interface IValidatorWithSuggestions extends IValidator { diff --git a/src/CliProgram/Validation/Validators/IntegerValidator.php b/src/CliProgram/Validation/Validators/IntegerValidator.php index 51821cf..310ff0d 100644 --- a/src/CliProgram/Validation/Validators/IntegerValidator.php +++ b/src/CliProgram/Validation/Validators/IntegerValidator.php @@ -7,11 +7,14 @@ use InvalidArgumentException; /** * An argument/option value validator expecting an integer * - * @template-implements BasedValidator - * @template-implements TInternalValueValidator + * @extends BasedValidator */ class IntegerValidator extends BasedValidator { use TIdenticalValidDefaultValidator; + + /** + * @use TInternalValueValidator + */ use TInternalValueValidator; /** @@ -42,7 +45,7 @@ class IntegerValidator extends BasedValidator { parent::__construct( new RegexValidator( - /** @lang PhpRegExp */ '/^[+-]?(?:\d{1,3}' . $this->thousandsSeparator . '?(?:\d{3}' . $this->thousandsSeparator . '?)*\d{3}|\d{1,3})$/' + /** @lang PhpRegExp */ "/^[+-]?(?:\\d{1,3}$this->thousandsSeparator?(?:\\d{3}$this->thousandsSeparator?)*\\d{3}|\\d{1,3})\$/" ) ); } diff --git a/src/CliProgram/Validation/Validators/ListValidator.php b/src/CliProgram/Validation/Validators/ListValidator.php index 546871a..cbe6ab7 100644 --- a/src/CliProgram/Validation/Validators/ListValidator.php +++ b/src/CliProgram/Validation/Validators/ListValidator.php @@ -3,68 +3,25 @@ namespace jrosset\CliProgram\Validation\Validators; use Arrayy\Type\StringCollection; -use Closure; /** * An argument/option value validator based on a list of value - * - * @template TValue - * @template-implements IValidator - * @template-implements TInternalValueValidator */ -class ListValidator implements IValidatorWithSuggestions { - use TIdenticalValidDefaultValidator; - use TInternalValueValidator; - - /** - * @var StringCollection The list of allowed values - */ - private StringCollection $allowedValues; - +class ListValidator extends AssociativeListValidator { /** * Create a validator * * @param StringCollection|null $allowedValues The list of allowed values */ public function __construct (?StringCollection $allowedValues = null) { - $this->setAllowedValues($allowedValues ?? new StringCollection()); - } - - /** - * @inheritDoc - */ - public function validate (mixed $value): bool { - if ($this->getAllowedValues()->contains($value)) { - $this->setValue($value); - return true; + //region Rebuild the allowed values collection with key = value + $realAllowedValues = new StringCollection(); + if ($allowedValues !== null) { + foreach ($allowedValues as $value) { + $realAllowedValues->add($value, $value); + } } - return false; - } - - /** - * The list of allowed values - * - * @return StringCollection The list of allowed values - */ - public function getAllowedValues (): StringCollection { - return $this->allowedValues; - } - /** - * Set the list of allowed values - * - * @param StringCollection $allowedValues The list of allowed values - * - * @return $this - */ - public function setAllowedValues (StringCollection $allowedValues): self { - $this->allowedValues = $allowedValues; - return $this; - } - - /** - * @inheritDoc - */ - public function getSuggestions (): Closure|array { - return $this->getAllowedValues()->toArray(); + //endregion + parent::__construct($realAllowedValues); } } diff --git a/src/CliProgram/Validation/Validators/RegexValidator.php b/src/CliProgram/Validation/Validators/RegexValidator.php index ec99856..24ac8b7 100644 --- a/src/CliProgram/Validation/Validators/RegexValidator.php +++ b/src/CliProgram/Validation/Validators/RegexValidator.php @@ -4,6 +4,8 @@ namespace jrosset\CliProgram\Validation\Validators; /** * An argument/option value validator based on a regex + * + * @implements IValidator */ class RegexValidator implements IValidator { use TIdenticalValidDefaultValidator; @@ -87,6 +89,8 @@ class RegexValidator implements IValidator { /** * @inheritDoc + * + * @return string|null The value or Null if not set */ public function getValue (): ?string { return $this->getMatch(static::GROUP_VALUE) ?? $this->getMatch(0); diff --git a/src/CliProgram/Validation/Validators/TInternalValueValidator.php b/src/CliProgram/Validation/Validators/TInternalValueValidator.php index 111be89..662a3ce 100644 --- a/src/CliProgram/Validation/Validators/TInternalValueValidator.php +++ b/src/CliProgram/Validation/Validators/TInternalValueValidator.php @@ -8,31 +8,30 @@ namespace jrosset\CliProgram\Validation\Validators; * * Call {@see self::setValue()} to set the value * - * @template TValue - * @template-implements IValidator + * @template TValue of mixed */ trait TInternalValueValidator { /** - * @var TValue|null The current value, after it's validation + * @var TValue|null The current value, after the validation */ - private $value = null; + private mixed $value = null; /** - * Get the value, after it's validation + * Get the value, after the validation * * @return TValue|null The value */ - public function getValue () { + public function getValue (): mixed { return $this->value; } /** * Set the value * - * @param TValue $value The value (after it's validation) + * @param TValue $value The value (after the validation) * * @return $this */ - protected function setValue ($value): static { + protected function setValue (mixed $value): static { $this->value = $value; return $this; } diff --git a/src/CliProgram/Validation/Validators/TimeValidator.php b/src/CliProgram/Validation/Validators/TimeValidator.php index 26ea54b..c96da3e 100644 --- a/src/CliProgram/Validation/Validators/TimeValidator.php +++ b/src/CliProgram/Validation/Validators/TimeValidator.php @@ -7,8 +7,6 @@ use DateTimeInterface; /** * An argument/option value validator expecting a date (without time) - * - * @template-implements BasedValidator */ class TimeValidator extends AbstractDateTimeValidator { /**