*/ private array $migrations; /** * @since 1.0.0 * * @param array $migrations Migrations to run. */ public function __construct( array $migrations = array() ) { $this->migrations = $migrations; } /** * Runs every migration whose version is greater than the stored version. * * Idempotent: calling it when the DB is up-to-date is a no-op. Migrations * are sorted by version before running so registration order doesn't matter. * * Stops at the first migration whose `run()` returns false and does not * advance the stored version past it, since later migrations may assume * every earlier one already applied cleanly. * * @since 1.0.0 * @since 1.6.0 Stops the batch and leaves the version unadvanced when a * migration reports failure instead of assuming success. * * @return void */ public function run_pending(): void { global $wpdb; $current_version = $this->get_current_version(); $pending = array_filter( $this->migrations, static fn ( MigrationInterface $migration ): bool => $migration->get_version() > $current_version ); usort( $pending, static fn ( MigrationInterface $a, MigrationInterface $b ): int => $a->get_version() <=> $b->get_version() ); foreach ( $pending as $migration ) { $succeeded = $migration->run( $wpdb ); if ( ! $succeeded ) { Logger::error( 'Migration %d failed verification — schema version not advanced', array( $migration->get_version() ) ); break; // Stop here; later migrations may assume this one applied. } $this->set_current_version( $migration->get_version() ); Logger::info( 'Applied migration %d', array( $migration->get_version() ) ); } } /** * Returns the highest applied migration version. * * @since 1.0.0 * * @return int The current schema version. Zero on a fresh install. */ public function get_current_version(): int { return (int) get_option( self::VERSION_OPTION, 0 ); } /** * Stores the new highest-applied migration version. * * @since 1.0.0 * * @param int $version The version to store. * * @return void */ private function set_current_version( int $version ): void { update_option( self::VERSION_OPTION, $version, false ); } }