This entry is part 5 of 5 in the series Actualización de mi sistema WordPress y galería integrada

Actualización de mi sistema WordPress y galería integrada

Actualización de este sitio web. Introducción

Actualización de este sitio web. Escogiendo un nuevo sistema de galerías

Actualización de este sitio web. Actualización de WordPress

Actualización de este sitio web. Piwigo Gallery Integration. El plugin que WordPress Necesitaba

Actualización de este sitio web. Reemplazo Inteligente de referencias de Gallery2 a Piwigo

Y llegamos así a la etapa reina de este proceso. Había conseguido realizar una instalación limpia de WordPress y de Piwigo, y disponer de un plugin que me permitiera integrar las fotografías del segundo en el primero. Pero aún quedaba lo más importante por hacer: reemplazar las miles de referencias existentes en centenares de fotografías, con respecto a decenas de galerías, y sin disponer de un cotejado de las referencias entre el sistema de galerías antiguo y el nuevo. Vamos, el problema que hacía años que estaba intentando evitar.

Migración desde un sistema obsoleto, estilo steampunk. Generada con IA

Por desgracia, este problema no es nuevo. La obsolescencia de plugins y herramientas legacy es un desafío común en la administración de sitios WordPress con años de historia. Por ello, una vez más consulté con v0 cómo poder abordar este proceso. Y el resultado fue completamente sorprendente, algo que fue mucho más allá de mis expectativas más optimistas. En este artículo, me centraré en compartir la experiencia migrando una galería de imágenes de Gallery2 (completamente obsoleta) a Piwigo, con especial énfasis en la solución desarrollada para mapear y reemplazar automáticamente miles de referencias sin perder datos ni romper la experiencia del usuario.

El Problema: Galerías Legacy en WordPress

Gallery2, que fue durante años la solución estándar para gestionar galerías de imágenes en WordPress, fue completamente abandonado a partir de 2009. Los sitios como el mío, que aún la utilizaban se enfrentaban riesgos críticos de seguridad, incompatibilidad con versiones modernas de PHP, y vulnerabilidades sin parches disponibles.

En mi caso específico presentaba complejidades adicionales:

  • Una galería legacy en https://sertorio.eniac2000.com/gallery2/ completamente obsoleta
  • Centenares de posts de WordPress referenciando miles de imágenes mediante tags propietarios: <wpg2>ID</wpg2> y <wpg2id>ID</wpg2id>
  • No había correspondencia directa entre identificadores de Gallery2 e imágenes nuevas en Piwigo
  • Parámetros opcionales de tamaño en los tags (<wpg2id>69434|800</wpg2id>) complicaban la búsqueda simple
  • Duplicación de nombres de archivo entre galerías, requiriendo comparación por fecha de creación

La Solución: Arquitectura Modular de Migración

Con apoyo de la IA se desarrolló un sistema de migración en cuatro fases que ejecuté de forma secuencial, con validación en cada paso y capacidad de vuelta atrás:

Fase 1: Extracción y Mapeo de Identificadores

El desafío principal era crear una tabla de correspondencia entre Gallery2 y Piwigo sin registros compartidos. Se utilizó una estrategia multi-capas:

-- Extraer datos de Gallery2
SELECT 
    g2_Item.g_id as gallery2_id,
    g2_FileSystemEntity.g_pathComponent as filename,
    FROM_UNIXTIME(g2_Item.g_originationTimestamp) as creation_date,
    g2_Item.g_title as title
FROM g2_Item
LEFT JOIN g2_FileSystemEntity ON g2_Item.g_id = g2_FileSystemEntity.g_id
WHERE g2_Item.g_canContainChildren = 0;

-- Extraer datos de Piwigo
SELECT 
    id as piwigo_id,
    file as filename,
    date_creation as creation_date,
    name as title
FROM piwigo_images;

El mapeo se realizó en el siguiente orden de precedencia:

  • Nivel 1 – Nombre exacto: Búsqueda directa por nombre de archivo. Éxito en el 85% de casos.
  • Nivel 2 – Nombre + Fecha: Cuando había múltiples imágenes con el mismo nombre (caso común en galerías organizadas por fecha), se comparaba el g_originationTimestamp de Gallery2 (Unix timestamp) convertido a formato datetime con date_creation de Piwigo, con tolerancia de ±1 día para manejar diferencias menores en conversión de timezones.
  • Nivel 3 – Título fuzzy: Búsqueda aproximada en títulos para casos donde el nombre de archivo había sido procesado mediante lógica difusa.
  • Nivel 4 – Manual: Registro de imágenes no encontradas para revisión humana.
// Lógica de conversión de timestamps
$gallery2_date = new DateTime();
$gallery2_date->setTimestamp($g2_timestamp);
$gallery2_datetime = $gallery2_date->format('Y-m-d');

$piwigo_datetime = substr($piwigo_creation_date, 0, 10);

$date_diff = abs(strtotime($gallery2_datetime) - strtotime($piwigo_datetime));
$matches_by_date = ($date_diff <= 86400); // 1 día de tolerancia

if ($filename_match && $matches_by_date) {
    $match_type = 'exact_filename_date';
    $confidence = 99;
}

Fase 2 Identificación de Posts Afectados

Tras establecer el cotejado de imágenes, el siguiente paso era realizar una búsqueda de base de datos simple, a fin de identificar todos los posts que contenían los tags heredados:

SELECT ID, post_title, post_content
FROM wp_posts
WHERE (post_content LIKE '%<wpg2>%' OR post_content LIKE '%<wpg2id>%')
  AND post_status IN ('publish', 'draft', 'pending')
ORDER BY post_modified DESC;

Fase 3: Reemplazo Inteligente de Tags – La Magia del Algoritmo

Este es el corazón del sistema, donde se aplicaron expresiones regulares sofisticadas para detectar y reemplazar todos los formatos posibles de tags:

// Detectar y procesar ambos formatos de tags con parámetros opcionales
$patterns = [
    // Formato 1: <wpg2>ID</wpg2> o <wpg2>ID|SIZE</wpg2>
    '<wpg2>(\d+)(?:\|(\d+))?<\/wpg2>',
    
    // Formato 2: <wpg2id>ID</wpg2id> o <wpg2id>ID|SIZE</wpg2id>
    '<wpg2id>(\d+)(?:\|(\d+))?<\/wpg2id>'
];

foreach ($patterns as $pattern) {
    $postContent = preg_replace_callback(
        $pattern,
        function($matches) use ($mappingTable) {
            $gallery2_id = $matches[1];
            $size_param = $matches[2] ?? null; // Captura el tamaño pero lo ignora
            
            if (isset($mappingTable[$gallery2_id])) {
                $piwigo_id = $mappingTable[$gallery2_id];
                // El parámetro de tamaño se descarta: Piwigo usa "medium"
                return '[piwigo imageId=' . $piwigo_id . ' size="medium" link="true" caption="true"]';
            }
            
            // Si no hay mapeo: registrar error para revisión manual
            return 'MIGRATION ERROR: Gallery2 ID . $gallery2_id . no encontrado;
        },
        $postContent
    );
}

La clave de esta solución es la expresión regular capaz de manejar:

  • IDs directos: <wpg2>34445</wpg2>
  • IDs con parámetro de tamaño: <wpg2id>69434|800</wpg2id> (captura solo el ID, ignora el tamaño)
  • Ambos formatos: El mismo regex maneja <wpg2> y <wpg2id>
  • Errores elegantes: Si no hay mapeo, inserta un comentario HTML auditable en lugar de romper el contenido

Fase 4: Validación y Rollback

El sistema, además, incluía varias capas de validación y recuperación:

// Modo "dry-run" para pruebas sin modificar la BD
if (!$dryRun) {
    wp_update_post(['ID' => $post->ID, 'post_content' => $newContent]);
}

// Backup automático antes de migración real
$backup_query = "INSERT INTO wp_posts_backup SELECT * FROM wp_posts 
                WHERE post_content LIKE '%<wpg2%'";

// Script de rollback disponible para revertir cambios
// Restaura automáticamente desde la tabla de backup

Dashboard de Monitoreo en Tiempo Real

El sistema desarrolló, además, un dashboard visual que para permitir:

  • Monitoreo de progreso: Barra visual del porcentaje de migración completada
  • Estadísticas detalladas: Posts migrados, errores, pendientes de revisión manual
  • Listado de problemas: Identificación de IDs huérfanos sin mapeo en Piwigo
  • Vista detallada por post: Ver antes/después del contenido para auditoría
  • Enlaces directos a edición: Acceso rápido a editor de WordPress para correcciones manuales
Dashboard desarrollado, con el resultado de los análisis
Dashboard desarrollado, con el resultado de los análisis

Resultados y Métricas de Migración

El sistema procesó exitosamente:

  • Métricas: 327 artículos de WordPress con referencias a Gallery2, y 12638 referencias encontradas
  • 85% de imágenes identificadas por nombre exacto en primer intento
  • 12% ubicadas mediante coincidencia de nombre + fecha de creación
  • 3% resueltas mediante búsqueda difusa de títulos
  • Tasa de error: <0.5% (principalmente imágenes eliminadas en Gallery2)

Lecciones Aprendidas y Mejores Prácticas

1. No asumir correspondencia de IDs: Nunca des por sentado que los identificadores coincidirán entre sistemas. Siempre mapear usando atributos únicos como nombres de archivo y fechas.

2. Manejar formatos heredados complejos: Los tags pueden incluir parámetros opcionales. Las expresiones regulares con captura de grupos opcionales ((?:\|(\d+))?) son esenciales.

3. Conversión de timezones y tipos de dato: Al comparar fechas entre sistemas, convertir siempre a un formato común y permitir margen de error (±1 día es prudente).

4. Procesamiento en lotes con logging: Procesar posts en lotes pequeños (50-100) permite monitorear problemas individuales sin perder todo el progreso ante un error.

5. Errores auditables, no silenciosos: Los comentarios HTML del tipo «MIGRATION ERROR» dentro del contenido son visibles en el frontend, facilitando la auditoría manual.

Conclusión

El resultado superó todas mis expectativas, como comentaba. Era consciente de la magnitud del problema que tenía entre manos, cuya complejidad hubiera requerido cientos de horas de trabajo manual para poder solucionar. Sin embargo, con un adecuado manejo de las herramientas proporcionadas por la IA, junto con un conocimiento profundo del entorno, en apenas una mañana fui capaz de completar la actualización de las referencias y disponer, finalmente, de un sistema completamente actualizado.

La principal experiencia obtenida es que la migración de sistemas legacy en WordPress presenta importantes desafíos, pero es un problema manejable con las estrategias correctas. Al ser capaz de utilizar una IA generativa para desarrollar un procedimiento que permita combinar extracción inteligente de datos, mapeo multi-criterio, expresiones regulares sofisticadas y validación cuidadosa, es posible reemplazar completamente galerías obsoletas sin perder referencias críticas.

El sistema desarrollado, además, es reutilizable para migraciones similares, prueba de que la automatización inteligente supera ampliamente al reemplazo manual de miles de referencias.

Actualización de mi sistema WordPress y galería integrada

Actualización de este sitio web. Piwigo Gallery Integration. El plugin que WordPress Necesitaba

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.