Initial commit (code), runtime ignoré, secrets exclus
This commit is contained in:
268
enseignant/export.php
Normal file
268
enseignant/export.php
Normal file
@ -0,0 +1,268 @@
|
||||
<?php
|
||||
/**
|
||||
* EXPORT ÉVALUATION - BASÉ SUR STRUCTURE RÉELLE BDD
|
||||
* Structure vérifiée via diagnostic_structure_bdd.php
|
||||
*/
|
||||
|
||||
require_once '../config/config.php';
|
||||
require_once '../config/database.php';
|
||||
require_once '../config/session.php';
|
||||
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
SessionManager::startSession();
|
||||
}
|
||||
|
||||
if (!isset($_SESSION['user_id']) || $_SESSION['type_libelle'] !== 'enseignant') {
|
||||
die('Accès refusé');
|
||||
}
|
||||
|
||||
$id_evaluation = $_GET['id_evaluation'] ?? null;
|
||||
$format = $_GET['format'] ?? 'csv';
|
||||
|
||||
if (!$id_evaluation || !in_array($format, ['csv', 'json'])) {
|
||||
die('Paramètres invalides');
|
||||
}
|
||||
|
||||
try {
|
||||
$db = Database::getInstance()->getConnection();
|
||||
|
||||
// Évaluation
|
||||
$stmt = $db->prepare("SELECT * FROM evaluations WHERE id_evaluation = ?");
|
||||
$stmt->execute([$id_evaluation]);
|
||||
$evaluation = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$evaluation) {
|
||||
die('Évaluation non trouvée');
|
||||
}
|
||||
|
||||
// Questions
|
||||
$stmt = $db->prepare("SELECT * FROM questions WHERE id_evaluation = ? ORDER BY ordre ASC");
|
||||
$stmt->execute([$id_evaluation]);
|
||||
$questions = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// Tentatives (CORRECTION: date_fin au lieu de date_soumission)
|
||||
$stmt = $db->prepare("
|
||||
SELECT
|
||||
te.*,
|
||||
TIMESTAMPDIFF(MINUTE, te.date_debut, COALESCE(te.date_fin, NOW())) as duree_minutes_calc,
|
||||
u.login, u.nom, u.prenom,
|
||||
c.nom_classe
|
||||
FROM tentatives_eleves te
|
||||
JOIN utilisateurs u ON te.id_eleve = u.id_utilisateur
|
||||
LEFT JOIN classes c ON u.id_classe = c.id_classe
|
||||
WHERE te.id_evaluation = ?
|
||||
ORDER BY u.nom, u.prenom
|
||||
");
|
||||
$stmt->execute([$id_evaluation]);
|
||||
$tentatives = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($format === 'csv') {
|
||||
exportCSV($evaluation, $questions, $tentatives);
|
||||
} else {
|
||||
exportJSON($evaluation, $questions, $tentatives);
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
die('Erreur: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Extrait réponse correcte depuis reponse_correcte_json
|
||||
* Format réel: {"reponse": "x = 4"}
|
||||
*/
|
||||
function extraireReponseCorrecte($question) {
|
||||
// 1. Essayer reponse_correcte_json d'abord (pour type number, text, etc.)
|
||||
$correcte_data = json_decode($question['reponse_correcte_json'] ?? '{}', true);
|
||||
|
||||
if (isset($correcte_data['reponse'])) {
|
||||
$rep = $correcte_data['reponse'];
|
||||
if (is_array($rep)) {
|
||||
return implode(' | ', $rep);
|
||||
}
|
||||
return $rep;
|
||||
}
|
||||
|
||||
// 2. Fallback: chercher dans options_json (pour checkbox, qcm, select)
|
||||
$options = json_decode($question['options_json'] ?? '{}', true);
|
||||
|
||||
if (isset($options['reponses']) && is_array($options['reponses'])) {
|
||||
$correctes = [];
|
||||
foreach ($options['reponses'] as $rep) {
|
||||
if (isset($rep['est_correcte']) && $rep['est_correcte'] === true) {
|
||||
$correctes[] = $rep['texte'] ?? $rep['id'];
|
||||
}
|
||||
}
|
||||
if (!empty($correctes)) {
|
||||
return implode(' + ', $correctes);
|
||||
}
|
||||
}
|
||||
|
||||
// 2b. Format avec 'options' (select)
|
||||
if (isset($options['options']) && is_array($options['options'])) {
|
||||
foreach ($options['options'] as $opt) {
|
||||
if (isset($opt['est_correcte']) && $opt['est_correcte'] === true) {
|
||||
return $opt['texte'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Fallback ultime: options_json peut être un simple array ["opt1", "opt2"]
|
||||
if (isset($options['correct_answer'])) {
|
||||
return $options['correct_answer'];
|
||||
}
|
||||
|
||||
return 'N/A';
|
||||
}
|
||||
|
||||
function exportCSV($evaluation, $questions, $tentatives) {
|
||||
$filename = sprintf(
|
||||
'eval_%d_%s_%s.csv',
|
||||
$evaluation['id_evaluation'],
|
||||
preg_replace('/[^a-z0-9]/i', '_', substr($evaluation['titre'], 0, 30)),
|
||||
date('Ymd_His')
|
||||
);
|
||||
|
||||
header('Content-Type: text/csv; charset=utf-8');
|
||||
header('Content-Disposition: attachment; filename="' . $filename . '"');
|
||||
header('Pragma: no-cache');
|
||||
header('Expires: 0');
|
||||
|
||||
$output = fopen('php://output', 'w');
|
||||
fprintf($output, chr(0xEF).chr(0xBB).chr(0xBF));
|
||||
|
||||
// En-tête
|
||||
$headers = ['ID', 'Élève', 'Classe', 'Login', 'Statut', 'Début', 'Fin', 'Durée(min)', 'Note', 'Note sur', '%'];
|
||||
|
||||
foreach ($questions as $q) {
|
||||
$headers[] = 'Q' . $q['ordre'];
|
||||
}
|
||||
foreach ($questions as $q) {
|
||||
$headers[] = 'Q' . $q['ordre'] . '_Correcte';
|
||||
}
|
||||
|
||||
fputcsv($output, $headers, ';');
|
||||
|
||||
// Données
|
||||
foreach ($tentatives as $t) {
|
||||
$reponses = json_decode($t['reponses_json'] ?? '{}', true) ?: [];
|
||||
|
||||
$row = [
|
||||
$t['id_tentative'],
|
||||
$t['prenom'] . ' ' . $t['nom'],
|
||||
$t['nom_classe'] ?: 'Libre',
|
||||
$t['login'],
|
||||
$t['statut'],
|
||||
$t['date_debut'],
|
||||
$t['date_fin'] ?: '-',
|
||||
$t['temps_passe'] ?? $t['duree_minutes_calc'],
|
||||
$t['note'] !== null ? number_format($t['note'], 2, ',', '') : 'N/A',
|
||||
$t['note_sur'] ?? $evaluation['note_totale'],
|
||||
$t['pourcentage'] !== null ? number_format($t['pourcentage'], 1, ',', '') . '%' : 'N/A'
|
||||
];
|
||||
|
||||
// Réponses élève
|
||||
foreach ($questions as $q) {
|
||||
$rep = $reponses[$q['id_question']] ?? '';
|
||||
if (is_array($rep)) {
|
||||
$rep = implode(' + ', $rep);
|
||||
} elseif (is_object($rep)) {
|
||||
$rep = json_encode($rep, JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
$row[] = $rep;
|
||||
}
|
||||
|
||||
// Réponses correctes
|
||||
foreach ($questions as $q) {
|
||||
$row[] = extraireReponseCorrecte($q);
|
||||
}
|
||||
|
||||
fputcsv($output, $row, ';');
|
||||
}
|
||||
|
||||
fclose($output);
|
||||
exit;
|
||||
}
|
||||
|
||||
function exportJSON($evaluation, $questions, $tentatives) {
|
||||
$filename = sprintf(
|
||||
'eval_%d_%s_%s.json',
|
||||
$evaluation['id_evaluation'],
|
||||
preg_replace('/[^a-z0-9]/i', '_', substr($evaluation['titre'], 0, 30)),
|
||||
date('Ymd_His')
|
||||
);
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
header('Content-Disposition: attachment; filename="' . $filename . '"');
|
||||
|
||||
$export = [
|
||||
'metadata' => [
|
||||
'date_export' => date('Y-m-d H:i:s'),
|
||||
'exporteur' => $_SESSION['login'] ?? 'Enseignant'
|
||||
],
|
||||
'evaluation' => [
|
||||
'id' => (int)$evaluation['id_evaluation'],
|
||||
'titre' => $evaluation['titre'],
|
||||
'description' => $evaluation['description'] ?? '',
|
||||
'type' => $evaluation['type'],
|
||||
'duree_minutes' => (int)$evaluation['duree_minutes'],
|
||||
'note_totale' => (float)$evaluation['note_totale'],
|
||||
'nb_questions' => count($questions),
|
||||
'tentatives_max' => (int)$evaluation['tentatives_max']
|
||||
],
|
||||
'questions' => [],
|
||||
'tentatives' => []
|
||||
];
|
||||
|
||||
foreach ($questions as $q) {
|
||||
$export['questions'][] = [
|
||||
'id' => (int)$q['id_question'],
|
||||
'ordre' => (int)$q['ordre'],
|
||||
'type' => $q['type_question'],
|
||||
'enonce' => $q['enonce'],
|
||||
'options' => json_decode($q['options_json'] ?? '[]', true),
|
||||
'reponse_correcte' => extraireReponseCorrecte($q),
|
||||
'points' => (float)$q['points'],
|
||||
'explication' => $q['explication'] ?? null
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($tentatives as $t) {
|
||||
$reponses = json_decode($t['reponses_json'] ?? '{}', true) ?: [];
|
||||
$details = [];
|
||||
|
||||
foreach ($questions as $q) {
|
||||
$details[] = [
|
||||
'question_id' => (int)$q['id_question'],
|
||||
'ordre' => (int)$q['ordre'],
|
||||
'reponse_eleve' => $reponses[$q['id_question']] ?? null,
|
||||
'reponse_correcte' => extraireReponseCorrecte($q)
|
||||
];
|
||||
}
|
||||
|
||||
$export['tentatives'][] = [
|
||||
'id' => (int)$t['id_tentative'],
|
||||
'eleve' => [
|
||||
'id' => (int)$t['id_eleve'],
|
||||
'nom' => $t['nom'],
|
||||
'prenom' => $t['prenom'],
|
||||
'login' => $t['login'],
|
||||
'classe' => $t['nom_classe'] ?? 'Libre'
|
||||
],
|
||||
'numero_tentative' => (int)$t['numero_tentative'],
|
||||
'statut' => $t['statut'],
|
||||
'note' => $t['note'] !== null ? (float)$t['note'] : null,
|
||||
'note_sur' => $t['note_sur'] !== null ? (float)$t['note_sur'] : (float)$evaluation['note_totale'],
|
||||
'pourcentage' => $t['pourcentage'] !== null ? (float)$t['pourcentage'] : null,
|
||||
'dates' => [
|
||||
'debut' => $t['date_debut'],
|
||||
'fin' => $t['date_fin']
|
||||
],
|
||||
'temps_passe_minutes' => $t['temps_passe'] ?? (int)$t['duree_minutes_calc'],
|
||||
'reponses_detaillees' => $details
|
||||
];
|
||||
}
|
||||
|
||||
echo json_encode($export, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
Reference in New Issue
Block a user