2025-02-16 12:22:19 +01:00
|
|
|
<?php
|
|
|
|
require_once '../../includes/config.php';
|
|
|
|
require_once '../../includes/auth.php';
|
|
|
|
require_once '../../includes/stories.php';
|
|
|
|
|
|
|
|
if (!Auth::check()) {
|
|
|
|
header('Location: ../login.php');
|
|
|
|
exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
$success = '';
|
|
|
|
$error = '';
|
|
|
|
|
|
|
|
try {
|
|
|
|
if (!isset($_FILES['importFile']) || $_FILES['importFile']['error'] !== UPLOAD_ERR_OK) {
|
|
|
|
throw new Exception('Erreur lors de l\'upload du fichier');
|
|
|
|
}
|
|
|
|
|
|
|
|
$overwrite = isset($_POST['overwrite']) && $_POST['overwrite'] === '1';
|
|
|
|
$tempDir = sys_get_temp_dir() . '/story_import_' . uniqid();
|
|
|
|
mkdir($tempDir);
|
|
|
|
|
|
|
|
// Extraire l'archive
|
|
|
|
$zip = new ZipArchive();
|
|
|
|
if ($zip->open($_FILES['importFile']['tmp_name']) !== true) {
|
|
|
|
throw new Exception('Impossible d\'ouvrir l\'archive ZIP');
|
|
|
|
}
|
|
|
|
|
|
|
|
$zip->extractTo($tempDir);
|
|
|
|
$zip->close();
|
|
|
|
|
|
|
|
// Vérifier la présence du manifeste
|
|
|
|
$manifestFile = $tempDir . '/manifest.json';
|
|
|
|
if (!file_exists($manifestFile)) {
|
|
|
|
throw new Exception('Archive invalide : manifeste manquant');
|
|
|
|
}
|
|
|
|
|
|
|
|
$manifest = json_decode(file_get_contents($manifestFile), true);
|
|
|
|
if (!$manifest || !isset($manifest['stories'])) {
|
|
|
|
throw new Exception('Manifeste invalide');
|
|
|
|
}
|
|
|
|
|
|
|
|
$importedCount = 0;
|
|
|
|
$skippedCount = 0;
|
|
|
|
$errors = [];
|
|
|
|
|
|
|
|
// Parcourir chaque roman dans le manifeste
|
|
|
|
foreach ($manifest['stories'] as $storyInfo) {
|
|
|
|
try {
|
|
|
|
$storyId = $storyInfo['id'];
|
|
|
|
$storyDir = $tempDir . '/' . $storyId;
|
|
|
|
|
|
|
|
if (!file_exists($storyDir . '/story.json')) {
|
|
|
|
throw new Exception("Fichier story.json manquant pour {$storyInfo['title']}");
|
|
|
|
}
|
|
|
|
|
|
|
|
$story = json_decode(file_get_contents($storyDir . '/story.json'), true);
|
|
|
|
if (!$story) {
|
|
|
|
throw new Exception("Données JSON invalides pour {$storyInfo['title']}");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Vérifier si le roman existe déjà
|
|
|
|
$existingStory = Stories::get($storyId);
|
|
|
|
if ($existingStory && !$overwrite) {
|
|
|
|
$skippedCount++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2025-02-17 17:52:31 +01:00
|
|
|
// Créer les dossiers nécessaires avec les permissions correctes
|
|
|
|
$baseDir = __DIR__ . '/../../';
|
|
|
|
$coverDir = $baseDir . 'assets/images/covers';
|
|
|
|
$chaptersImgDir = $baseDir . 'assets/images/chapters/' . $storyId;
|
|
|
|
$chaptersCoverDir = $baseDir . 'assets/images/chapters/' . $storyId . '/covers';
|
2025-02-16 12:22:19 +01:00
|
|
|
|
2025-02-17 17:52:31 +01:00
|
|
|
foreach ([$coverDir, $chaptersImgDir, $chaptersCoverDir] as $dir) {
|
|
|
|
if (!file_exists($dir)) {
|
|
|
|
if (!mkdir($dir, 0777, true)) {
|
|
|
|
throw new Exception("Impossible de créer le dossier: $dir");
|
|
|
|
}
|
|
|
|
chmod($dir, 0777);
|
|
|
|
}
|
|
|
|
}
|
2025-02-16 12:22:19 +01:00
|
|
|
|
2025-02-17 17:52:31 +01:00
|
|
|
// Gérer l'image de couverture du roman
|
2025-02-16 12:22:19 +01:00
|
|
|
if (!empty($story['cover'])) {
|
|
|
|
$coverFile = $storyDir . '/' . $story['cover'];
|
|
|
|
if (file_exists($coverFile)) {
|
2025-02-17 17:52:31 +01:00
|
|
|
// Extraire l'extension correctement
|
|
|
|
$originalName = basename($coverFile);
|
|
|
|
if (preg_match('/\.([^.]+)$/', $originalName, $matches)) {
|
|
|
|
$extension = $matches[1];
|
|
|
|
$newCoverPath = 'assets/images/covers/' . $storyId . '.' . $extension;
|
|
|
|
$targetPath = $baseDir . $newCoverPath;
|
|
|
|
|
|
|
|
if (!copy($coverFile, $targetPath)) {
|
|
|
|
throw new Exception("Impossible de copier la couverture du roman");
|
|
|
|
}
|
|
|
|
chmod($targetPath, 0777);
|
|
|
|
$story['cover'] = $newCoverPath;
|
|
|
|
}
|
2025-02-16 12:22:19 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Gérer les images des chapitres
|
|
|
|
foreach ($story['chapters'] as &$chapter) {
|
2025-02-17 17:52:31 +01:00
|
|
|
// Gérer les images de couverture des chapitres
|
|
|
|
if (!empty($chapter['cover'])) {
|
|
|
|
$chapterCoverFile = $storyDir . '/' . $chapter['cover'];
|
|
|
|
if (file_exists($chapterCoverFile)) {
|
|
|
|
// Extraire l'extension correctement
|
|
|
|
$originalName = basename($chapterCoverFile);
|
|
|
|
if (preg_match('/\.([^.]+)$/', $originalName, $matches)) {
|
|
|
|
$extension = $matches[1];
|
|
|
|
$newChapterCoverName = $chapter['id'] . '-cover.' . $extension;
|
|
|
|
$newChapterCoverPath = 'assets/images/chapters/' . $storyId . '/covers/' . $newChapterCoverName;
|
|
|
|
$targetPath = $baseDir . $newChapterCoverPath;
|
|
|
|
|
|
|
|
if (!copy($chapterCoverFile, $targetPath)) {
|
|
|
|
throw new Exception("Impossible de copier la couverture du chapitre");
|
|
|
|
}
|
|
|
|
chmod($targetPath, 0777);
|
|
|
|
$chapter['cover'] = $newChapterCoverPath;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Gérer le contenu et les images intégrées
|
2025-02-16 12:22:19 +01:00
|
|
|
if (!empty($chapter['content'])) {
|
|
|
|
$content = $chapter['content'];
|
|
|
|
if (is_string($content) && isJson($content)) {
|
|
|
|
$content = json_decode($content, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_array($content) && isset($content['ops'])) {
|
|
|
|
foreach ($content['ops'] as &$op) {
|
|
|
|
if (is_array($op['insert']) && isset($op['insert']['image'])) {
|
|
|
|
$imgPath = $storyDir . '/' . $op['insert']['image'];
|
|
|
|
if (file_exists($imgPath)) {
|
2025-02-17 17:52:31 +01:00
|
|
|
$originalName = basename($imgPath);
|
|
|
|
if (preg_match('/\.([^.]+)$/', $originalName, $matches)) {
|
|
|
|
$extension = $matches[1];
|
|
|
|
$newImgName = 'image_' . uniqid() . '.' . $extension;
|
|
|
|
$targetPath = $chaptersImgDir . '/' . $newImgName;
|
|
|
|
|
|
|
|
if (!copy($imgPath, $targetPath)) {
|
|
|
|
throw new Exception("Impossible de copier l'image intégrée");
|
|
|
|
}
|
|
|
|
chmod($targetPath, 0777);
|
|
|
|
$op['insert']['image'] = 'assets/images/chapters/' . $storyId . '/' . $newImgName;
|
|
|
|
}
|
2025-02-16 12:22:19 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$chapter['content'] = json_encode($content);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sauvegarder le roman
|
2025-02-17 17:52:31 +01:00
|
|
|
if (!Stories::save($story)) {
|
|
|
|
throw new Exception("Erreur lors de la sauvegarde de {$story['title']}");
|
|
|
|
}
|
2025-02-16 12:22:19 +01:00
|
|
|
$importedCount++;
|
|
|
|
|
|
|
|
} catch (Exception $e) {
|
2025-02-17 17:52:31 +01:00
|
|
|
error_log("Erreur d'import pour {$storyInfo['title']}: " . $e->getMessage());
|
|
|
|
error_log("Trace complète: " . print_r($e->getTraceAsString(), true));
|
2025-02-16 12:22:19 +01:00
|
|
|
$errors[] = "Erreur pour {$storyInfo['title']}: " . $e->getMessage();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Nettoyer
|
|
|
|
deleteDir($tempDir);
|
|
|
|
|
|
|
|
// Préparer le message de résultat
|
|
|
|
$messages = [];
|
|
|
|
if ($importedCount > 0) {
|
|
|
|
$messages[] = "$importedCount roman(s) importé(s)";
|
|
|
|
}
|
|
|
|
if ($skippedCount > 0) {
|
|
|
|
$messages[] = "$skippedCount roman(s) ignoré(s) (déjà existants)";
|
|
|
|
}
|
|
|
|
if (!empty($errors)) {
|
|
|
|
$messages[] = "Erreurs : " . implode(", ", $errors);
|
|
|
|
}
|
|
|
|
|
|
|
|
$_SESSION['import_result'] = [
|
|
|
|
'success' => implode(", ", $messages),
|
|
|
|
'error' => !empty($errors) ? implode("\n", $errors) : ''
|
|
|
|
];
|
|
|
|
|
|
|
|
header('Location: ../export-import.php');
|
|
|
|
exit;
|
|
|
|
|
|
|
|
} catch (Exception $e) {
|
2025-02-17 17:52:31 +01:00
|
|
|
error_log("Erreur générale d'import: " . $e->getMessage());
|
|
|
|
error_log("Trace complète: " . print_r($e->getTraceAsString(), true));
|
|
|
|
|
2025-02-16 12:22:19 +01:00
|
|
|
if (isset($tempDir) && file_exists($tempDir)) {
|
|
|
|
deleteDir($tempDir);
|
|
|
|
}
|
|
|
|
|
|
|
|
$_SESSION['import_result'] = [
|
|
|
|
'error' => 'Erreur lors de l\'import : ' . $e->getMessage()
|
|
|
|
];
|
|
|
|
|
|
|
|
header('Location: ../export-import.php');
|
|
|
|
exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fonction pour vérifier si une chaîne est du JSON valide
|
|
|
|
function isJson($string) {
|
|
|
|
json_decode($string);
|
|
|
|
return json_last_error() === JSON_ERROR_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fonction récursive pour supprimer un dossier et son contenu
|
|
|
|
function deleteDir($dir) {
|
|
|
|
if (!file_exists($dir)) return;
|
|
|
|
|
|
|
|
$files = new RecursiveIteratorIterator(
|
|
|
|
new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS),
|
|
|
|
RecursiveIteratorIterator::CHILD_FIRST
|
|
|
|
);
|
|
|
|
|
|
|
|
foreach ($files as $file) {
|
|
|
|
if ($file->isDir()) {
|
|
|
|
rmdir($file->getRealPath());
|
|
|
|
} else {
|
|
|
|
unlink($file->getRealPath());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rmdir($dir);
|
|
|
|
}
|