|
15 | 15 | use Symfony\Component\DependencyInjection\ContainerBuilder;
|
16 | 16 | use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
17 | 17 | use Symfony\Component\DependencyInjection\Reference;
|
18 |
| -use Symfony\Component\DependencyInjection\TypedReference; |
19 | 18 |
|
20 | 19 | /**
|
21 | 20 | * Trait that allows a generic method to find and sort service by priority option in the tag.
|
@@ -54,88 +53,104 @@ private function findAndSortTaggedServices($tagName, ContainerBuilder $container
|
54 | 53 |
|
55 | 54 | foreach ($container->findTaggedServiceIds($tagName, true) as $serviceId => $attributes) {
|
56 | 55 | $class = $r = null;
|
57 |
| - |
58 | 56 | $defaultPriority = null;
|
59 | 57 | $defaultIndex = null;
|
60 | 58 |
|
61 | 59 | foreach ($attributes as $attribute) {
|
62 | 60 | $index = $priority = null;
|
63 | 61 |
|
64 | 62 | if (isset($attribute['priority'])) {
|
65 |
| - $priority = $attribute['priority']; |
| 63 | + $priority = (int) $attribute['priority']; |
66 | 64 | } elseif (null === $defaultPriority && $defaultPriorityMethod) {
|
67 |
| - $class = $container->getDefinition($serviceId)->getClass(); |
68 |
| - $class = $container->getParameterBag()->resolveValue($class) ?: null; |
69 |
| - |
70 |
| - if (($r = ($r ?? $container->getReflectionClass($class))) && $r->hasMethod($defaultPriorityMethod)) { |
71 |
| - if (!($rm = $r->getMethod($defaultPriorityMethod))->isStatic()) { |
72 |
| - throw new InvalidArgumentException(sprintf('Method "%s::%s()" should be static: tag "%s" on service "%s".', $class, $defaultPriorityMethod, $tagName, $serviceId)); |
73 |
| - } |
74 |
| - |
75 |
| - if (!$rm->isPublic()) { |
76 |
| - throw new InvalidArgumentException(sprintf('Method "%s::%s()" should be public: tag "%s" on service "%s".', $class, $defaultPriorityMethod, $tagName, $serviceId)); |
77 |
| - } |
78 |
| - |
79 |
| - $defaultPriority = $rm->invoke(null); |
80 |
| - |
81 |
| - if (!\is_int($defaultPriority)) { |
82 |
| - throw new InvalidArgumentException(sprintf('Method "%s::%s()" should return an integer, got %s: tag "%s" on service "%s".', $class, $defaultPriorityMethod, \gettype($priority), $tagName, $serviceId)); |
83 |
| - } |
84 |
| - } |
| 65 | + [$defaultPriority, $class, $r] = PriorityTaggedServiceUtil::getDefaultPriority($container, $serviceId, $defaultPriorityMethod, $r, $tagName); |
85 | 66 | }
|
| 67 | + $priority = $priority ?? $defaultPriority ?? $defaultPriority = 0; |
86 | 68 |
|
87 |
| - $priority = $priority ?? $defaultPriority ?? 0; |
| 69 | + if (null === $indexAttribute && !$needsIndexes) { |
| 70 | + $services[$priority][] = new Reference($serviceId); |
| 71 | + continue 2; |
| 72 | + } |
88 | 73 |
|
89 | 74 | if (null !== $indexAttribute && isset($attribute[$indexAttribute])) {
|
90 | 75 | $index = $attribute[$indexAttribute];
|
91 |
| - } elseif (null === $defaultIndex && null === $indexAttribute && !$needsIndexes) { |
92 |
| - // With partially associative array, insertion to get next key is simpler. |
93 |
| - $services[$priority][] = null; |
94 |
| - end($services[$priority]); |
95 |
| - $defaultIndex = key($services[$priority]); |
96 | 76 | } elseif (null === $defaultIndex && $defaultIndexMethod) {
|
97 |
| - $class = $container->getDefinition($serviceId)->getClass(); |
98 |
| - $class = $container->getParameterBag()->resolveValue($class) ?: null; |
| 77 | + [$defaultIndex, $class, $r] = PriorityTaggedServiceUtil::getDefaultIndex($container, $serviceId, $defaultIndexMethod, $r, $tagName, $indexAttribute); |
| 78 | + } |
| 79 | + $index = $index ?? $defaultIndex ?? $defaultIndex = $serviceId; |
99 | 80 |
|
100 |
| - if (($r = ($r ?? $container->getReflectionClass($class))) && $r->hasMethod($defaultIndexMethod)) { |
101 |
| - if (!($rm = $r->getMethod($defaultIndexMethod))->isStatic()) { |
102 |
| - throw new InvalidArgumentException(sprintf('Method "%s::%s()" should be static: tag "%s" on service "%s" is missing "%s" attribute.', $class, $defaultIndexMethod, $tagName, $serviceId, $indexAttribute)); |
103 |
| - } |
| 81 | + $services[$priority][$index] = new Reference($serviceId); |
| 82 | + } |
| 83 | + } |
104 | 84 |
|
105 |
| - if (!$rm->isPublic()) { |
106 |
| - throw new InvalidArgumentException(sprintf('Method "%s::%s()" should be public: tag "%s" on service "%s" is missing "%s" attribute.', $class, $defaultIndexMethod, $tagName, $serviceId, $indexAttribute)); |
107 |
| - } |
| 85 | + if ($services) { |
| 86 | + krsort($services); |
| 87 | + $services = array_merge(...$services); |
| 88 | + } |
108 | 89 |
|
109 |
| - $defaultIndex = $rm->invoke(null); |
| 90 | + return $services; |
| 91 | + } |
| 92 | +} |
110 | 93 |
|
111 |
| - if (!\is_string($defaultIndex)) { |
112 |
| - throw new InvalidArgumentException(sprintf('Method "%s::%s()" should return a string, got %s: tag "%s" on service "%s" is missing "%s" attribute.', $class, $defaultIndexMethod, \gettype($defaultIndex), $tagName, $serviceId, $indexAttribute)); |
113 |
| - } |
114 |
| - } |
| 94 | +/** |
| 95 | + * @internal |
| 96 | + */ |
| 97 | +class PriorityTaggedServiceUtil |
| 98 | +{ |
| 99 | + /** |
| 100 | + * Gets the index defined by the default index method. |
| 101 | + */ |
| 102 | + public static function getDefaultIndex(ContainerBuilder $container, string $serviceId, string $defaultIndexMethod, ?\ReflectionClass $r, string $tagName, string $indexAttribute): ?array |
| 103 | + { |
| 104 | + $class = $container->getDefinition($serviceId)->getClass(); |
| 105 | + $class = $container->getParameterBag()->resolveValue($class) ?: null; |
115 | 106 |
|
116 |
| - $defaultIndex = $defaultIndex ?? $serviceId; |
117 |
| - } |
| 107 | + if (!($r = $r ?? $container->getReflectionClass($class)) || !$r->hasMethod($defaultIndexMethod)) { |
| 108 | + return null; |
| 109 | + } |
118 | 110 |
|
119 |
| - $index = $index ?? $defaultIndex; |
| 111 | + if (!($rm = $r->getMethod($defaultIndexMethod))->isStatic()) { |
| 112 | + throw new InvalidArgumentException(sprintf('Either method "%s::%s()" should be static or tag "%s" on service "%s" is missing attribute "%s".', $class, $defaultIndexMethod, $tagName, $serviceId, $indexAttribute)); |
| 113 | + } |
120 | 114 |
|
121 |
| - $reference = null; |
122 |
| - if (!$class || 'stdClass' === $class) { |
123 |
| - $reference = new Reference($serviceId); |
124 |
| - } elseif ($index === $serviceId) { |
125 |
| - $reference = new TypedReference($serviceId, $class); |
126 |
| - } else { |
127 |
| - $reference = new TypedReference($serviceId, $class, ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE, \is_string($index) ? $index : null); |
128 |
| - } |
| 115 | + if (!$rm->isPublic()) { |
| 116 | + throw new InvalidArgumentException(sprintf('Either method "%s::%s()" should be public or tag "%s" on service "%s" is missing attribute "%s".', $class, $defaultIndexMethod, $tagName, $serviceId, $indexAttribute)); |
| 117 | + } |
129 | 118 |
|
130 |
| - $services[$priority][$index] = $reference; |
131 |
| - } |
| 119 | + $defaultIndex = $rm->invoke(null); |
| 120 | + |
| 121 | + if (!\is_string($defaultIndex)) { |
| 122 | + throw new InvalidArgumentException(sprintf('Either method "%s::%s()" should return a string (got %s) or tag "%s" on service "%s" is missing attribute "%s".', $class, $defaultIndexMethod, \gettype($defaultIndex), $tagName, $serviceId, $indexAttribute)); |
132 | 123 | }
|
133 | 124 |
|
134 |
| - if ($services) { |
135 |
| - krsort($services); |
136 |
| - $services = array_merge(...$services); |
| 125 | + return [$defaultIndex, $class, $r]; |
| 126 | + } |
| 127 | + |
| 128 | + /** |
| 129 | + * Gets the priority defined by the default priority method. |
| 130 | + */ |
| 131 | + public static function getDefaultPriority(ContainerBuilder $container, string $serviceId, string $defaultPriorityMethod, ?\ReflectionClass $r, string $tagName): ?array |
| 132 | + { |
| 133 | + $class = $container->getDefinition($serviceId)->getClass(); |
| 134 | + $class = $container->getParameterBag()->resolveValue($class) ?: null; |
| 135 | + |
| 136 | + if (!($r = $r ?? $container->getReflectionClass($class)) || !$r->hasMethod($defaultPriorityMethod)) { |
| 137 | + return null; |
137 | 138 | }
|
138 | 139 |
|
139 |
| - return $services; |
| 140 | + if (!($rm = $r->getMethod($defaultPriorityMethod))->isStatic()) { |
| 141 | + throw new InvalidArgumentException(sprintf('Either method "%s::%s()" should be static or tag "%s" on service "%s" is missing attribute "priority".', $class, $defaultPriorityMethod, $tagName, $serviceId)); |
| 142 | + } |
| 143 | + |
| 144 | + if (!$rm->isPublic()) { |
| 145 | + throw new InvalidArgumentException(sprintf('Either method "%s::%s()" should be public or tag "%s" on service "%s" is missing attribute "priority".', $class, $defaultPriorityMethod, $tagName, $serviceId)); |
| 146 | + } |
| 147 | + |
| 148 | + $defaultPriority = $rm->invoke(null); |
| 149 | + |
| 150 | + if (!\is_int($defaultPriority)) { |
| 151 | + throw new InvalidArgumentException(sprintf('Method "%s::%s()" should return an integer (got %s) or tag "%s" on service "%s" is missing attribute "priority".', $class, $defaultPriorityMethod, \gettype($defaultPriority), $tagName, $serviceId)); |
| 152 | + } |
| 153 | + |
| 154 | + return [$defaultPriority, $class, $r]; |
140 | 155 | }
|
141 | 156 | }
|
0 commit comments