Skip to content

Commit

Permalink
Fix #20247: Support for variadic console controller action methods
Browse files Browse the repository at this point in the history
  • Loading branch information
brandonkelly authored Aug 19, 2024
1 parent 34d2396 commit 5abe83e
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 8 deletions.
1 change: 1 addition & 0 deletions framework/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Yii Framework 2 Change Log

- Bug #20232: Fix regression introduced in `GHSA-cjcc-p67m-7qxm` while attaching behavior defined by `__class` array key (erickskrauch)
- Bug #20231: Fix regression introduced in #20167 in `yii\validators\FileValidator` (bizley)
- Enh #20247: Support for variadic console controller action methods (brandonkelly)

2.0.51 July 18, 2024
--------------------
Expand Down
28 changes: 20 additions & 8 deletions framework/console/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ public function bindActionParams($action, $params)
$method = new \ReflectionMethod($action, 'run');
}

$paramKeys = array_keys($params);
$args = [];
$missing = [];
$actionParams = [];
Expand All @@ -212,16 +213,27 @@ public function bindActionParams($action, $params)
}

if ($key !== null) {
if (PHP_VERSION_ID >= 80000) {
$isArray = ($type = $param->getType()) instanceof \ReflectionNamedType && $type->getName() === 'array';
if ($param->isVariadic()) {
for ($j = array_search($key, $paramKeys); $j < count($paramKeys); $j++) {
$jKey = $paramKeys[$j];
if ($jKey !== $key && !is_int($jKey)) {
break;
}
$args[] = $actionParams[$key][] = $params[$jKey];
unset($params[$jKey]);
}
} else {
$isArray = $param->isArray();
}
if ($isArray) {
$params[$key] = $params[$key] === '' ? [] : preg_split('/\s*,\s*/', $params[$key]);
if (PHP_VERSION_ID >= 80000) {
$isArray = ($type = $param->getType()) instanceof \ReflectionNamedType && $type->getName() === 'array';
} else {
$isArray = $param->isArray();
}
if ($isArray) {
$params[$key] = $params[$key] === '' ? [] : preg_split('/\s*,\s*/', $params[$key]);
}
$args[] = $actionParams[$key] = $params[$key];
unset($params[$key]);
}
$args[] = $actionParams[$key] = $params[$key];
unset($params[$key]);
} elseif (
PHP_VERSION_ID >= 70100
&& ($type = $param->getType()) !== null
Expand Down
6 changes: 6 additions & 0 deletions tests/framework/console/ControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ public function testBindActionParams()
$this->assertEquals('from params', $fromParam);
$this->assertEquals('notdefault', $other);

$params = ['a', 'b', 'c1', 'c2', 'c3'];
[$a, $b, $c] = $controller->run('variadic', $params);
$this->assertEquals('a', $a);
$this->assertEquals('b', $b);
$this->assertEquals(['c1', 'c2', 'c3'], $c);

$params = ['avaliable'];
$message = Yii::t('yii', 'Missing required arguments: {params}', ['params' => implode(', ', ['missing'])]);
$this->expectException('yii\console\Exception');
Expand Down
5 changes: 5 additions & 0 deletions tests/framework/console/FakeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,9 @@ public function actionResponse($status = 0)
$response->exitStatus = (int) $status;
return $response;
}

public function actionVariadic($foo, $bar, ...$baz)
{
return [$foo, $bar, $baz];
}
}

0 comments on commit 5abe83e

Please sign in to comment.