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

2.x 2.7.5
Julien Rosset 6 months ago
parent c4a81079cc
commit 08282a7c01

@ -2,8 +2,10 @@
namespace jrosset\CliProgram\Validation; namespace jrosset\CliProgram\Validation;
use Closure;
use jrosset\CliProgram\Validation\Validators\InvalidValueException; use jrosset\CliProgram\Validation\Validators\InvalidValueException;
use jrosset\CliProgram\Validation\Validators\IValidator; use jrosset\CliProgram\Validation\Validators\IValidator;
use ReflectionFunction;
use Stringable; use Stringable;
use Symfony\Component\Console\Exception\InvalidArgumentException; use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
@ -24,16 +26,59 @@ trait TCommandWithValidation {
* @var array<string, IValidator> The validators of each {@see InputOption} * @var array<string, IValidator> The validators of each {@see InputOption}
*/ */
private array $optionsValidator = []; 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 * @inheritDoc
* *
* @throws Throwable If an argument or option is not valid * @throws Throwable If an argument or option is not valid
*/ */
protected function interact (InputInterface $input, OutputInterface $output): void { protected function initialize (InputInterface $input, OutputInterface $output): void {
parent::interact($input, $output); parent::setCode(
function (InputInterface $input, OutputInterface $output): int {
$this->validate($input, $output); $this->validate($input, $output);
return $this->realCode !== null
? ($this->realCode)($input, $output)
: $this->execute($input, $output);
}
);
parent::initialize($input, $output);
}
/**
* @inheritDoc
*
* @noinspection PhpMissingReturnTypeInspection
*/
public function setCode (callable $code) {
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();
}
}
}
// {@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 * Validate the command input
* *

Loading…
Cancel
Save