Lectures/admin/api/export-stories.php

166 lines
5.4 KiB
PHP

<?php
require_once '../../includes/config.php';
require_once '../../includes/auth.php';
require_once '../../includes/stories.php';
if (!Auth::check()) {
http_response_code(401);
exit('Non autorisé');
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
exit('Méthode non autorisée');
}
if (empty($_POST['stories'])) {
http_response_code(400);
exit('Aucun roman sélectionné');
}
try {
$selectedIds = $_POST['stories'];
$tempDir = sys_get_temp_dir() . '/story_export_' . uniqid();
mkdir($tempDir);
// Créer un fichier manifeste pour stocker les métadonnées
$manifest = [
'exportDate' => date('Y-m-d H:i:s'),
'stories' => []
];
foreach ($selectedIds as $storyId) {
$story = Stories::get($storyId);
if (!$story) continue;
// Créer un dossier pour ce roman
$storyDir = $tempDir . '/' . $storyId;
mkdir($storyDir);
mkdir($storyDir . '/images');
// Copier l'image de couverture si elle existe
if (!empty($story['cover'])) {
$coverPath = __DIR__ . '/../../' . $story['cover'];
if (file_exists($coverPath)) {
copy($coverPath, $storyDir . '/cover' . pathinfo($coverPath, PATHINFO_EXTENSION));
$story['cover'] = 'cover' . pathinfo($coverPath, PATHINFO_EXTENSION);
}
}
// Extraire et copier 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);
}
// Traiter le contenu pour les images
if (is_array($content) && isset($content['ops'])) {
foreach ($content['ops'] as &$op) {
if (is_array($op['insert']) && isset($op['insert']['image'])) {
$imgUrl = $op['insert']['image'];
$imgPath = __DIR__ . '/../../' . preg_replace('/^(?:\.\.\/)+/', '', $imgUrl);
if (file_exists($imgPath)) {
$newImgName = 'image_' . uniqid() . pathinfo($imgPath, PATHINFO_EXTENSION);
copy($imgPath, $storyDir . '/images/' . $newImgName);
$op['insert']['image'] = 'images/' . $newImgName;
}
}
}
$chapter['content'] = json_encode($content);
}
}
}
// Sauvegarder les données du roman
file_put_contents($storyDir . '/story.json', json_encode($story, JSON_PRETTY_PRINT));
// Ajouter au manifeste
$manifest['stories'][] = [
'id' => $story['id'],
'title' => $story['title']
];
}
// Sauvegarder le manifeste
file_put_contents($tempDir . '/manifest.json', json_encode($manifest, JSON_PRETTY_PRINT));
// Créer l'archive ZIP
$zipFile = sys_get_temp_dir() . '/romans_' . date('Y-m-d_His') . '.zip';
$zip = new ZipArchive();
if ($zip->open($zipFile, ZipArchive::CREATE | ZipArchive::OVERWRITE) === true) {
addDirToZip($zip, $tempDir, '');
$zip->close();
// Nettoyer le dossier temporaire
deleteDir($tempDir);
// Envoyer l'archive
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="' . basename($zipFile) . '"');
header('Content-Length: ' . filesize($zipFile));
readfile($zipFile);
unlink($zipFile);
} else {
throw new Exception('Impossible de créer l\'archive ZIP');
}
} catch (Exception $e) {
if (isset($tempDir) && file_exists($tempDir)) {
deleteDir($tempDir);
}
if (isset($zipFile) && file_exists($zipFile)) {
unlink($zipFile);
}
http_response_code(500);
echo 'Erreur lors de l\'export : ' . $e->getMessage();
}
// 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 ajouter un dossier à une archive ZIP
function addDirToZip($zip, $dir, $relativePath) {
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir),
RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($files as $file) {
if (!$file->isDir()) {
$filePath = $file->getRealPath();
$zipPath = $relativePath . substr($filePath, strlen($dir));
// Normaliser les séparateurs de chemin pour Windows
$zipPath = str_replace('\\', '/', $zipPath);
$zip->addFile($filePath, $zipPath);
}
}
}
// 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);
}