From bc581f54f2f871bc9abb1a76cf3fd2388302fd4c Mon Sep 17 00:00:00 2001 From: Paulo Castellano Date: Mon, 4 May 2026 14:26:36 -0300 Subject: [PATCH] refactor: read allowed MIMEs from MediaType enum in MediaAttacher MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The enum already has `allowedMimeTypes()` — it's the single source of truth for what each media type accepts (jpeg/png/gif/webp for image, mp4/quicktime/webm for video). MediaAttacher was duplicating the same arrays as ALLOWED_IMAGE_MIMES / ALLOWED_VIDEO_MIMES constants, which meant any change to the supported MIMEs needed two edits. Drop the constants. `resolveType()` now walks `[MediaType::Image, MediaType::Video]` and asks each type whether the MIME is on its allow-list. Document type is intentionally excluded so PDFs aren't accepted via URL fetch. Note on size: kept MediaAttacher's own MAX_BYTES = 50 MB (separate from the enum's per-type caps). URL fetches have different operational constraints than direct uploads (bandwidth, timeout, unbounded user input) — a smaller cap here is intentional. Out of scope but worth a follow-up: `StoreAssetRequest` and `storeChunked` are also drifted (web only accepts video/mp4 today, the enum + MediaAttacher accept mov/webm too). They should also read from the enum eventually. --- app/Services/Post/MediaAttacher.php | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/app/Services/Post/MediaAttacher.php b/app/Services/Post/MediaAttacher.php index db82da24..a332dc4d 100644 --- a/app/Services/Post/MediaAttacher.php +++ b/app/Services/Post/MediaAttacher.php @@ -40,11 +40,14 @@ */ class MediaAttacher { - private const ALLOWED_IMAGE_MIMES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']; - - private const ALLOWED_VIDEO_MIMES = ['video/mp4', 'video/quicktime', 'video/webm']; - - private const MAX_BYTES = 50 * 1024 * 1024; // 50 MB + /** + * Cap on URL-fetched payloads. Smaller than the web upload cap (which + * can be 1 GB for direct uploads) because URL fetches have stricter + * server-side concerns: bandwidth, timeout, and unbounded user input. + * 50 MB covers a long photo or a short video; bigger files should be + * uploaded directly. + */ + private const MAX_BYTES = 50 * 1024 * 1024; private static bool $skipUrlSafety = false; @@ -222,18 +225,21 @@ private function allowedMediaTypesFor(Post $post): array return array_map(fn ($value) => MediaType::from($value), $intersection); } + /** + * Resolve the MediaType for a given MIME by walking the enum's own + * allow-list. Document is excluded from URL fetches (no PDFs via URL + * — those go through direct upload only). + */ private function resolveType(?string $mime): ?MediaType { if ($mime === null || $mime === '') { return null; } - if (in_array($mime, self::ALLOWED_IMAGE_MIMES, true)) { - return MediaType::Image; - } - - if (in_array($mime, self::ALLOWED_VIDEO_MIMES, true)) { - return MediaType::Video; + foreach ([MediaType::Image, MediaType::Video] as $type) { + if (in_array($mime, $type->allowedMimeTypes(), true)) { + return $type; + } } return null;