requireAuth(); } public function index(): void { $page = max(1, (int) ($this->f3->get('GET.page') ?? 1)); $result = (new Media($this->db))->paginateLibrary($page, self::PER_PAGE); $this->render('admin/media.html', [ 'pageTitle' => 'Médiathèque', 'items' => $result['items'], 'pagination' => $result, 'paginationAlias' => 'media_index', ]); } public function upload(): void { $this->verifyCsrf(); try { // Lire le nom d'origine avant que Web::receive() déplace le fichier. $originalName = (string) ($this->f3->get('FILES.image.name') ?? ''); $received = Web::instance()->receive( fn(array $file): bool => (int) ($file['size'] ?? 0) > 0 && (int) ($file['size'] ?? 0) <= self::UPLOAD_MAX_BYTES && in_array($file['type'] ?? '', self::ACCEPTED_TYPES, true), overwrite: false, slug: true ); // UPLOADS étant absolu (bootstrap.php), les chemins retournés le sont aussi. $accepted = array_keys(array_filter($received)); if ($accepted === []) { throw new RuntimeException('Choisis une image valide à envoyer (JPG, PNG, WebP ≤ ' . (int) (self::UPLOAD_MAX_BYTES / 1024 / 1024) . ' Mo).'); } foreach ($accepted as $destPath) { (new Media($this->db))->upload($destPath, $originalName); } $this->flash('success', 'Image ajoutée.'); } catch (RuntimeException $e) { $this->flash('error', $e->getMessage()); } $this->f3->reroute('@media_index'); } public function updateAlt(): void { $this->verifyCsrf(); try { $alt = trim((string) ($this->f3->get('POST.alt') ?? '')); (new Media($this->db))->updateAlt((int) $this->f3->get('PARAMS.id'), $alt); $this->flash('success', 'Texte alternatif mis à jour.'); } catch (RuntimeException $e) { $this->flash('error', $e->getMessage()); } $this->f3->reroute('@media_index'); } public function delete(): void { $this->verifyCsrf(); try { (new Media($this->db))->delete((int) $this->f3->get('PARAMS.id')); $this->flash('success', 'Image supprimée.'); } catch (RuntimeException $e) { $this->flash('error', $e->getMessage()); } $this->f3->reroute('@media_index'); } }