getPDO(); // Check file upload if ($_FILES['csv_file']['error'] !== UPLOAD_ERR_OK) { throw new Exception("Erreur lors du téléversement du fichier."); } // Read CSV file $csvFile = $_FILES['csv_file']['tmp_name']; $handle = fopen($csvFile, 'r'); if (!$handle) { throw new Exception("Impossible d'ouvrir le fichier CSV."); } // Skip first two rows (empty and headers) fgetcsv($handle, 0, ',', '"', ''); // Empty row $headers = fgetcsv($handle, 0, ',', '"', ''); // Header row fgetcsv($handle, 0, ',', '"', ''); // Description row $headers = fgetcsv($handle, 0, ',', '"', ''); // Actual column names // Map CSV columns $columnMap = [ 0 => 'identifier', // Identifiant 1 => 'title', // Titre 2 => 'subtitle', // Sous-titre 3 => 'authors', // Auteur·ice(s) 4 => 'contact', // Contact 5 => 'supervisors', // Promoteur·ice(s) 6 => 'formats', // Format 7 => 'year', // Année 8 => 'ap', // AP 9 => 'orientation', // Orientation 10 => 'finality', // Finalité 11 => 'keywords', // Mots-clés 12 => 'synopsis', // Synopsis 13 => 'context', // Contexte 14 => 'remarks', // Remarques 15 => 'language', // Langue 16 => 'access', // Autorisation 17 => 'license', // License 18 => 'size_info', // taille 19 => 'jury_points', // Points sur 20 20 => 'baiu_link', // lien BAIU ]; // Orientation abbreviation mapping $orientationMap = [ 'SC' => 'Sculpture', 'VI' => 'Vidéographie', 'CA' => 'Cinéma d\'animation', 'IP' => 'Installation-Performance', 'PE' => 'Peinture', 'PH' => 'Photographie', 'DE' => 'Dessin', 'AN' => 'Arts Numériques', 'GR' => 'Graphisme', 'TY' => 'Typographie', 'DN' => 'Design Numérique', 'IL' => 'Illustration', 'BD' => 'Bande-Dessinée', 'SE' => 'Sérigraphie', 'GV' => 'Gravure', ]; // Process each row $lineNumber = 5; // Start after headers while (($row = fgetcsv($handle, 0, ',', '"', '')) !== false) { $lineNumber++; // Skip empty rows if (empty($row[0]) && empty($row[1])) { continue; } try { $db->beginTransaction(); // Extract data $identifier = trim($row[0] ?? ''); $title = trim($row[1] ?? ''); $subtitle = trim($row[2] ?? ''); $authorsRaw = trim($row[3] ?? ''); $contact = trim($row[4] ?? ''); $supervisorsRaw = trim($row[5] ?? ''); $formatsRaw = trim($row[6] ?? ''); $year = intval($row[7] ?? 0); $apCode = trim($row[8] ?? ''); $orientationCode = trim($row[9] ?? ''); $finalityName = trim($row[10] ?? ''); $keywordsRaw = trim($row[11] ?? ''); $synopsis = trim($row[12] ?? ''); $context = trim($row[13] ?? ''); $remarks = trim($row[14] ?? ''); $languageRaw = trim($row[15] ?? ''); $access = trim($row[16] ?? ''); $license = trim($row[17] ?? ''); $sizeInfo = trim($row[18] ?? ''); $juryPoints = !empty($row[19]) ? floatval($row[19]) : null; $baiuLink = trim($row[20] ?? ''); // Validate required fields if (empty($title) || empty($year)) { throw new Exception("Ligne $lineNumber: Titre et année requis."); } // Map orientation $orientationName = isset($orientationMap[$orientationCode]) ? $orientationMap[$orientationCode] : null; $orientationId = null; if ($orientationName) { $stmtOr = $pdo->prepare("SELECT id FROM orientations WHERE name = ?"); $stmtOr->execute([$orientationName]); $rowOr = $stmtOr->fetch(); $orientationId = $rowOr ? $rowOr['id'] : null; } // Map AP program $apProgramId = null; if (!empty($apCode)) { $stmt = $pdo->prepare("SELECT id FROM ap_programs WHERE code = ?"); $stmt->execute([$apCode]); $result = $stmt->fetch(); if ($result) { $apProgramId = $result['id']; } } // Map finality $finalityId = null; if (!empty($finalityName)) { $stmtFin = $pdo->prepare("SELECT id FROM finality_types WHERE name = ?"); $stmtFin->execute([$finalityName]); $rowFin = $stmtFin->fetch(); $finalityId = $rowFin ? $rowFin['id'] : null; } // Map access type (Autorisation column) // CSV values are expected to match access_types.name: "Libre", "Interne", "Interdit" $accessTypeId = null; if (!empty($access)) { $stmtAcc = $pdo->prepare("SELECT id FROM access_types WHERE name = ?"); $stmtAcc->execute([ucfirst(strtolower($access))]); $rowAcc = $stmtAcc->fetch(); $accessTypeId = $rowAcc ? $rowAcc['id'] : null; } // Default to Libre (id=1) when not specified so imported theses are visible if ($accessTypeId === null) { $accessTypeId = 1; } // Skip if identifier already exists if (!empty($identifier)) { $stmtCheck = $pdo->prepare("SELECT id FROM theses WHERE identifier = ?"); $stmtCheck->execute([$identifier]); if ($stmtCheck->fetch()) { $db->rollback(); $skippedCount++; $importResults[] = "⚠ Ligne $lineNumber: identifiant \"$identifier\" déjà présent, ignoré."; continue; } } // Insert thesis $stmt = $pdo->prepare(" INSERT INTO theses ( identifier, title, subtitle, year, orientation_id, ap_program_id, finality_id, synopsis, context_note, remarks, file_size_info, jury_points, baiu_link, access_type_id, is_published, submitted_at ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, CURRENT_TIMESTAMP) "); $stmt->execute([ !empty($identifier) ? $identifier : null, $title, !empty($subtitle) ? $subtitle : null, $year, $orientationId, $apProgramId, $finalityId, !empty($synopsis) ? $synopsis : null, !empty($context) ? $context : null, !empty($remarks) ? $remarks : null, !empty($sizeInfo) ? $sizeInfo : null, $juryPoints, !empty($baiuLink) ? $baiuLink : null, $accessTypeId ]); $thesisId = $pdo->lastInsertId(); // Add authors if (!empty($authorsRaw)) { $authors = array_map('trim', explode(',', $authorsRaw)); foreach ($authors as $index => $authorName) { if (!empty($authorName)) { $authorId = $db->findOrCreateAuthor($authorName, $index === 0 ? $contact : null); $stmt = $pdo->prepare("INSERT INTO thesis_authors (thesis_id, author_id, author_order) VALUES (?, ?, ?)"); $stmt->execute([$thesisId, $authorId, $index + 1]); } } } // Add supervisors if (!empty($supervisorsRaw)) { $supervisors = array_map('trim', explode(',', $supervisorsRaw)); foreach ($supervisors as $index => $supervisorName) { if (!empty($supervisorName)) { $supervisorId = $db->findOrCreateSupervisor($supervisorName); $stmt = $pdo->prepare("INSERT INTO thesis_supervisors (thesis_id, supervisor_id, supervisor_order) VALUES (?, ?, ?)"); $stmt->execute([$thesisId, $supervisorId, $index + 1]); } } } // Add keywords if (!empty($keywordsRaw)) { $keywords = array_map('trim', explode(',', $keywordsRaw)); $keywords = array_slice($keywords, 0, 10); // Max 10 foreach ($keywords as $keyword) { if (!empty($keyword)) { $tagId = $db->findOrCreateTag($keyword); if ($tagId) { $stmtTag = $pdo->prepare("INSERT INTO thesis_tags (thesis_id, tag_id) VALUES (?, ?)"); $stmtTag->execute([$thesisId, $tagId]); } } } } // Add language if (!empty($languageRaw)) { $stmtLang = $pdo->prepare("SELECT id FROM languages WHERE name = ?"); $stmtLang->execute([ucfirst(strtolower($languageRaw))]); $rowLang = $stmtLang->fetch(); $languageId = $rowLang ? $rowLang['id'] : null; if ($languageId) { $stmt = $pdo->prepare("INSERT INTO thesis_languages (thesis_id, language_id) VALUES (?, ?)"); $stmt->execute([$thesisId, $languageId]); } } // Add formats if (!empty($formatsRaw)) { $formats = array_map('trim', explode(',', $formatsRaw)); foreach ($formats as $formatName) { if (!empty($formatName)) { $stmtFmt = $pdo->prepare("SELECT id FROM format_types WHERE name = ?"); $stmtFmt->execute([ucfirst(strtolower($formatName))]); $rowFmt = $stmtFmt->fetch(); $formatId = $rowFmt ? $rowFmt['id'] : null; if ($formatId) { $stmt = $pdo->prepare("INSERT INTO thesis_formats (thesis_id, format_id) VALUES (?, ?)"); $stmt->execute([$thesisId, $formatId]); } } } } $db->commit(); $importedCount++; $importResults[] = "✓ Ligne $lineNumber: \"$title\" importé (ID: $thesisId)"; } catch (Exception $e) { $db->rollback(); $skippedCount++; $importResults[] = "✗ Ligne $lineNumber: " . $e->getMessage(); error_log("Import error on line $lineNumber: " . $e->getMessage()); } } fclose($handle); $message = "Import terminé : $importedCount TFE importés, $skippedCount ignorés."; } catch (Exception $e) { $errors[] = $e->getMessage(); error_log("CSV import error: " . $e->getMessage()); } } // Regenerate CSRF token $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } ?>

Importer une liste de TFE

⚠ Erreurs :
Colonnes attendues : Identifiant, Titre, Sous-titre, Auteur·ice(s), Contact, Promoteur·ice(s), Format, Année, AP, Orientation, Finalité, Mots-clés, Synopsis, Contexte, Remarques, Langue, Autorisation, License, taille, Points sur 20, lien BAIU
— Deux premières lignes ignorées (en-tête) — Séparateur : virgule — Encodage : UTF-8

Résultats de l'import