parent
de43de4ca0
commit
47c5d1be51
@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
namespace jrosset\CliProgram\Validation\Validators;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use jrosset\Collections\Collection;
|
||||
use jrosset\Collections\ICollection;
|
||||
use Stringable;
|
||||
|
||||
/**
|
||||
* An argument/option value validator for a directory path
|
||||
*/
|
||||
class DirectoryValidator implements IValidator {
|
||||
use TInternalValueValidator;
|
||||
|
||||
/**
|
||||
* @var ICollection<int> The options
|
||||
*/
|
||||
private ICollection $options;
|
||||
|
||||
/**
|
||||
* Initialization
|
||||
*
|
||||
* @param ICollection<int>|int[]|int|null $options The options
|
||||
*/
|
||||
public function __construct ($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 ($default) {
|
||||
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::IS_READABLE) && !is_readable($default)) {
|
||||
throw new InvalidArgumentException('The default value is not readable');
|
||||
}
|
||||
if ($this->getOptions()->contains(FilesystemValidationOption::IS_WRITABLE) && !is_writable($default)) {
|
||||
throw new InvalidArgumentException('The default value is not writable');
|
||||
}
|
||||
if ($this->getOptions()->contains(FilesystemValidationOption::MUST_EXISTS) && !file_exists($default)) {
|
||||
throw new InvalidArgumentException('The default value doesn\'t exist');
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function validate ($value): bool {
|
||||
if (!is_string($value) && !$value instanceof Stringable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->getOptions()->contains(FilesystemValidationOption::IS_READABLE) && !is_readable($value)) {
|
||||
return false;
|
||||
}
|
||||
if ($this->getOptions()->contains(FilesystemValidationOption::IS_WRITABLE) && !is_writable($value)) {
|
||||
return false;
|
||||
}
|
||||
if ($this->getOptions()->contains(FilesystemValidationOption::MUST_EXISTS) && !file_exists($value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->setValue($value);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* The options
|
||||
*
|
||||
* @return ICollection<FilesystemValidationOption> The options
|
||||
*/
|
||||
public function getOptions (): ICollection {
|
||||
return $this->options;
|
||||
}
|
||||
/**
|
||||
* Replace the options
|
||||
*
|
||||
* @param ICollection<int>|int[]|int|null $options The options
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setOptions ($options = null): self {
|
||||
if ($options instanceof ICollection) {
|
||||
$this->options = $options;
|
||||
}
|
||||
elseif (is_int($options)) {
|
||||
$this->options = new Collection([$options]);
|
||||
}
|
||||
elseif (is_array($options)) {
|
||||
$this->options = new Collection($options);
|
||||
}
|
||||
elseif ($options === null) {
|
||||
$this->options = new Collection();
|
||||
}
|
||||
else {
|
||||
throw new InvalidArgumentException();
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace jrosset\CliProgram\Validation\Validators;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use jrosset\Collections\ICollection;
|
||||
|
||||
/**
|
||||
* An argument/option value validator for a file path
|
||||
*/
|
||||
class FileValidator extends DirectoryValidator {
|
||||
/**
|
||||
* @var string|null The allowed extensions (regex pattern)
|
||||
*/
|
||||
private ?string $extensionsPattern;
|
||||
|
||||
/**
|
||||
* Initialization
|
||||
*
|
||||
* @param string|null $extensionsPattern The allowed extensions (regex pattern)
|
||||
* @param ICollection<int>|int[]|int|null $options The options
|
||||
*/
|
||||
public function __construct (?string $extensionsPattern = null, $options = null) {
|
||||
parent::__construct($options);
|
||||
$this->setExtensionsPattern($extensionsPattern);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getValidDefault ($default) {
|
||||
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 ($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): self {
|
||||
$this->extensionsPattern = $extensionsPattern;
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace jrosset\CliProgram\Validation\Validators;
|
||||
|
||||
/**
|
||||
* Options of a filesystem based validator
|
||||
*/
|
||||
abstract class FilesystemValidationOption {
|
||||
public const MUST_EXISTS = 1;
|
||||
public const IS_READABLE = 2;
|
||||
public const IS_WRITABLE = 3;
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace jrosset\Tests\Commands;
|
||||
|
||||
use jrosset\CliProgram\Validation\CommandWithValidation;
|
||||
use jrosset\CliProgram\Validation\Validators\FilesystemValidationOption;
|
||||
use jrosset\CliProgram\Validation\Validators\FileValidator;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class ReadFile extends CommandWithValidation {
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected static $defaultDescription = 'Read a file';
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configure (): void {
|
||||
parent::configure();
|
||||
|
||||
$this->addArgument(
|
||||
'file',
|
||||
InputArgument::REQUIRED,
|
||||
'The file to read',
|
||||
null,
|
||||
new FileValidator(
|
||||
/** @lang PhpRegExp */ '#\.txt$#i',
|
||||
FilesystemValidationOption::IS_READABLE
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
This is a file
|
Loading…
Reference in New Issue