vendor/doctrine/migrations/src/FilesystemMigrationsRepository.php line 64

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace Doctrine\Migrations;
  4. use Doctrine\Migrations\Exception\DuplicateMigrationVersion;
  5. use Doctrine\Migrations\Exception\MigrationClassNotFound;
  6. use Doctrine\Migrations\Exception\MigrationException;
  7. use Doctrine\Migrations\Finder\MigrationFinder;
  8. use Doctrine\Migrations\Metadata\AvailableMigration;
  9. use Doctrine\Migrations\Metadata\AvailableMigrationsSet;
  10. use Doctrine\Migrations\Version\MigrationFactory;
  11. use Doctrine\Migrations\Version\Version;
  12. use function class_exists;
  13. /**
  14. * The FilesystemMigrationsRepository class is responsible for retrieving migrations, determining what the current migration
  15. * version, etc.
  16. *
  17. * @internal
  18. */
  19. class FilesystemMigrationsRepository implements MigrationsRepository
  20. {
  21. private bool $migrationsLoaded = false;
  22. /** @var AvailableMigration[] */
  23. private array $migrations = [];
  24. /**
  25. * @param string[] $classes
  26. * @param array<string, string> $migrationDirectories
  27. */
  28. public function __construct(
  29. array $classes,
  30. private readonly array $migrationDirectories,
  31. private readonly MigrationFinder $migrationFinder,
  32. private readonly MigrationFactory $versionFactory,
  33. ) {
  34. $this->registerMigrations($classes);
  35. }
  36. private function registerMigrationInstance(Version $version, AbstractMigration $migration): AvailableMigration
  37. {
  38. if (isset($this->migrations[(string) $version])) {
  39. throw DuplicateMigrationVersion::new(
  40. (string) $version,
  41. (string) $version,
  42. );
  43. }
  44. $this->migrations[(string) $version] = new AvailableMigration($version, $migration);
  45. return $this->migrations[(string) $version];
  46. }
  47. /** @throws MigrationException */
  48. public function registerMigration(string $migrationClassName): AvailableMigration
  49. {
  50. $this->ensureMigrationClassExists($migrationClassName);
  51. $version = new Version($migrationClassName);
  52. $migration = $this->versionFactory->createVersion($migrationClassName);
  53. return $this->registerMigrationInstance($version, $migration);
  54. }
  55. /**
  56. * @param string[] $migrations
  57. *
  58. * @return AvailableMigration[]
  59. */
  60. private function registerMigrations(array $migrations): array
  61. {
  62. $versions = [];
  63. foreach ($migrations as $class) {
  64. $versions[] = $this->registerMigration($class);
  65. }
  66. return $versions;
  67. }
  68. public function hasMigration(string $version): bool
  69. {
  70. $this->loadMigrationsFromDirectories();
  71. return isset($this->migrations[$version]);
  72. }
  73. public function getMigration(Version $version): AvailableMigration
  74. {
  75. $this->loadMigrationsFromDirectories();
  76. if (! isset($this->migrations[(string) $version])) {
  77. throw MigrationClassNotFound::new((string) $version);
  78. }
  79. return $this->migrations[(string) $version];
  80. }
  81. /**
  82. * Returns a non-sorted set of migrations.
  83. */
  84. public function getMigrations(): AvailableMigrationsSet
  85. {
  86. $this->loadMigrationsFromDirectories();
  87. return new AvailableMigrationsSet($this->migrations);
  88. }
  89. /** @throws MigrationException */
  90. private function ensureMigrationClassExists(string $class): void
  91. {
  92. if (! class_exists($class)) {
  93. throw MigrationClassNotFound::new($class);
  94. }
  95. }
  96. private function loadMigrationsFromDirectories(): void
  97. {
  98. $migrationDirectories = $this->migrationDirectories;
  99. if ($this->migrationsLoaded) {
  100. return;
  101. }
  102. $this->migrationsLoaded = true;
  103. foreach ($migrationDirectories as $namespace => $path) {
  104. $migrations = $this->migrationFinder->findMigrations(
  105. $path,
  106. $namespace,
  107. );
  108. $this->registerMigrations($migrations);
  109. }
  110. }
  111. }