Files
roi-theme/migrate-legacy-options.php
FrankZamora 7a8daa72c6 chore: Add migration script for legacy theme options
Script to migrate data from wp_options (roi_theme_settings)
to normalized table wp_roi_theme_component_settings

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 21:58:28 -06:00

195 lines
7.1 KiB
PHP

<?php
/**
* Script de Migracion de Opciones Legacy
*
* Migra configuraciones de wp_options (roi_theme_options) a la tabla
* wp_roi_theme_component_settings (Clean Architecture).
*
* IMPORTANTE:
* - Ejecutar UNA SOLA VEZ
* - Hacer BACKUP de wp_options ANTES de ejecutar
* - Ejecutar via WP-CLI: wp eval-file wp-content/themes/roi-theme/migrate-legacy-options.php
*
* @package ROITheme
* @version 1.0.0
* @date 2025-01-26
*/
// Prevenir acceso directo
if (!defined('ABSPATH')) {
// Si se ejecuta via WP-CLI, ABSPATH estara definido
if (php_sapi_name() !== 'cli') {
exit('Acceso directo no permitido.');
}
}
/**
* Migrar configuraciones legacy a nueva tabla
*
* @return string Mensaje de resultado
*/
function roi_migrate_legacy_options(): string {
global $wpdb;
$results = [];
$results[] = "=== ROI Theme: Migracion de Opciones Legacy ===\n";
$results[] = "Fecha: " . date('Y-m-d H:i:s') . "\n\n";
// 1. Obtener opciones legacy
$legacy_options = get_option('roi_theme_options', []);
if (empty($legacy_options)) {
$results[] = "INFO: No se encontraron opciones legacy en 'roi_theme_options'.\n";
$results[] = " Esto es normal si el sitio ya usa Clean Architecture.\n";
} else {
$results[] = "INFO: Encontradas " . count($legacy_options) . " opciones legacy.\n\n";
}
// 2. Obtener theme_mods
$theme_mods = get_theme_mods();
$results[] = "INFO: Theme mods encontrados: " . count($theme_mods) . "\n\n";
$table = $wpdb->prefix . 'roi_theme_component_settings';
$migrated = 0;
$skipped = 0;
$errors = 0;
// 3. Mapeo de opciones legacy → componente/grupo/atributo
// Basado en seccion 3.4 del plan 02.02-limpieza-configuraciones-legacy.md
$mapping = [
// Opciones de roi_theme_options
'roi_adsense_delay_enabled' => [
'source' => 'roi_theme_options',
'target' => ['adsense-delay', 'visibility', 'is_enabled'],
'note' => 'Componente adsense-delay no existe en Admin Panel - PENDIENTE crear schema'
],
'show_category_badge' => [
'source' => 'roi_theme_options',
'target' => ['category-badge', 'visibility', 'is_enabled'],
'note' => 'Componente category-badge no existe en Admin Panel - PENDIENTE crear schema'
],
'toc_min_headings' => [
'source' => 'roi_theme_options',
'target' => ['table-of-contents', 'behavior', 'min_headings'],
'note' => 'Componente table-of-contents YA EXISTE en Admin Panel'
],
'roi_share_text' => [
'source' => 'roi_theme_options',
'target' => ['social-share', 'content', 'share_text'],
'note' => 'Componente social-share YA EXISTE en Admin Panel'
],
'roi_enable_share_buttons' => [
'source' => 'roi_theme_options',
'target' => ['social-share', 'visibility', 'is_enabled'],
'note' => 'Componente social-share YA EXISTE en Admin Panel'
],
'featured_image_single' => [
'source' => 'roi_theme_options',
'target' => ['featured-image', 'visibility', 'show_on_single'],
'note' => 'Componente featured-image YA EXISTE en Admin Panel'
],
'featured_image_page' => [
'source' => 'roi_theme_options',
'target' => ['featured-image', 'visibility', 'show_on_page'],
'note' => 'Componente featured-image YA EXISTE en Admin Panel'
],
];
// Opciones que se ELIMINAN intencionalmente (no migrar)
$intentionally_removed = [
'breadcrumb_separator' => 'Breadcrumbs eliminado - usar plugin si se necesita',
'roi_social_facebook' => 'Social links eliminados - no se usa',
'roi_social_twitter' => 'Social links eliminados - no se usa',
'roi_social_linkedin' => 'Social links eliminados - no se usa',
'roi_social_youtube' => 'Social links eliminados - no se usa',
'roi_typography_heading' => 'Typography eliminado - usar Custom CSS',
'roi_typography_body' => 'Typography eliminado - usar Custom CSS',
];
$results[] = "=== Procesando Migracion ===\n\n";
// 4. Procesar mapeo
foreach ($mapping as $legacy_key => $config) {
$source = $config['source'];
$target = $config['target'];
$note = $config['note'];
[$component, $group, $attribute] = $target;
// Obtener valor segun source
$value = null;
if ($source === 'roi_theme_options' && isset($legacy_options[$legacy_key])) {
$value = $legacy_options[$legacy_key];
} elseif ($source === 'theme_mods' && isset($theme_mods[$legacy_key])) {
$value = $theme_mods[$legacy_key];
}
if ($value !== null) {
// Verificar si ya existe en la nueva tabla
$existing = $wpdb->get_var($wpdb->prepare(
"SELECT COUNT(*) FROM {$table}
WHERE component_name = %s AND group_name = %s AND attribute_name = %s",
$component,
$group,
$attribute
));
if ($existing > 0) {
$results[] = "SKIP: {$legacy_key} -> Ya existe en {$component}/{$group}/{$attribute}\n";
$results[] = " Nota: {$note}\n";
$skipped++;
continue;
}
// Insertar en nueva tabla
$result = $wpdb->replace($table, [
'component_name' => $component,
'group_name' => $group,
'attribute_name' => $attribute,
'attribute_value' => is_bool($value) ? ($value ? '1' : '0') : (string)$value,
'is_editable' => 1,
]);
if ($result !== false) {
$results[] = "OK: {$legacy_key} -> {$component}/{$group}/{$attribute} = " . var_export($value, true) . "\n";
$results[] = " Nota: {$note}\n";
$migrated++;
} else {
$results[] = "ERR: {$legacy_key} -> Error al insertar: " . $wpdb->last_error . "\n";
$errors++;
}
} else {
$results[] = "SKIP: {$legacy_key} -> No encontrado en {$source}\n";
$skipped++;
}
}
// 5. Documentar opciones eliminadas intencionalmente
$results[] = "\n=== Opciones Eliminadas Intencionalmente ===\n\n";
foreach ($intentionally_removed as $key => $reason) {
if (isset($legacy_options[$key])) {
$results[] = "DEL: {$key} -> {$reason}\n";
}
}
// 6. Resumen
$results[] = "\n=== Resumen ===\n";
$results[] = "Migradas: {$migrated}\n";
$results[] = "Omitidas: {$skipped}\n";
$results[] = "Errores: {$errors}\n";
$results[] = "\n=== Fin de Migracion ===\n";
$output = implode('', $results);
// Guardar log
$log_file = get_template_directory() . '/migrate-legacy-options.log';
file_put_contents($log_file, $output);
return $output;
}
// Ejecutar si se llama directamente via WP-CLI
if (defined('WP_CLI') || (defined('ABSPATH') && php_sapi_name() === 'cli')) {
echo roi_migrate_legacy_options();
}