chore: initial snapshot of 2meet-data-optimizer-hivepress-addon v0.1.0
Baseline before backporting wp-data-optimizer v3.0.1-v3.4.6. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TbG1keQQ7XBa7qMQY16KCY
This commit is contained in:
@@ -0,0 +1,248 @@
|
||||
<?php
|
||||
/**
|
||||
* HPCT Import integration for WP Data Optimizer.
|
||||
*
|
||||
* @package WP_Data_Optimizer
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* HPCT Import — reads hp-custom-tables' feature flags and migration records,
|
||||
* maps them to WPDO's 7-state lifecycle, and copies progress data.
|
||||
*
|
||||
* After import, WPDO takes ownership of all 9 HPCT modules and their
|
||||
* corresponding hpct_* tables. The user is advised to deactivate hp-custom-tables.
|
||||
*
|
||||
* Usage:
|
||||
* - Admin UI: Tools > WP Data Optimizer > HPCT Import tab
|
||||
* - CLI: wp wpdo import-hpct
|
||||
*/
|
||||
class TMDO_HPCT_Import {
|
||||
|
||||
/** Option key that marks import as completed. */
|
||||
public const IMPORTED_OPTION = 'wpdo_hpct_imported';
|
||||
|
||||
/**
|
||||
* Check if HPCT import has already been completed.
|
||||
*/
|
||||
public static function is_imported(): bool {
|
||||
return (bool) get_option( self::IMPORTED_OPTION, false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if hp-custom-tables is active and has data to import.
|
||||
*/
|
||||
public static function can_import(): bool {
|
||||
if ( self::is_imported() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return TMDO_Compatibility::is_hpct_active();
|
||||
}
|
||||
|
||||
/**
|
||||
* Preview: return what will be imported without actually doing it.
|
||||
*
|
||||
* @return array{modules: array, migration_records: int, has_data: bool}
|
||||
*/
|
||||
public static function preview(): array {
|
||||
$hpct_features = get_option( 'hpct_features', array() );
|
||||
if ( ! is_array( $hpct_features ) ) {
|
||||
$hpct_features = array();
|
||||
}
|
||||
|
||||
$modules = array();
|
||||
foreach ( TMDO_Feature_Flags::HPCT_MODULES as $module ) {
|
||||
$hpct_status = $hpct_features[ $module ] ?? 'disabled';
|
||||
$wpdo_state = TMDO_Feature_Flags::map_hpct_status( $hpct_status );
|
||||
|
||||
$modules[] = array(
|
||||
'module' => $module,
|
||||
'hpct_status' => $hpct_status,
|
||||
'wpdo_state' => $wpdo_state,
|
||||
);
|
||||
}
|
||||
|
||||
// Count HPCT migration records.
|
||||
global $wpdb;
|
||||
$hpct_migrations_table = $wpdb->prefix . 'hpct_migrations';
|
||||
$migration_count = 0;
|
||||
|
||||
// Check if hpct_migrations table exists.
|
||||
if ( TMDO_IS_SQLITE ) {
|
||||
$table_exists = $wpdb->get_var(
|
||||
$wpdb->prepare(
|
||||
"SELECT COUNT(*) FROM sqlite_master WHERE type = 'table' AND name = %s",
|
||||
$hpct_migrations_table
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$table_exists = $wpdb->get_var(
|
||||
$wpdb->prepare(
|
||||
'SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = %s',
|
||||
$hpct_migrations_table
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ( $table_exists ) {
|
||||
$migration_count = (int) $wpdb->get_var( "SELECT COUNT(*) FROM `{$hpct_migrations_table}`" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- table name is $wpdb->prefix . 'hpct_migrations'.
|
||||
}
|
||||
|
||||
return array(
|
||||
'modules' => $modules,
|
||||
'migration_records' => $migration_count,
|
||||
'has_data' => ! empty( $hpct_features ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the import.
|
||||
*
|
||||
* @return array{success: bool, message: string, imported: array}
|
||||
*/
|
||||
public static function run(): array {
|
||||
if ( self::is_imported() ) {
|
||||
return array(
|
||||
'success' => false,
|
||||
'message' => 'HPCT import has already been completed.',
|
||||
'imported' => array(),
|
||||
);
|
||||
}
|
||||
|
||||
// Step 1: Read HPCT feature flags.
|
||||
$hpct_features = get_option( 'hpct_features', array() );
|
||||
if ( ! is_array( $hpct_features ) ) {
|
||||
$hpct_features = array();
|
||||
}
|
||||
|
||||
$imported = array();
|
||||
|
||||
// Step 2: Map each HPCT module state to WPDO state.
|
||||
foreach ( TMDO_Feature_Flags::HPCT_MODULES as $module ) {
|
||||
$hpct_status = $hpct_features[ $module ] ?? 'disabled';
|
||||
$wpdo_state = TMDO_Feature_Flags::map_hpct_status( $hpct_status );
|
||||
|
||||
TMDO_Feature_Flags::set( $module, $wpdo_state );
|
||||
|
||||
$imported[] = array(
|
||||
'module' => $module,
|
||||
'hpct_status' => $hpct_status,
|
||||
'wpdo_state' => $wpdo_state,
|
||||
);
|
||||
}
|
||||
|
||||
// Step 3: Copy HPCT migration records to WPDO.
|
||||
self::copy_migration_records();
|
||||
|
||||
// Step 4: Mark import as completed.
|
||||
update_option( self::IMPORTED_OPTION, true );
|
||||
|
||||
return array(
|
||||
'success' => true,
|
||||
'message' => sprintf(
|
||||
'Successfully imported %d HPCT modules. You can now deactivate hp-custom-tables.',
|
||||
count( $imported )
|
||||
),
|
||||
'imported' => $imported,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy HPCT migration progress records to wpdo_migrations.
|
||||
*/
|
||||
private static function copy_migration_records(): void {
|
||||
global $wpdb;
|
||||
|
||||
$hpct_table = $wpdb->prefix . 'hpct_migrations';
|
||||
$wpdo_table = TMDO_DB::table( 'wpdo_migrations' );
|
||||
$now = TMDO_DB::now();
|
||||
|
||||
// Check if hpct_migrations table exists.
|
||||
$exists = false;
|
||||
if ( TMDO_IS_SQLITE ) {
|
||||
$exists = (bool) $wpdb->get_var(
|
||||
$wpdb->prepare(
|
||||
"SELECT COUNT(*) FROM sqlite_master WHERE type = 'table' AND name = %s",
|
||||
$hpct_table
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$exists = (bool) $wpdb->get_var(
|
||||
$wpdb->prepare(
|
||||
'SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = %s',
|
||||
$hpct_table
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ( ! $exists ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$hpct_records = $wpdb->get_results( "SELECT * FROM `{$hpct_table}`", ARRAY_A ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- table name is $wpdb->prefix . 'hpct_migrations'.
|
||||
if ( ! $hpct_records ) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( $hpct_records as $record ) {
|
||||
$module = $record['module'] ?? '';
|
||||
if ( ! $module ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Map HPCT status to WPDO state.
|
||||
$hpct_status = $record['status'] ?? 'pending';
|
||||
$state = self::map_migration_status( $hpct_status );
|
||||
|
||||
// Check if WPDO already has a record for this module.
|
||||
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- table name from TMDO_DB::table().
|
||||
$existing = $wpdb->get_var(
|
||||
$wpdb->prepare(
|
||||
"SELECT id FROM `{$wpdo_table}` WHERE module = %s",
|
||||
$module
|
||||
)
|
||||
);
|
||||
// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
||||
|
||||
$data = array(
|
||||
'module' => $module,
|
||||
'zone' => '',
|
||||
'state' => $state,
|
||||
'total_rows' => (int) ( $record['total_rows'] ?? 0 ),
|
||||
'processed_rows' => (int) ( $record['processed_rows'] ?? 0 ),
|
||||
'last_offset' => (int) ( $record['last_offset'] ?? 0 ),
|
||||
'error_count' => (int) ( $record['error_count'] ?? 0 ),
|
||||
'started_at' => $record['started_at'] ?? null,
|
||||
'completed_at' => $record['completed_at'] ?? null,
|
||||
'updated_at' => $now,
|
||||
);
|
||||
|
||||
if ( $existing ) {
|
||||
$wpdb->update( $wpdo_table, $data, array( 'id' => (int) $existing ) );
|
||||
} else {
|
||||
$data['created_at'] = $now;
|
||||
$wpdb->insert( $wpdo_table, $data );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Map HPCT migration record status to WPDO migration state.
|
||||
*
|
||||
* @param string $hpct_status HPCT migration status string.
|
||||
* @return string Corresponding WPDO migration state.
|
||||
*/
|
||||
private static function map_migration_status( string $hpct_status ): string {
|
||||
return match ( $hpct_status ) {
|
||||
'pending' => 'idle',
|
||||
'running' => 'backfill',
|
||||
'completed' => 'verify',
|
||||
'failed' => 'idle',
|
||||
default => 'idle',
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user