FilesystemMigrationsRepository.php 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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. /** @var bool */
  22. private $migrationsLoaded = false;
  23. /** @var array<string, string> */
  24. private $migrationDirectories;
  25. /** @var MigrationFinder */
  26. private $migrationFinder;
  27. /** @var MigrationFactory */
  28. private $versionFactory;
  29. /** @var AvailableMigration[] */
  30. private $migrations = [];
  31. /**
  32. * @param string[] $classes
  33. * @param array<string, string> $migrationDirectories
  34. */
  35. public function __construct(
  36. array $classes,
  37. array $migrationDirectories,
  38. MigrationFinder $migrationFinder,
  39. MigrationFactory $versionFactory
  40. ) {
  41. $this->migrationDirectories = $migrationDirectories;
  42. $this->migrationFinder = $migrationFinder;
  43. $this->versionFactory = $versionFactory;
  44. $this->registerMigrations($classes);
  45. }
  46. private function registerMigrationInstance(Version $version, AbstractMigration $migration): AvailableMigration
  47. {
  48. if (isset($this->migrations[(string) $version])) {
  49. throw DuplicateMigrationVersion::new(
  50. (string) $version,
  51. (string) $version
  52. );
  53. }
  54. $this->migrations[(string) $version] = new AvailableMigration($version, $migration);
  55. return $this->migrations[(string) $version];
  56. }
  57. /** @throws MigrationException */
  58. public function registerMigration(string $migrationClassName): AvailableMigration
  59. {
  60. $this->ensureMigrationClassExists($migrationClassName);
  61. $version = new Version($migrationClassName);
  62. $migration = $this->versionFactory->createVersion($migrationClassName);
  63. return $this->registerMigrationInstance($version, $migration);
  64. }
  65. /**
  66. * @param string[] $migrations
  67. *
  68. * @return AvailableMigration[]
  69. */
  70. private function registerMigrations(array $migrations): array
  71. {
  72. $versions = [];
  73. foreach ($migrations as $class) {
  74. $versions[] = $this->registerMigration($class);
  75. }
  76. return $versions;
  77. }
  78. public function hasMigration(string $version): bool
  79. {
  80. $this->loadMigrationsFromDirectories();
  81. return isset($this->migrations[$version]);
  82. }
  83. public function getMigration(Version $version): AvailableMigration
  84. {
  85. $this->loadMigrationsFromDirectories();
  86. if (! isset($this->migrations[(string) $version])) {
  87. throw MigrationClassNotFound::new((string) $version);
  88. }
  89. return $this->migrations[(string) $version];
  90. }
  91. /**
  92. * Returns a non-sorted set of migrations.
  93. */
  94. public function getMigrations(): AvailableMigrationsSet
  95. {
  96. $this->loadMigrationsFromDirectories();
  97. return new AvailableMigrationsSet($this->migrations);
  98. }
  99. /** @throws MigrationException */
  100. private function ensureMigrationClassExists(string $class): void
  101. {
  102. if (! class_exists($class)) {
  103. throw MigrationClassNotFound::new($class);
  104. }
  105. }
  106. private function loadMigrationsFromDirectories(): void
  107. {
  108. $migrationDirectories = $this->migrationDirectories;
  109. if ($this->migrationsLoaded) {
  110. return;
  111. }
  112. $this->migrationsLoaded = true;
  113. foreach ($migrationDirectories as $namespace => $path) {
  114. $migrations = $this->migrationFinder->findMigrations(
  115. $path,
  116. $namespace
  117. );
  118. $this->registerMigrations($migrations);
  119. }
  120. }
  121. }