Skip to content

Commit ab0eecd

Browse files
authored
feat(container): support injecting properties using #[Inject] (#690)
1 parent 6a56d94 commit ab0eecd

File tree

9 files changed

+70
-5
lines changed

9 files changed

+70
-5
lines changed

phpstan.neon.dist

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ parameters:
2323
-
2424
message: '#.*exec*#'
2525
path: src/Tempest/Console/src/Terminal/Terminal.php
26+
-
27+
message: '#.*uninitialized readonly property \$console*#'
2628

2729
disallowedFunctionCalls:
2830
-

src/Tempest/Cache/src/CacheClearCommand.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
namespace Tempest\Cache;
66

7-
use Tempest\Console\Console;
87
use Tempest\Console\ConsoleCommand;
98
use Tempest\Console\HasConsole;
109
use Tempest\Container\Container;
@@ -14,7 +13,6 @@
1413
use HasConsole;
1514

1615
public function __construct(
17-
private Console $console,
1816
private CacheConfig $cacheConfig,
1917
private Container $container,
2018
) {

src/Tempest/Console/src/HasConsole.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
namespace Tempest\Console;
66

77
use Closure;
8+
use Tempest\Container\Inject;
89

910
trait HasConsole
1011
{
11-
public function __construct(private readonly Console $console)
12-
{
13-
}
12+
#[Inject]
13+
private readonly Console $console;
1414

1515
public function readln(): string
1616
{

src/Tempest/Container/src/GenericContainer.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,12 @@ private function autowire(string $className, mixed ...$params): object
334334
$this->singleton($className, $instance);
335335
}
336336

337+
foreach ($classReflector->getProperties() as $property) {
338+
if ($property->hasAttribute(Inject::class) && ! $property->isInitialized($instance)) {
339+
$property->set($instance, $this->get($property->getType()->getName()));
340+
}
341+
}
342+
337343
return $instance;
338344
}
339345

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tempest\Container;
6+
7+
use Attribute;
8+
9+
#[Attribute(Attribute::TARGET_PROPERTY)]
10+
final readonly class Inject
11+
{
12+
}

src/Tempest/Container/tests/ContainerTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
use Tempest\Container\Tests\Fixtures\ContainerObjectEInitializer;
3030
use Tempest\Container\Tests\Fixtures\DependencyWithBuiltinDependencies;
3131
use Tempest\Container\Tests\Fixtures\DependencyWithTaggedDependency;
32+
use Tempest\Container\Tests\Fixtures\InjectA;
33+
use Tempest\Container\Tests\Fixtures\InjectB;
3234
use Tempest\Container\Tests\Fixtures\IntersectionInitializer;
3335
use Tempest\Container\Tests\Fixtures\InvokableClass;
3436
use Tempest\Container\Tests\Fixtures\InvokableClassWithParameters;
@@ -379,4 +381,14 @@ public function test_builtin_dependency_initializer(): void
379381
$this->assertSame(["hallo", "array", 42], $a->arrayValue);
380382
$this->assertTrue($a->boolValue);
381383
}
384+
385+
public function test_inject(): void
386+
{
387+
$container = new GenericContainer();
388+
389+
/** @var InjectA $a */
390+
$a = $container->get(InjectA::class);
391+
392+
$this->assertInstanceOf(InjectB::class, $a->getB());
393+
}
382394
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tempest\Container\Tests\Fixtures;
6+
7+
use Tempest\Container\Inject;
8+
9+
final readonly class InjectA
10+
{
11+
#[Inject]
12+
private InjectB $b; // @phpstan-ignore-line
13+
14+
public function getB(): InjectB
15+
{
16+
return $this->b;
17+
}
18+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tempest\Container\Tests\Fixtures;
6+
7+
final readonly class InjectB
8+
{
9+
}

src/Tempest/Reflection/src/ClassReflector.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,14 @@ public function getPublicProperties(): Generator
4646
}
4747
}
4848

49+
/** @return Generator<PropertyReflector> */
50+
public function getProperties(): Generator
51+
{
52+
foreach ($this->reflectionClass->getProperties() as $property) {
53+
yield new PropertyReflector($property);
54+
}
55+
}
56+
4957
/** @return Generator<MethodReflector> */
5058
public function getPublicMethods(): Generator
5159
{

0 commit comments

Comments
 (0)