diff --git a/bin/castor b/bin/castor index 873b8d6f..9512426e 100755 --- a/bin/castor +++ b/bin/castor @@ -2,6 +2,7 @@ run(); +ApplicationFactory::create()->run(new Input()); diff --git a/bin/generate-tests.php b/bin/generate-tests.php index af439573..db6c9065 100755 --- a/bin/generate-tests.php +++ b/bin/generate-tests.php @@ -116,19 +116,21 @@ add_test([], $class, '{{ base }}/tests/Examples/fixtures/broken/' . $dir->getRelativePath()); } -add_test(['parallel:sleep', '--sleep5', '0', '--sleep7', '0', '--sleep10', '0'], 'ParallelSleepTest'); -add_test(['context:context', '--context', 'run'], 'ContextContextRunTest'); +add_test(['args:passthru', 'a', 'b', '--no', '--foo', 'bar', '-x'], 'ArgPassthruExpanded'); +add_test(['context:context', '--context', 'dynamic'], 'ContextContextDynamicTest'); add_test(['context:context', '--context', 'my_default', '-v'], 'ContextContextMyDefaultTest'); add_test(['context:context', '--context', 'no_no_exist'], 'ContextContextDoNotExistTest'); -add_test(['context:context', '--context', 'production'], 'ContextContextProductionTest'); add_test(['context:context', '--context', 'path'], 'ContextContextPathTest'); -add_test(['context:context', '--context', 'dynamic'], 'ContextContextDynamicTest'); +add_test(['context:context', '--context', 'production'], 'ContextContextProductionTest'); +add_test(['context:context', '--context', 'run'], 'ContextContextRunTest'); add_test(['enabled:hello', '--context', 'production'], 'EnabledInProduction'); -add_test([], 'NewProjectTest', '/tmp'); +add_test(['parallel:sleep', '--sleep5', '0', '--sleep7', '0', '--sleep10', '0'], 'ParallelSleepTest'); +// In /tmp +add_test(['completion', 'bash'], 'NoConfigCompletionTest', '/tmp'); add_test(['init'], 'NewProjectInitTest', '/tmp'); -add_test(['unknown:task'], 'NoConfigUnknownTest', '/tmp'); add_test(['unknown:task', 'toto', '--foo', 1], 'NoConfigUnknownWithArgsTest', '/tmp'); -add_test(['completion', 'bash'], 'NoConfigCompletionTest', '/tmp'); +add_test(['unknown:task'], 'NoConfigUnknownTest', '/tmp'); +add_test([], 'NewProjectTest', '/tmp'); function add_test(array $args, string $class, ?string $cwd = null) { diff --git a/examples/args.php b/examples/args.php index f5827c0b..304ea346 100644 --- a/examples/args.php +++ b/examples/args.php @@ -6,6 +6,7 @@ use Castor\Attribute\AsOption; use Castor\Attribute\AsTask; +use function Castor\input; use function Castor\run; /** @@ -32,3 +33,9 @@ function another_args( ): void { run(['echo', $required, $test2]); } + +#[AsTask(description: 'Dumps all arguments and options, without configuration not validation', ignoreValidationErrors: true)] +function passthru() +{ + var_dump(input()->getRawParameters()); +} diff --git a/src/Attribute/AsTask.php b/src/Attribute/AsTask.php index e681d0a1..f745fb75 100644 --- a/src/Attribute/AsTask.php +++ b/src/Attribute/AsTask.php @@ -16,6 +16,7 @@ public function __construct( public array $aliases = [], public array $onSignals = [], public string|bool $enabled = true, + public bool $ignoreValidationErrors = false, ) { } } diff --git a/src/Console/Command/SymfonyTaskCommand.php b/src/Console/Command/SymfonyTaskCommand.php index 75b1c18a..827a0930 100644 --- a/src/Console/Command/SymfonyTaskCommand.php +++ b/src/Console/Command/SymfonyTaskCommand.php @@ -3,6 +3,7 @@ namespace Castor\Console\Command; use Castor\Attribute\AsSymfonyTask; +use Castor\Console\Input\Input; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -67,10 +68,12 @@ protected function configure(): void } } + /** + * @var Input $input + */ protected function execute(InputInterface $input, OutputInterface $output): int { - $r = new \ReflectionProperty($input, 'tokens'); - $extra = array_filter($r->getValue($input), fn ($item) => $item !== $this->taskAttribute->name); + $extra = array_filter($input->getRawParameters(), fn ($item) => $item !== $this->taskAttribute->name); $p = new Process([...$this->taskAttribute->console, $this->taskAttribute->originalName, ...$extra]); $p->run(fn ($type, $bytes) => print ($bytes)); diff --git a/src/Console/Command/TaskCommand.php b/src/Console/Command/TaskCommand.php index 54d415a6..adefbb2e 100644 --- a/src/Console/Command/TaskCommand.php +++ b/src/Console/Command/TaskCommand.php @@ -76,6 +76,10 @@ public function isEnabled(): bool protected function configure(): void { + if ($this->taskAttribute->ignoreValidationErrors) { + $this->ignoreValidationErrors(); + } + foreach ($this->function->getParameters() as $parameter) { $taskArgumentAttribute = $parameter->getAttributes(AsCommandArgument::class, \ReflectionAttribute::IS_INSTANCEOF)[0] ?? null; diff --git a/src/Console/Input/Input.php b/src/Console/Input/Input.php new file mode 100644 index 00000000..253cebda --- /dev/null +++ b/src/Console/Input/Input.php @@ -0,0 +1,13 @@ + $this->tokens)->bindTo($this, ArgvInput::class)(); + } +} diff --git a/src/GlobalHelper.php b/src/GlobalHelper.php index c6a210ab..d6a75044 100644 --- a/src/GlobalHelper.php +++ b/src/GlobalHelper.php @@ -6,7 +6,7 @@ use Monolog\Logger; use Psr\Cache\CacheItemPoolInterface; use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\Input; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Filesystem\Filesystem; @@ -57,7 +57,7 @@ public static function getLogger(): Logger return self::getApplication()->logger; } - public static function getInput(): InputInterface + public static function getInput(): Input { return self::getApplication()->getInput(); } diff --git a/src/functions.php b/src/functions.php index b3407765..8dd17424 100644 --- a/src/functions.php +++ b/src/functions.php @@ -16,6 +16,7 @@ use Psr\Cache\CacheItemPoolInterface; use Spatie\Ssh\Ssh; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\Input; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\Console\Output\OutputInterface; @@ -631,7 +632,7 @@ function get_application(): Application return app(); } -function input(): InputInterface +function input(): Input { return GlobalHelper::getInput(); } diff --git a/tests/Examples/Generated/ArgPassthruExpanded.php b/tests/Examples/Generated/ArgPassthruExpanded.php new file mode 100644 index 00000000..05f989f2 --- /dev/null +++ b/tests/Examples/Generated/ArgPassthruExpanded.php @@ -0,0 +1,22 @@ +runTask(['args:passthru', 'a', 'b', '--no', '--foo', 'bar', '-x']); + + $this->assertSame(0, $process->getExitCode()); + $this->assertStringEqualsFile(__FILE__ . '.output.txt', $process->getOutput()); + if (file_exists(__FILE__ . '.err.txt')) { + $this->assertStringEqualsFile(__FILE__ . '.err.txt', $process->getErrorOutput()); + } else { + $this->assertSame('', $process->getErrorOutput()); + } + } +} diff --git a/tests/Examples/Generated/ArgPassthruExpanded.php.output.txt b/tests/Examples/Generated/ArgPassthruExpanded.php.output.txt new file mode 100644 index 00000000..f2f3e3ca --- /dev/null +++ b/tests/Examples/Generated/ArgPassthruExpanded.php.output.txt @@ -0,0 +1,18 @@ +array(8) { + [0]=> + string(9) "--no-ansi" + [1]=> + string(13) "args:passthru" + [2]=> + string(1) "a" + [3]=> + string(1) "b" + [4]=> + string(4) "--no" + [5]=> + string(5) "--foo" + [6]=> + string(3) "bar" + [7]=> + string(2) "-x" +} diff --git a/tests/Examples/Generated/ArgsPassthruTest.php b/tests/Examples/Generated/ArgsPassthruTest.php new file mode 100644 index 00000000..3f6b2d02 --- /dev/null +++ b/tests/Examples/Generated/ArgsPassthruTest.php @@ -0,0 +1,22 @@ +runTask(['args:passthru']); + + $this->assertSame(0, $process->getExitCode()); + $this->assertStringEqualsFile(__FILE__ . '.output.txt', $process->getOutput()); + if (file_exists(__FILE__ . '.err.txt')) { + $this->assertStringEqualsFile(__FILE__ . '.err.txt', $process->getErrorOutput()); + } else { + $this->assertSame('', $process->getErrorOutput()); + } + } +} diff --git a/tests/Examples/Generated/ArgsPassthruTest.php.output.txt b/tests/Examples/Generated/ArgsPassthruTest.php.output.txt new file mode 100644 index 00000000..c74dd623 --- /dev/null +++ b/tests/Examples/Generated/ArgsPassthruTest.php.output.txt @@ -0,0 +1,6 @@ +array(2) { + [0]=> + string(9) "--no-ansi" + [1]=> + string(13) "args:passthru" +} diff --git a/tests/Examples/Generated/ListTest.php.output.txt b/tests/Examples/Generated/ListTest.php.output.txt index 8155299e..269a7c83 100644 --- a/tests/Examples/Generated/ListTest.php.output.txt +++ b/tests/Examples/Generated/ListTest.php.output.txt @@ -6,6 +6,7 @@ list List commands no-namespace Task without a namespace args:another-args Dumps all arguments and options, without configuration args:args Dumps all arguments and options, with custom configuration +args:passthru Dumps all arguments and options, without configuration not validation bar:bar Prints bar, but also executes foo cache:complex Cache with usage of CacheItemInterface cache:simple Cache a simple call