diff --git a/mailpoet/lib/Migrator/MigratorException.php b/mailpoet/lib/Migrator/MigratorException.php index d724c767b3..981fae3805 100644 --- a/mailpoet/lib/Migrator/MigratorException.php +++ b/mailpoet/lib/Migrator/MigratorException.php @@ -18,6 +18,12 @@ class MigratorException extends InvalidStateException { ); } + public static function duplicateMigrationNames(array $names): self { + return self::create()->withMessage( + sprintf('Duplicate migration names are not allowed. Duplicate names found: "%s".', join(', ', $names)) + ); + } + public static function migrationFileWriteFailed(string $path): self { return self::create()->withMessage( sprintf('Could not write migration file "%s".', $path) diff --git a/mailpoet/lib/Migrator/Repository.php b/mailpoet/lib/Migrator/Repository.php index 7298496725..91d17920e2 100644 --- a/mailpoet/lib/Migrator/Repository.php +++ b/mailpoet/lib/Migrator/Repository.php @@ -55,10 +55,15 @@ class Repository { * @return array */ public function loadAll(): array { - return array_merge( + $migrations = array_merge( $this->loadForLevel(self::MIGRATIONS_LEVEL_DB), $this->loadForLevel(self::MIGRATIONS_LEVEL_APP) ); + $duplicateNames = array_diff_assoc(array_column($migrations, 'name'), array_unique(array_column($migrations, 'name'))); + if (!empty($duplicateNames)) { + throw MigratorException::duplicateMigrationNames($duplicateNames); + } + return $migrations; } private function loadForLevel(string $level): array { diff --git a/mailpoet/tests/unit/Migrator/RepositoryTest.php b/mailpoet/tests/unit/Migrator/RepositoryTest.php index 5271569b55..a48b545278 100644 --- a/mailpoet/tests/unit/Migrator/RepositoryTest.php +++ b/mailpoet/tests/unit/Migrator/RepositoryTest.php @@ -59,6 +59,18 @@ class RepositoryTest extends MailPoetUnitTest { $repository->create('abc'); } + public function testItFailsWhenThereAreMigrationsWithDuplicateNames(): void { + $migrationsDir = __DIR__ . '/TestMigrationsDuplicates'; + $repository = $this->make(Repository::class, [ + 'migrationsDir' => $migrationsDir, + 'templateFile' => self::TEMPLATE_FILE, + ]); + + $this->expectException(MigratorException::class); + $this->expectExceptionMessage('Duplicate migration names are not allowed. Duplicate names found: "MigrationDuplicate".'); + $repository->loadAll(); + } + public function testItLoadsMigrationFiles(): void { $repository = $this->make(Repository::class, [ 'migrationsDir' => __DIR__ . '/TestMigrations', diff --git a/mailpoet/tests/unit/Migrator/TestMigrationsDuplicates/App/MigrationDuplicate.php b/mailpoet/tests/unit/Migrator/TestMigrationsDuplicates/App/MigrationDuplicate.php new file mode 100644 index 0000000000..039c7c3ce8 --- /dev/null +++ b/mailpoet/tests/unit/Migrator/TestMigrationsDuplicates/App/MigrationDuplicate.php @@ -0,0 +1,11 @@ +