diff --git a/framework/web/Controller.php b/framework/web/Controller.php index 73efa839e5..6833c12078 100644 --- a/framework/web/Controller.php +++ b/framework/web/Controller.php @@ -73,6 +73,12 @@ class Controller extends \yii\base\Controller $name = $param->getName(); if (($class = $param->getClass()) !== null) { $className = $class->getName(); + } + // We only enter the class injection code path if: + // - A class is hinted in the method signature + // - And the param name of hinted class does not exist in existing $params, or the value in existing $params is not an instance of the hinted class + // The latter two checks allow us to manually inject classes via $params while ignoring wrongly injected values (no instances of hinted class). + if ($class !== null && (!array_key_exists($name, $params) || !$params[$name] instanceof $className)) { if (Yii::$app->has($name) && ($obj = Yii::$app->get($name)) instanceof $className) { $args[] = $actionParams[$name] = $obj; } else { diff --git a/tests/framework/web/ControllerTest.php b/tests/framework/web/ControllerTest.php index 20930b025a..d0fe43a248 100644 --- a/tests/framework/web/ControllerTest.php +++ b/tests/framework/web/ControllerTest.php @@ -77,5 +77,18 @@ class ControllerTest extends TestCase $result = $controller->runAction('aksi6', $params); $this->assertEquals(['d426', false, true], $result); + + // Manually inject an instance of \StdClass + // In this case we don't want a newly created instance, but use the existing one + $stdClass = new \StdClass; + $stdClass->test = 'dummy'; + $result = $controller->runAction('aksi7', array_merge($params, ['validator' => $stdClass])); + $this->assertEquals(['d426', 'dummy'], $result); + + // Manually inject a string instead of an instance of \StdClass + // Since this is wrong usage, we expect a new instance of the type hinted \StdClass anyway + $stdClass = 'string'; + $result = $controller->runAction('aksi8', array_merge($params, ['validator' => $stdClass])); + $this->assertEquals(['d426', 'object'], $result); } } diff --git a/tests/framework/web/FakeController.php b/tests/framework/web/FakeController.php index 83da66904d..8a353d9380 100644 --- a/tests/framework/web/FakeController.php +++ b/tests/framework/web/FakeController.php @@ -46,4 +46,14 @@ class FakeController extends Controller { return [$q, $validator->validate($q), $validator->validate('misbahuldmunir@gmail.com')]; } + + public function actionAksi7($q, \StdClass $validator) + { + return [$q, $validator->test]; + } + + public function actionAksi8($q, \StdClass $validator) + { + return [$q, gettype($validator)]; + } }