Skip to content

Commit

Permalink
Add support for getting raw parameters without validation
Browse files Browse the repository at this point in the history
  • Loading branch information
lyrixx committed Mar 11, 2024
1 parent b4bbadf commit e0728ea
Show file tree
Hide file tree
Showing 14 changed files with 114 additions and 13 deletions.
3 changes: 2 additions & 1 deletion bin/castor
Expand Up @@ -2,6 +2,7 @@
<?php

use Castor\Console\ApplicationFactory;
use Castor\Console\Input\Input;

if (file_exists($file = __DIR__ . '/../vendor/autoload.php')) {
require $file;
Expand All @@ -11,4 +12,4 @@ if (file_exists($file = __DIR__ . '/../vendor/autoload.php')) {
throw new \RuntimeException('Unable to find autoloader.');
}

ApplicationFactory::create()->run();
ApplicationFactory::create()->run(new Input());
16 changes: 9 additions & 7 deletions bin/generate-tests.php
Expand Up @@ -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)
{
Expand Down
7 changes: 7 additions & 0 deletions examples/args.php
Expand Up @@ -6,6 +6,7 @@
use Castor\Attribute\AsOption;
use Castor\Attribute\AsTask;

use function Castor\input;
use function Castor\run;

/**
Expand All @@ -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)]

Check failure on line 37 in examples/args.php

View workflow job for this annotation

GitHub Actions / Static Analysis

Function args\passthru() has no return type specified.
function passthru()
{
var_dump(input()->getRawParameters());

Check failure on line 40 in examples/args.php

View workflow job for this annotation

GitHub Actions / Static Analysis

Call to an undefined method Symfony\Component\Console\Input\Input::getRawParameters().
}
1 change: 1 addition & 0 deletions src/Attribute/AsTask.php
Expand Up @@ -16,6 +16,7 @@ public function __construct(
public array $aliases = [],
public array $onSignals = [],
public string|bool $enabled = true,
public bool $ignoreValidationErrors = false,
) {
}
}
7 changes: 5 additions & 2 deletions src/Console/Command/SymfonyTaskCommand.php
Expand Up @@ -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;
Expand Down Expand Up @@ -67,10 +68,12 @@ protected function configure(): void
}
}

/**
* @var Input $input
*/
protected function execute(InputInterface $input, OutputInterface $output): int

Check failure on line 74 in src/Console/Command/SymfonyTaskCommand.php

View workflow job for this annotation

GitHub Actions / Static Analysis

PHPDoc tag @var above a method has no effect.
{
$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);

Check failure on line 76 in src/Console/Command/SymfonyTaskCommand.php

View workflow job for this annotation

GitHub Actions / Static Analysis

Call to an undefined method Symfony\Component\Console\Input\InputInterface::getRawParameters().

$p = new Process([...$this->taskAttribute->console, $this->taskAttribute->originalName, ...$extra]);
$p->run(fn ($type, $bytes) => print ($bytes));
Expand Down
4 changes: 4 additions & 0 deletions src/Console/Command/TaskCommand.php
Expand Up @@ -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;

Expand Down
13 changes: 13 additions & 0 deletions src/Console/Input/Input.php
@@ -0,0 +1,13 @@
<?php

namespace Castor\Console\Input;

use Symfony\Component\Console\Input\ArgvInput;

class Input extends ArgvInput
{
public function getRawParameters()

Check failure on line 9 in src/Console/Input/Input.php

View workflow job for this annotation

GitHub Actions / Static Analysis

Method Castor\Console\Input\Input::getRawParameters() has no return type specified.
{
return (fn () => $this->tokens)->bindTo($this, ArgvInput::class)();

Check failure on line 11 in src/Console/Input/Input.php

View workflow job for this annotation

GitHub Actions / Static Analysis

Access to private property $tokens of parent class Symfony\Component\Console\Input\ArgvInput.
}
}
4 changes: 2 additions & 2 deletions src/GlobalHelper.php
Expand Up @@ -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;
Expand Down Expand Up @@ -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();

Check failure on line 62 in src/GlobalHelper.php

View workflow job for this annotation

GitHub Actions / Static Analysis

Method Castor\GlobalHelper::getInput() should return Symfony\Component\Console\Input\Input but returns Symfony\Component\Console\Input\InputInterface.
}
Expand Down
3 changes: 2 additions & 1 deletion src/functions.php
Expand Up @@ -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;
Expand Down Expand Up @@ -631,7 +632,7 @@ function get_application(): Application
return app();
}

function input(): InputInterface
function input(): Input
{
return GlobalHelper::getInput();
}
Expand Down
22 changes: 22 additions & 0 deletions tests/Examples/Generated/ArgPassthruExpanded.php
@@ -0,0 +1,22 @@
<?php

namespace Castor\Tests\Examples\Generated;

use Castor\Tests\TaskTestCase;

class ArgPassthruExpanded extends TaskTestCase
{
// args:passthru
public function test(): void
{
$process = $this->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());
}
}
}
18 changes: 18 additions & 0 deletions 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"
}
22 changes: 22 additions & 0 deletions tests/Examples/Generated/ArgsPassthruTest.php
@@ -0,0 +1,22 @@
<?php

namespace Castor\Tests\Examples\Generated;

use Castor\Tests\TaskTestCase;

class ArgsPassthruTest extends TaskTestCase
{
// args:passthru
public function test(): void
{
$process = $this->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());
}
}
}
6 changes: 6 additions & 0 deletions tests/Examples/Generated/ArgsPassthruTest.php.output.txt
@@ -0,0 +1,6 @@
array(2) {
[0]=>
string(9) "--no-ansi"
[1]=>
string(13) "args:passthru"
}
1 change: 1 addition & 0 deletions tests/Examples/Generated/ListTest.php.output.txt
Expand Up @@ -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
Expand Down

0 comments on commit e0728ea

Please sign in to comment.