View source
<?php
namespace Drupal\Tests\Core\DependencyInjection\Compiler;
use Drupal\Core\DependencyInjection\Compiler\TaggedHandlersPass;
use Drupal\Tests\UnitTestCase;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Reference;
class TaggedHandlersPassTest extends UnitTestCase {
protected function buildContainer($environment = 'dev') {
$container = new ContainerBuilder();
$container
->setParameter('kernel.environment', $environment);
return $container;
}
public function testProcessNoConsumers() {
$container = $this
->buildContainer();
$container
->register('consumer_id', __NAMESPACE__ . '\\ValidConsumer');
$handler_pass = new TaggedHandlersPass();
$handler_pass
->process($container);
$this
->assertCount(2, $container
->getDefinitions());
$this
->assertFalse($container
->getDefinition('consumer_id')
->hasMethodCall('addHandler'));
}
public function testProcessRequiredHandlers() {
$container = $this
->buildContainer();
$container
->register('consumer_id', __NAMESPACE__ . '\\ValidConsumer')
->addTag('service_collector', [
'required' => TRUE,
]);
$handler_pass = new TaggedHandlersPass();
$this
->expectException(LogicException::class);
$this
->expectExceptionMessage("At least one service tagged with 'consumer_id' is required.");
$handler_pass
->process($container);
}
public function testIdCollectorProcessRequiredHandlers() {
$this
->expectException(LogicException::class);
$this
->expectExceptionMessage("At least one service tagged with 'consumer_id' is required.");
$container = $this
->buildContainer();
$container
->register('consumer_id', __NAMESPACE__ . '\\ValidConsumer')
->addTag('service_id_collector', [
'required' => TRUE,
]);
$handler_pass = new TaggedHandlersPass();
$handler_pass
->process($container);
}
public function testProcessMissingInterface() {
$container = $this
->buildContainer();
$container
->register('consumer_id0', __NAMESPACE__ . '\\ValidConsumer')
->addTag('service_collector');
$container
->register('consumer_id1', __NAMESPACE__ . '\\InvalidConsumer')
->addTag('service_collector');
$handler_pass = new TaggedHandlersPass();
$this
->expectException(LogicException::class);
$this
->expectExceptionMessage("Service consumer 'consumer_id1' class method Drupal\\Tests\\Core\\DependencyInjection\\Compiler\\InvalidConsumer::addHandler() has to type-hint an interface.");
$handler_pass
->process($container);
}
public function testProcess() {
$container = $this
->buildContainer();
$container
->register('consumer_id', __NAMESPACE__ . '\\ValidConsumer')
->addTag('service_collector');
$container
->register('handler1', __NAMESPACE__ . '\\ValidHandler')
->addTag('consumer_id');
$container
->register('handler2', __NAMESPACE__ . '\\ValidHandler')
->addTag('consumer_id');
$handler_pass = new TaggedHandlersPass();
$handler_pass
->process($container);
$method_calls = $container
->getDefinition('consumer_id')
->getMethodCalls();
$this
->assertCount(2, $method_calls);
}
public function testserviceIdProcess() {
$container = $this
->buildContainer();
$container
->register('consumer_id', __NAMESPACE__ . '\\ValidConsumer')
->addTag('service_id_collector');
$container
->register('handler1', __NAMESPACE__ . '\\ValidHandler')
->addTag('consumer_id');
$container
->register('handler2', __NAMESPACE__ . '\\ValidHandler')
->addTag('consumer_id');
$handler_pass = new TaggedHandlersPass();
$handler_pass
->process($container);
$arguments = $container
->getDefinition('consumer_id')
->getArguments();
$this
->assertCount(1, $arguments);
$this
->assertCount(2, $arguments[0]);
}
public function testProcessPriority() {
$container = $this
->buildContainer();
$container
->register('consumer_id', __NAMESPACE__ . '\\ValidConsumer')
->addTag('service_collector');
$container
->register('handler1', __NAMESPACE__ . '\\ValidHandler')
->addTag('consumer_id');
$container
->register('handler2', __NAMESPACE__ . '\\ValidHandler')
->addTag('consumer_id', [
'priority' => 10,
]);
$handler_pass = new TaggedHandlersPass();
$handler_pass
->process($container);
$method_calls = $container
->getDefinition('consumer_id')
->getMethodCalls();
$this
->assertCount(2, $method_calls);
$this
->assertEquals(new Reference('handler2'), $method_calls[0][1][0]);
$this
->assertEquals(10, $method_calls[0][1][1]);
$this
->assertEquals(new Reference('handler1'), $method_calls[1][1][0]);
$this
->assertEquals(0, $method_calls[1][1][1]);
}
public function testserviceIdProcessPriority() {
$container = $this
->buildContainer();
$container
->register('consumer_id', __NAMESPACE__ . '\\ValidConsumer')
->addTag('service_id_collector');
$container
->register('handler1', __NAMESPACE__ . '\\ValidHandler')
->addTag('consumer_id');
$container
->register('handler2', __NAMESPACE__ . '\\ValidHandler')
->addTag('consumer_id', [
'priority' => 20,
]);
$container
->register('handler3', __NAMESPACE__ . '\\ValidHandler')
->addTag('consumer_id', [
'priority' => 10,
]);
$handler_pass = new TaggedHandlersPass();
$handler_pass
->process($container);
$arguments = $container
->getDefinition('consumer_id')
->getArguments();
$this
->assertCount(1, $arguments);
$this
->assertSame([
'handler2',
'handler3',
'handler1',
], $arguments[0]);
}
public function testProcessNoPriorityParam() {
$container = $this
->buildContainer();
$container
->register('consumer_id', __NAMESPACE__ . '\\ValidConsumer')
->addTag('service_collector', [
'call' => 'addNoPriority',
]);
$container
->register('handler1', __NAMESPACE__ . '\\ValidHandler')
->addTag('consumer_id');
$container
->register('handler2', __NAMESPACE__ . '\\ValidHandler')
->addTag('consumer_id', [
'priority' => 10,
]);
$handler_pass = new TaggedHandlersPass();
$handler_pass
->process($container);
$method_calls = $container
->getDefinition('consumer_id')
->getMethodCalls();
$this
->assertCount(2, $method_calls);
$this
->assertEquals(new Reference('handler2'), $method_calls[0][1][0]);
$this
->assertCount(1, $method_calls[0][1]);
$this
->assertEquals(new Reference('handler1'), $method_calls[1][1][0]);
$this
->assertCount(1, $method_calls[0][1]);
}
public function testProcessWithIdParameter() {
$container = $this
->buildContainer();
$container
->register('consumer_id', __NAMESPACE__ . '\\ValidConsumer')
->addTag('service_collector', [
'call' => 'addWithId',
]);
$container
->register('handler1', __NAMESPACE__ . '\\ValidHandler')
->addTag('consumer_id');
$container
->register('handler2', __NAMESPACE__ . '\\ValidHandler')
->addTag('consumer_id', [
'priority' => 10,
]);
$handler_pass = new TaggedHandlersPass();
$handler_pass
->process($container);
$method_calls = $container
->getDefinition('consumer_id')
->getMethodCalls();
$this
->assertCount(2, $method_calls);
$this
->assertEquals(new Reference('handler2'), $method_calls[0][1][0]);
$this
->assertEquals('handler2', $method_calls[0][1][1]);
$this
->assertEquals(10, $method_calls[0][1][2]);
$this
->assertEquals(new Reference('handler1'), $method_calls[1][1][0]);
$this
->assertEquals('handler1', $method_calls[1][1][1]);
$this
->assertEquals(0, $method_calls[1][1][2]);
}
public function testProcessInterfaceMismatch() {
$container = $this
->buildContainer();
$container
->register('consumer_id', __NAMESPACE__ . '\\ValidConsumer')
->addTag('service_collector');
$container
->register('handler1', __NAMESPACE__ . '\\InvalidHandler')
->addTag('consumer_id');
$container
->register('handler2', __NAMESPACE__ . '\\ValidHandler')
->addTag('consumer_id', [
'priority' => 10,
]);
$handler_pass = new TaggedHandlersPass();
$this
->expectException(LogicException::class);
$handler_pass
->process($container);
}
public function testProcessWithExtraArguments() {
$container = $this
->buildContainer();
$container
->register('consumer_id', __NAMESPACE__ . '\\ValidConsumerWithExtraArguments')
->addTag('service_collector');
$container
->register('handler1', __NAMESPACE__ . '\\ValidHandler')
->addTag('consumer_id', [
'extra1' => 'extra1',
'extra2' => 'extra2',
]);
$handler_pass = new TaggedHandlersPass();
$handler_pass
->process($container);
$method_calls = $container
->getDefinition('consumer_id')
->getMethodCalls();
$this
->assertCount(4, $method_calls[0][1]);
$this
->assertEquals(new Reference('handler1'), $method_calls[0][1][0]);
$this
->assertEquals(0, $method_calls[0][1][1]);
$this
->assertEquals('extra1', $method_calls[0][1][2]);
$this
->assertEquals('extra2', $method_calls[0][1][3]);
}
public function testProcessNoPriorityAndExtraArguments() {
$container = $this
->buildContainer();
$container
->register('consumer_id', __NAMESPACE__ . '\\ValidConsumerWithExtraArguments')
->addTag('service_collector', [
'call' => 'addNoPriority',
]);
$container
->register('handler1', __NAMESPACE__ . '\\ValidHandler')
->addTag('consumer_id', [
'extra' => 'extra',
]);
$handler_pass = new TaggedHandlersPass();
$handler_pass
->process($container);
$method_calls = $container
->getDefinition('consumer_id')
->getMethodCalls();
$this
->assertCount(2, $method_calls[0][1]);
$this
->assertEquals(new Reference('handler1'), $method_calls[0][1][0]);
$this
->assertEquals('extra', $method_calls[0][1][1]);
}
public function testProcessWithIdAndExtraArguments() {
$container = $this
->buildContainer();
$container
->register('consumer_id', __NAMESPACE__ . '\\ValidConsumerWithExtraArguments')
->addTag('service_collector', [
'call' => 'addWithId',
]);
$container
->register('handler1', __NAMESPACE__ . '\\ValidHandler')
->addTag('consumer_id', [
'extra1' => 'extra1',
]);
$handler_pass = new TaggedHandlersPass();
$handler_pass
->process($container);
$method_calls = $container
->getDefinition('consumer_id')
->getMethodCalls();
$this
->assertCount(5, $method_calls[0][1]);
$this
->assertEquals(new Reference('handler1'), $method_calls[0][1][0]);
$this
->assertEquals('handler1', $method_calls[0][1][1]);
$this
->assertEquals(0, $method_calls[0][1][2]);
$this
->assertEquals('extra1', $method_calls[0][1][3]);
$this
->assertNull($method_calls[0][1][4]);
}
public function testProcessWithDifferentArgumentsOrderAndDefaultValue() {
$container = $this
->buildContainer();
$container
->register('consumer_id', __NAMESPACE__ . '\\ValidConsumerWithExtraArguments')
->addTag('service_collector', [
'call' => 'addWithDifferentOrder',
]);
$container
->register('handler1', __NAMESPACE__ . '\\ValidHandler')
->addTag('consumer_id', [
'priority' => 0,
'extra1' => 'extra1',
'extra3' => 'extra3',
]);
$handler_pass = new TaggedHandlersPass();
$handler_pass
->process($container);
$method_calls = $container
->getDefinition('consumer_id')
->getMethodCalls();
$this
->assertCount(5, $method_calls[0][1]);
$expected = [
new Reference('handler1'),
'extra1',
0,
'default2',
'extra3',
];
$this
->assertEquals($expected, array_values($method_calls[0][1]));
}
}
interface HandlerInterface {
}
class ValidConsumer {
public function addHandler(HandlerInterface $instance, $priority = 0) {
}
public function addNoPriority(HandlerInterface $instance) {
}
public function addWithId(HandlerInterface $instance, $id, $priority = 0) {
}
}
class InvalidConsumer {
public function addHandler($instance, $priority = 0) {
}
}
class ValidConsumerWithExtraArguments {
public function addHandler(HandlerInterface $instance, $priority = 0, $extra1 = '', $extra2 = '') {
}
public function addNoPriority(HandlerInterface $instance, $extra) {
}
public function addWithId(HandlerInterface $instance, $id, $priority = 0, $extra1 = '', $extra2 = NULL) {
}
public function addWithDifferentOrder(HandlerInterface $instance, $extra1, $priority = 0, $extra2 = 'default2', $extra3 = 'default3') {
}
}
class ValidHandler implements HandlerInterface {
}
class InvalidHandler {
}