diff --git a/src/CliProgram/Validation/Validators/DirectoryValidator.php b/src/CliProgram/Validation/Validators/DirectoryValidator.php new file mode 100644 index 0000000..c7ace8c --- /dev/null +++ b/src/CliProgram/Validation/Validators/DirectoryValidator.php @@ -0,0 +1,106 @@ + The options + */ + private ICollection $options; + + /** + * Initialization + * + * @param ICollection|FilesystemValidationOption[]|FilesystemValidationOption|null $options The options + */ + public function __construct (ICollection|array|FilesystemValidationOption|null $options = null) { + $this->setOptions($options); + } + + /** + * Get a valid default value from the initial/given default value + * + * @param string|Stringable|null $default The initial/given default value + * + * @return string|bool|int|float|array|null The valid default value + * + * @throws InvalidArgumentException If the default value is not a string or null + * @throws InvalidArgumentException If the default directory doesn't match the options + */ + public function getValidDefault (mixed $default): string|bool|int|float|array|null { + if ($default === null) { + return null; + } + if (!is_string($default) && !$default instanceof Stringable) { + throw new InvalidArgumentException('The default value must be a string or null'); + } + + if ($this->getOptions()->contains(FilesystemValidationOption::IsReadable) && !is_readable($default)) { + throw new InvalidArgumentException('The default value is not readable'); + } + if ($this->getOptions()->contains(FilesystemValidationOption::IsWritable) && !is_writable($default)) { + throw new InvalidArgumentException('The default value is not writable'); + } + if ($this->getOptions()->contains(FilesystemValidationOption::MustExists) && !file_exists($default)) { + throw new InvalidArgumentException('The default value doesn\'t exist'); + } + return $default; + } + + /** + * @inheritDoc + */ + public function validate (mixed $value): bool { + if (!is_string($value) && !$value instanceof Stringable) { + return false; + } + + if ($this->getOptions()->contains(FilesystemValidationOption::IsReadable) && !is_readable($value)) { + return false; + } + if ($this->getOptions()->contains(FilesystemValidationOption::IsWritable) && !is_writable($value)) { + return false; + } + if ($this->getOptions()->contains(FilesystemValidationOption::MustExists) && !file_exists($value)) { + return false; + } + + $this->setValue($value); + return true; + } + + /** + * The options + * + * @return ICollection The options + */ + public function getOptions (): ICollection { + return $this->options; + } + /** + * Replace the options + * + * @param ICollection|FilesystemValidationOption[]|FilesystemValidationOption|null $options The options + * + * @return $this + */ + public function setOptions (ICollection|array|FilesystemValidationOption|null $options = null): static { + $this->options = match (true) { + $options instanceof ICollection => $options, + $options instanceof FilesystemValidationOption => new Collection([$options]), + is_array($options) => new Collection($options), + $options === null => new Collection(), + }; + return $this; + } +} \ No newline at end of file diff --git a/src/CliProgram/Validation/Validators/FileValidator.php b/src/CliProgram/Validation/Validators/FileValidator.php new file mode 100644 index 0000000..24ccaa4 --- /dev/null +++ b/src/CliProgram/Validation/Validators/FileValidator.php @@ -0,0 +1,72 @@ +|FilesystemValidationOption[]|FilesystemValidationOption|null $options The options + */ + public function __construct (?string $extensionsPattern = null, ICollection|FilesystemValidationOption|array|null $options = null) { + parent::__construct($options); + $this->setExtensionsPattern($extensionsPattern); + } + + /** + * @inheritDoc + */ + public function getValidDefault (mixed $default): string|bool|int|float|array|null { + if (($default = parent::getValidDefault($default)) === null) { + return null; + } + if ($this->extensionsPattern !== null && preg_match($this->extensionsPattern, $default) !== 1) { + throw new InvalidArgumentException('The default value has not a valid extension'); + } + return $default; + } + /** + * @inheritDoc + */ + public function validate (mixed $value): bool { + if (!parent::validate($value)) { + return false; + } + if ($this->extensionsPattern !== null && preg_match($this->extensionsPattern, $value) !== 1) { + return false; + } + return true; + } + + /** + * The allowed extensions (regex pattern) + * + * @return string|null The allowed extensions (regex pattern) + */ + public function getExtensionsPattern (): ?string { + return $this->extensionsPattern; + } + /** + * Replace the allowed extensions + * + * @param string|null $extensionsPattern The allowed extensions (regex pattern) + * + * @return $this + */ + public function setExtensionsPattern (?string $extensionsPattern = null): static { + $this->extensionsPattern = $extensionsPattern; + return $this; + } +} \ No newline at end of file diff --git a/src/CliProgram/Validation/Validators/FilesystemValidationOption.php b/src/CliProgram/Validation/Validators/FilesystemValidationOption.php new file mode 100644 index 0000000..46a0c9d --- /dev/null +++ b/src/CliProgram/Validation/Validators/FilesystemValidationOption.php @@ -0,0 +1,12 @@ +addArgument( + 'file', + InputArgument::REQUIRED, + 'The file to read', + null, + new FileValidator( + /** @lang PhpRegExp */ '#\.txt$#i', + FilesystemValidationOption::IsReadable + ) + ); + } + + /** + * @inheritDoc + */ + protected function execute (InputInterface $input, OutputInterface $output): int { + if (($fileContent = file_get_contents($input->getArgument('file'))) === false) { + return Command::FAILURE; + } + $output->writeln($fileContent); + return Command::SUCCESS; + } +} \ No newline at end of file diff --git a/tests/file.txt b/tests/file.txt new file mode 100644 index 0000000..91aaf46 --- /dev/null +++ b/tests/file.txt @@ -0,0 +1 @@ +This is a file \ No newline at end of file