diff options
| author | polo <ordipolo@gmx.fr> | 2025-06-18 00:28:06 +0200 |
|---|---|---|
| committer | polo <ordipolo@gmx.fr> | 2025-06-18 00:28:06 +0200 |
| commit | d93c85e53b2d53ce61687b8caef7253e946d9e6e (patch) | |
| tree | 92473dbc3d5ac1de765d754e924beb597b8ea07b | |
| parent | ee3c6ec8320e47e96a838e077329e3f68c2da83a (diff) | |
| download | tinymce-d93c85e53b2d53ce61687b8caef7253e946d9e6e.tar.gz tinymce-d93c85e53b2d53ce61687b8caef7253e946d9e6e.tar.bz2 tinymce-d93c85e53b2d53ce61687b8caef7253e946d9e6e.zip | |
upload des images dans un code html copié-collé
| -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 | }) |
