'pdf', 'image/jpeg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp', ]; private const MAX_SIZE = 8 * 1024 * 1024; // 8 Mo /** * @param string $field Nom du champ dans $_FILES * @param string $subdir Sous-dossier de public/uploads/ (ex. "factures") * @return string|null Chemin relatif stocké (ex. "uploads/factures/abc123.pdf"), null si aucun fichier envoyé * @throws InvalidArgumentException si un fichier est envoyé mais invalide */ public static function handle(string $field, string $subdir): ?string { if (empty($_FILES[$field]) || $_FILES[$field]['error'] === UPLOAD_ERR_NO_FILE) { return null; } $file = $_FILES[$field]; if ($file['error'] !== UPLOAD_ERR_OK) { throw new InvalidArgumentException("Échec de l'envoi du fichier."); } if ($file['size'] > self::MAX_SIZE) { throw new InvalidArgumentException('Fichier trop lourd (8 Mo maximum).'); } $mime = mime_content_type($file['tmp_name']); if (!isset(self::EXTENSIONS[$mime])) { throw new InvalidArgumentException('Format non supporté (PDF, JPEG, PNG ou WebP uniquement).'); } $dir = __DIR__ . '/../public/uploads/' . $subdir; if (!is_dir($dir)) { mkdir($dir, 0755, true); } // Nom aléatoire : plusieurs pièces jointes possibles pour le même // créateur/commande (une par facture/avoir/encaissement), contrairement // à la photo représentant (une seule, nommée par son id). $filename = bin2hex(random_bytes(16)) . '.' . self::EXTENSIONS[$mime]; if (!move_uploaded_file($file['tmp_name'], $dir . '/' . $filename)) { throw new InvalidArgumentException("Échec de l'enregistrement du fichier."); } return 'uploads/' . $subdir . '/' . $filename; } } 'pdf', 'image/jpeg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp', ]; private const MAX_SIZE = 8 * 1024 * 1024; // 8 Mo /** * @param string $field Nom du champ dans $_FILES * @param string $subdir Sous-dossier de public/uploads/ (ex. "factures") * @return string|null Chemin relatif stocké (ex. "uploads/factures/abc123.pdf"), null si aucun fichier envoyé * @throws InvalidArgumentException si un fichier est envoyé mais invalide */ public static function handle(string $field, string $subdir): ?string { if (empty($_FILES[$field]) || $_FILES[$field]['error'] === UPLOAD_ERR_NO_FILE) { return null; } $file = $_FILES[$field]; if ($file['error'] !== UPLOAD_ERR_OK) { throw new InvalidArgumentException("Échec de l'envoi du fichier."); } if ($file['size'] > self::MAX_SIZE) { throw new InvalidArgumentException('Fichier trop lourd (8 Mo maximum).'); } $mime = mime_content_type($file['tmp_name']); if (!isset(self::EXTENSIONS[$mime])) { throw new InvalidArgumentException('Format non supporté (PDF, JPEG, PNG ou WebP uniquement).'); } $dir = __DIR__ . '/../public/uploads/' . $subdir; if (!is_dir($dir)) { mkdir($dir, 0755, true); } // Nom aléatoire : plusieurs pièces jointes possibles pour le même // créateur/commande (une par facture/avoir/encaissement), contrairement // à la photo représentant (une seule, nommée par son id). $filename = bin2hex(random_bytes(16)) . '.' . self::EXTENSIONS[$mime]; if (!move_uploaded_file($file['tmp_name'], $dir . '/' . $filename)) { throw new InvalidArgumentException("Échec de l'enregistrement du fichier."); } return 'uploads/' . $subdir . '/' . $filename; } } 'pdf', 'image/jpeg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp', ]; private const MAX_SIZE = 8 * 1024 * 1024; // 8 Mo /** * @param string $field Nom du champ dans $_FILES * @param string $subdir Sous-dossier de public/uploads/ (ex. "factures") * @return string|null Chemin relatif stocké (ex. "uploads/factures/abc123.pdf"), null si aucun fichier envoyé * @throws InvalidArgumentException si un fichier est envoyé mais invalide */ public static function handle(string $field, string $subdir): ?string { if (empty($_FILES[$field]) || $_FILES[$field]['error'] === UPLOAD_ERR_NO_FILE) { return null; } $file = $_FILES[$field]; if ($file['error'] !== UPLOAD_ERR_OK) { throw new InvalidArgumentException("Échec de l'envoi du fichier."); } if ($file['size'] > self::MAX_SIZE) { throw new InvalidArgumentException('Fichier trop lourd (8 Mo maximum).'); } $mime = mime_content_type($file['tmp_name']); if (!isset(self::EXTENSIONS[$mime])) { throw new InvalidArgumentException('Format non supporté (PDF, JPEG, PNG ou WebP uniquement).'); } $dir = __DIR__ . '/../public/uploads/' . $subdir; if (!is_dir($dir)) { mkdir($dir, 0755, true); } // Nom aléatoire : plusieurs pièces jointes possibles pour le même // créateur/commande (une par facture/avoir/encaissement), contrairement // à la photo représentant (une seule, nommée par son id). $filename = bin2hex(random_bytes(16)) . '.' . self::EXTENSIONS[$mime]; if (!move_uploaded_file($file['tmp_name'], $dir . '/' . $filename)) { throw new InvalidArgumentException("Échec de l'enregistrement du fichier."); } return 'uploads/' . $subdir . '/' . $filename; } } 'pdf', 'image/jpeg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp', ]; private const MAX_SIZE = 8 * 1024 * 1024; // 8 Mo /** * @param string $field Nom du champ dans $_FILES * @param string $subdir Sous-dossier de public/uploads/ (ex. "factures") * @return string|null Chemin relatif stocké (ex. "uploads/factures/abc123.pdf"), null si aucun fichier envoyé * @throws InvalidArgumentException si un fichier est envoyé mais invalide */ public static function handle(string $field, string $subdir): ?string { if (empty($_FILES[$field]) || $_FILES[$field]['error'] === UPLOAD_ERR_NO_FILE) { return null; } $file = $_FILES[$field]; if ($file['error'] !== UPLOAD_ERR_OK) { throw new InvalidArgumentException("Échec de l'envoi du fichier."); } if ($file['size'] > self::MAX_SIZE) { throw new InvalidArgumentException('Fichier trop lourd (8 Mo maximum).'); } $mime = mime_content_type($file['tmp_name']); if (!isset(self::EXTENSIONS[$mime])) { throw new InvalidArgumentException('Format non supporté (PDF, JPEG, PNG ou WebP uniquement).'); } $dir = __DIR__ . '/../public/uploads/' . $subdir; if (!is_dir($dir)) { mkdir($dir, 0755, true); } // Nom aléatoire : plusieurs pièces jointes possibles pour le même // créateur/commande (une par facture/avoir/encaissement), contrairement // à la photo représentant (une seule, nommée par son id). $filename = bin2hex(random_bytes(16)) . '.' . self::EXTENSIONS[$mime]; if (!move_uploaded_file($file['tmp_name'], $dir . '/' . $filename)) { throw new InvalidArgumentException("Échec de l'enregistrement du fichier."); } return 'uploads/' . $subdir . '/' . $filename; } } 'pdf', 'image/jpeg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp', ]; private const MAX_SIZE = 8 * 1024 * 1024; // 8 Mo /** * @param string $field Nom du champ dans $_FILES * @param string $subdir Sous-dossier de public/uploads/ (ex. "factures") * @return string|null Chemin relatif stocké (ex. "uploads/factures/abc123.pdf"), null si aucun fichier envoyé * @throws InvalidArgumentException si un fichier est envoyé mais invalide */ public static function handle(string $field, string $subdir): ?string { if (empty($_FILES[$field]) || $_FILES[$field]['error'] === UPLOAD_ERR_NO_FILE) { return null; } $file = $_FILES[$field]; if ($file['error'] !== UPLOAD_ERR_OK) { throw new InvalidArgumentException("Échec de l'envoi du fichier."); } if ($file['size'] > self::MAX_SIZE) { throw new InvalidArgumentException('Fichier trop lourd (8 Mo maximum).'); } $mime = mime_content_type($file['tmp_name']); if (!isset(self::EXTENSIONS[$mime])) { throw new InvalidArgumentException('Format non supporté (PDF, JPEG, PNG ou WebP uniquement).'); } $dir = __DIR__ . '/../public/uploads/' . $subdir; if (!is_dir($dir)) { mkdir($dir, 0755, true); } // Nom aléatoire : plusieurs pièces jointes possibles pour le même // créateur/commande (une par facture/avoir/encaissement), contrairement // à la photo représentant (une seule, nommée par son id). $filename = bin2hex(random_bytes(16)) . '.' . self::EXTENSIONS[$mime]; if (!move_uploaded_file($file['tmp_name'], $dir . '/' . $filename)) { throw new InvalidArgumentException("Échec de l'enregistrement du fichier."); } return 'uploads/' . $subdir . '/' . $filename; } } 'pdf', 'image/jpeg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp', ]; private const MAX_SIZE = 8 * 1024 * 1024; // 8 Mo /** * @param string $field Nom du champ dans $_FILES * @param string $subdir Sous-dossier de public/uploads/ (ex. "factures") * @return string|null Chemin relatif stocké (ex. "uploads/factures/abc123.pdf"), null si aucun fichier envoyé * @throws InvalidArgumentException si un fichier est envoyé mais invalide */ public static function handle(string $field, string $subdir): ?string { if (empty($_FILES[$field]) || $_FILES[$field]['error'] === UPLOAD_ERR_NO_FILE) { return null; } $file = $_FILES[$field]; if ($file['error'] !== UPLOAD_ERR_OK) { throw new InvalidArgumentException("Échec de l'envoi du fichier."); } if ($file['size'] > self::MAX_SIZE) { throw new InvalidArgumentException('Fichier trop lourd (8 Mo maximum).'); } $mime = mime_content_type($file['tmp_name']); if (!isset(self::EXTENSIONS[$mime])) { throw new InvalidArgumentException('Format non supporté (PDF, JPEG, PNG ou WebP uniquement).'); } $dir = __DIR__ . '/../public/uploads/' . $subdir; if (!is_dir($dir)) { mkdir($dir, 0755, true); } // Nom aléatoire : plusieurs pièces jointes possibles pour le même // créateur/commande (une par facture/avoir/encaissement), contrairement // à la photo représentant (une seule, nommée par son id). $filename = bin2hex(random_bytes(16)) . '.' . self::EXTENSIONS[$mime]; if (!move_uploaded_file($file['tmp_name'], $dir . '/' . $filename)) { throw new InvalidArgumentException("Échec de l'enregistrement du fichier."); } return 'uploads/' . $subdir . '/' . $filename; } } 'pdf', 'image/jpeg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp', ]; private const MAX_SIZE = 8 * 1024 * 1024; // 8 Mo /** * @param string $field Nom du champ dans $_FILES * @param string $subdir Sous-dossier de public/uploads/ (ex. "factures") * @return string|null Chemin relatif stocké (ex. "uploads/factures/abc123.pdf"), null si aucun fichier envoyé * @throws InvalidArgumentException si un fichier est envoyé mais invalide */ public static function handle(string $field, string $subdir): ?string { if (empty($_FILES[$field]) || $_FILES[$field]['error'] === UPLOAD_ERR_NO_FILE) { return null; } $file = $_FILES[$field]; if ($file['error'] !== UPLOAD_ERR_OK) { throw new InvalidArgumentException("Échec de l'envoi du fichier."); } if ($file['size'] > self::MAX_SIZE) { throw new InvalidArgumentException('Fichier trop lourd (8 Mo maximum).'); } $mime = mime_content_type($file['tmp_name']); if (!isset(self::EXTENSIONS[$mime])) { throw new InvalidArgumentException('Format non supporté (PDF, JPEG, PNG ou WebP uniquement).'); } $dir = __DIR__ . '/../public/uploads/' . $subdir; if (!is_dir($dir)) { mkdir($dir, 0755, true); } // Nom aléatoire : plusieurs pièces jointes possibles pour le même // créateur/commande (une par facture/avoir/encaissement), contrairement // à la photo représentant (une seule, nommée par son id). $filename = bin2hex(random_bytes(16)) . '.' . self::EXTENSIONS[$mime]; if (!move_uploaded_file($file['tmp_name'], $dir . '/' . $filename)) { throw new InvalidArgumentException("Échec de l'enregistrement du fichier."); } return 'uploads/' . $subdir . '/' . $filename; } } 'pdf', 'image/jpeg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp', ]; private const MAX_SIZE = 8 * 1024 * 1024; // 8 Mo /** * @param string $field Nom du champ dans $_FILES * @param string $subdir Sous-dossier de public/uploads/ (ex. "factures") * @return string|null Chemin relatif stocké (ex. "uploads/factures/abc123.pdf"), null si aucun fichier envoyé * @throws InvalidArgumentException si un fichier est envoyé mais invalide */ public static function handle(string $field, string $subdir): ?string { if (empty($_FILES[$field]) || $_FILES[$field]['error'] === UPLOAD_ERR_NO_FILE) { return null; } $file = $_FILES[$field]; if ($file['error'] !== UPLOAD_ERR_OK) { throw new InvalidArgumentException("Échec de l'envoi du fichier."); } if ($file['size'] > self::MAX_SIZE) { throw new InvalidArgumentException('Fichier trop lourd (8 Mo maximum).'); } $mime = mime_content_type($file['tmp_name']); if (!isset(self::EXTENSIONS[$mime])) { throw new InvalidArgumentException('Format non supporté (PDF, JPEG, PNG ou WebP uniquement).'); } $dir = __DIR__ . '/../public/uploads/' . $subdir; if (!is_dir($dir)) { mkdir($dir, 0755, true); } // Nom aléatoire : plusieurs pièces jointes possibles pour le même // créateur/commande (une par facture/avoir/encaissement), contrairement // à la photo représentant (une seule, nommée par son id). $filename = bin2hex(random_bytes(16)) . '.' . self::EXTENSIONS[$mime]; if (!move_uploaded_file($file['tmp_name'], $dir . '/' . $filename)) { throw new InvalidArgumentException("Échec de l'enregistrement du fichier."); } return 'uploads/' . $subdir . '/' . $filename; } } 'pdf', 'image/jpeg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp', ]; private const MAX_SIZE = 8 * 1024 * 1024; // 8 Mo /** * @param string $field Nom du champ dans $_FILES * @param string $subdir Sous-dossier de public/uploads/ (ex. "factures") * @return string|null Chemin relatif stocké (ex. "uploads/factures/abc123.pdf"), null si aucun fichier envoyé * @throws InvalidArgumentException si un fichier est envoyé mais invalide */ public static function handle(string $field, string $subdir): ?string { if (empty($_FILES[$field]) || $_FILES[$field]['error'] === UPLOAD_ERR_NO_FILE) { return null; } $file = $_FILES[$field]; if ($file['error'] !== UPLOAD_ERR_OK) { throw new InvalidArgumentException("Échec de l'envoi du fichier."); } if ($file['size'] > self::MAX_SIZE) { throw new InvalidArgumentException('Fichier trop lourd (8 Mo maximum).'); } $mime = mime_content_type($file['tmp_name']); if (!isset(self::EXTENSIONS[$mime])) { throw new InvalidArgumentException('Format non supporté (PDF, JPEG, PNG ou WebP uniquement).'); } $dir = __DIR__ . '/../public/uploads/' . $subdir; if (!is_dir($dir)) { mkdir($dir, 0755, true); } // Nom aléatoire : plusieurs pièces jointes possibles pour le même // créateur/commande (une par facture/avoir/encaissement), contrairement // à la photo représentant (une seule, nommée par son id). $filename = bin2hex(random_bytes(16)) . '.' . self::EXTENSIONS[$mime]; if (!move_uploaded_file($file['tmp_name'], $dir . '/' . $filename)) { throw new InvalidArgumentException("Échec de l'enregistrement du fichier."); } return 'uploads/' . $subdir . '/' . $filename; } } 'pdf', 'image/jpeg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp', ]; private const MAX_SIZE = 8 * 1024 * 1024; // 8 Mo /** * @param string $field Nom du champ dans $_FILES * @param string $subdir Sous-dossier de public/uploads/ (ex. "factures") * @return string|null Chemin relatif stocké (ex. "uploads/factures/abc123.pdf"), null si aucun fichier envoyé * @throws InvalidArgumentException si un fichier est envoyé mais invalide */ public static function handle(string $field, string $subdir): ?string { if (empty($_FILES[$field]) || $_FILES[$field]['error'] === UPLOAD_ERR_NO_FILE) { return null; } $file = $_FILES[$field]; if ($file['error'] !== UPLOAD_ERR_OK) { throw new InvalidArgumentException("Échec de l'envoi du fichier."); } if ($file['size'] > self::MAX_SIZE) { throw new InvalidArgumentException('Fichier trop lourd (8 Mo maximum).'); } $mime = mime_content_type($file['tmp_name']); if (!isset(self::EXTENSIONS[$mime])) { throw new InvalidArgumentException('Format non supporté (PDF, JPEG, PNG ou WebP uniquement).'); } $dir = __DIR__ . '/../public/uploads/' . $subdir; if (!is_dir($dir)) { mkdir($dir, 0755, true); } // Nom aléatoire : plusieurs pièces jointes possibles pour le même // créateur/commande (une par facture/avoir/encaissement), contrairement // à la photo représentant (une seule, nommée par son id). $filename = bin2hex(random_bytes(16)) . '.' . self::EXTENSIONS[$mime]; if (!move_uploaded_file($file['tmp_name'], $dir . '/' . $filename)) { throw new InvalidArgumentException("Échec de l'enregistrement du fichier."); } return 'uploads/' . $subdir . '/' . $filename; } } 'pdf', 'image/jpeg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp', ]; private const MAX_SIZE = 8 * 1024 * 1024; // 8 Mo /** * @param string $field Nom du champ dans $_FILES * @param string $subdir Sous-dossier de public/uploads/ (ex. "factures") * @return string|null Chemin relatif stocké (ex. "uploads/factures/abc123.pdf"), null si aucun fichier envoyé * @throws InvalidArgumentException si un fichier est envoyé mais invalide */ public static function handle(string $field, string $subdir): ?string { if (empty($_FILES[$field]) || $_FILES[$field]['error'] === UPLOAD_ERR_NO_FILE) { return null; } $file = $_FILES[$field]; if ($file['error'] !== UPLOAD_ERR_OK) { throw new InvalidArgumentException("Échec de l'envoi du fichier."); } if ($file['size'] > self::MAX_SIZE) { throw new InvalidArgumentException('Fichier trop lourd (8 Mo maximum).'); } $mime = mime_content_type($file['tmp_name']); if (!isset(self::EXTENSIONS[$mime])) { throw new InvalidArgumentException('Format non supporté (PDF, JPEG, PNG ou WebP uniquement).'); } $dir = __DIR__ . '/../public/uploads/' . $subdir; if (!is_dir($dir)) { mkdir($dir, 0755, true); } // Nom aléatoire : plusieurs pièces jointes possibles pour le même // créateur/commande (une par facture/avoir/encaissement), contrairement // à la photo représentant (une seule, nommée par son id). $filename = bin2hex(random_bytes(16)) . '.' . self::EXTENSIONS[$mime]; if (!move_uploaded_file($file['tmp_name'], $dir . '/' . $filename)) { throw new InvalidArgumentException("Échec de l'enregistrement du fichier."); } return 'uploads/' . $subdir . '/' . $filename; } } 'pdf', 'image/jpeg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp', ]; private const MAX_SIZE = 8 * 1024 * 1024; // 8 Mo /** * @param string $field Nom du champ dans $_FILES * @param string $subdir Sous-dossier de public/uploads/ (ex. "factures") * @return string|null Chemin relatif stocké (ex. "uploads/factures/abc123.pdf"), null si aucun fichier envoyé * @throws InvalidArgumentException si un fichier est envoyé mais invalide */ public static function handle(string $field, string $subdir): ?string { if (empty($_FILES[$field]) || $_FILES[$field]['error'] === UPLOAD_ERR_NO_FILE) { return null; } $file = $_FILES[$field]; if ($file['error'] !== UPLOAD_ERR_OK) { throw new InvalidArgumentException("Échec de l'envoi du fichier."); } if ($file['size'] > self::MAX_SIZE) { throw new InvalidArgumentException('Fichier trop lourd (8 Mo maximum).'); } $mime = mime_content_type($file['tmp_name']); if (!isset(self::EXTENSIONS[$mime])) { throw new InvalidArgumentException('Format non supporté (PDF, JPEG, PNG ou WebP uniquement).'); } $dir = __DIR__ . '/../public/uploads/' . $subdir; if (!is_dir($dir)) { mkdir($dir, 0755, true); } // Nom aléatoire : plusieurs pièces jointes possibles pour le même // créateur/commande (une par facture/avoir/encaissement), contrairement // à la photo représentant (une seule, nommée par son id). $filename = bin2hex(random_bytes(16)) . '.' . self::EXTENSIONS[$mime]; if (!move_uploaded_file($file['tmp_name'], $dir . '/' . $filename)) { throw new InvalidArgumentException("Échec de l'enregistrement du fichier."); } return 'uploads/' . $subdir . '/' . $filename; } } 'pdf', 'image/jpeg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp', ]; private const MAX_SIZE = 8 * 1024 * 1024; // 8 Mo /** * @param string $field Nom du champ dans $_FILES * @param string $subdir Sous-dossier de public/uploads/ (ex. "factures") * @return string|null Chemin relatif stocké (ex. "uploads/factures/abc123.pdf"), null si aucun fichier envoyé * @throws InvalidArgumentException si un fichier est envoyé mais invalide */ public static function handle(string $field, string $subdir): ?string { if (empty($_FILES[$field]) || $_FILES[$field]['error'] === UPLOAD_ERR_NO_FILE) { return null; } $file = $_FILES[$field]; if ($file['error'] !== UPLOAD_ERR_OK) { throw new InvalidArgumentException("Échec de l'envoi du fichier."); } if ($file['size'] > self::MAX_SIZE) { throw new InvalidArgumentException('Fichier trop lourd (8 Mo maximum).'); } $mime = mime_content_type($file['tmp_name']); if (!isset(self::EXTENSIONS[$mime])) { throw new InvalidArgumentException('Format non supporté (PDF, JPEG, PNG ou WebP uniquement).'); } $dir = __DIR__ . '/../public/uploads/' . $subdir; if (!is_dir($dir)) { mkdir($dir, 0755, true); } // Nom aléatoire : plusieurs pièces jointes possibles pour le même // créateur/commande (une par facture/avoir/encaissement), contrairement // à la photo représentant (une seule, nommée par son id). $filename = bin2hex(random_bytes(16)) . '.' . self::EXTENSIONS[$mime]; if (!move_uploaded_file($file['tmp_name'], $dir . '/' . $filename)) { throw new InvalidArgumentException("Échec de l'enregistrement du fichier."); } return 'uploads/' . $subdir . '/' . $filename; } } 'pdf', 'image/jpeg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp', ]; private const MAX_SIZE = 8 * 1024 * 1024; // 8 Mo /** * @param string $field Nom du champ dans $_FILES * @param string $subdir Sous-dossier de public/uploads/ (ex. "factures") * @return string|null Chemin relatif stocké (ex. "uploads/factures/abc123.pdf"), null si aucun fichier envoyé * @throws InvalidArgumentException si un fichier est envoyé mais invalide */ public static function handle(string $field, string $subdir): ?string { if (empty($_FILES[$field]) || $_FILES[$field]['error'] === UPLOAD_ERR_NO_FILE) { return null; } $file = $_FILES[$field]; if ($file['error'] !== UPLOAD_ERR_OK) { throw new InvalidArgumentException("Échec de l'envoi du fichier."); } if ($file['size'] > self::MAX_SIZE) { throw new InvalidArgumentException('Fichier trop lourd (8 Mo maximum).'); } $mime = mime_content_type($file['tmp_name']); if (!isset(self::EXTENSIONS[$mime])) { throw new InvalidArgumentException('Format non supporté (PDF, JPEG, PNG ou WebP uniquement).'); } $dir = __DIR__ . '/../public/uploads/' . $subdir; if (!is_dir($dir)) { mkdir($dir, 0755, true); } // Nom aléatoire : plusieurs pièces jointes possibles pour le même // créateur/commande (une par facture/avoir/encaissement), contrairement // à la photo représentant (une seule, nommée par son id). $filename = bin2hex(random_bytes(16)) . '.' . self::EXTENSIONS[$mime]; if (!move_uploaded_file($file['tmp_name'], $dir . '/' . $filename)) { throw new InvalidArgumentException("Échec de l'enregistrement du fichier."); } return 'uploads/' . $subdir . '/' . $filename; } } 'pdf', 'image/jpeg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp', ]; private const MAX_SIZE = 8 * 1024 * 1024; // 8 Mo /** * @param string $field Nom du champ dans $_FILES * @param string $subdir Sous-dossier de public/uploads/ (ex. "factures") * @return string|null Chemin relatif stocké (ex. "uploads/factures/abc123.pdf"), null si aucun fichier envoyé * @throws InvalidArgumentException si un fichier est envoyé mais invalide */ public static function handle(string $field, string $subdir): ?string { if (empty($_FILES[$field]) || $_FILES[$field]['error'] === UPLOAD_ERR_NO_FILE) { return null; } $file = $_FILES[$field]; if ($file['error'] !== UPLOAD_ERR_OK) { throw new InvalidArgumentException("Échec de l'envoi du fichier."); } if ($file['size'] > self::MAX_SIZE) { throw new InvalidArgumentException('Fichier trop lourd (8 Mo maximum).'); } $mime = mime_content_type($file['tmp_name']); if (!isset(self::EXTENSIONS[$mime])) { throw new InvalidArgumentException('Format non supporté (PDF, JPEG, PNG ou WebP uniquement).'); } $dir = __DIR__ . '/../public/uploads/' . $subdir; if (!is_dir($dir)) { mkdir($dir, 0755, true); } // Nom aléatoire : plusieurs pièces jointes possibles pour le même // créateur/commande (une par facture/avoir/encaissement), contrairement // à la photo représentant (une seule, nommée par son id). $filename = bin2hex(random_bytes(16)) . '.' . self::EXTENSIONS[$mime]; if (!move_uploaded_file($file['tmp_name'], $dir . '/' . $filename)) { throw new InvalidArgumentException("Échec de l'enregistrement du fichier."); } return 'uploads/' . $subdir . '/' . $filename; } } 'pdf', 'image/jpeg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp', ]; private const MAX_SIZE = 8 * 1024 * 1024; // 8 Mo /** * @param string $field Nom du champ dans $_FILES * @param string $subdir Sous-dossier de public/uploads/ (ex. "factures") * @return string|null Chemin relatif stocké (ex. "uploads/factures/abc123.pdf"), null si aucun fichier envoyé * @throws InvalidArgumentException si un fichier est envoyé mais invalide */ public static function handle(string $field, string $subdir): ?string { if (empty($_FILES[$field]) || $_FILES[$field]['error'] === UPLOAD_ERR_NO_FILE) { return null; } $file = $_FILES[$field]; if ($file['error'] !== UPLOAD_ERR_OK) { throw new InvalidArgumentException("Échec de l'envoi du fichier."); } if ($file['size'] > self::MAX_SIZE) { throw new InvalidArgumentException('Fichier trop lourd (8 Mo maximum).'); } $mime = mime_content_type($file['tmp_name']); if (!isset(self::EXTENSIONS[$mime])) { throw new InvalidArgumentException('Format non supporté (PDF, JPEG, PNG ou WebP uniquement).'); } $dir = __DIR__ . '/../public/uploads/' . $subdir; if (!is_dir($dir)) { mkdir($dir, 0755, true); } // Nom aléatoire : plusieurs pièces jointes possibles pour le même // créateur/commande (une par facture/avoir/encaissement), contrairement // à la photo représentant (une seule, nommée par son id). $filename = bin2hex(random_bytes(16)) . '.' . self::EXTENSIONS[$mime]; if (!move_uploaded_file($file['tmp_name'], $dir . '/' . $filename)) { throw new InvalidArgumentException("Échec de l'enregistrement du fichier."); } return 'uploads/' . $subdir . '/' . $filename; } } 'pdf', 'image/jpeg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp', ]; private const MAX_SIZE = 8 * 1024 * 1024; // 8 Mo /** * @param string $field Nom du champ dans $_FILES * @param string $subdir Sous-dossier de public/uploads/ (ex. "factures") * @return string|null Chemin relatif stocké (ex. "uploads/factures/abc123.pdf"), null si aucun fichier envoyé * @throws InvalidArgumentException si un fichier est envoyé mais invalide */ public static function handle(string $field, string $subdir): ?string { if (empty($_FILES[$field]) || $_FILES[$field]['error'] === UPLOAD_ERR_NO_FILE) { return null; } $file = $_FILES[$field]; if ($file['error'] !== UPLOAD_ERR_OK) { throw new InvalidArgumentException("Échec de l'envoi du fichier."); } if ($file['size'] > self::MAX_SIZE) { throw new InvalidArgumentException('Fichier trop lourd (8 Mo maximum).'); } $mime = mime_content_type($file['tmp_name']); if (!isset(self::EXTENSIONS[$mime])) { throw new InvalidArgumentException('Format non supporté (PDF, JPEG, PNG ou WebP uniquement).'); } $dir = __DIR__ . '/../public/uploads/' . $subdir; if (!is_dir($dir)) { mkdir($dir, 0755, true); } // Nom aléatoire : plusieurs pièces jointes possibles pour le même // créateur/commande (une par facture/avoir/encaissement), contrairement // à la photo représentant (une seule, nommée par son id). $filename = bin2hex(random_bytes(16)) . '.' . self::EXTENSIONS[$mime]; if (!move_uploaded_file($file['tmp_name'], $dir . '/' . $filename)) { throw new InvalidArgumentException("Échec de l'enregistrement du fichier."); } return 'uploads/' . $subdir . '/' . $filename; } } 'pdf', 'image/jpeg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp', ]; private const MAX_SIZE = 8 * 1024 * 1024; // 8 Mo /** * @param string $field Nom du champ dans $_FILES * @param string $subdir Sous-dossier de public/uploads/ (ex. "factures") * @return string|null Chemin relatif stocké (ex. "uploads/factures/abc123.pdf"), null si aucun fichier envoyé * @throws InvalidArgumentException si un fichier est envoyé mais invalide */ public static function handle(string $field, string $subdir): ?string { if (empty($_FILES[$field]) || $_FILES[$field]['error'] === UPLOAD_ERR_NO_FILE) { return null; } $file = $_FILES[$field]; if ($file['error'] !== UPLOAD_ERR_OK) { throw new InvalidArgumentException("Échec de l'envoi du fichier."); } if ($file['size'] > self::MAX_SIZE) { throw new InvalidArgumentException('Fichier trop lourd (8 Mo maximum).'); } $mime = mime_content_type($file['tmp_name']); if (!isset(self::EXTENSIONS[$mime])) { throw new InvalidArgumentException('Format non supporté (PDF, JPEG, PNG ou WebP uniquement).'); } $dir = __DIR__ . '/../public/uploads/' . $subdir; if (!is_dir($dir)) { mkdir($dir, 0755, true); } // Nom aléatoire : plusieurs pièces jointes possibles pour le même // créateur/commande (une par facture/avoir/encaissement), contrairement // à la photo représentant (une seule, nommée par son id). $filename = bin2hex(random_bytes(16)) . '.' . self::EXTENSIONS[$mime]; if (!move_uploaded_file($file['tmp_name'], $dir . '/' . $filename)) { throw new InvalidArgumentException("Échec de l'enregistrement du fichier."); } return 'uploads/' . $subdir . '/' . $filename; } } 'pdf', 'image/jpeg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp', ]; private const MAX_SIZE = 8 * 1024 * 1024; // 8 Mo /** * @param string $field Nom du champ dans $_FILES * @param string $subdir Sous-dossier de public/uploads/ (ex. "factures") * @return string|null Chemin relatif stocké (ex. "uploads/factures/abc123.pdf"), null si aucun fichier envoyé * @throws InvalidArgumentException si un fichier est envoyé mais invalide */ public static function handle(string $field, string $subdir): ?string { if (empty($_FILES[$field]) || $_FILES[$field]['error'] === UPLOAD_ERR_NO_FILE) { return null; } $file = $_FILES[$field]; if ($file['error'] !== UPLOAD_ERR_OK) { throw new InvalidArgumentException("Échec de l'envoi du fichier."); } if ($file['size'] > self::MAX_SIZE) { throw new InvalidArgumentException('Fichier trop lourd (8 Mo maximum).'); } $mime = mime_content_type($file['tmp_name']); if (!isset(self::EXTENSIONS[$mime])) { throw new InvalidArgumentException('Format non supporté (PDF, JPEG, PNG ou WebP uniquement).'); } $dir = __DIR__ . '/../public/uploads/' . $subdir; if (!is_dir($dir)) { mkdir($dir, 0755, true); } // Nom aléatoire : plusieurs pièces jointes possibles pour le même // créateur/commande (une par facture/avoir/encaissement), contrairement // à la photo représentant (une seule, nommée par son id). $filename = bin2hex(random_bytes(16)) . '.' . self::EXTENSIONS[$mime]; if (!move_uploaded_file($file['tmp_name'], $dir . '/' . $filename)) { throw new InvalidArgumentException("Échec de l'enregistrement du fichier."); } return 'uploads/' . $subdir . '/' . $filename; } }