Skip to content

Commit 57baeeb

Browse files
Add @DependencyInjection annotation
1 parent 4f6a3b9 commit 57baeeb

File tree

4 files changed

+102
-10
lines changed

4 files changed

+102
-10
lines changed

README.MD

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,4 +199,47 @@ class AnotherChild extends MyParent {}
199199
*/
200200
class SomeChild extends MyParent {}
201201

202+
```
203+
204+
205+
#### Example 5: DependencyInjection via Annotation
206+
207+
In case you want to inject something from your container into the constructor (e.g. tagged_iterator) which is not handled by autowiring
208+
you can use the `@DependencyInjection` annotation.
209+
210+
```php
211+
<?php
212+
213+
namespace App;
214+
215+
use SimonMarx\Symfony\Bundles\ServiceAnnotations\Annotation\DependencyInjection;
216+
217+
class SomeClass {
218+
/**
219+
* The annotation also works for public properties injection
220+
*
221+
* @DependencyInjection(serviceId="my_service")
222+
*/
223+
public SomeInterface $service;
224+
225+
/**
226+
* if you have more than one argument in constructor use "target" to identify which argument should get the injection
227+
*
228+
* @DependencyInjection(target="handlers", tagged="your_tag_id")
229+
* @DependencyInjection(target="anotherService", serviceId="some_service")
230+
*/
231+
public function __construct(SomeAutowiredService $service, iterable $handlers, SomeService $anotherService) {
232+
233+
}
234+
235+
/**
236+
* if you have only one argument in your constructor there is no need for the "target" option
237+
*
238+
* @DependencyInjection(tagged="your_tag_id")
239+
*/
240+
public function __construct(iterable $handlers) {
241+
242+
}
243+
}
244+
202245
```

SimaServiceAnnotationsBundle.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
namespace SimonMarx\Symfony\Bundles\ServiceAnnotations;
55

66

7+
use SimonMarx\Symfony\Bundles\ServiceAnnotations\DependencyInjection\Compiler\DependencyInjectionPass;
78
use SimonMarx\Symfony\Bundles\ServiceAnnotations\DependencyInjection\Compiler\NoServicePass;
89
use SimonMarx\Symfony\Bundles\ServiceAnnotations\DependencyInjection\Compiler\ServiceAliasPass;
910
use SimonMarx\Symfony\Bundles\ServiceAnnotations\DependencyInjection\Compiler\ServiceTagArgumentPass;
@@ -22,6 +23,6 @@ public function build(ContainerBuilder $container)
2223
->addCompilerPass(new ServiceAliasPass())
2324
->addCompilerPass(new ServiceTagArgumentPass())
2425
->addCompilerPass(new NoServicePass())
25-
;
26+
->addCompilerPass(new DependencyInjectionPass());
2627
}
2728
}

Utils/CompilerPassServiceAnnotationTrait.php

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Doctrine\Common\Annotations\AnnotationReader;
1212
use ReflectionClass;
1313
use SimonMarx\Symfony\Bundles\ServiceAnnotations\Annotation\IgnoreParentServiceAnnotations;
14+
use SimonMarx\Symfony\Bundles\ServiceAnnotations\Struct\ClassAnnotationScan;
1415
use Symfony\Component\DependencyInjection\Definition;
1516

1617
trait CompilerPassServiceAnnotationTrait
@@ -21,9 +22,12 @@ trait CompilerPassServiceAnnotationTrait
2122

2223
private array $annotationCache = [];
2324

25+
private array $fullScanCache = [];
26+
2427
public function __construct()
2528
{
2629
$this->annotationReader = new AnnotationReader();
30+
AnnotationReader::addGlobalIgnoredName('required');
2731
}
2832

2933
private function definitionHasValidClass(Definition $definition): bool
@@ -64,10 +68,10 @@ private function warmupDefinitionAnnotationCache(Definition $definition): void
6468
return;
6569
}
6670

67-
$this->annotationCache[$cacheKey] = $this->crawlAnnotationsRecursive($rc);
71+
$this->annotationCache[$cacheKey] = $this->crawlClassAnnotationsRecursive($rc);
6872
}
6973

70-
private function crawlAnnotationsRecursive(ReflectionClass $reflectionClass): array
74+
private function crawlClassAnnotationsRecursive(ReflectionClass $reflectionClass): array
7175
{
7276
$annotations = $this->annotationReader->getClassAnnotations($reflectionClass);
7377
$ignored = $this->annotationReader->getClassAnnotation($reflectionClass, IgnoreParentServiceAnnotations::class);
@@ -79,7 +83,7 @@ private function crawlAnnotationsRecursive(ReflectionClass $reflectionClass): ar
7983
|| $reflectionClass->getParentClass()->isInterface()
8084
)
8185
) {
82-
$parentAnnotations = $this->crawlAnnotationsRecursive($reflectionClass->getParentClass());
86+
$parentAnnotations = $this->crawlClassAnnotationsRecursive($reflectionClass->getParentClass());
8387

8488
if ($ignored instanceof IgnoreParentServiceAnnotations) {
8589
foreach ($parentAnnotations as $parentAnnotation) {
@@ -93,7 +97,7 @@ private function crawlAnnotationsRecursive(ReflectionClass $reflectionClass): ar
9397
}
9498

9599
foreach ($reflectionClass->getInterfaces() as $interface) {
96-
$interfaceAnnotations = $this->crawlAnnotationsRecursive($interface);
100+
$interfaceAnnotations = $this->crawlClassAnnotationsRecursive($interface);
97101

98102
if ($ignored instanceof IgnoreParentServiceAnnotations) {
99103
foreach ($interfaceAnnotations as $interfaceAnnotation) {
@@ -135,4 +139,15 @@ private function getDefinitionAnnotations(Definition $definition): array
135139

136140
return $this->annotationCache[$cacheKey] ?? [];
137141
}
142+
143+
private function fullAnnotationScan(Definition $definition): ClassAnnotationScan
144+
{
145+
$cacheKey = $this->getDefinitionCacheKey($definition);
146+
147+
if (false === \array_key_exists($cacheKey, $this->fullScanCache)) {
148+
$this->fullScanCache[$cacheKey] = new ClassAnnotationScan($definition->getClass());
149+
}
150+
151+
return $this->fullScanCache[$cacheKey];
152+
}
138153
}

Utils/ReflectionCacheTrait.php

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,58 @@
44
namespace SimonMarx\Symfony\Bundles\ServiceAnnotations\Utils;
55

66

7+
use App\Command\PermissionPersistCommand;
78
use ReflectionClass;
89
use ReflectionException;
10+
use ReflectionMethod;
11+
use ReflectionProperty;
912

1013
trait ReflectionCacheTrait
1114
{
12-
private array $classCache = [];
15+
private array $classReflectionCache = [];
1316

1417
private function getClassReflection(string $className): ?ReflectionClass
1518
{
16-
$hashKey = md5($className);
19+
$cacheKey = \md5($className);
1720

18-
if (false === \array_key_exists($hashKey, $this->classCache)) {
21+
if (false === \array_key_exists($cacheKey, $this->classReflectionCache)) {
1922
try {
20-
$this->classCache[$hashKey] = new ReflectionClass($className);
23+
$this->classReflectionCache[$cacheKey] = new ReflectionClass($className);
2124
} catch (ReflectionException $reflectionException) {
2225
return null;
2326
}
2427
}
2528

26-
return $this->classCache[$hashKey] ?? null;
29+
return $this->classReflectionCache[$cacheKey] ?? null;
30+
}
31+
32+
public function getMethodReflection(string $className, string $methodName): ?ReflectionMethod
33+
{
34+
$rc = $this->getClassReflection($className);
35+
36+
if (null === $rc) {
37+
return null;
38+
}
39+
40+
try {
41+
return $rc->getMethod($methodName);
42+
} catch (ReflectionException $exception) {
43+
return null;
44+
}
45+
}
46+
47+
public function getPropertyReflection(string $className, string $propertyName): ?ReflectionProperty
48+
{
49+
$rc = $this->getClassReflection($className);
50+
51+
if (null === $rc) {
52+
return null;
53+
}
54+
55+
try {
56+
return $rc->getProperty($propertyName);
57+
} catch (ReflectionException $exception) {
58+
return null;
59+
}
2760
}
2861
}

0 commit comments

Comments
 (0)