*/ private array $migrationDirectories; private MigrationFinder $migrationFinder; private MigrationFactory $versionFactory; /** @var AvailableMigration[] */ private array $migrations = []; /** * @param string[] $classes * @param array $migrationDirectories */ public function __construct( array $classes, array $migrationDirectories, MigrationFinder $migrationFinder, MigrationFactory $versionFactory ) { $this->migrationDirectories = $migrationDirectories; $this->migrationFinder = $migrationFinder; $this->versionFactory = $versionFactory; $this->registerMigrations($classes); } private function registerMigrationInstance(Version $version, AbstractMigration $migration): AvailableMigration { if (isset($this->migrations[(string) $version])) { throw DuplicateMigrationVersion::new( (string) $version, (string) $version ); } $this->migrations[(string) $version] = new AvailableMigration($version, $migration); return $this->migrations[(string) $version]; } /** @throws MigrationException */ public function registerMigration(string $migrationClassName): AvailableMigration { $this->ensureMigrationClassExists($migrationClassName); $version = new Version($migrationClassName); $migration = $this->versionFactory->createVersion($migrationClassName); return $this->registerMigrationInstance($version, $migration); } /** * @param string[] $migrations * * @return AvailableMigration[] */ private function registerMigrations(array $migrations): array { $versions = []; foreach ($migrations as $class) { $versions[] = $this->registerMigration($class); } return $versions; } public function hasMigration(string $version): bool { $this->loadMigrationsFromDirectories(); return isset($this->migrations[$version]); } public function getMigration(Version $version): AvailableMigration { $this->loadMigrationsFromDirectories(); if (! isset($this->migrations[(string) $version])) { throw MigrationClassNotFound::new((string) $version); } return $this->migrations[(string) $version]; } /** * Returns a non-sorted set of migrations. */ public function getMigrations(): AvailableMigrationsSet { $this->loadMigrationsFromDirectories(); return new AvailableMigrationsSet($this->migrations); } /** @throws MigrationException */ private function ensureMigrationClassExists(string $class): void { if (! class_exists($class)) { throw MigrationClassNotFound::new($class); } } private function loadMigrationsFromDirectories(): void { $migrationDirectories = $this->migrationDirectories; if ($this->migrationsLoaded) { return; } $this->migrationsLoaded = true; foreach ($migrationDirectories as $namespace => $path) { $migrations = $this->migrationFinder->findMigrations( $path, $namespace ); $this->registerMigrations($migrations); } } }