diff --git a/.travis.yml b/.travis.yml index 9c9821d88..a6b4a6c30 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,7 +45,12 @@ jobs: - php: 7.1 env: stability=RC SYMFONY_DEPRECATIONS_HELPER=weak SYMFONY_VERSION="3.4.*" install: - - composer config minimum-stability RC + - travis_retry composer update -n --prefer-dist + + - php: 7.1 + env: stability=dev SYMFONY_DEPRECATIONS_HELPER=weak SYMFONY_VERSION="4.1.*" + install: + - composer require --dev "symfony/messenger" --no-update - travis_retry composer update -n --prefer-dist - php: 7.2 diff --git a/DependencyInjection/Compiler/MessengerPass.php b/DependencyInjection/Compiler/MessengerPass.php new file mode 100644 index 000000000..1ee532430 --- /dev/null +++ b/DependencyInjection/Compiler/MessengerPass.php @@ -0,0 +1,27 @@ +hasAlias('message_bus') && is_subclass_of($container->findDefinition('message_bus')->getClass(), MessageBusInterface::class)) { + return; + } + + // Remove wired services if the Messenger component actually isn't enabled: + $container->removeDefinition('doctrine.orm.messenger.middleware_factory.transaction'); + $container->removeDefinition('messenger.middleware.doctrine_transaction_middleware'); + } +} diff --git a/DependencyInjection/DoctrineExtension.php b/DependencyInjection/DoctrineExtension.php index b9eaee737..1959003f7 100644 --- a/DependencyInjection/DoctrineExtension.php +++ b/DependencyInjection/DoctrineExtension.php @@ -9,6 +9,7 @@ use Doctrine\ORM\Version; use Symfony\Bridge\Doctrine\DependencyInjection\AbstractDoctrineExtension; use Symfony\Bridge\Doctrine\Form\Type\DoctrineType; +use Symfony\Bridge\Doctrine\Messenger\DoctrineTransactionMiddlewareFactory; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\ChildDefinition; @@ -20,6 +21,7 @@ use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ServiceLocator; use Symfony\Component\Form\AbstractType; +use Symfony\Component\Messenger\MessageBusInterface; /** * DoctrineExtension is an extension for the Doctrine DBAL and ORM library. @@ -388,6 +390,16 @@ protected function ormLoad(array $config, ContainerBuilder $container) ->addTag(ServiceRepositoryCompilerPass::REPOSITORY_SERVICE_TAG); } + // If the Messenger component is installed and the doctrine transaction middleware factory is available, wire it: + if (interface_exists(MessageBusInterface::class) && class_exists(DoctrineTransactionMiddlewareFactory::class)) { + $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); + $loader->load('messenger.xml'); + + $container->getDefinition('messenger.middleware.doctrine_transaction_middleware') + ->replaceArgument(0, $config['default_entity_manager']) + ; + } + /* * Compatibility for Symfony 3.2 and lower: gives the service a default argument. * When DoctrineBundle requires 3.3 or higher, this can be moved to an anonymous diff --git a/DoctrineBundle.php b/DoctrineBundle.php index 637d6ed97..5c0fe757a 100644 --- a/DoctrineBundle.php +++ b/DoctrineBundle.php @@ -3,6 +3,7 @@ namespace Doctrine\Bundle\DoctrineBundle; use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\EntityListenerPass; +use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\MessengerPass; use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\ServiceRepositoryCompilerPass; use Doctrine\Common\Util\ClassUtils; use Doctrine\ORM\Proxy\Autoloader; @@ -38,6 +39,7 @@ public function build(ContainerBuilder $container) $container->addCompilerPass(new DoctrineValidationPass('orm')); $container->addCompilerPass(new EntityListenerPass()); $container->addCompilerPass(new ServiceRepositoryCompilerPass()); + $container->addCompilerPass(new MessengerPass()); } /** diff --git a/Resources/config/messenger.xml b/Resources/config/messenger.xml new file mode 100644 index 000000000..c44d38599 --- /dev/null +++ b/Resources/config/messenger.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + diff --git a/Tests/DependencyInjection/Compiler/MessengerPassTest.php b/Tests/DependencyInjection/Compiler/MessengerPassTest.php new file mode 100644 index 000000000..968a5e4ba --- /dev/null +++ b/Tests/DependencyInjection/Compiler/MessengerPassTest.php @@ -0,0 +1,68 @@ +markTestSkipped('Symfony Messenger component is not installed'); + } + + public function testRemovesDefinitionsWhenMessengerComponentIsDisabled() + { + $pass = new MessengerPass(); + $container = new ContainerBuilder(); + $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../../../Resources/config')); + $loader->load('messenger.xml'); + + $pass->process($container); + + $this->assertFalse($container->hasDefinition('doctrine.orm.messenger.middleware_factory.transaction')); + $this->assertFalse($container->hasDefinition('messenger.middleware.doctrine_transaction_middleware')); + } + + public function testRemoveDefinitionsWhenHasAliasButNotMessengerComponent() + { + $pass = new MessengerPass(); + $container = new ContainerBuilder(); + $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../../../Resources/config')); + $loader->load('messenger.xml'); + + $container->register('some_other_bus', \stdClass::class); + $container->setAlias('message_bus', 'some_other_bus'); + + $pass->process($container); + + $this->assertFalse($container->hasDefinition('doctrine.orm.messenger.middleware_factory.transaction')); + $this->assertFalse($container->hasDefinition('messenger.middleware.doctrine_transaction_middleware')); + } + + public function testDoesNotRemoveDefinitionsWhenMessengerComponentIsEnabled() + { + $pass = new MessengerPass(); + $container = new ContainerBuilder(); + $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../../../Resources/config')); + $loader->load('messenger.xml'); + + $container->register('messenger.bus.default', MessageBus::class); + $container->setAlias('message_bus', 'messenger.bus.default'); + + $pass->process($container); + + $this->assertTrue($container->hasDefinition('doctrine.orm.messenger.middleware_factory.transaction')); + $this->assertTrue($container->hasDefinition('messenger.middleware.doctrine_transaction_middleware')); + } +} diff --git a/Tests/DependencyInjection/DoctrineExtensionTest.php b/Tests/DependencyInjection/DoctrineExtensionTest.php index a3e1c7dbe..408dca345 100644 --- a/Tests/DependencyInjection/DoctrineExtensionTest.php +++ b/Tests/DependencyInjection/DoctrineExtensionTest.php @@ -18,6 +18,7 @@ use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\Messenger\MessageBusInterface; class DoctrineExtensionTest extends TestCase { @@ -676,6 +677,31 @@ public function testAnnotationsBundleMappingDetectionWithVendorNamespace() $this->assertEquals('Fixtures\Bundles\Vendor\AnnotationsBundle\Entity', $calls[0][1][1]); } + public function testMessengerIntegration() + { + if (! interface_exists(MessageBusInterface::class)) { + $this->markTestSkipped('Symfony Messenger component is not installed'); + } + + $container = $this->getContainer(); + $extension = new DoctrineExtension(); + + $config = BundleConfigurationBuilder::createBuilder() + ->addBaseConnection() + ->addEntityManager([ + 'default_entity_manager' => 'default', + 'entity_managers' => [ + 'default' => [], + ], + ]) + ->build(); + $extension->load([$config], $container); + + $this->assertNotNull($container->getDefinition('doctrine.orm.messenger.middleware_factory.transaction')); + $this->assertNotNull($middlewarePrototype = $container->getDefinition('messenger.middleware.doctrine_transaction_middleware')); + $this->assertSame('default', $middlewarePrototype->getArgument(0)); + } + public function testCacheConfiguration() { $container = $this->getContainer();