[file name]: save_signalement.php
[file content begin]
<?php
// save_signalement.php — version corrigée avec le bon nom de colonne
error_reporting(E_ALL);
ini_set('display_errors', 1);

// === CONNEXION PDO ===
require_once __DIR__ . '/../src/includes/config.php';

if (!isset($pdo) || !($pdo instanceof PDO)) {
    // En cas d'erreur, rediriger vers une page d'erreur
    session_start();
    $_SESSION['form_errors'] = ["Erreur de connexion à la base de données."];
    header("Location: signalement.php");
    exit;
}

// === Récupération des données du formulaire ===
$type_situation_id = filter_input(INPUT_POST, 'type_situation_id', FILTER_VALIDATE_INT);
$lieu = trim((string)($_POST['lieu'] ?? ''));
$description = trim((string)($_POST['description'] ?? ''));

// Générer un numéro de dossier
$numero_dossier = (string)($_POST['numero_dossier'] ?? '');
if ($numero_dossier === '') {
    $numero_dossier = genererNumeroDossier('ethique');
}

// === Validation des données ===
$errors = [];
if (!$type_situation_id || $type_situation_id < 2) {
    $errors[] = "Le type de situation est obligatoire.";
}
if (empty($lieu)) {
    $errors[] = "Le lieu des faits est obligatoire.";
}
if (empty($description)) {
    $errors[] = "La description détaillée est obligatoire.";
}

if (!empty($errors)) {
    // Rediriger vers le formulaire avec les erreurs
    session_start();
    $_SESSION['form_errors'] = $errors;
    $_SESSION['form_data'] = $_POST;
    header("Location: signalement.php");
    exit;
}

// === Préparation des données ===
// Type de dossier FIXE = 1 (Signalement éthique)
$type_dossier_id = 1;

// Récupérer le libellé du type de situation
$type_situation_label = "Signalement éthique";
try {
    $stmtCheck = $pdo->prepare("SELECT libelle FROM types_situation WHERE id = ? AND dossier_type_id = 1 AND actif = 1");
    $stmtCheck->execute([$type_situation_id]);
    $type_situation = $stmtCheck->fetch(PDO::FETCH_ASSOC);
    
    if ($type_situation) {
        $type_situation_label = $type_situation['libelle'];
    }
} catch (Exception $e) {
    error_log("Erreur récupération type situation: " . $e->getMessage());
}

// Générer le titre automatiquement
$titre = "Signalement - " . $type_situation_label;

$mode_depot = 'anonyme';
$service_cible_id = 1; // Service Éthique
$statut_id = 1; // Statut "Reçu"

// === Gestion de l'upload de fichier ===
$hasFile = isset($_FILES['fichier']) && is_array($_FILES['fichier']) && $_FILES['fichier']['error'] !== UPLOAD_ERR_NO_FILE;
$uploadOk = false;
$uploadRel = null;
$hash = null;
$origName = null;
$sizeBytes = null;

if ($hasFile) {
    $f = $_FILES['fichier'];
    
    if ($f['error'] !== UPLOAD_ERR_OK) {
        session_start();
        $_SESSION['form_errors'] = ["Erreur lors de l'upload du fichier (code {$f['error']})."];
        $_SESSION['form_data'] = $_POST;
        header("Location: signalement.php");
        exit;
    }

    $origName = $f['name'];
    $sizeBytes = (int)$f['size'];
    $tmp = $f['tmp_name'];

    // Vérification taille (10MB max)
    if ($sizeBytes > 10 * 1024 * 1024) {
        session_start();
        $_SESSION['form_errors'] = ["Le fichier est trop volumineux (> 10 Mo)."];
        $_SESSION['form_data'] = $_POST;
        header("Location: signalement.php");
        exit;
    }

    // Vérification extension
    $ext = strtolower(pathinfo($origName, PATHINFO_EXTENSION));
    $allowed = ['pdf', 'jpg', 'jpeg', 'png', 'doc', 'docx', 'mp3', 'wav'];
    
    if ($ext && !in_array($ext, $allowed, true)) {
        session_start();
        $_SESSION['form_errors'] = ["Type de fichier non autorisé (.$ext). Formats acceptés: " . implode(', ', $allowed)];
        $_SESSION['form_data'] = $_POST;
        header("Location: signalement.php");
        exit;
    }

    // Préparation répertoire d'upload
    $baseUploadDir = __DIR__ . '/uploads';
    $subDir = date('Y') . '/' . date('m');
    $targetDir = $baseUploadDir . '/' . $subDir;
    
    if (!is_dir($targetDir) && !mkdir($targetDir, 0775, true) && !is_dir($targetDir)) {
        session_start();
        $_SESSION['form_errors'] = ["Impossible de créer le répertoire de stockage."];
        $_SESSION['form_data'] = $_POST;
        header("Location: signalement.php");
        exit;
    }

    // Génération nom sécurisé
    $safe = preg_replace('/[^a-zA-Z0-9_\-]/', '_', pathinfo($origName, PATHINFO_FILENAME)) ?: 'pj';
    $serverName = $safe . '-' . bin2hex(random_bytes(4)) . ($ext ? ".$ext" : '');
    $targetPath = $targetDir . '/' . $serverName;
    $uploadRel = 'uploads/' . $subDir . '/' . $serverName;

    // Hash et déplacement
    $hash = hash_file('sha256', $tmp);
    
    if (!move_uploaded_file($tmp, $targetPath)) {
        session_start();
        $_SESSION['form_errors'] = ["Erreur lors de l'enregistrement du fichier."];
        $_SESSION['form_data'] = $_POST;
        header("Location: signalement.php");
        exit;
    }
    
    $uploadOk = true;
}

// === Insertion en base ===
try {
    $pdo->beginTransaction();

    // Vérifier si la colonne type_situation_id existe
    $hasTypeSituationColumn = false;
    try {
        $checkColumn = $pdo->query("SHOW COLUMNS FROM dossiers LIKE 'type_situation_id'");
        $hasTypeSituationColumn = $checkColumn->rowCount() > 0;
    } catch (Exception $e) {
        $hasTypeSituationColumn = false;
    }

    // Vérifier si la colonne lieu existe
    $hasLieuColumn = false;
    try {
        $checkLieuColumn = $pdo->query("SHOW COLUMNS FROM dossiers LIKE 'lieu'");
        $hasLieuColumn = $checkLieuColumn->rowCount() > 0;
    } catch (Exception $e) {
        $hasLieuColumn = false;
    }

    // Construction dynamique de la requête SQL
    $columns = [
        'numero_dossier', 
        'type_id', 
        'titre', 
        'description', 
        'mode_depot',
        'service_cible_id', 
        'statut_id', 
        'date_creation'
    ];
    
    $placeholders = [
        ':numero', 
        ':type_dossier', 
        ':titre', 
        ':descr', 
        ':mode',
        ':service', 
        ':statut', 
        'NOW()'
    ];
    
    $params = [
        ':numero'       => $numero_dossier,
        ':type_dossier' => $type_dossier_id,
        ':titre'        => $titre,
        ':descr'        => $description,
        ':mode'         => $mode_depot,
        ':service'      => $service_cible_id,
        ':statut'       => $statut_id,
    ];

    // Ajouter type_situation_id si la colonne existe
    if ($hasTypeSituationColumn) {
        $columns[] = 'type_situation_id';
        $placeholders[] = ':type_situation';
        $params[':type_situation'] = $type_situation_id;
    }

    // Ajouter lieu si la colonne existe
    if ($hasLieuColumn) {
        $columns[] = 'lieu';
        $placeholders[] = ':lieu';
        $params[':lieu'] = $lieu;
    }

    // Construction de la requête finale
    $sqlDossier = "
        INSERT INTO dossiers (" . implode(', ', $columns) . ")
        VALUES (" . implode(', ', $placeholders) . ")
    ";
    
    $stmt = $pdo->prepare($sqlDossier);
    $stmt->execute($params);
    
    $dossier_id = (int)$pdo->lastInsertId();

    // Insertion pièce jointe si présente
    if ($uploadOk) {
        // Vérifier la structure de la table pieces_jointes
        $checkPiecesColumns = $pdo->query("SHOW COLUMNS FROM pieces_jointes");
        $piecesColumns = $checkPiecesColumns->fetchAll(PDO::FETCH_COLUMN);
        
        // Construction dynamique pour pieces_jointes
        $pjColumns = ['dossier_id', 'nom_fichier', 'chemin_stockage'];
        $pjPlaceholders = [':dossier_id', ':nom_fichier', ':chemin'];
        $pjParams = [
            ':dossier_id'  => $dossier_id,
            ':nom_fichier' => $origName,
            ':chemin'      => $uploadRel,
        ];

        // Ajouter taille si la colonne existe
        if (in_array('taille', $piecesColumns)) {
            $pjColumns[] = 'taille';
            $pjPlaceholders[] = ':taille';
            $pjParams[':taille'] = $sizeBytes;
        }
        
        // Ajouter hash_sha256 si la colonne existe
        if (in_array('hash_sha256', $piecesColumns)) {
            $pjColumns[] = 'hash_sha256';
            $pjPlaceholders[] = ':hash';
            $pjParams[':hash'] = $hash;
        }

        $sqlPiece = "
            INSERT INTO pieces_jointes (" . implode(', ', $pjColumns) . ")
            VALUES (" . implode(', ', $pjPlaceholders) . ")
        ";
        
        $stmt2 = $pdo->prepare($sqlPiece);
        $stmt2->execute($pjParams);
    }

    $pdo->commit();

    // Redirection vers la page de succès
    header("Location: merci.php?numero=" . urlencode($numero_dossier) . "&type=ethique");
    exit;

} catch (Throwable $e) {
    if ($pdo->inTransaction()) {
        $pdo->rollBack();
    }
    
    // Rediriger vers le formulaire avec erreur
    session_start();
    $_SESSION['form_errors'] = ["Erreur lors de l'enregistrement : " . $e->getMessage()];
    $_SESSION['form_data'] = $_POST;
    header("Location: signalement.php");
    exit;
}
?>
[file content end]