Skip to content

Commit fc1a8dd

Browse files
authored
Fixed @Inject does not works in nested trait. (#3520)
1 parent 5614690 commit fc1a8dd

File tree

6 files changed

+122
-11
lines changed

6 files changed

+122
-11
lines changed

src/Aop/PropertyHandlerTrait.php

+21-11
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,7 @@ protected function __handlePropertyHandler(string $className)
3030

3131
// Inject the properties of traits.
3232
// Because the property annotations of trait couldn't be collected by class.
33-
$traitNames = $reflectionClass->getTraitNames();
34-
if (is_array($traitNames)) {
35-
foreach ($traitNames ?? [] as $traitName) {
36-
$traitProperties = ReflectionManager::reflectPropertyNames($traitName);
37-
$traitProperties = array_diff($traitProperties, $handled);
38-
$handled = array_merge(
39-
$handled,
40-
$this->__handle($className, $traitName, $traitProperties)
41-
);
42-
}
43-
}
33+
$handled = $this->__handleTrait($reflectionClass, $handled, $className);
4434

4535
// Inject the properties of parent class.
4636
// It can be used to deal with parent classes whose subclasses have constructor function, but don't execute `parent::__construct()`.
@@ -64,6 +54,26 @@ protected function __handlePropertyHandler(string $className)
6454
}
6555
}
6656

57+
protected function __handleTrait(\ReflectionClass $reflectionClass, array $handled, string $className): array
58+
{
59+
foreach ($reflectionClass->getTraits() ?? [] as $reflectionTrait) {
60+
if (in_array($reflectionTrait->getName(), [ProxyTrait::class, PropertyHandlerTrait::class])) {
61+
continue;
62+
}
63+
$traitProperties = ReflectionManager::reflectPropertyNames($reflectionTrait->getName());
64+
$traitProperties = array_diff($traitProperties, $handled);
65+
if (! $traitProperties) {
66+
continue;
67+
}
68+
$handled = array_merge(
69+
$handled,
70+
$this->__handle($className, $reflectionTrait->getName(), $traitProperties)
71+
);
72+
$handled = $this->__handleTrait($reflectionTrait, $handled, $className);
73+
}
74+
return $handled;
75+
}
76+
6777
protected function __handle(string $currentClassName, string $targetClassName, array $properties): array
6878
{
6979
$handled = [];

tests/InjectTest.php

+31
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,14 @@
3131
use HyperfTest\Di\Stub\Inject\Bar;
3232
use HyperfTest\Di\Stub\Inject\Foo;
3333
use HyperfTest\Di\Stub\Inject\Foo2Trait;
34+
use HyperfTest\Di\Stub\Inject\Foo3Trait;
3435
use HyperfTest\Di\Stub\Inject\FooTrait;
3536
use HyperfTest\Di\Stub\Inject\Origin2Class;
3637
use HyperfTest\Di\Stub\Inject\Origin3Class;
3738
use HyperfTest\Di\Stub\Inject\Origin4Class;
3839
use HyperfTest\Di\Stub\Inject\Origin5Class;
3940
use HyperfTest\Di\Stub\Inject\Origin6Class;
41+
use HyperfTest\Di\Stub\Inject\Origin7Class;
4042
use HyperfTest\Di\Stub\Inject\OriginClass;
4143
use HyperfTest\Di\Stub\Inject\Parent2Class;
4244
use HyperfTest\Di\Stub\Inject\Parent3Class;
@@ -176,6 +178,33 @@ public function testInject2Trait()
176178
$this->assertInstanceOf(Tar::class, $origin->getFoo());
177179
}
178180

181+
public function testInjectTraitNesting()
182+
{
183+
$this->getContainer();
184+
$classes = [
185+
FooTrait::class,
186+
Foo3Trait::class,
187+
Origin7Class::class,
188+
];
189+
190+
if (! is_dir($dir = BASE_PATH . '/runtime/container/proxy/')) {
191+
mkdir($dir, 0777, true);
192+
}
193+
194+
$ast = new Ast();
195+
foreach ($classes as $class) {
196+
$code = $ast->proxy($class);
197+
$id = md5($class);
198+
file_put_contents($file = $dir . $id . '.proxy.php', $code);
199+
require_once $file;
200+
}
201+
202+
$origin = new Origin7Class();
203+
$this->assertInstanceOf(Bar::class, $origin->getFoo());
204+
$this->assertInstanceOf(Bar::class, $origin->getBar());
205+
$this->assertSame('foo3', $origin->getValue());
206+
}
207+
179208
public function testInjectParentParent()
180209
{
181210
$this->getContainer();
@@ -306,12 +335,14 @@ protected function getContainer()
306335
Origin2Class::class,
307336
Origin3Class::class,
308337
Foo2Trait::class,
338+
Foo3Trait::class,
309339
Origin4Class::class,
310340
Origin5Class::class,
311341
Parent2Class::class,
312342
Parent3Class::class,
313343
Parent4Class::class,
314344
Origin6Class::class,
345+
Origin7Class::class,
315346
];
316347

317348
foreach ($classes as $class) {

tests/ReflectionTest.php

+8
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Hyperf\Di\ReflectionManager;
1515
use HyperfTest\Di\Stub\Ast\Bar;
16+
use HyperfTest\Di\Stub\Inject\Foo3Trait;
1617
use PHPUnit\Framework\TestCase;
1718

1819
/**
@@ -43,4 +44,11 @@ public function testReturnType()
4344
$this->assertTrue($parameter->getType() instanceof \ReflectionNamedType);
4445
}
4546
}
47+
48+
public function testReflectionPropertyForTraitUseTrait()
49+
{
50+
$res = ReflectionManager::reflectPropertyNames(Foo3Trait::class);
51+
52+
$this->assertSame(['bar', 'foo'], $res);
53+
}
4654
}

tests/Stub/Inject/Foo3Trait.php

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
/**
5+
* This file is part of Hyperf.
6+
*
7+
* @link https://www.hyperf.io
8+
* @document https://hyperf.wiki
9+
* @contact [email protected]
10+
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
11+
*/
12+
namespace HyperfTest\Di\Stub\Inject;
13+
14+
use Hyperf\Di\Annotation\Inject;
15+
16+
trait Foo3Trait
17+
{
18+
use FooTrait;
19+
20+
/**
21+
* @Inject
22+
* @var Bar
23+
*/
24+
protected $bar;
25+
26+
public function getValue()
27+
{
28+
return 'foo3';
29+
}
30+
}

tests/Stub/Inject/FooTrait.php

+5
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,9 @@ trait FooTrait
2020
* @var Bar
2121
*/
2222
protected $foo;
23+
24+
public function getValue()
25+
{
26+
return 'foo';
27+
}
2328
}

tests/Stub/Inject/Origin7Class.php

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
/**
5+
* This file is part of Hyperf.
6+
*
7+
* @link https://www.hyperf.io
8+
* @document https://hyperf.wiki
9+
* @contact [email protected]
10+
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
11+
*/
12+
namespace HyperfTest\Di\Stub\Inject;
13+
14+
class Origin7Class
15+
{
16+
use Foo3Trait;
17+
18+
public function getFoo()
19+
{
20+
return $this->foo;
21+
}
22+
23+
public function getBar()
24+
{
25+
return $this->bar;
26+
}
27+
}

0 commit comments

Comments
 (0)