il est de nouveau possible d'ajouter des images dans la page "à propos"

This commit is contained in:
Esenjin 2025-02-17 20:16:46 +01:00
parent 313edb9c28
commit 31d611267a
2 changed files with 228 additions and 38 deletions

View File

@ -0,0 +1,193 @@
<?php
require_once '../../includes/config.php';
require_once '../../includes/auth.php';
class AboutImageUploadHandler {
private $uploadDir;
private $allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
private $maxFileSize = 5242880; // 5MB
private $maxWidth = 1200;
private $maxHeight = 1200;
public function __construct() {
$this->uploadDir = __DIR__ . '/../../assets/images/about/';
$this->ensureUploadDirectory();
}
public function handleUpload($file) {
try {
// Vérifications de base
if ($file['error'] !== UPLOAD_ERR_OK) {
throw new Exception($this->getUploadErrorMessage($file['error']));
}
// Vérification du type MIME
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mimeType = $finfo->file($file['tmp_name']);
if (!in_array($mimeType, $this->allowedTypes)) {
throw new Exception('Type de fichier non autorisé. Types acceptés : JPG, PNG, GIF, WEBP');
}
// Vérification de la taille
if ($file['size'] > $this->maxFileSize) {
throw new Exception('Fichier trop volumineux. Taille maximum : 5MB');
}
// Vérification et redimensionnement de l'image
[$width, $height, $type] = getimagesize($file['tmp_name']);
$needsResize = $width > $this->maxWidth || $height > $this->maxHeight;
// Génération d'un nom de fichier unique
$extension = $this->getExtensionFromMimeType($mimeType);
$filename = uniqid() . '.' . $extension;
$targetPath = $this->uploadDir . $filename;
if ($needsResize) {
// Calcul des nouvelles dimensions en conservant le ratio
$ratio = min($this->maxWidth / $width, $this->maxHeight / $height);
$newWidth = round($width * $ratio);
$newHeight = round($height * $ratio);
// Création de la nouvelle image
$sourceImage = $this->createImageFromFile($file['tmp_name'], $mimeType);
$newImage = imagecreatetruecolor($newWidth, $newHeight);
// Préservation de la transparence pour PNG
if ($mimeType === 'image/png') {
imagealphablending($newImage, false);
imagesavealpha($newImage, true);
}
// Redimensionnement
imagecopyresampled(
$newImage, $sourceImage,
0, 0, 0, 0,
$newWidth, $newHeight,
$width, $height
);
// Sauvegarde de l'image redimensionnée
$this->saveImage($newImage, $targetPath, $mimeType);
// Libération de la mémoire
imagedestroy($sourceImage);
imagedestroy($newImage);
} else {
// Déplacement du fichier original si pas besoin de redimensionnement
if (!move_uploaded_file($file['tmp_name'], $targetPath)) {
throw new Exception('Erreur lors du déplacement du fichier uploadé');
}
}
// Retourner le chemin relatif pour l'éditeur
return [
'success' => true,
'url' => '../assets/images/about/' . $filename,
'width' => $needsResize ? $newWidth : $width,
'height' => $needsResize ? $newHeight : $height
];
} catch (Exception $e) {
return [
'success' => false,
'error' => $e->getMessage()
];
}
}
private function ensureUploadDirectory() {
if (!file_exists($this->uploadDir)) {
if (!mkdir($this->uploadDir, 0755, true)) {
throw new Exception('Impossible de créer le dossier d\'upload');
}
}
if (!is_writable($this->uploadDir)) {
throw new Exception('Le dossier d\'upload n\'est pas accessible en écriture');
}
}
private function createImageFromFile($file, $mimeType) {
switch ($mimeType) {
case 'image/jpeg':
return imagecreatefromjpeg($file);
case 'image/png':
return imagecreatefrompng($file);
case 'image/gif':
return imagecreatefromgif($file);
case 'image/webp':
return imagecreatefromwebp($file);
default:
throw new Exception('Type d\'image non supporté');
}
}
private function saveImage($image, $path, $mimeType) {
switch ($mimeType) {
case 'image/jpeg':
return imagejpeg($image, $path, 85);
case 'image/png':
return imagepng($image, $path, 8);
case 'image/gif':
return imagegif($image, $path);
case 'image/webp':
return imagewebp($image, $path, 85);
default:
throw new Exception('Type d\'image non supporté pour la sauvegarde');
}
}
private function getExtensionFromMimeType($mimeType) {
$map = [
'image/jpeg' => 'jpg',
'image/png' => 'png',
'image/gif' => 'gif',
'image/webp' => 'webp'
];
return $map[$mimeType] ?? 'jpg';
}
private function getUploadErrorMessage($error) {
$errors = [
UPLOAD_ERR_INI_SIZE => 'Le fichier dépasse la taille maximale autorisée par PHP',
UPLOAD_ERR_FORM_SIZE => 'Le fichier dépasse la taille maximale autorisée par le formulaire',
UPLOAD_ERR_PARTIAL => 'Le fichier n\'a été que partiellement uploadé',
UPLOAD_ERR_NO_FILE => 'Aucun fichier n\'a été uploadé',
UPLOAD_ERR_NO_TMP_DIR => 'Dossier temporaire manquant',
UPLOAD_ERR_CANT_WRITE => 'Échec de l\'écriture du fichier sur le disque',
UPLOAD_ERR_EXTENSION => 'Une extension PHP a arrêté l\'upload'
];
return $errors[$error] ?? 'Erreur inconnue lors de l\'upload';
}
}
// Point d'entrée du script
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
exit(json_encode(['error' => 'Méthode non autorisée']));
}
// Vérification de l'authentification
if (!Auth::check()) {
http_response_code(401);
exit(json_encode(['error' => 'Non autorisé']));
}
// Traitement de l'upload
try {
$handler = new AboutImageUploadHandler();
$result = $handler->handleUpload($_FILES['image']);
if (!$result['success']) {
http_response_code(400);
}
header('Content-Type: application/json');
echo json_encode($result);
} catch (Exception $e) {
http_response_code(500);
echo json_encode([
'success' => false,
'error' => 'Erreur serveur : ' . $e->getMessage()
]);
}

View File

@ -19,50 +19,47 @@ document.addEventListener('DOMContentLoaded', function() {
['clean']
],
handlers: {
image: handleImageUpload
image: function() {
const input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('accept', 'image/*');
input.click();
input.onchange = async () => {
const file = input.files[0];
if (file) {
const formData = new FormData();
formData.append('image', file);
try {
const response = await fetch('api/about-image-upload.php', {
method: 'POST',
body: formData
});
if (!response.ok) throw new Error('Upload failed');
const result = await response.json();
if (result.success) {
const range = aboutEditor.getSelection(true);
aboutEditor.insertEmbed(range.index, 'image', result.url);
aboutEditor.setSelection(range.index + 1);
} else {
showNotification(result.error || 'Erreur lors de l\'upload', 'error');
}
} catch (error) {
console.error('Error:', error);
showNotification('Erreur lors de l\'upload de l\'image', 'error');
}
}
};
}
}
}
},
placeholder: 'Commencez à écrire le contenu de la page À propos...'
});
// Gestion de l'upload d'images
function handleImageUpload() {
const input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('accept', 'image/*');
input.click();
input.onchange = async () => {
const file = input.files[0];
if (file) {
const formData = new FormData();
formData.append('image', file);
try {
const response = await fetch('api/upload-image.php', {
method: 'POST',
body: formData
});
if (!response.ok) throw new Error('Upload failed');
const result = await response.json();
if (result.success) {
const range = aboutEditor.getSelection(true);
aboutEditor.insertEmbed(range.index, 'image', result.url);
aboutEditor.setSelection(range.index + 1);
} else {
showNotification(result.error || 'Erreur lors de l\'upload', 'error');
}
} catch (error) {
console.error('Error:', error);
showNotification('Erreur lors de l\'upload de l\'image', 'error');
}
}
};
}
// Initialisation du contenu si existant
const editorElement = document.getElementById('aboutEditor');
const initialContent = editorElement.getAttribute('data-initial-content');