diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 051b6e5..d16d1e4 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -12,6 +12,7 @@ Yii Framework 2 Change Log - Bug #19187: Fix `yii\filters\PageCache` to store original headers names instead of normalized ones (bizley) - Bug #19191: Change `\Exception` to `\Throwable` in `BadRequestHttpException` and `HttpException` (Dmitrijlin) - Bug #19204: Support numbers in Inflector::camel2words (longthanhtran) +- Bug #19004: Container::resolveCallableDependencies() unable to handle union and intersection types (sartor) - Bug #19047: Fix deprecated preg_match() passing null parameters #2 in db\mysql\Schema.php (longthanhtran) diff --git a/framework/di/Container.php b/framework/di/Container.php index 5d36b69..f0a70f0 100644 --- a/framework/di/Container.php +++ b/framework/di/Container.php @@ -665,7 +665,19 @@ class Container extends Component if (PHP_VERSION_ID >= 80000) { $class = $param->getType(); - $isClass = $class !== null && !$param->getType()->isBuiltin(); + if ($class instanceof \ReflectionUnionType || (PHP_VERSION_ID >= 80100 && $class instanceof \ReflectionIntersectionType)) { + $isClass = false; + foreach ($class->getTypes() as $type) { + if (!$type->isBuiltin()) { + $class = $type; + $isClass = true; + break; + } + } + } else { + $isClass = $class !== null && !$class->isBuiltin(); + } + } else { $class = $param->getClass(); $isClass = $class !== null; diff --git a/tests/framework/di/ContainerTest.php b/tests/framework/di/ContainerTest.php index 71c8e2f..f854fc6 100644 --- a/tests/framework/di/ContainerTest.php +++ b/tests/framework/di/ContainerTest.php @@ -24,6 +24,7 @@ use yiiunit\framework\di\stubs\Foo; use yiiunit\framework\di\stubs\FooProperty; use yiiunit\framework\di\stubs\Kappa; use yiiunit\framework\di\stubs\Qux; +use yiiunit\framework\di\stubs\QuxAnother; use yiiunit\framework\di\stubs\QuxInterface; use yiiunit\framework\di\stubs\QuxFactory; use yiiunit\framework\di\stubs\UnionTypeNotNull; @@ -673,4 +674,56 @@ class ContainerTest extends TestCase $this->expectException('TypeError'); (new Container())->get(UnionTypeNotNull::className()); } + + public function testResolveCallableDependenciesUnionTypes() + { + if (PHP_VERSION_ID < 80000) { + $this->markTestSkipped('Can not be tested on PHP < 8.0'); + return; + } + + $this->mockApplication([ + 'components' => [ + Beta::className(), + ], + ]); + + Yii::$container->set('yiiunit\framework\di\stubs\QuxInterface', [ + 'class' => Qux::className(), + ]); + + $className = 'yiiunit\framework\di\stubs\StaticMethodsWithUnionTypes'; + + $params = Yii::$container->resolveCallableDependencies([$className, 'withBetaUnion']); + $this->assertInstanceOf(Beta::classname(), $params[0]); + + $params = Yii::$container->resolveCallableDependencies([$className, 'withBetaUnionInverse']); + $this->assertInstanceOf(Beta::classname(), $params[0]); + + $params = Yii::$container->resolveCallableDependencies([$className, 'withBetaAndQuxUnion']); + $this->assertInstanceOf(Beta::classname(), $params[0]); + + $params = Yii::$container->resolveCallableDependencies([$className, 'withQuxAndBetaUnion']); + $this->assertInstanceOf(Qux::classname(), $params[0]); + } + + public function testResolveCallableDependenciesIntersectionTypes() + { + if (PHP_VERSION_ID < 80100) { + $this->markTestSkipped('Can not be tested on PHP < 8.1'); + return; + } + + Yii::$container->set('yiiunit\framework\di\stubs\QuxInterface', [ + 'class' => Qux::className(), + ]); + + $className = 'yiiunit\framework\di\stubs\StaticMethodsWithIntersectionTypes'; + + $params = Yii::$container->resolveCallableDependencies([$className, 'withQuxInterfaceAndQuxAnotherIntersection']); + $this->assertInstanceOf(Qux::classname(), $params[0]); + + $params = Yii::$container->resolveCallableDependencies([$className, 'withQuxAnotherAndQuxInterfaceIntersection']); + $this->assertInstanceOf(QuxAnother::classname(), $params[0]); + } } diff --git a/tests/framework/di/stubs/QuxAnother.php b/tests/framework/di/stubs/QuxAnother.php new file mode 100644 index 0000000..65ca672 --- /dev/null +++ b/tests/framework/di/stubs/QuxAnother.php @@ -0,0 +1,17 @@ +