59 lines
1.8 KiB
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.");
|
|
}
|
|
}
|