Lines
96.15%
50 / 52
Methods
90.00%
9 / 10
Classes
0.00%
0 / 1
| Name | Lines | Methods | CRAP | ||||
|---|---|---|---|---|---|---|---|
| __construct | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | ||
| register | 100.00% | 3 / 3 | 100.00% | 1 / 1 | 1 | ||
| registerDefaultMigrations | 100.00% | 18 / 18 | 100.00% | 1 / 1 | 1 | ||
| getMigrations | 83.33% | 10 / 12 | 0.00% | 0 / 1 | 5.12 | ||
| getMigration | 100.00% | 2 / 2 | 100.00% | 1 / 1 | 1 | ||
| getVersions | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | ||
| getPendingMigrations | 100.00% | 6 / 6 | 100.00% | 1 / 1 | 3 | ||
| getUnappliedMigrations | 100.00% | 6 / 6 | 100.00% | 1 / 1 | 3 | ||
| getLatestVersion | 100.00% | 2 / 2 | 100.00% | 1 / 1 | 2 | ||
| hasMigration | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | ||
| 24 | class MigrationRegistry | |
| 25 | { | |
| 26 | /** @var array<string, class-string> */ | |
| 27 | private array $migrationClasses = []; | |
| 28 | ||
| 29 | /** @var array<string, MigrationInterface>|null */ | |
| 30 | private ?array $migrations = null; | |
| 31 | ||
| 32 | public function __construct( | |
| 33 | private readonly Configuration $configuration, | |
| 34 | ) { | |
| 35 | $this->registerDefaultMigrations(); | |
| 36 | } | |
| 37 | ||
| 38 | /** | |
| 39 | * Registers a migration class. | |
| 40 | * | |
| 41 | * @param class-string<MigrationInterface> $className | |
| 42 | */ | |
| 43 | public function register(string $version, string $className): self | |
| 44 | { | |
| 45 | $this->migrationClasses[$version] = $className; | |
| 46 | $this->migrations = null; // Reset cache | |
| 47 | return $this; | |
| 48 | } | |
| 49 | ||
| 50 | /** | |
| 51 | * Registers all migrations in the Versions directory. | |
| 52 | */ | |
| 53 | private function registerDefaultMigrations(): void | |
| 54 | { | |
| 55 | $this->migrationClasses = [ | |
| 56 | '3.2.0-alpha' => Versions\Migration320Alpha::class, | |
| 57 | '3.2.0-beta' => Versions\Migration320Beta::class, | |
| 58 | '3.2.0-beta.2' => Versions\Migration320Beta2::class, | |
| 59 | '3.2.0-RC' => Versions\Migration320RC::class, | |
| 60 | '3.2.3' => Versions\Migration323::class, | |
| 61 | '4.0.0-alpha' => Versions\Migration400Alpha::class, | |
| 62 | '4.0.0-alpha.2' => Versions\Migration400Alpha2::class, | |
| 63 | '4.0.0-alpha.3' => Versions\Migration400Alpha3::class, | |
| 64 | '4.0.0-beta.2' => Versions\Migration400Beta2::class, | |
| 65 | '4.0.5' => Versions\Migration405::class, | |
| 66 | '4.0.7' => Versions\Migration407::class, | |
| 67 | '4.0.9' => Versions\Migration409::class, | |
| 68 | '4.1.0-alpha' => Versions\Migration410Alpha::class, | |
| 69 | '4.1.0-alpha.2' => Versions\Migration410Alpha2::class, | |
| 70 | '4.1.0-alpha.3' => Versions\Migration410Alpha3::class, | |
| 71 | '4.2.0-alpha' => Versions\Migration420Alpha::class, | |
| 72 | ]; | |
| 73 | } | |
| 74 | ||
| 75 | /** | |
| 76 | * Returns all registered migrations, sorted by version. | |
| 77 | * | |
| 78 | * @return array<string, MigrationInterface> | |
| 79 | */ | |
| 80 | public function getMigrations(): array | |
| 81 | { | |
| 82 | if ($this->migrations !== null) { | |
| 83 | return $this->migrations; | |
| 84 | } | |
| 85 | ||
| 86 | $this->migrations = []; | |
| 87 | ||
| 88 | foreach ($this->migrationClasses as $version => $className) { | |
| 89 | if (!class_exists($className)) { | |
| 90 | continue; | |
| 91 | } | |
| 92 | ||
| 93 | /* @mago-expect analysis:unknown-class-instantiation - the registry instantiates version-keyed migration classes dynamically */ | |
| 94 | $migration = new $className($this->configuration); | |
| 95 | if (!$migration instanceof MigrationInterface) { | |
| 96 | continue; | |
| 97 | } | |
| 98 | ||
| 99 | $this->migrations[$version] = $migration; | |
| 100 | } | |
| 101 | ||
| 102 | // Sort by version | |
| 103 | uksort($this->migrations, callback: 'version_compare'); | |
| 104 | ||
| 105 | return $this->migrations; | |
| 106 | } | |
| 107 | ||
| 108 | /** | |
| 109 | * Returns a specific migration by version. | |
| 110 | */ | |
| 111 | public function getMigration(string $version): ?MigrationInterface | |
| 112 | { | |
| 113 | $migrations = $this->getMigrations(); | |
| 114 | return $migrations[$version] ?? null; | |
| 115 | } | |
| 116 | ||
| 117 | /** | |
| 118 | * Returns all versions in order. | |
| 119 | * | |
| 120 | * @return string[] | |
| 121 | */ | |
| 122 | public function getVersions(): array | |
| 123 | { | |
| 124 | return array_keys($this->getMigrations()); | |
| 125 | } | |
| 126 | ||
| 127 | /** | |
| 128 | * Returns migrations that need to be applied to get from $currentVersion to the latest. | |
| 129 | * | |
| 130 | * @return array<string, MigrationInterface> | |
| 131 | */ | |
| 132 | public function getPendingMigrations(string $currentVersion): array | |
| 133 | { | |
| 134 | $pending = []; | |
| 135 | ||
| 136 | foreach ($this->getMigrations() as $version => $migration) { | |
| 137 | if (!version_compare(version1: $currentVersion, version2: $version, operator: '<')) { | |
| 138 | continue; | |
| 139 | } | |
| 140 | ||
| 141 | $pending[$version] = $migration; | |
| 142 | } | |
| 143 | ||
| 144 | return $pending; | |
| 145 | } | |
| 146 | ||
| 147 | /** | |
| 148 | * Returns migrations that need to be applied based on what's already tracked. | |
| 149 | * | |
| 150 | * @param string[] $appliedVersions | |
| 151 | * @return MigrationInterface[] | |
| 152 | */ | |
| 153 | public function getUnappliedMigrations(array $appliedVersions): array | |
| 154 | { | |
| 155 | $unapplied = []; | |
| 156 | ||
| 157 | foreach ($this->getMigrations() as $version => $migration) { | |
| 158 | if (in_array($version, $appliedVersions, strict: true)) { | |
| 159 | continue; | |
| 160 | } | |
| 161 | ||
| 162 | $unapplied[$version] = $migration; | |
| 163 | } | |
| 164 | ||
| 165 | return $unapplied; | |
| 166 | } | |
| 167 | ||
| 168 | /** | |
| 169 | * Returns the latest migration version. | |
| 170 | */ | |
| 171 | public function getLatestVersion(): ?string | |
| 172 | { | |
| 173 | $versions = $this->getVersions(); | |
| 174 | return $versions !== [] ? end($versions) : null; | |
| 175 | } | |
| 176 | ||
| 177 | /** | |
| 178 | * Checks if a migration version exists. | |
| 179 | */ | |
| 180 | public function hasMigration(string $version): bool | |
| 181 | { | |
| 182 | return array_key_exists($version, $this->migrationClasses); | |
| 183 | } | |
| 184 | } |