diff options
author | polo <ordipolo@gmx.fr> | 2025-08-03 00:23:11 +0200 |
---|---|---|
committer | polo <ordipolo@gmx.fr> | 2025-08-03 00:23:11 +0200 |
commit | 547d7feed68e89957f062b8ed9b988f28c5830ce (patch) | |
tree | 7e07ea2b2065468900201cddacad5db559446a7d /src/controller/ImageUploadController.php | |
parent | 9934a32f7e02c484d6b122c9af860ab1ca9b2dca (diff) | |
download | cms-547d7feed68e89957f062b8ed9b988f28c5830ce.zip |
réorganisation 3: classes controller
Diffstat (limited to 'src/controller/ImageUploadController.php')
-rw-r--r-- | src/controller/ImageUploadController.php | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/src/controller/ImageUploadController.php b/src/controller/ImageUploadController.php new file mode 100644 index 0000000..29b8059 --- /dev/null +++ b/src/controller/ImageUploadController.php | |||
@@ -0,0 +1,184 @@ | |||
1 | <?php | ||
2 | // src/controller/ImageUploadController.php | ||
3 | |||
4 | declare(strict_types=1); | ||
5 | |||
6 | class ImageUploadController | ||
7 | { | ||
8 | static public function imagickCleanImage(string $image_data, string $local_path, string $format = 'jpeg'): bool // "string" parce que file_get_contents... | ||
9 | { | ||
10 | try{ | ||
11 | $imagick = new Imagick(); | ||
12 | $imagick->readImageBlob($image_data); | ||
13 | $imagick->stripImage(); // nettoyage métadonnées | ||
14 | $imagick->setImageFormat($format); | ||
15 | if($format === 'jpeg'){ | ||
16 | $imagick->setImageCompression(Imagick::COMPRESSION_JPEG); | ||
17 | $imagick->setImageCompressionQuality(85); // optionnel | ||
18 | } | ||
19 | $imagick->writeImage($local_path); // enregistrement | ||
20 | $imagick->clear(); | ||
21 | $imagick->destroy(); | ||
22 | return true; | ||
23 | } | ||
24 | catch(Exception $e){ | ||
25 | return false; | ||
26 | } | ||
27 | } | ||
28 | static public function curlDownloadImage(string $url, $maxRetries = 3, $timeout = 10): string|false | ||
29 | { | ||
30 | $attempt = 0; | ||
31 | $imageData = false; | ||
32 | |||
33 | while($attempt < $maxRetries){ | ||
34 | $ch = curl_init($url); // instance de CurlHandle | ||
35 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); | ||
36 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); | ||
37 | curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); | ||
38 | curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); | ||
39 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); | ||
40 | curl_setopt($ch, CURLOPT_USERAGENT, 'TinyMCE-Image-Downloader'); | ||
41 | |||
42 | $imageData = curl_exec($ch); | ||
43 | $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); | ||
44 | //$curlError = curl_error($ch); | ||
45 | |||
46 | curl_close($ch); | ||
47 | |||
48 | if($imageData !== false && $httpCode >= 200 && $httpCode < 300){ | ||
49 | return $imageData; | ||
50 | } | ||
51 | |||
52 | $attempt++; | ||
53 | sleep(1); | ||
54 | } | ||
55 | |||
56 | return false; // échec après trois tentatives | ||
57 | } | ||
58 | |||
59 | // téléchargement par le plugin (bouton "insérer une image") | ||
60 | static public function imageUploadTinyMce(): void | ||
61 | { | ||
62 | if(isset($_FILES['file'])){ | ||
63 | $file = $_FILES['file']; | ||
64 | $dest = 'images/'; | ||
65 | $dest_mini = 'images-mini/'; | ||
66 | |||
67 | // Vérifier si les répertoires existent, sinon les créer | ||
68 | if(!is_dir($dest)) { | ||
69 | mkdir($dest, 0700, true); | ||
70 | } | ||
71 | if(!is_dir($dest_mini)) { | ||
72 | mkdir($dest_mini, 0700, true); | ||
73 | } | ||
74 | |||
75 | $allowed_extensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'tiff', 'tif']; | ||
76 | $name = Security::secureFileName(pathinfo($file['name'], PATHINFO_FILENAME)); | ||
77 | $extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION)); | ||
78 | if(!in_array($extension, $allowed_extensions) || $extension === 'jpg'){ | ||
79 | $extension = 'jpeg'; | ||
80 | } | ||
81 | $file_path = $dest . $name . '_' . uniqid() . '.' . $extension; | ||
82 | |||
83 | // créer une miniature de l'image | ||
84 | // | ||
85 | |||
86 | if(self::imagickCleanImage(file_get_contents($file['tmp_name']), $file_path, $extension)){ // recréer l’image pour la nettoyer | ||
87 | echo json_encode(['location' => $file_path]); // renvoyer l'URL de l'image téléchargée | ||
88 | } | ||
89 | else{ | ||
90 | http_response_code(500); | ||
91 | echo json_encode(['message' => 'Erreur image non valide']); | ||
92 | } | ||
93 | } | ||
94 | else{ | ||
95 | http_response_code(400); | ||
96 | echo json_encode(['message' => 'Erreur 400: Bad Request']); | ||
97 | } | ||
98 | die; | ||
99 | } | ||
100 | |||
101 | // collage de HTML => recherche de balises <img>, téléchargement côté serveur et renvoi de l'adresse sur le serveur | ||
102 | static public function uploadImageHtml(): void | ||
103 | { | ||
104 | $json = json_decode(file_get_contents('php://input'), true); | ||
105 | |||
106 | if(isset($json['image_url'])){ | ||
107 | $image_data = self::curlDownloadImage($json['image_url']); // téléchargement de l’image par le serveur avec cURL au lieu de file_get_contents | ||
108 | $dest = 'images/'; | ||
109 | |||
110 | if(!is_dir($dest)) { // Vérifier si le répertoire existe, sinon le créer | ||
111 | mkdir($dest, 0777, true); | ||
112 | } | ||
113 | |||
114 | if($image_data === false){ | ||
115 | http_response_code(400); | ||
116 | echo json_encode(['message' => "Erreur, le serveur n'a pas réussi à télécharger l'image."]); | ||
117 | die; | ||
118 | } | ||
119 | |||
120 | $allowed_extensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'tiff', 'tif']; | ||
121 | $url_path = parse_url($json['image_url'], PHP_URL_PATH); | ||
122 | $name = Security::secureFileName(pathinfo($url_path, PATHINFO_FILENAME)); | ||
123 | $extension = strtolower(pathinfo($url_path, PATHINFO_EXTENSION)); | ||
124 | if(!in_array($extension, $allowed_extensions) || $extension === 'jpg'){ | ||
125 | $extension = 'jpeg'; | ||
126 | } | ||
127 | $local_path = $dest . $name . '_' . uniqid() . '.' . $extension; | ||
128 | |||
129 | if(self::imagickCleanImage($image_data, $local_path, $extension)){ // recréer l’image pour la nettoyer | ||
130 | echo json_encode(['location' => $local_path]); // nouvelle adresse | ||
131 | } | ||
132 | else{ | ||
133 | http_response_code(500); | ||
134 | echo json_encode(['message' => 'Erreur image non valide']); | ||
135 | } | ||
136 | } | ||
137 | else{ | ||
138 | echo json_encode(['message' => 'Erreur 400: Bad Request']); | ||
139 | } | ||
140 | die; | ||
141 | } | ||
142 | |||
143 | // collage simple d'une image (base64 dans le presse-papier) non encapsulée dans du HTML | ||
144 | static public function uploadImageBase64(): void | ||
145 | { | ||
146 | $json = json_decode(file_get_contents('php://input'), true); | ||
147 | $dest = 'images/'; | ||
148 | |||
149 | if(!is_dir('images')){ | ||
150 | mkdir('images', 0777, true); | ||
151 | } | ||
152 | |||
153 | // détection de data:image/ et de ;base64, et capture du format dans $type | ||
154 | if(!isset($json['image_base64']) || !preg_match('/^data:image\/(\w+);base64,/', $json['image_base64'], $type)){ | ||
155 | http_response_code(400); | ||
156 | echo json_encode(['message' => 'Données image base64 manquantes ou invalides']); | ||
157 | die; | ||
158 | } | ||
159 | |||
160 | $allowed_extensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'tiff', 'tif']; | ||
161 | $extension = strtolower($type[1]); | ||
162 | if(!in_array($extension, $allowed_extensions) || $extension === 'jpg'){ | ||
163 | $extension = 'jpeg'; | ||
164 | } | ||
165 | |||
166 | $image_data = base64_decode(substr($json['image_base64'], strpos($json['image_base64'], ',') + 1)); // découpe la chaine à la virgule puis convertit en binaire | ||
167 | if($image_data === false){ | ||
168 | http_response_code(400); | ||
169 | echo json_encode(['message' => 'Décodage base64 invalide']); | ||
170 | die; | ||
171 | } | ||
172 | |||
173 | $local_path = $dest . 'pasted_image_' . uniqid() . '.' . $extension; | ||
174 | |||
175 | if(self::imagickCleanImage($image_data, $local_path)){ | ||
176 | echo json_encode(['location' => $local_path]); | ||
177 | } | ||
178 | else{ | ||
179 | http_response_code(500); | ||
180 | echo json_encode(['message' => 'Erreur image non valide']); | ||
181 | } | ||
182 | die; | ||
183 | } | ||
184 | } \ No newline at end of file | ||