268 lines
8.8 KiB
PHP
268 lines
8.8 KiB
PHP
<?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;
|
|
}
|
|
?>
|