exportar.php Exportación CSV jerárquica 1 líneas
1
<?php
// ============================================================
// SIDE - ARC 1.0
// Archivo: exportar.php
// Propósito: Exportación contextual recursiva a CSV.
//            Recupera el registro raíz indicado y TODOS sus
//            subordinados en cascada mediante WITH RECURSIVE.
//            El CSV resultante es compatible con importar.php.
//            Protegido: solo administradores.
// ============================================================

require_once 'conexion.php';
require_once 'helpers.php';
requerir_admin();

// --- Validar ID del registro raíz de la exportación ---
if (!isset($_GET['id']) || !is_numeric($_GET['id'])) {
    header('Location: /apps/side-arc/cuadro_clasificacion.php');
    exit;
}

$id_raiz = (int) $_GET['id'];

// --- Verificar que el registro existe ---
$stmt = mysqli_prepare($conexion,
    "SELECT id, titulo FROM descripcion_isadg WHERE id = ? LIMIT 1");
mysqli_stmt_bind_param($stmt, 'i', $id_raiz);
mysqli_stmt_execute($stmt);
$res      = mysqli_stmt_get_result($stmt);
$registro = mysqli_fetch_assoc($res);
mysqli_free_result($res);
mysqli_stmt_close($stmt);

if (!$registro) {
    header('Location: /apps/side-arc/cuadro_clasificacion.php');
    exit;
}

// ============================================================
// CONSULTA RECURSIVA: registro raíz + todos sus descendientes
// WITH RECURSIVE desciende por parent_id hasta las hojas.
// Se añade la columna 'profundidad' para ordenar el árbol
// correctamente en el CSV (raíz primero, hojas al final).
// ============================================================
$sql = "
    WITH RECURSIVE descendientes AS (

        -- Caso base: el registro raíz seleccionado
        SELECT
            id, parent_id, codigo_referencia, titulo, fechas,
            nivel_descripcion, volumen_soporte, nombre_productor,
            historia_institucional, alcance_contenido,
            valoracion_eliminacion, organizacion,
            condiciones_acceso, condiciones_reproduccion,
            lengua_escritura, caracteristicas_fisicas,
            unidades_relacionadas, notas,
            fecha_ingreso_registro, fechas_descripciones,
            estado, nombre_descriptor, nota_archivero,
            fecha_creacion_revision, reglas_normas,
            pa_nombre, pa_geografico, pam_materia,
            fecha_inicial_filtro, fecha_final_filtro,
            0 AS profundidad
        FROM descripcion_isadg
        WHERE id = ?

        UNION ALL

        -- Caso recursivo: hijos de cada nodo ya encontrado
        SELECT
            d.id, d.parent_id, d.codigo_referencia, d.titulo, d.fechas,
            d.nivel_descripcion, d.volumen_soporte, d.nombre_productor,
            d.historia_institucional, d.alcance_contenido,
            d.valoracion_eliminacion, d.organizacion,
            d.condiciones_acceso, d.condiciones_reproduccion,
            d.lengua_escritura, d.caracteristicas_fisicas,
            d.unidades_relacionadas, d.notas,
            d.fecha_ingreso_registro, d.fechas_descripciones,
            d.estado, d.nombre_descriptor, d.nota_archivero,
            d.fecha_creacion_revision, d.reglas_normas,
            d.pa_nombre, d.pa_geografico, d.pam_materia,
            d.fecha_inicial_filtro, d.fecha_final_filtro,
            desc2.profundidad + 1
        FROM descripcion_isadg d
        INNER JOIN descendientes desc2 ON d.parent_id = desc2.id
    )
    SELECT * FROM descendientes
    ORDER BY profundidad ASC, titulo ASC
";

$stmt2 = mysqli_prepare($conexion, $sql);
mysqli_stmt_bind_param($stmt2, 'i', $id_raiz);
mysqli_stmt_execute($stmt2);
$res2 = mysqli_stmt_get_result($stmt2);

// ============================================================
// COLUMNAS DEL CSV
// Coinciden exactamente con las columnas de importar.php
// para garantizar compatibilidad de ida y vuelta.
// Las columnas de sistema (id, parent_id, objeto_digital,
// profundidad) se excluyen del CSV exportable.
// ============================================================
$columnas_csv = [
    'codigo_referencia', 'titulo', 'fechas', 'nivel_descripcion',
    'volumen_soporte', 'nombre_productor', 'historia_institucional',
    'alcance_contenido', 'valoracion_eliminacion', 'organizacion',
    'condiciones_acceso', 'condiciones_reproduccion', 'lengua_escritura',
    'caracteristicas_fisicas', 'unidades_relacionadas', 'notas',
    'fecha_ingreso_registro', 'fechas_descripciones', 'estado',
    'nombre_descriptor', 'nota_archivero', 'fecha_creacion_revision',
    'reglas_normas', 'pa_nombre', 'pa_geografico', 'pam_materia',
    'fecha_inicial_filtro', 'fecha_final_filtro',
];

// ============================================================
// GENERAR NOMBRE DEL ARCHIVO
// Usa el título del registro raíz saneado para el nombre.
// ============================================================
$titulo_seguro = preg_replace('/[^a-zA-Z0-9_\-]/', '_', $registro['titulo']);
$titulo_seguro = substr($titulo_seguro, 0, 60);
$nombre_archivo = 'exportacion_' . $titulo_seguro . '_' . date('Ymd_His') . '.csv';

// ============================================================
// ENVIAR CABECERAS HTTP PARA DESCARGA
// ============================================================
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename="' . $nombre_archivo . '"');
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');

// ============================================================
// ESCRIBIR CSV DIRECTAMENTE A LA SALIDA
// ============================================================
$out = fopen('php://output', 'w');

// BOM UTF-8 para compatibilidad con Excel
fputs($out, "\xEF\xBB\xBF");

// Fila de cabecera
fputcsv($out, $columnas_csv, ',', '"');

// Contador de registros exportados
$total_exportados = 0;

// Filas de datos
while ($fila = mysqli_fetch_assoc($res2)) {
    $fila_csv = [];
    foreach ($columnas_csv as $col) {
        // Convertir NULL a cadena vacía en el CSV
        $fila_csv[] = $fila[$col] ?? '';
    }
    fputcsv($out, $fila_csv, ',', '"');
    $total_exportados++;
}

fclose($out);
mysqli_free_result($res2);
mysqli_stmt_close($stmt2);
mysqli_close($conexion);

// La salida ya fue enviada como descarga: no hay más HTML.
exit;