5 * Contains \Drupal\Tests\Core\DependencyInjection\Compiler\TaggedHandlersPassTest.
8 namespace Drupal\Tests\Core\DependencyInjection\Compiler;
10 use Drupal\Core\DependencyInjection\Compiler\TaggedHandlersPass;
11 use Drupal\Tests\UnitTestCase;
12 use Symfony\Component\DependencyInjection\ContainerBuilder;
13 use Symfony\Component\DependencyInjection\Exception\LogicException;
14 use Symfony\Component\DependencyInjection\Reference;
17 * @coversDefaultClass \Drupal\Core\DependencyInjection\Compiler\TaggedHandlersPass
18 * @group DependencyInjection
20 class TaggedHandlersPassTest extends UnitTestCase {
22 protected function buildContainer($environment = 'dev') {
23 $container = new ContainerBuilder();
24 $container->setParameter('kernel.environment', $environment);
29 * Tests without any consumers.
33 public function testProcessNoConsumers() {
34 $container = $this->buildContainer();
36 ->register('consumer_id', __NAMESPACE__ . '\ValidConsumer');
38 $handler_pass = new TaggedHandlersPass();
39 $handler_pass->process($container);
41 $this->assertCount(2, $container->getDefinitions());
42 $this->assertFalse($container->getDefinition('consumer_id')->hasMethodCall('addHandler'));
46 * Tests a required consumer with no handlers.
50 public function testProcessRequiredHandlers() {
51 $container = $this->buildContainer();
53 ->register('consumer_id', __NAMESPACE__ . '\ValidConsumer')
54 ->addTag('service_collector', [
58 $handler_pass = new TaggedHandlersPass();
59 $this->setExpectedException(LogicException::class, "At least one service tagged with 'consumer_id' is required.");
60 $handler_pass->process($container);
64 * Tests a required consumer with no handlers.
67 * @covers ::processServiceIdCollectorPass
69 public function testIdCollectorProcessRequiredHandlers() {
70 $this->setExpectedException(LogicException::class, "At least one service tagged with 'consumer_id' is required.");
71 $container = $this->buildContainer();
73 ->register('consumer_id', __NAMESPACE__ . '\ValidConsumer')
74 ->addTag('service_id_collector', [
78 $handler_pass = new TaggedHandlersPass();
79 $handler_pass->process($container);
83 * Tests consumer with missing interface in non-production environment.
87 public function testProcessMissingInterface() {
88 $container = $this->buildContainer();
90 ->register('consumer_id0', __NAMESPACE__ . '\ValidConsumer')
91 ->addTag('service_collector');
93 ->register('consumer_id1', __NAMESPACE__ . '\InvalidConsumer')
94 ->addTag('service_collector');
96 $handler_pass = new TaggedHandlersPass();
97 $this->setExpectedException(LogicException::class, "Service consumer 'consumer_id1' class method Drupal\Tests\Core\DependencyInjection\Compiler\InvalidConsumer::addHandler() has to type-hint an interface.");
98 $handler_pass->process($container);
102 * Tests one consumer and two handlers.
106 public function testProcess() {
107 $container = $this->buildContainer();
109 ->register('consumer_id', __NAMESPACE__ . '\ValidConsumer')
110 ->addTag('service_collector');
113 ->register('handler1', __NAMESPACE__ . '\ValidHandler')
114 ->addTag('consumer_id');
116 ->register('handler2', __NAMESPACE__ . '\ValidHandler')
117 ->addTag('consumer_id');
119 $handler_pass = new TaggedHandlersPass();
120 $handler_pass->process($container);
122 $method_calls = $container->getDefinition('consumer_id')->getMethodCalls();
123 $this->assertCount(2, $method_calls);
127 * Tests one consumer and two handlers with service ID collection.
131 public function testserviceIdProcess() {
132 $container = $this->buildContainer();
134 ->register('consumer_id', __NAMESPACE__ . '\ValidConsumer')
135 ->addTag('service_id_collector');
138 ->register('handler1', __NAMESPACE__ . '\ValidHandler')
139 ->addTag('consumer_id');
141 ->register('handler2', __NAMESPACE__ . '\ValidHandler')
142 ->addTag('consumer_id');
144 $handler_pass = new TaggedHandlersPass();
145 $handler_pass->process($container);
147 $arguments = $container->getDefinition('consumer_id')->getArguments();
148 $this->assertCount(1, $arguments);
149 $this->assertCount(2, $arguments[0]);
153 * Tests handler priority sorting.
157 public function testProcessPriority() {
158 $container = $this->buildContainer();
160 ->register('consumer_id', __NAMESPACE__ . '\ValidConsumer')
161 ->addTag('service_collector');
164 ->register('handler1', __NAMESPACE__ . '\ValidHandler')
165 ->addTag('consumer_id');
167 ->register('handler2', __NAMESPACE__ . '\ValidHandler')
168 ->addTag('consumer_id', [
172 $handler_pass = new TaggedHandlersPass();
173 $handler_pass->process($container);
175 $method_calls = $container->getDefinition('consumer_id')->getMethodCalls();
176 $this->assertCount(2, $method_calls);
177 $this->assertEquals(new Reference('handler2'), $method_calls[0][1][0]);
178 $this->assertEquals(10, $method_calls[0][1][1]);
179 $this->assertEquals(new Reference('handler1'), $method_calls[1][1][0]);
180 $this->assertEquals(0, $method_calls[1][1][1]);
184 * Tests handler priority sorting for service ID collection.
188 public function testserviceIdProcessPriority() {
189 $container = $this->buildContainer();
191 ->register('consumer_id', __NAMESPACE__ . '\ValidConsumer')
192 ->addTag('service_id_collector');
195 ->register('handler1', __NAMESPACE__ . '\ValidHandler')
196 ->addTag('consumer_id');
198 ->register('handler2', __NAMESPACE__ . '\ValidHandler')
199 ->addTag('consumer_id', [
203 ->register('handler3', __NAMESPACE__ . '\ValidHandler')
204 ->addTag('consumer_id', [
208 $handler_pass = new TaggedHandlersPass();
209 $handler_pass->process($container);
211 $arguments = $container->getDefinition('consumer_id')->getArguments();
212 $this->assertCount(1, $arguments);
213 $this->assertSame(['handler2', 'handler3', 'handler1'], $arguments[0]);
217 * Tests consumer method without priority parameter.
221 public function testProcessNoPriorityParam() {
222 $container = $this->buildContainer();
224 ->register('consumer_id', __NAMESPACE__ . '\ValidConsumer')
225 ->addTag('service_collector', [
226 'call' => 'addNoPriority',
230 ->register('handler1', __NAMESPACE__ . '\ValidHandler')
231 ->addTag('consumer_id');
233 ->register('handler2', __NAMESPACE__ . '\ValidHandler')
234 ->addTag('consumer_id', [
238 $handler_pass = new TaggedHandlersPass();
239 $handler_pass->process($container);
241 $method_calls = $container->getDefinition('consumer_id')->getMethodCalls();
242 $this->assertCount(2, $method_calls);
243 $this->assertEquals(new Reference('handler2'), $method_calls[0][1][0]);
244 $this->assertCount(1, $method_calls[0][1]);
245 $this->assertEquals(new Reference('handler1'), $method_calls[1][1][0]);
246 $this->assertCount(1, $method_calls[0][1]);
250 * Tests consumer method with an ID parameter.
254 public function testProcessWithIdParameter() {
255 $container = $this->buildContainer();
257 ->register('consumer_id', __NAMESPACE__ . '\ValidConsumer')
258 ->addTag('service_collector', [
259 'call' => 'addWithId',
263 ->register('handler1', __NAMESPACE__ . '\ValidHandler')
264 ->addTag('consumer_id');
266 ->register('handler2', __NAMESPACE__ . '\ValidHandler')
267 ->addTag('consumer_id', [
271 $handler_pass = new TaggedHandlersPass();
272 $handler_pass->process($container);
274 $method_calls = $container->getDefinition('consumer_id')->getMethodCalls();
275 $this->assertCount(2, $method_calls);
276 $this->assertEquals(new Reference('handler2'), $method_calls[0][1][0]);
277 $this->assertEquals('handler2', $method_calls[0][1][1]);
278 $this->assertEquals(10, $method_calls[0][1][2]);
279 $this->assertEquals(new Reference('handler1'), $method_calls[1][1][0]);
280 $this->assertEquals('handler1', $method_calls[1][1][1]);
281 $this->assertEquals(0, $method_calls[1][1][2]);
285 * Tests interface validation in non-production environment.
289 public function testProcessInterfaceMismatch() {
290 $container = $this->buildContainer();
293 ->register('consumer_id', __NAMESPACE__ . '\ValidConsumer')
294 ->addTag('service_collector');
296 ->register('handler1', __NAMESPACE__ . '\InvalidHandler')
297 ->addTag('consumer_id');
299 ->register('handler2', __NAMESPACE__ . '\ValidHandler')
300 ->addTag('consumer_id', [
304 $handler_pass = new TaggedHandlersPass();
305 $this->setExpectedException(LogicException::class);
306 $handler_pass->process($container);
310 * Tests consumer method with extra parameters.
314 public function testProcessWithExtraArguments() {
315 $container = $this->buildContainer();
318 ->register('consumer_id', __NAMESPACE__ . '\ValidConsumerWithExtraArguments')
319 ->addTag('service_collector');
322 ->register('handler1', __NAMESPACE__ . '\ValidHandler')
323 ->addTag('consumer_id', [
324 'extra1' => 'extra1',
325 'extra2' => 'extra2',
328 $handler_pass = new TaggedHandlersPass();
329 $handler_pass->process($container);
331 $method_calls = $container->getDefinition('consumer_id')->getMethodCalls();
332 $this->assertCount(4, $method_calls[0][1]);
333 $this->assertEquals(new Reference('handler1'), $method_calls[0][1][0]);
334 $this->assertEquals(0, $method_calls[0][1][1]);
335 $this->assertEquals('extra1', $method_calls[0][1][2]);
336 $this->assertEquals('extra2', $method_calls[0][1][3]);
340 * Tests consumer method with extra parameters and no priority.
344 public function testProcessNoPriorityAndExtraArguments() {
345 $container = $this->buildContainer();
348 ->register('consumer_id', __NAMESPACE__ . '\ValidConsumerWithExtraArguments')
349 ->addTag('service_collector', [
350 'call' => 'addNoPriority'
354 ->register('handler1', __NAMESPACE__ . '\ValidHandler')
355 ->addTag('consumer_id', [
359 $handler_pass = new TaggedHandlersPass();
360 $handler_pass->process($container);
362 $method_calls = $container->getDefinition('consumer_id')->getMethodCalls();
363 $this->assertCount(2, $method_calls[0][1]);
364 $this->assertEquals(new Reference('handler1'), $method_calls[0][1][0]);
365 $this->assertEquals('extra', $method_calls[0][1][1]);
369 * Tests consumer method with priority, id and extra parameters.
373 public function testProcessWithIdAndExtraArguments() {
374 $container = $this->buildContainer();
377 ->register('consumer_id', __NAMESPACE__ . '\ValidConsumerWithExtraArguments')
378 ->addTag('service_collector', [
379 'call' => 'addWithId'
383 ->register('handler1', __NAMESPACE__ . '\ValidHandler')
384 ->addTag('consumer_id', [
385 'extra1' => 'extra1',
388 $handler_pass = new TaggedHandlersPass();
389 $handler_pass->process($container);
391 $method_calls = $container->getDefinition('consumer_id')->getMethodCalls();
392 $this->assertCount(5, $method_calls[0][1]);
393 $this->assertEquals(new Reference('handler1'), $method_calls[0][1][0]);
394 $this->assertEquals('handler1', $method_calls[0][1][1]);
395 $this->assertEquals(0, $method_calls[0][1][2]);
396 $this->assertEquals('extra1', $method_calls[0][1][3]);
397 $this->assertNull($method_calls[0][1][4]);
401 * Tests consumer method with priority and extra parameters in different order.
405 public function testProcessWithDifferentArgumentsOrderAndDefaultValue() {
406 $container = $this->buildContainer();
409 ->register('consumer_id', __NAMESPACE__ . '\ValidConsumerWithExtraArguments')
410 ->addTag('service_collector', [
411 'call' => 'addWithDifferentOrder'
415 ->register('handler1', __NAMESPACE__ . '\ValidHandler')
416 ->addTag('consumer_id', [
418 'extra1' => 'extra1',
422 $handler_pass = new TaggedHandlersPass();
423 $handler_pass->process($container);
425 $method_calls = $container->getDefinition('consumer_id')->getMethodCalls();
426 $this->assertCount(5, $method_calls[0][1]);
427 $expected = [new Reference('handler1'), 'extra1', 0, 'default2', 'extra3'];
428 $this->assertEquals($expected, array_values($method_calls[0][1]));
433 interface HandlerInterface {
435 class ValidConsumer {
436 public function addHandler(HandlerInterface $instance, $priority = 0) {
438 public function addNoPriority(HandlerInterface $instance) {
440 public function addWithId(HandlerInterface $instance, $id, $priority = 0) {
444 class InvalidConsumer {
445 public function addHandler($instance, $priority = 0) {
449 class ValidConsumerWithExtraArguments {
450 public function addHandler(HandlerInterface $instance, $priority = 0, $extra1 = '', $extra2 = '') {
452 public function addNoPriority(HandlerInterface $instance, $extra) {
454 public function addWithId(HandlerInterface $instance, $id, $priority = 0, $extra1 = '', $extra2 = NULL) {
456 public function addWithDifferentOrder(HandlerInterface $instance, $extra1, $priority = 0, $extra2 = 'default2', $extra3 = 'default3') {
460 class ValidHandler implements HandlerInterface {
462 class InvalidHandler {