diff options
-rw-r--r-- | public/index.php | 116 |
1 files changed, 102 insertions, 14 deletions
diff --git a/public/index.php b/public/index.php index 4c0201a..d6179b1 100644 --- a/public/index.php +++ b/public/index.php | |||
@@ -1,4 +1,23 @@ | |||
1 | <?php | 1 | <?php |
2 | function imagickCleanImage(string $image_data, string $local_path): bool // "string" parce que file_get_contents... | ||
3 | { | ||
4 | try{ | ||
5 | $imagick = new Imagick(); | ||
6 | $imagick->readImageBlob($image_data); | ||
7 | $imagick->stripImage(); // nettoyage métadonnées | ||
8 | $imagick->setImageFormat('jpeg'); | ||
9 | $imagick->setImageCompression(Imagick::COMPRESSION_JPEG); | ||
10 | $imagick->setImageCompressionQuality(85); // optionnel | ||
11 | $imagick->writeImage($local_path); // enregistrement | ||
12 | $imagick->clear(); | ||
13 | $imagick->destroy(); | ||
14 | return true; | ||
15 | } | ||
16 | catch (Exception $e) { | ||
17 | return false; | ||
18 | } | ||
19 | } | ||
20 | |||
2 | if(isset($_GET['action']) && $_GET['action'] == 'editor_submit'){ | 21 | if(isset($_GET['action']) && $_GET['action'] == 'editor_submit'){ |
3 | // récupération des données | 22 | // récupération des données |
4 | $data = file_get_contents('php://input'); | 23 | $data = file_get_contents('php://input'); |
@@ -41,19 +60,18 @@ elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image'){ | |||
41 | $file = $_FILES['file']; | 60 | $file = $_FILES['file']; |
42 | $dest = 'images/'; | 61 | $dest = 'images/'; |
43 | 62 | ||
44 | // Vérifier si le répertoire existe, sinon le créer | 63 | if(!is_dir($dest)) { // Vérifier si le répertoire existe, sinon le créer |
45 | if(!is_dir($dest)) { | ||
46 | mkdir($dest, 0777, true); | 64 | mkdir($dest, 0777, true); |
47 | } | 65 | } |
48 | 66 | ||
49 | $filePath = $dest . basename($file['name']); | 67 | $file_path = 'images/' . uniqid() . '.jpg'; |
50 | if(move_uploaded_file($file['tmp_name'], $filePath)) { | 68 | if(imagickCleanImage(file_get_contents($file['tmp_name']), $file_path)){ // recréer l’image pour la nettoyer |
51 | $image_url = str_replace(basename($_SERVER['SCRIPT_NAME']), '', $_SERVER['SCRIPT_NAME']); | 69 | $image_url = str_replace(basename($_SERVER['SCRIPT_NAME']), '', $_SERVER['SCRIPT_NAME']); |
52 | echo json_encode(['location' => $image_url . $filePath]); // renvoyer l'URL de l'image téléchargée | 70 | echo json_encode(['location' => $image_url . $file_path]); // renvoyer l'URL de l'image téléchargée |
53 | } | 71 | } |
54 | else{ | 72 | else{ |
55 | http_response_code(500); | 73 | http_response_code(500); |
56 | echo json_encode(['message' => 'Erreur 500: Internal Server Error']); | 74 | echo json_encode(['message' => 'Erreur image non valide']); |
57 | } | 75 | } |
58 | } | 76 | } |
59 | else{ | 77 | else{ |
@@ -62,6 +80,32 @@ elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image'){ | |||
62 | } | 80 | } |
63 | die; | 81 | die; |
64 | } | 82 | } |
83 | elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image_url'){ | ||
84 | $json = json_decode(file_get_contents('php://input'), true); | ||
85 | |||
86 | if(isset($json['image_url'])){ | ||
87 | $image_data = file_get_contents($json['image_url']); // téléchargement de l’image par le serveur | ||
88 | |||
89 | if($image_data === false){ | ||
90 | http_response_code(400); | ||
91 | echo json_encode(['message' => "Erreur, le serveur n'a pas réussi à télécharger l'image."]); | ||
92 | die; | ||
93 | } | ||
94 | |||
95 | $local_path = 'images/' . uniqid() . '.jpg'; | ||
96 | if(imagickCleanImage($image_data, $local_path)){ // recréer l’image pour la nettoyer | ||
97 | echo json_encode(['location' => $local_path]); // nouvelle adresse | ||
98 | } | ||
99 | else{ | ||
100 | http_response_code(500); | ||
101 | echo json_encode(['message' => 'Erreur image non valide']); | ||
102 | } | ||
103 | } | ||
104 | else{ | ||
105 | echo json_encode(['message' => 'Erreur 400: Bad Request']); | ||
106 | } | ||
107 | die; | ||
108 | } | ||
65 | ?> | 109 | ?> |
66 | <!DOCTYPE html> | 110 | <!DOCTYPE html> |
67 | <html lang="fr"> | 111 | <html lang="fr"> |
@@ -98,6 +142,7 @@ elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image'){ | |||
98 | menubar: false, | 142 | menubar: false, |
99 | toolbar_mode: 'wrap', | 143 | toolbar_mode: 'wrap', |
100 | statusbar: false, | 144 | statusbar: false, |
145 | paste_data_images: true, | ||
101 | setup: function (editor) { | 146 | setup: function (editor) { |
102 | editor.on('init', function () { | 147 | editor.on('init', function () { |
103 | editors[articleId] = editor; | 148 | editors[articleId] = editor; |
@@ -108,19 +153,61 @@ elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image'){ | |||
108 | document.querySelector(`#cancel-${articleId}`).classList.remove('hidden'); | 153 | document.querySelector(`#cancel-${articleId}`).classList.remove('hidden'); |
109 | document.querySelector(`#submit-${articleId}`).classList.remove('hidden'); | 154 | document.querySelector(`#submit-${articleId}`).classList.remove('hidden'); |
110 | }); | 155 | }); |
156 | editor.on('PastePreProcess', function (e){ // déclenchement au collage AVANT insertion dans l'éditeur | ||
157 | //const images = e.node.querySelectorAll('img'); | ||
158 | let parser = new DOMParser(); | ||
159 | let doc = parser.parseFromString(e.content, 'text/html'); | ||
160 | let images = doc.querySelectorAll('img'); | ||
161 | |||
162 | let downloads_in_progress = []; | ||
163 | |||
164 | images.forEach(image => { | ||
165 | if(image.src.startsWith('http')){ | ||
166 | // le fait d'avoir lancer un téléchargement | ||
167 | let promise = fetch('index.php?action=upload_image_url', { | ||
168 | method: 'POST', | ||
169 | headers: { 'Content-Type': 'application/json' }, | ||
170 | body: JSON.stringify({ image_url: image.src }) | ||
171 | }) | ||
172 | .then(response => response.json()) | ||
173 | .then(data => { | ||
174 | if(data.location){ | ||
175 | image.src = data.location; // remplacer l'image par celle du serveur | ||
176 | } | ||
177 | }) | ||
178 | .catch(error => { | ||
179 | console.error('Erreur lors de l’upload de l’image :', error); | ||
180 | }); | ||
181 | |||
182 | downloads_in_progress.push(promise); | ||
183 | } | ||
184 | }); | ||
185 | |||
186 | console.log(downloads_in_progress); | ||
187 | |||
188 | if(downloads_in_progress.length > 0){ | ||
189 | // faire attendre tinymce que le serveur récupère les images avant insertion | ||
190 | e.preventDefault(); | ||
191 | |||
192 | Promise.all(downloads_in_progress).then(() => { | ||
193 | e.content = doc.body.innerHTML; | ||
194 | editor.insertContent(e.content); | ||
195 | }); | ||
196 | } | ||
197 | }); | ||
111 | }, | 198 | }, |
112 | // upload d'image | 199 | // upload d'image |
113 | images_upload_handler: (blobInfo, progress) => new Promise((resolve, reject) => { | 200 | images_upload_handler: (blobInfo, progress) => new Promise((resolve, reject) => { |
114 | const formData = new FormData(); | 201 | const formData = new FormData(); |
115 | formData.append("file", blobInfo.blob()); | 202 | formData.append("file", blobInfo.blob()); |
116 | 203 | ||
117 | fetch("index.php?action=upload_image", { | 204 | fetch('index.php?action=upload_image', { |
118 | method: "POST", | 205 | method: 'POST', |
119 | body: formData | 206 | body: formData |
120 | }) | 207 | }) |
121 | .then(response => response.json()) | 208 | .then(response => response.json()) |
122 | .then(data => { | 209 | .then(data => { |
123 | if (data.location) { | 210 | if(data.location) { |
124 | resolve(data.location); | 211 | resolve(data.location); |
125 | } | 212 | } |
126 | else { | 213 | else { |
@@ -165,7 +252,7 @@ elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image'){ | |||
165 | } | 252 | } |
166 | } | 253 | } |
167 | 254 | ||
168 | function closeEditor(articleId) { | 255 | function closeEditor(articleId){ |
169 | // Récupérer le contenu d'origine de l'article | 256 | // Récupérer le contenu d'origine de l'article |
170 | const originalContent = document.getElementById(articleId).getAttribute('data-original-content'); | 257 | const originalContent = document.getElementById(articleId).getAttribute('data-original-content'); |
171 | 258 | ||
@@ -186,7 +273,7 @@ elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image'){ | |||
186 | function submitArticle(articleId) { | 273 | function submitArticle(articleId) { |
187 | // Récupérer l'éditeur correspondant à l'article | 274 | // Récupérer l'éditeur correspondant à l'article |
188 | const editor = editors[articleId]; | 275 | const editor = editors[articleId]; |
189 | if (!editor) { | 276 | if(!editor){ |
190 | console.error('Éditeur non trouvé pour l\'article:', articleId); | 277 | console.error('Éditeur non trouvé pour l\'article:', articleId); |
191 | return; | 278 | return; |
192 | } | 279 | } |
@@ -207,12 +294,13 @@ elseif(isset($_GET['action']) && $_GET['action'] == 'upload_image'){ | |||
207 | // Fermer l'éditeur et mettre à jour le contenu de l'article | 294 | // Fermer l'éditeur et mettre à jour le contenu de l'article |
208 | closeEditor(articleId); | 295 | closeEditor(articleId); |
209 | document.getElementById(articleId).innerHTML = newContent; | 296 | document.getElementById(articleId).innerHTML = newContent; |
210 | console.log(newContent); | 297 | //console.log(newContent); |
211 | if (data.success) { | 298 | if(data.success){ |
212 | // Fermer l'éditeur et mettre à jour le contenu de l'article | 299 | // Fermer l'éditeur et mettre à jour le contenu de l'article |
213 | tinymce.remove(`#${articleId}`); | 300 | tinymce.remove(`#${articleId}`); |
214 | document.getElementById(articleId).innerHTML = newContent; | 301 | document.getElementById(articleId).innerHTML = newContent; |
215 | } else { | 302 | } |
303 | else{ | ||
216 | alert('Erreur lors de la sauvegarde de l\'article.'); | 304 | alert('Erreur lors de la sauvegarde de l\'article.'); |
217 | } | 305 | } |
218 | }) | 306 | }) |