Skip to content

Commit b5f2638

Browse files
authored
[console] [7.3] add array argument support to /InvokableCommandInputAttributeRector (#842)
* misc * [console] [7.3] add array argument support to /InvokableCommandInputAttributeRector
1 parent eaa09ba commit b5f2638

5 files changed

Lines changed: 91 additions & 23 deletions

File tree

rules-tests/Symfony73/Rector/Class_/InvokableCommandInputAttributeRector/Fixture/argument_with_default_value.php.inc renamed to rules-tests/Symfony73/Rector/Class_/InvokableCommandInputAttributeRector/Fixture/DefaultValue/argument_with_default_value.php.inc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
namespace Rector\Symfony\Tests\Symfony73\Rector\Class_\InvokableCommandInputAttributeRector\Fixture;
3+
namespace Rector\Symfony\Tests\Symfony73\Rector\Class_\InvokableCommandInputAttributeRector\Fixture\DefaultValue;
44

55
use Symfony\Component\Console\Attribute\AsCommand;
66
use Symfony\Component\Console\Command\Command;
@@ -28,7 +28,7 @@ class ArgumentWithDefaultValue extends Command
2828
-----
2929
<?php
3030

31-
namespace Rector\Symfony\Tests\Symfony73\Rector\Class_\InvokableCommandInputAttributeRector\Fixture;
31+
namespace Rector\Symfony\Tests\Symfony73\Rector\Class_\InvokableCommandInputAttributeRector\Fixture\DefaultValue;
3232

3333
use Symfony\Component\Console\Attribute\AsCommand;
3434
use Symfony\Component\Console\Command\Command;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
namespace Rector\Symfony\Tests\Symfony73\Rector\Class_\InvokableCommandInputAttributeRector\Fixture\DefaultValue;
4+
5+
use Symfony\Component\Console\Attribute\AsCommand;
6+
use Symfony\Component\Console\Command\Command;
7+
use Symfony\Component\Console\Input\InputArgument;
8+
use Symfony\Component\Console\Input\InputInterface;
9+
use Symfony\Component\Console\Output\OutputInterface;
10+
11+
#[AsCommand(
12+
name: 'app:hello',
13+
)]
14+
class IterableTypeWithDefaultValue extends Command
15+
{
16+
protected function configure(): void
17+
{
18+
$this->addArgument('iterable', InputArgument::REQUIRED | InputArgument::IS_ARRAY, null, ['many values']);
19+
}
20+
21+
protected function execute(InputInterface $input, OutputInterface $output): int
22+
{
23+
}
24+
}
25+
26+
?>
27+
-----
28+
<?php
29+
30+
namespace Rector\Symfony\Tests\Symfony73\Rector\Class_\InvokableCommandInputAttributeRector\Fixture\DefaultValue;
31+
32+
use Symfony\Component\Console\Attribute\AsCommand;
33+
use Symfony\Component\Console\Command\Command;
34+
use Symfony\Component\Console\Input\InputArgument;
35+
use Symfony\Component\Console\Input\InputInterface;
36+
use Symfony\Component\Console\Output\OutputInterface;
37+
38+
#[AsCommand(
39+
name: 'app:hello',
40+
)]
41+
class IterableTypeWithDefaultValue
42+
{
43+
public function __invoke(
44+
#[\Symfony\Component\Console\Attribute\Argument(name: 'iterable')]
45+
array $iterable = ['many values']
46+
): int
47+
{
48+
}
49+
}
50+
51+
?>

rules/Symfony73/NodeAnalyzer/CommandArgumentsResolver.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Rector\Symfony\Symfony73\NodeAnalyzer;
66

7+
use PhpParser\Node\Expr;
78
use PhpParser\Node\Stmt\ClassMethod;
89
use Rector\PhpParser\Node\Value\ValueResolver;
910
use Rector\Symfony\Symfony73\NodeFinder\MethodCallFinder;
@@ -30,12 +31,22 @@ public function resolve(ClassMethod $configureClassMethod): array
3031

3132
$argumentName = $this->valueResolver->getValue($addArgumentArgs[0]->value);
3233

34+
$modeExpr = $addArgumentArgs[1]->value ?? null;
35+
36+
$isArray = false;
37+
if ($modeExpr instanceof Expr) {
38+
$modeValue = $this->valueResolver->getValue($modeExpr);
39+
// binary check for InputArgument::IS_ARRAY
40+
$isArray = (bool) ($modeValue & 4);
41+
}
42+
3343
$commandArguments[] = new CommandArgument(
3444
$argumentName,
3545
$addArgumentArgs[0]->value,
3646
$addArgumentArgs[1]->value ?? null,
3747
$addArgumentArgs[2]->value ?? null,
3848
$addArgumentArgs[3]->value ?? null,
49+
$isArray
3950
);
4051
}
4152

rules/Symfony73/NodeFactory/CommandInvokeParamsFactory.php

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,12 @@ private function createArgumentParams(array $commandArguments): array
4949
foreach ($commandArguments as $commandArgument) {
5050
$variableName = $this->createCamelCase($commandArgument->getNameValue());
5151
$argumentParam = new Param(new Variable($variableName));
52-
$argumentParam->type = new Identifier('string');
52+
53+
if ($commandArgument->isArray()) {
54+
$argumentParam->type = new Identifier('array');
55+
} else {
56+
$argumentParam->type = new Identifier('string');
57+
}
5358

5459
if ($commandArgument->getDefault() instanceof Expr) {
5560
$argumentParam->default = $commandArgument->getDefault();
@@ -63,7 +68,7 @@ private function createArgumentParams(array $commandArguments): array
6368

6469
$argumentArgs = [new Arg(value: $commandArgument->getName(), name: new Identifier('name'))];
6570

66-
if ($this->hasUsefulDescription($commandArgument)) {
71+
if ($this->isNonEmptyExpr($commandArgument->getDescription())) {
6772
$argumentArgs[] = new Arg(value: $commandArgument->getDescription(), name: new Identifier(
6873
'description'
6974
));
@@ -97,19 +102,15 @@ private function createOptionParams(array $commandOptions): array
97102

98103
$optionArgs = [new Arg(value: $commandOption->getName(), name: new Identifier('name'))];
99104

100-
if ($commandOption->getShortcut() instanceof Expr && ! $this->valueResolver->isNull(
101-
$commandOption->getShortcut()
102-
)) {
105+
if ($this->isNonEmptyExpr($commandOption->getShortcut())) {
103106
$optionArgs[] = new Arg(value: $commandOption->getShortcut(), name: new Identifier('shortcut'));
104107
}
105108

106-
if ($commandOption->getMode() instanceof Expr && ! $this->valueResolver->isNull(
107-
$commandOption->getMode()
108-
)) {
109+
if ($this->isNonEmptyExpr($commandOption->getMode())) {
109110
$optionArgs[] = new Arg(value: $commandOption->getMode(), name: new Identifier('mode'));
110111
}
111112

112-
if ($this->hasUsefulDescription($commandOption)) {
113+
if ($this->isNonEmptyExpr($commandOption->getDescription())) {
113114
$optionArgs[] = new Arg(value: $commandOption->getDescription(), name: new Identifier('description'));
114115
}
115116

@@ -135,26 +136,25 @@ private function createCamelCase(string $value): string
135136
return lcfirst($value);
136137
}
137138

138-
private function hasUsefulDescription(CommandArgument|CommandOption $commandArgumentOrOption): bool
139+
private function isOptionalArgument(CommandArgument $commandArgument): bool
140+
{
141+
if (! $commandArgument->getMode() instanceof Expr) {
142+
return true;
143+
}
144+
145+
return $this->valueResolver->isValue($commandArgument->getMode(), 2);
146+
}
147+
148+
private function isNonEmptyExpr(?Expr $expr): bool
139149
{
140-
if (! $commandArgumentOrOption->getDescription() instanceof Expr) {
150+
if (! $expr instanceof Expr) {
141151
return false;
142152
}
143153

144-
$expr = $commandArgumentOrOption->getDescription();
145154
if ($this->valueResolver->isNull($expr)) {
146155
return false;
147156
}
148157

149158
return ! $this->valueResolver->isValue($expr, '');
150159
}
151-
152-
private function isOptionalArgument(CommandArgument $commandArgument): bool
153-
{
154-
if (! $commandArgument->getMode() instanceof Expr) {
155-
return true;
156-
}
157-
158-
return $this->valueResolver->isValue($commandArgument->getMode(), 2);
159-
}
160160
}

rules/Symfony73/ValueObject/CommandArgument.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public function __construct(
1414
private ?Expr $mode,
1515
private ?Expr $description,
1616
private ?Expr $default,
17+
private bool $isArray
1718
) {
1819
}
1920

@@ -41,4 +42,9 @@ public function getDefault(): ?Expr
4142
{
4243
return $this->default;
4344
}
45+
46+
public function isArray(): bool
47+
{
48+
return $this->isArray;
49+
}
4450
}

0 commit comments

Comments
 (0)