diff --git a/CHANGELOG.md b/CHANGELOG.md index ab7cb9f..86745eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ Yii1 Dependency Injection extension ----------------------- - Bug: Fixed `DI::create()` unable to handle Yii-style class alias (klimov-paul) +- Bug: Fixed controller action invocation with wrong set of arguments results in 500 error instead of 400 (klimov-paul) 1.0.2, August 16, 2023 diff --git a/src/console/ResolvesActionViaDI.php b/src/console/ResolvesActionViaDI.php index 5e5903d..383eb75 100644 --- a/src/console/ResolvesActionViaDI.php +++ b/src/console/ResolvesActionViaDI.php @@ -42,7 +42,7 @@ public function run($args) $params = []; $arguments = []; // named and unnamed options - foreach ($method->getParameters() as $i => $param) { + foreach ($method->getParameters() as $param) { $name = $param->getName(); if ($param->hasType() && !$param->getType()->isBuiltin()) { diff --git a/src/web/Action.php b/src/web/Action.php index d03d3fb..83584cf 100644 --- a/src/web/Action.php +++ b/src/web/Action.php @@ -2,8 +2,6 @@ namespace yii1tech\di\web; -use yii1tech\di\DI; - /** * {@inheritdoc} * @@ -12,13 +10,5 @@ */ class Action extends \CAction { - /** - * {@inheritdoc} - */ - public function runWithParams($params) - { - DI::invoke([$this, 'run'], $params); - - return true; - } + use RunsActionWithParamsViaDI; } \ No newline at end of file diff --git a/src/web/InlineAction.php b/src/web/InlineAction.php index 91994bd..29ce323 100644 --- a/src/web/InlineAction.php +++ b/src/web/InlineAction.php @@ -2,8 +2,6 @@ namespace yii1tech\di\web; -use yii1tech\di\DI; - /** * {@inheritdoc} * @@ -12,6 +10,8 @@ */ class InlineAction extends \CInlineAction { + use RunsActionWithParamsViaDI; + /** * {@inheritdoc} */ @@ -19,16 +19,4 @@ public function run() { $this->runWithParams([]); } - - /** - * {@inheritdoc} - */ - public function runWithParams($params) - { - $method = 'action' . $this->getId(); - - DI::invoke([$this->getController(), $method], $params); - - return true; - } } \ No newline at end of file diff --git a/src/web/RunsActionWithParamsViaDI.php b/src/web/RunsActionWithParamsViaDI.php new file mode 100644 index 0000000..a6d6d0e --- /dev/null +++ b/src/web/RunsActionWithParamsViaDI.php @@ -0,0 +1,59 @@ + + * @since 1.0.3 + */ +trait RunsActionWithParamsViaDI +{ + /** + * {@inheritdoc} + */ + protected function runWithParamsInternal($object, $method, $params) + { + $arguments = []; + foreach ($method->getParameters() as $param) { + $name = $param->getName(); + + if ($param->hasType() && !$param->getType()->isBuiltin()) { + if (DI::has($param->getType()->getName())) { + $arguments[$name] = DI::get($param->getType()->getName()); + + continue; + } + } + + if (isset($params[$name])) { + if (version_compare(PHP_VERSION, '8.0', '>=')) { + $isArray = $param->getType() && $param->getType()->getName() === 'array'; + } else { + $isArray = $param->isArray(); + } + + if ($isArray) { + $arguments[$name] = is_array($params[$name]) ? $params[$name] : array($params[$name]); + } elseif (!is_array($params[$name])) { + $arguments[$name] = $params[$name]; + } else { + return false; + } + } elseif ($param->isDefaultValueAvailable()) { + $arguments[$name] = $param->getDefaultValue(); + } else { + return false; + } + } + + $method->invokeArgs($object, $arguments); + + return true; + } +} \ No newline at end of file diff --git a/tests/web/WebApplicationTest.php b/tests/web/WebApplicationTest.php index c7b6068..93da52c 100644 --- a/tests/web/WebApplicationTest.php +++ b/tests/web/WebApplicationTest.php @@ -4,6 +4,7 @@ use CDummyCache; use CFormatter; +use CHttpException; use ICache; use Yii; use yii1tech\di\Container; @@ -115,6 +116,21 @@ public function testRunActionWithParams(): void $this->assertEquals($_GET['id'], $GLOBALS['id']); } + /** + * @depends testRunActionWithParams + */ + public function testRunActionWithMissingParams(): void + { + try { + Yii::app()->runController('plain/format'); + } catch (CHttpException $exception) { + // blank + } + + $this->assertTrue(isset($exception)); + $this->assertEquals(400, $exception->statusCode); + } + /** * @depends testCreateController */ @@ -136,4 +152,19 @@ public function testRunExternalAction(): void $this->assertTrue(isset($GLOBALS['id'])); $this->assertEquals($_GET['id'], $GLOBALS['id']); } + + /** + * @depends testRunExternalAction + */ + public function testRunExternalActionWithMissingParams(): void + { + try { + Yii::app()->runController('plain/external'); + } catch (CHttpException $exception) { + // blank + } + + $this->assertTrue(isset($exception)); + $this->assertEquals(400, $exception->statusCode); + } } \ No newline at end of file