diff --git a/config/services.xml b/config/services.xml
index cb978718..b0e3154f 100644
--- a/config/services.xml
+++ b/config/services.xml
@@ -11,6 +11,14 @@
+
+ Doctrine\Migrations\Finder\MigrationFinder
+
+
+
+ Doctrine\Migrations\MigrationsRepository
+
+
@@ -146,6 +154,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ migrations locator
+
+
+
+
+
+
+
+
+ migrations locator
+
+
diff --git a/src/DependencyInjection/CompilerPass/RegisterMigrationsPass.php b/src/DependencyInjection/CompilerPass/RegisterMigrationsPass.php
new file mode 100644
index 00000000..b4795b9f
--- /dev/null
+++ b/src/DependencyInjection/CompilerPass/RegisterMigrationsPass.php
@@ -0,0 +1,44 @@
+findTaggedServiceIds('doctrine_migrations.migration', true) as $id => $attributes) {
+ $definition = $container->getDefinition($id);
+ $definition->setBindings([
+ Connection::class => new BoundArgument(new Reference('doctrine.migrations.connection')),
+ LoggerInterface::class => new BoundArgument(new Reference('doctrine.migrations.logger')),
+ ]);
+
+ $migrationRefs[$id] = new TypedReference($id, $definition->getClass());
+ }
+
+ if ($migrationRefs !== []) {
+ $container->getDefinition('doctrine.migrations.filter_service_migration_finder')
+ ->replaceArgument(1, new ServiceLocatorArgument($migrationRefs));
+ $container->getDefinition('doctrine.migrations.service_migrations_repository')
+ ->replaceArgument(1, new ServiceLocatorArgument($migrationRefs));
+ } else {
+ $container->removeDefinition('doctrine.migrations.connection');
+ $container->removeDefinition('doctrine.migrations.logger');
+ $container->removeDefinition('doctrine.migrations.filter_service_migration_finder');
+ $container->removeDefinition('doctrine.migrations.service_migrations_repository');
+ }
+ }
+}
diff --git a/src/DependencyInjection/DoctrineMigrationsExtension.php b/src/DependencyInjection/DoctrineMigrationsExtension.php
index 0bdb9056..75a81319 100644
--- a/src/DependencyInjection/DoctrineMigrationsExtension.php
+++ b/src/DependencyInjection/DoctrineMigrationsExtension.php
@@ -6,6 +6,7 @@
use Doctrine\Bundle\MigrationsBundle\Collector\MigrationsCollector;
use Doctrine\Bundle\MigrationsBundle\Collector\MigrationsFlattener;
+use Doctrine\Migrations\AbstractMigration;
use Doctrine\Migrations\Metadata\Storage\MetadataStorage;
use Doctrine\Migrations\Metadata\Storage\TableMetadataStorageConfiguration;
use Doctrine\Migrations\Version\MigrationFactory;
@@ -48,6 +49,9 @@ public function load(array $configs, ContainerBuilder $container): void
$loader->load('services.xml');
+ $container->registerForAutoconfiguration(AbstractMigration::class)
+ ->addTag('doctrine_migrations.migration');
+
$configurationDefinition = $container->getDefinition('doctrine.migrations.configuration');
foreach ($config['migrations_paths'] as $ns => $path) {
diff --git a/src/DoctrineMigrationsBundle.php b/src/DoctrineMigrationsBundle.php
index 6b3f22f3..648bdb89 100644
--- a/src/DoctrineMigrationsBundle.php
+++ b/src/DoctrineMigrationsBundle.php
@@ -5,6 +5,7 @@
namespace Doctrine\Bundle\MigrationsBundle;
use Doctrine\Bundle\MigrationsBundle\DependencyInjection\CompilerPass\ConfigureDependencyFactoryPass;
+use Doctrine\Bundle\MigrationsBundle\DependencyInjection\CompilerPass\RegisterMigrationsPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
@@ -12,10 +13,10 @@
class DoctrineMigrationsBundle extends Bundle
{
- /** @return void */
- public function build(ContainerBuilder $container)
+ public function build(ContainerBuilder $container): void
{
$container->addCompilerPass(new ConfigureDependencyFactoryPass());
+ $container->addCompilerPass(new RegisterMigrationsPass());
}
public function getPath(): string
diff --git a/src/MigrationFinder/FilterServiceMigrationFinder.php b/src/MigrationFinder/FilterServiceMigrationFinder.php
new file mode 100644
index 00000000..53860da8
--- /dev/null
+++ b/src/MigrationFinder/FilterServiceMigrationFinder.php
@@ -0,0 +1,46 @@
+migrationFinder = $migrationFinder;
+ $this->container = $container;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function findMigrations(string $directory, ?string $namespace = null): array
+ {
+ $migrations = $this->migrationFinder->findMigrations(
+ $directory,
+ $namespace
+ );
+
+ foreach ($migrations as $i => $migration) {
+ if (! $this->container->has($migration)) {
+ continue;
+ }
+
+ unset($migrations[$i]);
+ }
+
+ return array_values($migrations);
+ }
+}
diff --git a/src/MigrationsRepository/ServiceMigrationsRepository.php b/src/MigrationsRepository/ServiceMigrationsRepository.php
new file mode 100644
index 00000000..43ebf30a
--- /dev/null
+++ b/src/MigrationsRepository/ServiceMigrationsRepository.php
@@ -0,0 +1,95 @@
+ */
+ private $container;
+
+ /** @var AvailableMigration[] */
+ private $migrations = [];
+
+ /** @param ServiceProviderInterface $container */
+ public function __construct(
+ MigrationsRepository $migrationRepository,
+ ServiceProviderInterface $container
+ ) {
+ $this->migrationRepository = $migrationRepository;
+ $this->container = $container;
+ }
+
+ public function hasMigration(string $version): bool
+ {
+ return $this->container->has($version) || $this->migrationRepository->hasMigration($version);
+ }
+
+ public function getMigration(Version $version): AvailableMigration
+ {
+ if (! isset($this->migrations[(string) $version]) && ! $this->loadMigrationFromContainer($version)) {
+ return $this->migrationRepository->getMigration($version);
+ }
+
+ return $this->migrations[(string) $version];
+ }
+
+ /**
+ * Returns a non-sorted set of migrations.
+ */
+ public function getMigrations(): AvailableMigrationsSet
+ {
+ $this->loadMigrationsFromContainer();
+
+ $migrations = $this->migrations;
+ foreach ($this->migrationRepository->getMigrations()->getItems() as $availableMigration) {
+ $version = $availableMigration->getVersion();
+
+ if (isset($migrations[(string) $version])) {
+ throw DuplicateMigrationVersion::new(
+ (string) $version,
+ (string) $version
+ );
+ }
+
+ $migrations[(string) $version] = $availableMigration;
+ }
+
+ return new AvailableMigrationsSet($migrations);
+ }
+
+ private function loadMigrationsFromContainer(): void
+ {
+ foreach ($this->container->getProvidedServices() as $id) {
+ if (isset($this->migrations[$id])) {
+ continue;
+ }
+
+ $this->loadMigrationFromContainer(new Version($id));
+ }
+ }
+
+ private function loadMigrationFromContainer(Version $version): bool
+ {
+ if (! $this->container->has((string) $version)) {
+ return false;
+ }
+
+ $migration = $this->container->get((string) $version);
+ $this->migrations[(string) $version] = new AvailableMigration($version, $migration);
+
+ return true;
+ }
+}