1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Overblog\GraphQLBundle\DependencyInjection\Compiler; |
4
|
|
|
|
5
|
|
|
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; |
6
|
|
|
use Symfony\Component\DependencyInjection\ContainerAwareInterface; |
7
|
|
|
use Symfony\Component\DependencyInjection\ContainerBuilder; |
8
|
|
|
use Symfony\Component\DependencyInjection\Definition; |
9
|
|
|
use Symfony\Component\DependencyInjection\Reference; |
10
|
|
|
|
11
|
|
|
abstract class TaggedServiceMappingPass implements CompilerPassInterface |
12
|
|
|
{ |
13
|
30 |
|
private function getTaggedServiceMapping(ContainerBuilder $container, $tagName) |
14
|
|
|
{ |
15
|
30 |
|
$serviceMapping = []; |
16
|
|
|
|
17
|
30 |
|
$taggedServices = $container->findTaggedServiceIds($tagName, true); |
18
|
30 |
|
$isType = TypeTaggedServiceMappingPass::TAG_NAME === $tagName; |
19
|
|
|
|
20
|
30 |
|
foreach ($taggedServices as $id => $tags) { |
21
|
30 |
|
$className = $container->findDefinition($id)->getClass(); |
22
|
30 |
|
foreach ($tags as $attributes) { |
23
|
30 |
|
$this->checkRequirements($id, $attributes); |
24
|
28 |
|
$attributes = array_merge($attributes, ['id' => $id, 'aliases' => []]); |
25
|
|
|
|
26
|
28 |
|
if (!$isType) { |
27
|
28 |
|
$attributes['method'] = isset($attributes['method']) ? $attributes['method'] : '__invoke'; |
28
|
|
|
} |
29
|
28 |
|
if ($isType || '__invoke' === $attributes['method']) { |
30
|
27 |
|
$solutionID = $className; |
31
|
|
|
} else { |
32
|
17 |
|
$solutionID = sprintf('%s::%s', $className, $attributes['method']); |
33
|
|
|
} |
34
|
|
|
|
35
|
28 |
|
if (!isset($serviceMapping[$solutionID])) { |
36
|
28 |
|
$serviceMapping[$solutionID] = $attributes; |
37
|
|
|
} |
38
|
|
|
|
39
|
28 |
|
if (isset($attributes['alias']) && $solutionID !== $attributes['alias']) { |
40
|
28 |
|
$serviceMapping[$solutionID]['aliases'][] = $attributes['alias']; |
41
|
|
|
} |
42
|
|
|
} |
43
|
|
|
} |
44
|
|
|
|
45
|
28 |
|
return $serviceMapping; |
46
|
|
|
} |
47
|
|
|
|
48
|
30 |
|
public function process(ContainerBuilder $container) |
49
|
|
|
{ |
50
|
30 |
|
$mapping = $this->getTaggedServiceMapping($container, $this->getTagName()); |
51
|
28 |
|
$resolverDefinition = $container->findDefinition($this->getResolverServiceID()); |
52
|
|
|
|
53
|
28 |
|
foreach ($mapping as $solutionID => $attributes) { |
54
|
28 |
|
$attributes['aliases'] = array_unique($attributes['aliases']); |
55
|
28 |
|
$aliases = $attributes['aliases']; |
56
|
28 |
|
$serviceID = $attributes['id']; |
57
|
|
|
|
58
|
28 |
|
$solutionDefinition = $container->findDefinition($serviceID); |
59
|
|
|
// make solution service public to improve lazy loading |
60
|
28 |
|
$solutionDefinition->setPublic(true); |
61
|
28 |
|
$this->autowireSolutionImplementingContainerAwareInterface($solutionDefinition, empty($attributes['generated'])); |
62
|
|
|
|
63
|
28 |
|
$resolverDefinition->addMethodCall( |
64
|
28 |
|
'addSolution', |
65
|
28 |
|
[$solutionID, [[new Reference('service_container'), 'get'], [$serviceID]], $aliases, $attributes] |
66
|
|
|
); |
67
|
|
|
} |
68
|
28 |
|
} |
69
|
|
|
|
70
|
30 |
|
protected function checkRequirements($id, array $tag) |
71
|
|
|
{ |
72
|
30 |
View Code Duplication |
if (isset($tag['alias']) && !is_string($tag['alias'])) { |
|
|
|
|
73
|
1 |
|
throw new \InvalidArgumentException( |
74
|
1 |
|
sprintf('Service tagged "%s" must have valid "alias" argument.', $id) |
75
|
|
|
); |
76
|
|
|
} |
77
|
29 |
|
} |
78
|
|
|
|
79
|
28 |
|
private function autowireSolutionImplementingContainerAwareInterface(Definition $solutionDefinition, $isGenerated) |
80
|
|
|
{ |
81
|
28 |
|
$methods = array_map( |
82
|
28 |
|
function ($methodCall) { |
83
|
2 |
|
return $methodCall[0]; |
84
|
28 |
|
}, |
85
|
28 |
|
$solutionDefinition->getMethodCalls() |
86
|
|
|
); |
87
|
|
|
if ( |
88
|
28 |
|
$isGenerated |
89
|
28 |
|
&& is_subclass_of($solutionDefinition->getClass(), ContainerAwareInterface::class) |
|
|
|
|
90
|
28 |
|
&& !in_array('setContainer', $methods) |
91
|
|
|
) { |
92
|
2 |
|
@trigger_error( |
|
|
|
|
93
|
2 |
|
sprintf( |
94
|
2 |
|
'Autowire method "%s::setContainer" for custom tagged (type, resolver or mutation) services is deprecated as of 0.9 and will be removed in 1.0.', |
95
|
2 |
|
ContainerAwareInterface::class |
96
|
|
|
), |
97
|
2 |
|
E_USER_DEPRECATED |
98
|
|
|
); |
99
|
2 |
|
$solutionDefinition->addMethodCall('setContainer', [new Reference('service_container')]); |
100
|
|
|
} |
101
|
28 |
|
} |
102
|
|
|
|
103
|
|
|
abstract protected function getTagName(); |
104
|
|
|
|
105
|
|
|
/** |
106
|
|
|
* @return string |
107
|
|
|
*/ |
108
|
|
|
abstract protected function getResolverServiceID(); |
109
|
|
|
} |
110
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.