Files
2026-07-03 02:02:13 +02:00

127 lines
5.1 KiB
PHP

<?php
// Import d'une sauvegarde JSON (créée par exportData.php)
// ATTENTION : les données actuelles des tables présentes dans le fichier sont ÉCRASÉES
// On démarre la session
require_once(__DIR__ . '/../functions/security.php');
// On ajoute la DB
require_once('../functions/databaseConnection.php');
// On ajoute les logs Discord
require_once('../functions/sendLogs.php');
// Si l'utilisateur n'est pas admin il ne peut pas executer le reste du script
if (!isset($_SESSION['role']) || $_SESSION['role'] !== 'admin') {
header('Location: ../pages/home.php');
exit;
}
// Vérification du jeton CSRF : bloque les requêtes forgées depuis un autre site
requireCsrfToken();
// La requête doit être un POST avec un fichier sinon on refuse
if ($_SERVER['REQUEST_METHOD'] !== 'POST' || !isset($_FILES['jsonfile']) || $_FILES['jsonfile']['error'] !== UPLOAD_ERR_OK) {
header('Location: ../pages/admin.php');
exit;
}
// Lecture et décodage du fichier JSON
$contenu = file_get_contents($_FILES['jsonfile']['tmp_name']);
$donnees = json_decode($contenu, true);
if (!is_array($donnees)) {
die("Erreur : le fichier n'est pas un JSON valide.");
}
// Même liste blanche que l'export : seules ces tables / colonnes peuvent être importées.
// L'ORDRE COMPTE : chaque table de PDF associée (project_pdfs...) doit être importée
// juste après sa table parente (projects...), car sa clé étrangère exige que la ligne
// parente existe déjà (voir migration Juillet 2026 (6))
$tables = [
'settings' => ['name', 'value'],
'skills' => ['id', 'title', 'icon', 'items', 'position', 'created_at'],
'projects' => ['id', 'title', 'status', 'tags', 'description', 'image_url', 'markdown', 'link_url', 'created_at'],
'project_pdfs' => ['project_id', 'pdf_filename', 'pdf_data'],
'experiences' => ['id', 'title', 'status', 'xptype', 'tags', 'description', 'duration', 'image_url', 'markdown', 'link_url', 'created_at'],
'experience_pdfs' => ['experience_id', 'pdf_filename', 'pdf_data'],
'schools' => ['id', 'title', 'status', 'tags', 'description', 'duration', 'image_url', 'markdown', 'link_url', 'created_at'],
'school_pdfs' => ['school_id', 'pdf_filename', 'pdf_data'],
'users' => ['id', 'username', 'password', 'role', 'created_at', 'last_login'],
];
// Colonnes binaires : encodées en base64 par exportData.php, à redécoder ici
$colonnesBinaires = [
'project_pdfs' => ['pdf_data'],
'experience_pdfs' => ['pdf_data'],
'school_pdfs' => ['pdf_data'],
];
try {
// Transaction : si une erreur survient, TOUT est annulé (la base reste intacte)
$dbh->beginTransaction();
foreach ($tables as $table => $colonnesAutorisees) {
// On ne touche qu'aux tables présentes dans le fichier
if (!isset($donnees[$table]) || !is_array($donnees[$table])) {
continue;
}
// Sécurité : on refuse de vider la table users si la sauvegarde n'en contient aucun
// (sinon l'admin se retrouverait enfermé dehors sans aucun compte)
if ($table === 'users' && count($donnees[$table]) === 0) {
continue;
}
// On écrase les données existantes de la table
$dbh->exec('DELETE FROM `' . $table . '`');
// Colonnes binaires (PDF) de cette table, à redécoder du base64
$binaires = $colonnesBinaires[$table] ?? [];
// Puis on insère chaque ligne de la sauvegarde
foreach ($donnees[$table] as $ligne) {
if (!is_array($ligne)) {
continue;
}
// On ne garde que les colonnes autorisées ET présentes dans la ligne
$colonnes = array_values(array_intersect($colonnesAutorisees, array_keys($ligne)));
if (empty($colonnes)) {
continue;
}
$placeholders = array_map(function ($c) { return ':' . $c; }, $colonnes);
$stmt = $dbh->prepare(
'INSERT INTO `' . $table . '` (`' . implode('`, `', $colonnes) . '`) VALUES (' . implode(', ', $placeholders) . ')'
);
foreach ($colonnes as $colonne) {
$valeur = $ligne[$colonne];
// Les colonnes binaires (pdf_data) sont ré-encodées en base64 par l'export : on les redécode
if (in_array($colonne, $binaires, true) && $valeur !== null) {
$stmt->bindValue(':' . $colonne, base64_decode($valeur), PDO::PARAM_LOB);
} else {
$stmt->bindValue(':' . $colonne, $valeur);
}
}
$stmt->execute();
}
}
// Tout s'est bien passé : on valide définitivement
$dbh->commit();
} catch (Exception $e) {
// En cas d'erreur on annule tout : la base revient à son état d'avant l'import
$dbh->rollBack();
die("Erreur pendant l'import, aucune donnée n'a été modifiée : " . $e->getMessage());
}
// Log Discord
sendLog("Import d'une sauvegarde JSON : données du site écrasées");
// On renvoie l'utilisateur sur admin.php (?import=1 déclenche la notification de succès)
header('Location: ../pages/admin.php?import=1');
exit;