Skip to content

Commit

Permalink
fix controller action invocation with wrong set of arguments results …
Browse files Browse the repository at this point in the history
…in 500 error instead of 400
  • Loading branch information
klimov-paul committed Aug 30, 2023
1 parent f1e4c9f commit bb40142
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 26 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/console/ResolvesActionViaDI.php
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand Down
12 changes: 1 addition & 11 deletions src/web/Action.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

namespace yii1tech\di\web;

use yii1tech\di\DI;

/**
* {@inheritdoc}
*
Expand All @@ -12,13 +10,5 @@
*/
class Action extends \CAction
{
/**
* {@inheritdoc}
*/
public function runWithParams($params)
{
DI::invoke([$this, 'run'], $params);

return true;
}
use RunsActionWithParamsViaDI;
}
16 changes: 2 additions & 14 deletions src/web/InlineAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

namespace yii1tech\di\web;

use yii1tech\di\DI;

/**
* {@inheritdoc}
*
Expand All @@ -12,23 +10,13 @@
*/
class InlineAction extends \CInlineAction
{
use RunsActionWithParamsViaDI;

/**
* {@inheritdoc}
*/
public function run()
{
$this->runWithParams([]);
}

/**
* {@inheritdoc}
*/
public function runWithParams($params)
{
$method = 'action' . $this->getId();

DI::invoke([$this->getController(), $method], $params);

return true;
}
}
59 changes: 59 additions & 0 deletions src/web/RunsActionWithParamsViaDI.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

namespace yii1tech\di\web;

use yii1tech\di\DI;

/**
* RunsActionWithParamsViaDI allows dependency injection at the action method level.
*
* @mixin \CAction
*
* @author Paul Klimov <[email protected]>
* @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;
}
}
31 changes: 31 additions & 0 deletions tests/web/WebApplicationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use CDummyCache;
use CFormatter;
use CHttpException;
use ICache;
use Yii;
use yii1tech\di\Container;
Expand Down Expand Up @@ -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
*/
Expand All @@ -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);
}
}

0 comments on commit bb40142

Please sign in to comment.