eliminar.php Lógica de eliminación en cascada 1 líneas
1
<?php
// ============================================================
// SIDE - ARC 1.0
// Archivo: eliminar.php
// ============================================================

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

// --- Validar ID ---
if (!isset($_GET['id']) || !is_numeric($_GET['id'])) {
    header('Location: /apps/side-arc/cuadro_clasificacion.php');
    exit;
}

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

// --- Cargar datos del registro ---
$stmt = mysqli_prepare($conexion,
    "SELECT id, titulo, nivel_descripcion, parent_id
     FROM descripcion_isadg WHERE id = ? LIMIT 1");
mysqli_stmt_bind_param($stmt, 'i', $id);
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;
}

// --- Niveles con bloqueo total (no permiten cascada) ---
$niveles_bloqueados = [
    'Fondo',
    '1era División de Fondo',
    '2da División de Fondo',
    'Subfondo',
];

// --- Niveles que permiten eliminación en cascada ---
$niveles_cascada = [
    'Serie',
    'Subserie',
    'Unidad Documental Compuesta',
    'Unidad Documental Simple',
];

$nivel_actual   = $registro['nivel_descripcion'];
$es_bloqueado   = in_array($nivel_actual, $niveles_bloqueados, true);
$parent_id      = $registro['parent_id'];

// --- Contar hijos directos ---
$total_hijos = contar_hijos($conexion, $id);

// ============================================================
// CASO 1: Nivel bloqueado CON hijos → bloqueo total
// ============================================================
if ($es_bloqueado && $total_hijos > 0) {
    $titulo_pagina = 'Eliminación bloqueada';
    require_once 'header.php';
    ?>
    <nav class="breadcrumb">
        <a href="/apps/side-arc/cuadro_clasificacion.php">Cuadro de Clasificación</a>
        <span class="breadcrumb__sep">›</span>
        <a href="/apps/side-arc/ficha.php?id=<?= $id ?>"><?= h($registro['titulo']) ?></a>
        <span class="breadcrumb__sep">›</span>
        <span>Eliminar</span>
    </nav>
    <div class="eliminar-contenedor">
        <div class="alerta alerta--error">
            <strong>Eliminación bloqueada</strong>
        </div>
        <div class="eliminar-card eliminar-card--bloqueado">
            <p class="eliminar-card__texto">
                El registro <strong>"<?= h($registro['titulo']) ?>"</strong>
                es de nivel <strong><?= h($nivel_actual) ?></strong> y contiene
                <strong><?= $total_hijos ?> entidad(es) subordinada(s)</strong>.
            </p>
            <p class="eliminar-card__texto">
                Los registros de nivel Fondo, División de Fondo y Subfondo
                no pueden eliminarse mientras tengan subordinados.
                Debe eliminar o reubicar todos sus registros dependientes primero.
            </p>
            <div class="eliminar-card__acciones">
                <a href="/apps/side-arc/subordinados.php?parent_id=<?= $id ?>"
                   class="btn btn--primario">
                    Ver entidades subordinadas
                </a>
                <a href="/apps/side-arc/ficha.php?id=<?= $id ?>"
                   class="btn btn--cancelar">
                    Volver a la ficha
                </a>
            </div>
        </div>
    </div>
    <?php
    mysqli_close($conexion);
    require_once 'footer.php';
    exit;
}

// ============================================================
// CASO 2: Nivel cascada CON hijos → mostrar confirmación
// ============================================================
if (in_array($nivel_actual, $niveles_cascada, true) && $total_hijos > 0) {

    // Contar total de descendientes con WITH RECURSIVE
    $sql_count = "WITH RECURSIVE descendientes AS (
                    SELECT id FROM descripcion_isadg WHERE id = ?
                    UNION ALL
                    SELECT d.id FROM descripcion_isadg d
                    INNER JOIN descendientes desc2 ON d.parent_id = desc2.id
                  )
                  SELECT COUNT(*) AS total FROM descendientes";
    $stmt_c = mysqli_prepare($conexion, $sql_count);
    mysqli_stmt_bind_param($stmt_c, 'i', $id);
    mysqli_stmt_execute($stmt_c);
    $res_c         = mysqli_stmt_get_result($stmt_c);
    $total_cascade = (int) mysqli_fetch_assoc($res_c)['total'];
    mysqli_stmt_close($stmt_c);

    // Si viene confirmación POST → ejecutar eliminación en cascada
    if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['confirmar'])) {

        $sql_del = "WITH RECURSIVE descendientes AS (
                        SELECT id FROM descripcion_isadg WHERE id = ?
                        UNION ALL
                        SELECT d.id FROM descripcion_isadg d
                        INNER JOIN descendientes desc2 ON d.parent_id = desc2.id
                    )
                    DELETE FROM descripcion_isadg
                    WHERE id IN (SELECT id FROM descendientes)";

        // MariaDB no permite WITH RECURSIVE en DELETE directamente
        // Usamos una tabla temporal
        mysqli_query($conexion, "CREATE TEMPORARY TABLE ids_eliminar
                                 WITH RECURSIVE descendientes AS (
                                     SELECT id FROM descripcion_isadg WHERE id = $id
                                     UNION ALL
                                     SELECT d.id FROM descripcion_isadg d
                                     INNER JOIN descendientes desc2 ON d.parent_id = desc2.id
                                 )
                                 SELECT id FROM descendientes");

        mysqli_query($conexion, "DELETE FROM descripcion_isadg
                                 WHERE id IN (SELECT id FROM ids_eliminar)");

        mysqli_query($conexion, "DROP TEMPORARY TABLE ids_eliminar");
        mysqli_close($conexion);

        $_SESSION['form_exito'] = 'El registro y sus ' . ($total_cascade - 1) . ' subordinado(s) fueron eliminados correctamente.';

        if ($parent_id !== null) {
            header('Location: /apps/side-arc/ficha.php?id=' . $parent_id);
        } else {
            header('Location: /apps/side-arc/cuadro_clasificacion.php');
        }
        exit;
    }

    // Mostrar pantalla de confirmación
    $titulo_pagina = 'Confirmar eliminación';
    require_once 'header.php';
    ?>
    <nav class="breadcrumb">
        <a href="/apps/side-arc/cuadro_clasificacion.php">Cuadro de Clasificación</a>
        <span class="breadcrumb__sep">›</span>
        <a href="/apps/side-arc/ficha.php?id=<?= $id ?>"><?= h($registro['titulo']) ?></a>
        <span class="breadcrumb__sep">›</span>
        <span>Eliminar</span>
    </nav>
    <div class="eliminar-contenedor">
        <div class="alerta alerta--advertencia">
            <strong>Confirmación requerida</strong>
        </div>
        <div class="eliminar-card">
            <p class="eliminar-card__texto">
                Está a punto de eliminar el registro
                <strong>"<?= h($registro['titulo']) ?>"</strong>
                de nivel <strong><?= h($nivel_actual) ?></strong>.
            </p>
            <p class="eliminar-card__texto">
                Esta acción eliminará en total
                <strong><?= $total_cascade ?> registro(s)</strong>
                (el registro seleccionado y todos sus subordinados en cascada).
                <strong>Esta acción no se puede deshacer.</strong>
            </p>
            <div class="eliminar-card__acciones">
                <form method="POST" action="/apps/side-arc/eliminar.php?id=<?= $id ?>">
                    <button type="submit" name="confirmar" value="1"
                            class="btn btn--peligro">
                        Confirmar eliminación de <?= $total_cascade ?> registro(s)
                    </button>
                </form>
                <a href="/apps/side-arc/ficha.php?id=<?= $id ?>"
                   class="btn btn--cancelar">
                    Cancelar
                </a>
            </div>
        </div>
    </div>
    <?php
    mysqli_close($conexion);
    require_once 'footer.php';
    exit;
}

// ============================================================
// CASO 3: Sin hijos → eliminar directamente
// ============================================================
$stmt_del = mysqli_prepare($conexion,
    "DELETE FROM descripcion_isadg WHERE id = ?");
mysqli_stmt_bind_param($stmt_del, 'i', $id);
$eliminado = mysqli_stmt_execute($stmt_del);
mysqli_stmt_close($stmt_del);
mysqli_close($conexion);

if (!$eliminado) {
    $_SESSION['form_error'] = 'Error al intentar eliminar el registro.';
    header('Location: /apps/side-arc/ficha.php?id=' . $id);
    exit;
}

$_SESSION['form_exito'] = 'El registro fue eliminado correctamente.';
if ($parent_id !== null) {
    header('Location: /apps/side-arc/ficha.php?id=' . $parent_id);
} else {
    header('Location: /apps/side-arc/cuadro_clasificacion.php');
}
exit;