Skip to content

Commit b5f4185

Browse files
authored
feat(console): support variadic argument (#1572)
1 parent 2d29bd5 commit b5f4185

File tree

5 files changed

+75
-0
lines changed

5 files changed

+75
-0
lines changed

packages/console/src/ConsoleInputBuilder.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,18 @@ public function build(): array
2626
$argumentDefinitions = $this->command->getArgumentDefinitions();
2727

2828
foreach ($argumentDefinitions as $argumentDefinition) {
29+
if ($argumentDefinition->isVariadic) {
30+
$arguments = $this->argumentBag->findForVariadicArgument($argumentDefinition);
31+
32+
if ($arguments === []) {
33+
$invalidArguments[] = $argumentDefinition;
34+
} else {
35+
$validArguments = [...$validArguments, ...$arguments];
36+
}
37+
38+
continue;
39+
}
40+
2941
$argument = $argumentDefinition->type === 'array'
3042
? $this->argumentBag->findArrayFor($argumentDefinition)
3143
: $this->argumentBag->findFor($argumentDefinition);

packages/console/src/Input/ConsoleArgumentBag.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,26 @@ public function findArrayFor(ConsoleArgumentDefinition $argumentDefinition): Con
129129
);
130130
}
131131

132+
/**
133+
* @return list<ConsoleInputArgument>
134+
*/
135+
public function findForVariadicArgument(ConsoleArgumentDefinition $argumentDefinition): array
136+
{
137+
$arguments = [];
138+
139+
foreach ($this->arguments as $argument) {
140+
if ($argument->position >= $argumentDefinition->position) {
141+
$arguments[] = new ConsoleInputArgument(
142+
name: $argumentDefinition->name,
143+
position: $argument->position,
144+
value: $this->resolveArgumentValue($argumentDefinition, $argument)->value,
145+
);
146+
}
147+
}
148+
149+
return $arguments;
150+
}
151+
132152
public function add(ConsoleInputArgument $argument): self
133153
{
134154
$this->arguments[] = $argument;

packages/console/src/Input/ConsoleArgumentDefinition.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public function __construct(
1818
public mixed $default,
1919
public bool $hasDefault,
2020
public int $position,
21+
public bool $isVariadic = false,
2122
public ?string $description = null,
2223
public array $aliases = [],
2324
public ?string $help = null,
@@ -36,6 +37,7 @@ public static function fromParameter(ParameterReflector $parameter): ConsoleArgu
3637
default: $default,
3738
hasDefault: $parameter->isDefaultValueAvailable(),
3839
position: $parameter->getPosition(),
40+
isVariadic: $parameter->isVariadic(),
3941
description: $attribute?->description,
4042
aliases: $attribute->aliases ?? [],
4143
help: $attribute?->help,

tests/Integration/Console/ConsoleArgumentBagTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,4 +190,14 @@ public function test_name_mapping(): void
190190
->assertSee('foo')
191191
->assertSee('true');
192192
}
193+
194+
#[TestWith(['variadic-string-argument foo bar baz', '["foo","bar","baz"]'])]
195+
#[TestWith(['variadic-integer-argument 1 2 3', '[1,2,3]'])]
196+
#[TestWith(['variadic-backed-enum-argument a b c', '["a","b","c"]'])]
197+
public function test_variadic_argument(string $command, string $jsonOutput): void
198+
{
199+
$this->console
200+
->call($command)
201+
->assertSee($jsonOutput);
202+
}
193203
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Tempest\Integration\Console\Fixtures;
6+
7+
use Tempest\Console\ConsoleCommand;
8+
use Tempest\Console\HasConsole;
9+
10+
final readonly class VariadicCommand
11+
{
12+
use HasConsole;
13+
14+
#[ConsoleCommand('variadic-string-argument')]
15+
public function string(string ...$input): void
16+
{
17+
$this->writeln(json_encode($input));
18+
}
19+
20+
#[ConsoleCommand('variadic-integer-argument')]
21+
public function integer(int ...$input): void
22+
{
23+
$this->writeln(json_encode($input));
24+
}
25+
26+
#[ConsoleCommand('variadic-backed-enum-argument')]
27+
public function backedEnum(TestStringEnum ...$input): void
28+
{
29+
$this->writeln(json_encode($input));
30+
}
31+
}

0 commit comments

Comments
 (0)