Browse Source

Fix #19004: Container::resolveCallableDependencies() unable to handle union and intersection types

Co-authored-by: Sartor <sartor@syneforge.com>
tags/2.0.45
Sartor 3 years ago committed by GitHub
parent
commit
7a2689e761
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      framework/CHANGELOG.md
  2. 14
      framework/di/Container.php
  3. 53
      tests/framework/di/ContainerTest.php
  4. 17
      tests/framework/di/stubs/QuxAnother.php
  5. 15
      tests/framework/di/stubs/StaticMethodsWithIntersectionTypes.php
  6. 23
      tests/framework/di/stubs/StaticMethodsWithUnionTypes.php

1
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)

14
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;

53
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]);
}
}

17
tests/framework/di/stubs/QuxAnother.php

@ -0,0 +1,17 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yiiunit\framework\di\stubs;
use yii\base\BaseObject;
class QuxAnother extends BaseObject implements QuxInterface
{
public function quxMethod()
{
}
}

15
tests/framework/di/stubs/StaticMethodsWithIntersectionTypes.php

@ -0,0 +1,15 @@
<?php
namespace yiiunit\framework\di\stubs;
// Syntax valid only for PHP 8.1+
class StaticMethodsWithIntersectionTypes
{
public static function withQuxInterfaceAndQuxAnotherIntersection(QuxInterface & QuxAnother $Qux)
{
}
public static function withQuxAnotherAndQuxInterfaceIntersection(QuxAnother & QuxInterface $Qux)
{
}
}

23
tests/framework/di/stubs/StaticMethodsWithUnionTypes.php

@ -0,0 +1,23 @@
<?php
namespace yiiunit\framework\di\stubs;
// Syntax valid only for PHP 8.0+
class StaticMethodsWithUnionTypes
{
public static function withBetaUnion(string | Beta $beta)
{
}
public static function withBetaUnionInverse(Beta | string $beta)
{
}
public static function withBetaAndQuxUnion(Beta | QuxInterface $betaOrQux)
{
}
public static function withQuxAndBetaUnion(QuxInterface | Beta $betaOrQux)
{
}
}
Loading…
Cancel
Save