From c85cd25149d82fbc7ae20d03d76f5168a67f39ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Paris?= Date: Thu, 14 Mar 2024 16:20:20 +0100 Subject: [PATCH] Add support for --complete When using orm:schema-tool:update together with --complete, all assets not described by the current metadata is dropped. This is an issue when using doctrine/migrations, because not using that option is deprecated, and because when it is used, the table that holds the migrations is dropped as well since it is not described by ORM metadata. A solution to that is configuring an asset filter that filters out the metadata table except when running commands inside the migrations namespace. --- config/services.xml | 5 ++ .../DoctrineMigrationsExtension.php | 10 +++- src/EventListener/SchemaFilterListener.php | 58 +++++++++++++++++++ .../SchemaFilterListenerTest.php | 39 +++++++++++++ 4 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 src/EventListener/SchemaFilterListener.php create mode 100644 tests/Collector/EventListener/SchemaFilterListenerTest.php diff --git a/config/services.xml b/config/services.xml index cb97871..a96aa09 100644 --- a/config/services.xml +++ b/config/services.xml @@ -146,6 +146,11 @@ + + + + + diff --git a/src/DependencyInjection/DoctrineMigrationsExtension.php b/src/DependencyInjection/DoctrineMigrationsExtension.php index 1bb753d..5e6645f 100644 --- a/src/DependencyInjection/DoctrineMigrationsExtension.php +++ b/src/DependencyInjection/DoctrineMigrationsExtension.php @@ -90,15 +90,21 @@ public function load(array $configs, ContainerBuilder $container): void $diDefinition->addMethodCall('setDefinition', [$doctrineId, new Reference($symfonyId)]); } - if (! isset($config['services'][MetadataStorage::class])) { + if (isset($config['services'][MetadataStorage::class])) { + $container->removeDefinition('doctrine_migrations.schema_filter_listener'); + } else { + $filterDefinition = $container->getDefinition('doctrine_migrations.schema_filter_listener'); $storageConfiguration = $config['storage']['table_storage']; $storageDefinition = new Definition(TableMetadataStorageConfiguration::class); $container->setDefinition('doctrine.migrations.storage.table_storage', $storageDefinition); $container->setAlias('doctrine.migrations.metadata_storage', 'doctrine.migrations.storage.table_storage'); - if ($storageConfiguration['table_name'] !== null) { + if ($storageConfiguration['table_name'] === null) { + $filterDefinition->addArgument('doctrine_migration_versions'); + } else { $storageDefinition->addMethodCall('setTableName', [$storageConfiguration['table_name']]); + $filterDefinition->addArgument($storageConfiguration['table_name']); } if ($storageConfiguration['version_column_name'] !== null) { diff --git a/src/EventListener/SchemaFilterListener.php b/src/EventListener/SchemaFilterListener.php new file mode 100644 index 0000000..203739b --- /dev/null +++ b/src/EventListener/SchemaFilterListener.php @@ -0,0 +1,58 @@ +configurationTableName = $configurationTableName; + } + + /** @var bool */ + private $enabled = true; + + /** @param AbstractAsset|string $asset */ + public function __invoke($asset): bool + { + if (! $this->enabled) { + return true; + } + + if ($asset instanceof AbstractAsset) { + $asset = $asset->getName(); + } + + return $asset !== $this->configurationTableName; + } + + private function disable(): void + { + $this->enabled = false; + } + + public function onConsoleCommand(ConsoleCommandEvent $event): void + { + $command = $event->getCommand(); + + if (! $command instanceof DoctrineCommand) { + return; + } + + $this->disable(); + } +} diff --git a/tests/Collector/EventListener/SchemaFilterListenerTest.php b/tests/Collector/EventListener/SchemaFilterListenerTest.php new file mode 100644 index 0000000..2d2e0a1 --- /dev/null +++ b/tests/Collector/EventListener/SchemaFilterListenerTest.php @@ -0,0 +1,39 @@ +onConsoleCommand(new ConsoleCommandEvent( + $migrationsCommand, + new ArrayInput([]), + new NullOutput() + )); + + self::assertTrue($listener(new Table('doctrine_migration_versions'))); + } +}