311 lines
6.7 KiB
PHP
311 lines
6.7 KiB
PHP
<?php
|
|
/**
|
|
* Data Migrator Class
|
|
*
|
|
* Migración de datos de wp_options a tabla personalizada
|
|
*
|
|
* @package Apus_Theme
|
|
* @since 2.2.0
|
|
*/
|
|
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
class APUS_Data_Migrator {
|
|
|
|
/**
|
|
* Opción para trackear si la migración se completó
|
|
*/
|
|
const MIGRATION_FLAG = 'apus_data_migrated';
|
|
|
|
/**
|
|
* Opción antigua en wp_options
|
|
*/
|
|
const OLD_OPTION_NAME = 'apus_theme_settings';
|
|
|
|
/**
|
|
* DB Manager instance
|
|
*/
|
|
private $db_manager;
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
public function __construct() {
|
|
$this->db_manager = new APUS_DB_Manager();
|
|
}
|
|
|
|
/**
|
|
* Verificar si la migración ya se ejecutó
|
|
*/
|
|
public function is_migrated() {
|
|
return get_option(self::MIGRATION_FLAG) === '1';
|
|
}
|
|
|
|
/**
|
|
* Ejecutar migración si es necesaria
|
|
*/
|
|
public function maybe_migrate() {
|
|
if ($this->is_migrated()) {
|
|
return array(
|
|
'success' => true,
|
|
'message' => 'La migración ya fue ejecutada anteriormente'
|
|
);
|
|
}
|
|
|
|
if (!$this->db_manager->table_exists()) {
|
|
return array(
|
|
'success' => false,
|
|
'message' => 'La tabla de destino no existe'
|
|
);
|
|
}
|
|
|
|
return $this->migrate();
|
|
}
|
|
|
|
/**
|
|
* Ejecutar migración completa
|
|
*/
|
|
public function migrate() {
|
|
global $wpdb;
|
|
|
|
// Comenzar transacción
|
|
$wpdb->query('START TRANSACTION');
|
|
|
|
try {
|
|
// Obtener datos de wp_options
|
|
$old_data = get_option(self::OLD_OPTION_NAME);
|
|
|
|
if (empty($old_data)) {
|
|
throw new Exception('No hay datos para migrar en wp_options');
|
|
}
|
|
|
|
$total_migrated = 0;
|
|
|
|
// Verificar estructura de datos
|
|
if (!isset($old_data['components']) || !is_array($old_data['components'])) {
|
|
throw new Exception('Estructura de datos inválida');
|
|
}
|
|
|
|
// Obtener versión y timestamp
|
|
$version = isset($old_data['version']) ? $old_data['version'] : APUS_ADMIN_PANEL_VERSION;
|
|
|
|
// Migrar cada componente
|
|
foreach ($old_data['components'] as $component_name => $component_data) {
|
|
if (!is_array($component_data)) {
|
|
continue;
|
|
}
|
|
|
|
$migrated = $this->migrate_component($component_name, $component_data, $version);
|
|
$total_migrated += $migrated;
|
|
}
|
|
|
|
// Marcar migración como completada
|
|
update_option(self::MIGRATION_FLAG, '1', false);
|
|
|
|
// Commit transacción
|
|
$wpdb->query('COMMIT');
|
|
|
|
error_log("APUS Data Migrator: Migración completada. Total de registros: $total_migrated");
|
|
|
|
return array(
|
|
'success' => true,
|
|
'message' => 'Migración completada exitosamente',
|
|
'total_migrated' => $total_migrated
|
|
);
|
|
|
|
} catch (Exception $e) {
|
|
// Rollback en caso de error
|
|
$wpdb->query('ROLLBACK');
|
|
|
|
error_log("APUS Data Migrator: Error en migración - " . $e->getMessage());
|
|
|
|
return array(
|
|
'success' => false,
|
|
'message' => 'Error en migración: ' . $e->getMessage()
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Migrar un componente específico
|
|
*
|
|
* @param string $component_name Nombre del componente
|
|
* @param array $component_data Datos del componente
|
|
* @param string $version Versión
|
|
* @return int Número de registros migrados
|
|
*/
|
|
private function migrate_component($component_name, $component_data, $version) {
|
|
$count = 0;
|
|
|
|
foreach ($component_data as $key => $value) {
|
|
// Determinar tipo de dato
|
|
$data_type = $this->determine_data_type($key, $value);
|
|
|
|
// Si es un array/objeto anidado (como custom_styles), guardarlo como JSON
|
|
if ($data_type === 'json') {
|
|
$result = $this->db_manager->save_config(
|
|
$component_name,
|
|
$key,
|
|
$value,
|
|
$data_type,
|
|
$version
|
|
);
|
|
} else {
|
|
$result = $this->db_manager->save_config(
|
|
$component_name,
|
|
$key,
|
|
$value,
|
|
$data_type,
|
|
$version
|
|
);
|
|
}
|
|
|
|
if ($result !== false) {
|
|
$count++;
|
|
}
|
|
}
|
|
|
|
return $count;
|
|
}
|
|
|
|
/**
|
|
* Determinar el tipo de dato
|
|
*
|
|
* @param string $key Clave de configuración
|
|
* @param mixed $value Valor
|
|
* @return string Tipo de dato (string, boolean, integer, json)
|
|
*/
|
|
private function determine_data_type($key, $value) {
|
|
if (is_bool($value)) {
|
|
return 'boolean';
|
|
}
|
|
|
|
if (is_int($value)) {
|
|
return 'integer';
|
|
}
|
|
|
|
if (is_array($value)) {
|
|
return 'json';
|
|
}
|
|
|
|
// Por nombre de clave
|
|
if (in_array($key, array('enabled', 'show_on_mobile', 'show_on_desktop', 'show_icon', 'show_link'))) {
|
|
return 'boolean';
|
|
}
|
|
|
|
return 'string';
|
|
}
|
|
|
|
/**
|
|
* Crear backup de datos antiguos
|
|
*
|
|
* @return bool Éxito de la operación
|
|
*/
|
|
public function backup_old_data() {
|
|
$old_data = get_option(self::OLD_OPTION_NAME);
|
|
|
|
if (empty($old_data)) {
|
|
return false;
|
|
}
|
|
|
|
$backup_option = self::OLD_OPTION_NAME . '_backup_' . time();
|
|
return update_option($backup_option, $old_data, false);
|
|
}
|
|
|
|
/**
|
|
* Restaurar desde backup (rollback)
|
|
*
|
|
* @param string $backup_option Nombre de la opción de backup
|
|
* @return bool Éxito de la operación
|
|
*/
|
|
public function rollback($backup_option) {
|
|
$backup_data = get_option($backup_option);
|
|
|
|
if (empty($backup_data)) {
|
|
return false;
|
|
}
|
|
|
|
// Restaurar datos antiguos
|
|
update_option(self::OLD_OPTION_NAME, $backup_data, false);
|
|
|
|
// Limpiar flag de migración
|
|
delete_option(self::MIGRATION_FLAG);
|
|
|
|
// Limpiar tabla personalizada
|
|
global $wpdb;
|
|
$table_name = $this->db_manager->get_table_name();
|
|
$wpdb->query("TRUNCATE TABLE $table_name");
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Comparar datos entre wp_options y tabla personalizada
|
|
*
|
|
* @return array Resultado de la comparación
|
|
*/
|
|
public function verify_migration() {
|
|
$old_data = get_option(self::OLD_OPTION_NAME);
|
|
|
|
if (empty($old_data) || !isset($old_data['components'])) {
|
|
return array(
|
|
'success' => false,
|
|
'message' => 'No hay datos en wp_options para comparar'
|
|
);
|
|
}
|
|
|
|
$discrepancies = array();
|
|
|
|
foreach ($old_data['components'] as $component_name => $component_data) {
|
|
$new_data = $this->db_manager->get_config($component_name);
|
|
|
|
foreach ($component_data as $key => $old_value) {
|
|
$new_value = isset($new_data[$key]) ? $new_data[$key] : null;
|
|
|
|
// Comparar valores (teniendo en cuenta conversiones de tipo)
|
|
if ($this->normalize_value($old_value) !== $this->normalize_value($new_value)) {
|
|
$discrepancies[] = array(
|
|
'component' => $component_name,
|
|
'key' => $key,
|
|
'old_value' => $old_value,
|
|
'new_value' => $new_value
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (empty($discrepancies)) {
|
|
return array(
|
|
'success' => true,
|
|
'message' => 'Migración verificada: todos los datos coinciden'
|
|
);
|
|
}
|
|
|
|
return array(
|
|
'success' => false,
|
|
'message' => 'Se encontraron discrepancias en la migración',
|
|
'discrepancies' => $discrepancies
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Normalizar valor para comparación
|
|
*
|
|
* @param mixed $value Valor a normalizar
|
|
* @return mixed Valor normalizado
|
|
*/
|
|
private function normalize_value($value) {
|
|
if (is_bool($value)) {
|
|
return $value ? 1 : 0;
|
|
}
|
|
|
|
if (is_array($value)) {
|
|
return json_encode($value);
|
|
}
|
|
|
|
return $value;
|
|
}
|
|
}
|