prefix . self::$table_name; $charset_collate = $wpdb->get_charset_collate(); $sql = "CREATE TABLE IF NOT EXISTS {$table} ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, migration VARCHAR(255) NOT NULL, batch INT NOT NULL, migrated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ) $charset_collate;"; require_once ABSPATH . 'wp-admin/includes/upgrade.php'; dbDelta( $sql ); } /** * Check if a given migration has already been applied. * * @param string $migration_name * @return bool */ public static function is_migrated( $migration_name ) { global $wpdb; // Table name is safe - $wpdb->prefix is controlled by WordPress core $table = $wpdb->prefix . self::$table_name; // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- $wpdb->prefix is trusted return (bool) $wpdb->get_var( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter $wpdb->prepare( "SELECT COUNT(*) FROM {$table} WHERE migration = %s", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- $table uses $wpdb->prefix $migration_name ) ); } /** * Record a migration as applied. * * @param string $migration_name * @param int $batch * @return void */ public static function mark_as_migrated( $migration_name, $batch = 1 ) { global $wpdb; $table = $wpdb->prefix . self::$table_name; $wpdb->insert( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $table, [ 'migration' => $migration_name, 'batch' => $batch, 'migrated_at' => current_time( 'mysql' ), ] ); } /** * Remove a migration record (used for rollback). * * @param string $migration_name * @return void */ public static function remove_migration( $migration_name ) { global $wpdb; $table = $wpdb->prefix . self::$table_name; $wpdb->delete( $table, [ 'migration' => $migration_name ] ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching } /** * Get the latest batch number. * * @return int */ public static function get_latest_batch() { global $wpdb; // Table name is safe - $wpdb->prefix is controlled by WordPress core $table = $wpdb->prefix . self::$table_name; // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- $wpdb->prefix is trusted return (int) $wpdb->get_var( "SELECT MAX(batch) FROM {$table}" ) ?: 1; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter } /** * Get all migrations in the latest batch. * * @return array */ public static function get_latest_batch_migrations() { global $wpdb; // Table name is safe - $wpdb->prefix is controlled by WordPress core $table = $wpdb->prefix . self::$table_name; // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- $wpdb->prefix is trusted $latest_batch = self::get_latest_batch(); return $wpdb->get_results( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter $wpdb->prepare( "SELECT * FROM {$table} WHERE batch = %d ORDER BY id DESC", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- $table uses $wpdb->prefix $latest_batch ) ); } }