Aller au contenu

Médias

Le gestionnaire de médias d’ArtisanCMS offre une solution complète pour l’upload, l’organisation et l’optimisation de vos fichiers. Il inclut la conversion WebP automatique, la génération d’images responsives et l’intégration de banques d’images.

Le modèle Media (App\Models\Media) représente un fichier uploadé :

ChampTypeDescription
filenamestringNom du fichier sur le disque
original_namestringNom original lors de l’upload
mime_typestringType MIME validé
sizeintegerTaille en octets
pathstringChemin relatif sur le disque
altstringTexte alternatif (accessibilité)
titlestringTitre du média
folder_idintegerDossier virtuel parent
metadatajsonDimensions, durée, etc.

ArtisanCMS valide les fichiers par leur type MIME réel (analyse du contenu binaire), et non par l’extension du fichier. Cela empêche l’upload de fichiers malveillants renommés :

// config/cms.php - Types MIME autorisés
'allowed_mime_types' => [
'image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml',
'application/pdf',
'video/mp4', 'video/webm',
'audio/mpeg', 'audio/wav',
],
'max_upload_size' => 10240, // 10 Mo par défaut (en Ko)

L’upload est géré par Admin\MediaController qui délègue au MediaService :

// Route d'upload
Route::post('media/upload', [MediaController::class, 'store']);

Le MediaService se charge de la validation, du stockage et du déclenchement de l’optimisation.

Toutes les images uploadées (JPEG, PNG) sont automatiquement converties en format WebP pour réduire leur poids sans perte visible de qualité.

L’ImageOptimizer génère plusieurs tailles pour chaque image :

TailleLargeurUtilisation
thumbnail150pxVignettes admin
small300pxMiniatures
medium768pxContenu mobile
large1200pxContenu desktop
fullOriginaleHaute résolution

Les balises <img> générées incluent automatiquement l’attribut srcset pour un chargement adaptatif.

Pour protéger la vie privée des utilisateurs, les métadonnées EXIF (localisation GPS, modèle d’appareil photo, etc.) sont automatiquement supprimées lors de l’upload.

Le MediaFolderService permet d’organiser les médias en dossiers sans modifier la structure de fichiers sur le disque :

class MediaFolderService
{
public function createFolder(string $name, ?int $parentId = null): MediaFolder;
public function moveMedia(Media $media, int $folderId): void;
public function deleteFolder(int $folderId): bool;
public function getFolderTree(): Collection;
}

L’interface d’administration offre un explorateur de fichiers avec drag-and-drop pour déplacer les médias entre dossiers.

Le StockPhotoService permet de rechercher et importer des photos libres de droits directement depuis l’interface de gestion des médias :

class StockPhotoService
{
public function search(string $query, string $provider = 'unsplash'): Collection;
public function import(string $photoId, string $provider): Media;
}

Les clés API sont configurées dans le fichier .env :

Fenêtre de terminal
UNSPLASH_ACCESS_KEY=votre_cle_unsplash
PEXELS_API_KEY=votre_cle_pexels

Le modèle MediaUsage suit ou chaque média est utilisé dans le contenu :

// Savoir ou un média est utilisé
$usages = $media->usages; // Pages, articles, entrées qui utilisent ce média

Cela permet d’afficher un avertissement lorsqu’un utilisateur tente de supprimer un média encore utilisé.

Le OrphanMediaDetectorService identifie les médias qui ne sont plus référencés par aucun contenu :

class OrphanMediaDetectorService
{
public function detect(): Collection; // Liste des médias orphelins
public function cleanup(): int; // Supprime et retourne le nombre supprimé
}

Cette fonctionnalité aide a maintenir un espace de stockage propre en éliminant les fichiers inutilisés.

Les paramètres du gestionnaire de médias se trouvent dans config/cms.php :

return [
'media' => [
'disk' => 'public',
'max_upload_size' => 10240, // 10 Mo
'allowed_mime_types' => [...],
'image_sizes' => [
'thumbnail' => ['width' => 150, 'height' => 150, 'crop' => true],
'small' => ['width' => 300, 'height' => null],
'medium' => ['width' => 768, 'height' => null],
'large' => ['width' => 1200, 'height' => null],
],
'webp_quality' => 80,
'strip_exif' => true,
],
];