refactor: read allowed MIMEs from MediaType enum in MediaAttacher

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.
This commit is contained in:
Paulo Castellano 2026-05-04 14:26:36 -03:00
parent 6ae48f014f
commit bc581f54f2

View file

@ -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;