Fix command with validation when using -n/--no-interaction option

master 3.8.7
Julien Rosset 6 months ago
parent 6c31a16e80
commit fefb3bf3c1

@ -5,13 +5,14 @@ namespace jrosset\CliProgram\Validation;
use Closure;
use jrosset\CliProgram\Validation\Validators\InvalidValueException;
use jrosset\CliProgram\Validation\Validators\IValidator;
use ReflectionFunction;
use Stringable;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Throwable;
/**
* Provide a value validation process ({@see IValidator}) to {@see self::addArgument()} and {@see self::addOption()}
@ -25,16 +26,58 @@ trait TCommandWithValidation {
* @var array<string, IValidator> The validators of each {@see InputOption}
*/
private array $optionsValidator = [];
/**
* @var Closure|null The <i>real</i> code ({@see Command::$code} is used to perform input validation before execution) to execute when running this command.
* <br><br>If set, it overrides the code defined in the execute() method.
*/
private ?Closure $realCode = null;
/**
* @inheritDoc
*
* @throws Throwable If an argument or option is not valid
*/
protected function interact (InputInterface $input, OutputInterface $output): void {
parent::interact($input, $output);
protected function initialize (InputInterface $input, OutputInterface $output): void {
parent::setCode(
function (InputInterface $input, OutputInterface $output): int {
$this->validate($input, $output);
return $this->realCode !== null
? ($this->realCode)($input, $output)
: $this->execute($input, $output);
}
);
parent::initialize($input, $output);
}
/**
* @inheritDoc
*/
public function setCode (callable $code): static {
if ($code instanceof Closure) {
/** @noinspection PhpUnhandledExceptionInspection */
$codeReflection = new ReflectionFunction($code);
if ($codeReflection->getClosureThis() === null) {
set_error_handler(
static function () {
}
);
try {
if ($rebindCode = Closure::bind($code, $this)) {
$code = $rebindCode;
}
}
finally {
restore_error_handler();
}
}
}
else {
$code = $code(...);
}
// {@see Command::$code} is used to perform input validation before execution, so set {@see self::$realCode} instead
$this->realCode = $code;
return $this;
}
/**
* Validate the command input
*

@ -11,14 +11,14 @@ abstract class BasedValidator implements IValidator {
/**
* @var TValidator The internal validator
*/
private $internalValidator;
private IValidator $internalValidator;
/**
* Create a validator
*
* @param TValidator $internalValidator The internal validator
*/
public function __construct ($internalValidator) {
public function __construct (IValidator $internalValidator) {
$this->internalValidator = $internalValidator;
}
/**
@ -26,7 +26,7 @@ abstract class BasedValidator implements IValidator {
*
* @return TValidator The internal validator
*/
protected function getInternalValidator () {
protected function getInternalValidator (): IValidator {
return $this->internalValidator;
}

@ -13,7 +13,7 @@ namespace jrosset\CliProgram\Validation\Validators;
*/
trait TInternalValueValidator {
/**
* @var TValue|null The current value, after
* @var TValue|null The current value, after it's validation
*/
private $value = null;

Loading…
Cancel
Save