diff --git a/DependencyInjection/DoctrineMigrationsExtension.php b/DependencyInjection/DoctrineMigrationsExtension.php index 7b2e525..87f75cb 100644 --- a/DependencyInjection/DoctrineMigrationsExtension.php +++ b/DependencyInjection/DoctrineMigrationsExtension.php @@ -7,12 +7,19 @@ use Doctrine\Migrations\Metadata\Storage\MetadataStorage; use Doctrine\Migrations\Metadata\Storage\TableMetadataStorageConfiguration; use InvalidArgumentException; +use RuntimeException; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpKernel\DependencyInjection\Extension; +use function array_keys; +use function explode; +use function implode; +use function sprintf; +use function strlen; +use function substr; /** * DoctrineMigrationsExtension. @@ -38,6 +45,7 @@ public function load(array $configs, ContainerBuilder $container) : void $configurationDefinition = $container->getDefinition('doctrine.migrations.configuration'); foreach ($config['migrations_paths'] as $ns => $path) { + $path = $this->checkIfBundleRelativePath($path, $container); $configurationDefinition->addMethodCall('addMigrationsDirectory', [$ns, $path]); } @@ -98,6 +106,34 @@ public function load(array $configs, ContainerBuilder $container) : void $container->setParameter('doctrine.migrations.preferred_connection', $config['connection']); } + private function checkIfBundleRelativePath(string $path, ContainerBuilder $container) : string + { + if (isset($path[0]) && $path[0] === '@') { + $pathParts = explode('/', $path); + $bundleName = substr($pathParts[0], 1); + + $bundlePath = $this->getBundlePath($bundleName, $container); + return $bundlePath . substr($path, strlen('@' . $bundleName)); + } + + return $path; + } + + private function getBundlePath(string $bundleName, ContainerBuilder $container) : string + { + $bundleMetadata = $container->getParameter('kernel.bundles_metadata'); + + if (! isset($bundleMetadata[$bundleName])) { + throw new RuntimeException(sprintf( + 'The bundle "%s" has not been registered, available bundles: %s', + $bundleName, + implode(', ', array_keys($bundleMetadata)) + )); + } + + return $bundleMetadata[$bundleName]['path']; + } + /** * Returns the base path for the XSD files. * diff --git a/Resources/doc/index.rst b/Resources/doc/index.rst index c7623e3..3d4b015 100644 --- a/Resources/doc/index.rst +++ b/Resources/doc/index.rst @@ -47,6 +47,7 @@ application: migrations_paths: 'App\Migrations': 'src/App' 'AnotherApp\Migrations': '/path/to/other/migrations' + 'SomeBundle\Migrations': '@SomeBundle/Migrations' # List of additional migration classes to be loaded, optional migrations: diff --git a/Tests/DependencyInjection/DoctrineMigrationsExtensionTest.php b/Tests/DependencyInjection/DoctrineMigrationsExtensionTest.php index a892550..85e3695 100644 --- a/Tests/DependencyInjection/DoctrineMigrationsExtensionTest.php +++ b/Tests/DependencyInjection/DoctrineMigrationsExtensionTest.php @@ -7,6 +7,7 @@ use Doctrine\Bundle\MigrationsBundle\DependencyInjection\DoctrineMigrationsExtension; use Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle; use Doctrine\Bundle\MigrationsBundle\Tests\Fixtures\CustomEntityManager; +use Doctrine\Bundle\MigrationsBundle\Tests\Fixtures\TestBundle\TestBundle; use Doctrine\DBAL\Connection; use Doctrine\Migrations\Configuration\Configuration; use Doctrine\Migrations\DependencyFactory; @@ -101,6 +102,30 @@ public function testNoConfigsAreNeeded() : void self::assertSame([], $config->getMigrationDirectories()); } + public function testBundleRelativePathResolution() : void + { + $container = $this->getContainer([ + 'migrations_paths' => [ + 'DoctrineMigrationsTest' => '@TestBundle', + 'DoctrineMigrationsTestAnother' => '@TestBundle/another-path', + ], + ]); + + $conn = $this->createMock(Connection::class); + $container->set('doctrine.dbal.default_connection', $conn); + $container->compile(); + + $config = $container->get('doctrine.migrations.configuration'); + $bundle = new TestBundle(); + + self::assertInstanceOf(Configuration::class, $config); + self::assertSame([ + 'DoctrineMigrationsTest' => $bundle->getPath(), + 'DoctrineMigrationsTestAnother' => $bundle->getPath() . '/another-path', + + ], $config->getMigrationDirectories()); + } + private function assertConfigs(?object $config) : void { self::assertInstanceOf(Configuration::class, $config); @@ -288,9 +313,16 @@ private function getContainer(array $config) : ContainerBuilder private function getContainerBuilder() : ContainerBuilder { + $bundle = new TestBundle(); return new ContainerBuilder(new ParameterBag([ 'kernel.debug' => false, - 'kernel.bundles' => [], + 'kernel.bundles' => [$bundle->getName() => TestBundle::class], + 'kernel.bundles_metadata' => [ + $bundle->getName() => [ + 'path' => $bundle->getPath(), + 'namespace' => $bundle->getNamespace(), + ], + ], 'kernel.cache_dir' => sys_get_temp_dir(), 'kernel.environment' => 'test', 'kernel.project_dir' => __DIR__ . '/../', diff --git a/Tests/Fixtures/TestBundle/TestBundle.php b/Tests/Fixtures/TestBundle/TestBundle.php new file mode 100644 index 0000000..1408d4e --- /dev/null +++ b/Tests/Fixtures/TestBundle/TestBundle.php @@ -0,0 +1,11 @@ +