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; } // Créer les dossiers nécessaires $coverDir = __DIR__ . '/../../assets/images/covers/'; $chaptersImgDir = __DIR__ . '/../../assets/images/chapters/' . $storyId; if (!file_exists($coverDir)) mkdir($coverDir, 0755, true); if (!file_exists($chaptersImgDir)) mkdir($chaptersImgDir, 0755, true); // Gérer l'image de couverture if (!empty($story['cover'])) { $coverFile = $storyDir . '/' . $story['cover']; if (file_exists($coverFile)) { $newCoverPath = 'assets/images/covers/' . $storyId . '.' . pathinfo($coverFile, PATHINFO_EXTENSION); copy($coverFile, __DIR__ . '/../../' . $newCoverPath); $story['cover'] = $newCoverPath; } } // Gérer les images des chapitres foreach ($story['chapters'] as &$chapter) { 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)) { $newImgName = 'image_' . uniqid() . '.' . pathinfo($imgPath, PATHINFO_EXTENSION); copy($imgPath, $chaptersImgDir . '/' . $newImgName); $op['insert']['image'] = 'assets/images/chapters/' . $storyId . '/' . $newImgName; } } } $chapter['content'] = json_encode($content); } } } // Sauvegarder le roman Stories::save($story); $importedCount++; } catch (Exception $e) { $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) { 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); }