shopit-back/app/Domains/Shared/Rules/ImageOrBase64Rule.php

59 lines
1.8 KiB
PHP

<?php
namespace App\Domains\Shared\Rules;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Http\UploadedFile;
class ImageOrBase64Rule implements ValidationRule
{
public function validate(string $attribute, mixed $value, Closure $fail): void
{
if ($value instanceof UploadedFile) {
$mime = $value->getMimeType();
if (! str_starts_with((string) $mime, 'image/')) {
$fail("The :attribute must be a valid image file.");
}
return;
}
if (is_string($value)) {
$payload = trim($value);
if (\Illuminate\Support\Str::isUuid($payload)) {
return;
}
if ($payload === '') {
$fail("The :attribute must not be empty.");
return;
}
$declaredMimeType = null;
if (preg_match('/^data:(?<mime>[-\w.+\/]+);base64,(?<data>.+)$/s', $payload, $matches) === 1) {
$declaredMimeType = strtolower($matches['mime']);
$payload = $matches['data'];
}
$decoded = base64_decode(preg_replace('/\s+/', '', $payload), true);
if ($decoded === false || $decoded === '') {
$fail("The :attribute must be a valid base64-encoded image.");
return;
}
$finfo = new \finfo(FILEINFO_MIME_TYPE);
$detectedMime = $finfo->buffer($decoded);
$mime = $detectedMime ?: $declaredMimeType;
if (! $mime || ! str_starts_with((string) $mime, 'image/')) {
$fail("The :attribute must be a valid image (file or base64).");
}
return;
}
$fail("The :attribute must be an image file or a base64-encoded image string.");
}
}