diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 259b51aa5c..33ea61eed5 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -9,7 +9,7 @@ Yii Framework 2 Change Log - Bug #18026: Fix `ArrayHelper::getValue()` did not work with `ArrayAccess` objects (mikk150) - Enh #18048: Use `Instance::ensure()` to set `User::$accessChecker` (lav45) - Bug #18051: Fix missing support for custom validation method in EachValidator (bizley) -- Enh #17722: Add action injection support (SamMousa, samdark) +- Enh #17722: Add action injection support (SamMousa, samdark, erickskrauch) - Bug #18041: Fix RBAC migration for MSSQL (darkdef) - Bug #18081: Fix for PDO_DBLIB/MSSQL. Set flag ANSI_NULL_DFLT_ON to ON for current connect to DB (darkdef) - Bug #13828: Fix retrieving inserted data for a primary key of type uniqueidentifier for SQL Server 2005 or later (darkdef) diff --git a/framework/base/Controller.php b/framework/base/Controller.php index 0b5fbffef2..b98135c10c 100644 --- a/framework/base/Controller.php +++ b/framework/base/Controller.php @@ -565,9 +565,12 @@ class Controller extends Component implements ViewContextInterface if (($component = $this->module->get($name, false)) instanceof $typeName) { $args[] = $component; $requestedParams[$name] = "Component: " . get_class($component) . " \$$name"; + } elseif ($this->module->has($typeName) && ($service = $this->module->get($typeName)) instanceof $typeName) { + $args[] = $service; + $requestedParams[$name] = 'Module ' . get_class($this->module) . " DI: $typeName \$$name"; } elseif (\Yii::$container->has($typeName) && ($service = \Yii::$container->get($typeName)) instanceof $typeName) { $args[] = $service; - $requestedParams[$name] = "DI: $typeName \$$name"; + $requestedParams[$name] = "Container DI: $typeName \$$name"; } elseif ($type->allowsNull()) { $args[] = null; $requestedParams[$name] = "Unavailable service: $name"; diff --git a/tests/framework/console/ControllerTest.php b/tests/framework/console/ControllerTest.php index 0109279018..cbe1b75ef9 100644 --- a/tests/framework/console/ControllerTest.php +++ b/tests/framework/console/ControllerTest.php @@ -170,12 +170,35 @@ class ControllerTest extends TestCase $this->assertEquals('Component: yii\console\Request $request', \Yii::$app->requestedParams['request']); $this->assertEquals($params['between'], $args[2]); $this->assertInstanceOf(DummyService::className(), $args[3]); - $this->assertEquals('DI: yiiunit\framework\console\stubs\DummyService $dummyService', \Yii::$app->requestedParams['dummyService']); + $this->assertEquals('Container DI: yiiunit\framework\console\stubs\DummyService $dummyService', \Yii::$app->requestedParams['dummyService']); $this->assertNull($args[4]); $this->assertEquals('Unavailable service: post', \Yii::$app->requestedParams['post']); $this->assertEquals($params['after'], $args[5]); } + public function testInjectedActionParamsFromModule() + { + if (PHP_VERSION_ID < 70100) { + $this->markTestSkipped('Can not be tested on PHP < 7.1'); + return; + } + $module = new \yii\base\Module('fake', new Application([ + 'id' => 'app', + 'basePath' => __DIR__, + ])); + $module->set('yii\data\DataProviderInterface', [ + 'class' => \yii\data\ArrayDataProvider::className(), + ]); + // Use the PHP71 controller for this test + $this->controller = new FakePhp71Controller('fake', $module); + $this->mockWebApplication(['controller' => $this->controller]); + + $injectionAction = new InlineAction('injection', $this->controller, 'actionModuleServiceInjection'); + $args = $this->controller->bindActionParams($injectionAction, []); + $this->assertInstanceOf(\yii\data\ArrayDataProvider::className(), $args[0]); + $this->assertEquals('Module yii\base\Module DI: yii\data\DataProviderInterface $dataProvider', \Yii::$app->requestedParams['dataProvider']); + } + public function assertResponseStatus($status, $response) { $this->assertInstanceOf('yii\console\Response', $response); diff --git a/tests/framework/console/FakePhp71Controller.php b/tests/framework/console/FakePhp71Controller.php index 9b5ff601f7..985940d6bb 100644 --- a/tests/framework/console/FakePhp71Controller.php +++ b/tests/framework/console/FakePhp71Controller.php @@ -7,6 +7,7 @@ namespace yiiunit\framework\console; +use yii\data\DataProviderInterface; use yiiunit\framework\console\stubs\DummyService; use yii\console\Controller; use yii\console\Request; @@ -21,4 +22,8 @@ class FakePhp71Controller extends Controller public function actionNullableInjection(?Request $request, ?Post $post) { } + + public function actionModuleServiceInjection(DataProviderInterface $dataProvider) + { + } } diff --git a/tests/framework/web/ControllerTest.php b/tests/framework/web/ControllerTest.php index fd2048cc1a..1ddc9037fa 100644 --- a/tests/framework/web/ControllerTest.php +++ b/tests/framework/web/ControllerTest.php @@ -155,11 +155,43 @@ class ControllerTest extends TestCase $this->assertEquals('Component: yii\web\Request $request', \Yii::$app->requestedParams['request']); $this->assertEquals($params['between'], $args[2]); $this->assertInstanceOf(VendorImage::className(), $args[3]); - $this->assertEquals('DI: yiiunit\framework\web\stubs\VendorImage $vendorImage', \Yii::$app->requestedParams['vendorImage']); + $this->assertEquals('Container DI: yiiunit\framework\web\stubs\VendorImage $vendorImage', \Yii::$app->requestedParams['vendorImage']); $this->assertNull($args[4]); $this->assertEquals('Unavailable service: post', \Yii::$app->requestedParams['post']); $this->assertEquals($params['after'], $args[5]); } + + public function testInjectedActionParamsFromModule() + { + if (PHP_VERSION_ID < 70100) { + $this->markTestSkipped('Can not be tested on PHP < 7.1'); + return; + } + $module = new \yii\base\Module('fake', new \yii\web\Application([ + 'id' => 'app', + 'basePath' => __DIR__, + + 'components' => [ + 'request' => [ + 'cookieValidationKey' => 'wefJDF8sfdsfSDefwqdxj9oq', + 'scriptFile' => __DIR__ . '/index.php', + 'scriptUrl' => '/index.php', + ], + ], + ])); + $module->set('yii\data\DataProviderInterface', [ + 'class' => \yii\data\ArrayDataProvider::className(), + ]); + // Use the PHP71 controller for this test + $this->controller = new FakePhp71Controller('fake', $module); + $this->mockWebApplication(['controller' => $this->controller]); + + $injectionAction = new InlineAction('injection', $this->controller, 'actionModuleServiceInjection'); + $args = $this->controller->bindActionParams($injectionAction, []); + $this->assertInstanceOf(\yii\data\ArrayDataProvider::className(), $args[0]); + $this->assertEquals('Module yii\base\Module DI: yii\data\DataProviderInterface $dataProvider', \Yii::$app->requestedParams['dataProvider']); + } + /** * @see https://github.com/yiisoft/yii2/issues/17701 */ diff --git a/tests/framework/web/FakePhp71Controller.php b/tests/framework/web/FakePhp71Controller.php index 9c67256f52..9c8a44b12b 100644 --- a/tests/framework/web/FakePhp71Controller.php +++ b/tests/framework/web/FakePhp71Controller.php @@ -7,6 +7,7 @@ namespace yiiunit\framework\web; +use yii\data\DataProviderInterface; use yii\web\Controller; use yii\web\Request; use yiiunit\framework\web\stubs\VendorImage; @@ -27,4 +28,8 @@ class FakePhp71Controller extends Controller public function actionNullableInjection(?Request $request, ?Post $post) { } + + public function actionModuleServiceInjection(DataProviderInterface $dataProvider) + { + } }