1
|
|
|
<?php |
2
|
|
|
namespace Acelaya\ZsmAnnotatedServices\Factory; |
3
|
|
|
|
4
|
|
|
use Acelaya\ZsmAnnotatedServices\Annotation\Inject; |
5
|
|
|
use Acelaya\ZsmAnnotatedServices\Exception\RuntimeException; |
6
|
|
|
use Doctrine\Common\Annotations\AnnotationReader; |
7
|
|
|
use Doctrine\Common\Annotations\AnnotationRegistry; |
8
|
|
|
use Doctrine\Common\Annotations\CachedReader; |
9
|
|
|
use Doctrine\Common\Cache\Cache; |
10
|
|
|
use Zend\ServiceManager\ServiceLocatorInterface; |
11
|
|
|
|
12
|
|
|
abstract class AbstractAnnotatedFactory |
13
|
|
|
{ |
14
|
|
|
const CACHE_SERVICE = 'Acelaya\ZsmAnnotatedServices\Cache'; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* @var AnnotationReader |
18
|
|
|
*/ |
19
|
|
|
private static $annotationReader; |
20
|
|
|
|
21
|
8 |
|
protected function processDependenciesFromAnnotations(ServiceLocatorInterface $container, $serviceName) |
22
|
|
|
{ |
23
|
8 |
|
if (! class_exists($serviceName)) { |
24
|
1 |
|
throw new RuntimeException(sprintf( |
25
|
|
|
'Annotated factories can only be used with services that are identified by their FQCN. ' . |
26
|
1 |
|
'Provided "%s" service name is not a valid class.', |
27
|
|
|
$serviceName |
28
|
|
|
)); |
29
|
|
|
} |
30
|
|
|
|
31
|
7 |
|
$annotationReader = $this->createAnnotationReader($container); |
32
|
7 |
|
$refClass = new \ReflectionClass($serviceName); |
33
|
7 |
|
$constructor = $refClass->getConstructor(); |
34
|
7 |
|
if (! isset($constructor)) { |
35
|
1 |
|
return new $serviceName(); |
36
|
|
|
} |
37
|
|
|
|
38
|
|
|
/** @var Inject $inject */ |
39
|
6 |
|
$inject = $annotationReader->getMethodAnnotation($constructor, Inject::class); |
40
|
6 |
|
if (! isset($inject)) { |
41
|
1 |
|
throw new RuntimeException(sprintf( |
42
|
|
|
'You need to use the "%s" annotation in your services constructors so that he "%s" factory can ' . |
43
|
1 |
|
'create them.', |
44
|
1 |
|
static::class, |
45
|
1 |
|
Inject::class |
46
|
|
|
)); |
47
|
|
|
} |
48
|
|
|
|
49
|
5 |
|
$services = []; |
50
|
5 |
|
foreach ($inject->getServices() as $serviceKey) { |
51
|
5 |
|
if (! $container->has($serviceKey)) { |
52
|
1 |
|
throw new RuntimeException(sprintf( |
53
|
1 |
|
'Defined injectable service "%s" could not be found in container.', |
54
|
|
|
$serviceKey |
55
|
|
|
)); |
56
|
|
|
} |
57
|
|
|
|
58
|
4 |
|
$services[] = $container->get($serviceKey); |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
// TODO use array unpacking instead of reflection when dropping PHP 5.5 support |
62
|
|
|
// return new $serviceName(...$services); |
|
|
|
|
63
|
4 |
|
return $refClass->newInstanceArgs($services); |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* @param ServiceLocatorInterface $container |
68
|
|
|
* @return AnnotationReader|CachedReader |
69
|
|
|
*/ |
70
|
7 |
|
private function createAnnotationReader(ServiceLocatorInterface $container) |
71
|
|
|
{ |
72
|
7 |
|
if (isset(self::$annotationReader)) { |
73
|
5 |
|
return self::$annotationReader; |
74
|
|
|
} |
75
|
|
|
|
76
|
2 |
|
AnnotationRegistry::registerLoader(function ($class) { |
77
|
2 |
|
$file = str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php'; |
78
|
2 |
|
$file = realpath(__DIR__ . '/../Annotation/' . basename($file)); |
79
|
2 |
|
if (! $file) { |
80
|
2 |
|
return false; |
81
|
|
|
} |
82
|
|
|
|
83
|
1 |
|
require_once $file; |
84
|
1 |
|
return true; |
85
|
2 |
|
}); |
86
|
|
|
|
87
|
2 |
|
if (! $container->has(self::CACHE_SERVICE)) { |
88
|
1 |
|
return self::$annotationReader = new AnnotationReader(); |
89
|
|
|
} else { |
90
|
|
|
/** @var Cache $cache */ |
91
|
1 |
|
$cache = $container->get(self::CACHE_SERVICE); |
92
|
1 |
|
return self::$annotationReader = new CachedReader(new AnnotationReader(), $cache); |
|
|
|
|
93
|
|
|
} |
94
|
|
|
} |
95
|
|
|
} |
96
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.