refactor(backend): reorganize domains into Core, Commerce, Ticketing and Shared
This commit is contained in:
86
app/Shared/Rules/CroppedImageOrBase64Rule.php
Normal file
86
app/Shared/Rules/CroppedImageOrBase64Rule.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Shared\Rules;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
|
||||
class CroppedImageOrBase64Rule implements ValidationRule
|
||||
{
|
||||
public function validate(string $attribute, mixed $value, Closure $fail): void
|
||||
{
|
||||
if (! is_array($value)) {
|
||||
(new ImageOrBase64Rule)->validate($attribute, $value, $fail);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (! array_key_exists('image', $value)) {
|
||||
$fail('The :attribute.image field is required.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$valid = true;
|
||||
(new ImageOrBase64Rule)->validate(
|
||||
"{$attribute}.image",
|
||||
$value['image'],
|
||||
function (string $message) use ($fail, &$valid): void {
|
||||
$valid = false;
|
||||
$fail($message);
|
||||
}
|
||||
);
|
||||
|
||||
if (! $valid) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset($value['crops']) && is_array($value['crops'])) {
|
||||
foreach (['desktop', 'mobile'] as $variant) {
|
||||
$crop = $value['crops'][$variant] ?? null;
|
||||
|
||||
if (! is_array($crop)) {
|
||||
$fail("The :attribute.crops.{$variant} field must be an object.");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->validateRange("{$attribute}.crops.{$variant}", 'crop_horizontal', $crop, $fail);
|
||||
$this->validateRange("{$attribute}.crops.{$variant}", 'crop_vertical', $crop, $fail);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Backwards compatibility with the original single-crop payload.
|
||||
$this->validateRange($attribute, 'crop_horizontal', $value, $fail);
|
||||
$this->validateRange($attribute, 'crop_vertical', $value, $fail);
|
||||
}
|
||||
|
||||
private function validateRange(string $attribute, string $axis, array $value, Closure $fail): void
|
||||
{
|
||||
$range = $value[$axis] ?? null;
|
||||
|
||||
if (! is_array($range)) {
|
||||
$fail("The :attribute.{$axis} field must be an object.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$start = $range['start_percentage'] ?? null;
|
||||
$end = $range['end_percentage'] ?? null;
|
||||
|
||||
if (
|
||||
! is_numeric($start)
|
||||
|| ! is_numeric($end)
|
||||
|| (float) $start < 0
|
||||
|| (float) $end > 100
|
||||
|| (float) $start >= (float) $end
|
||||
) {
|
||||
$fail(
|
||||
"The :attribute.{$axis} field must satisfy "
|
||||
.'0 <= start_percentage < end_percentage <= 100.'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
58
app/Shared/Rules/ImageOrBase64Rule.php
Normal file
58
app/Shared/Rules/ImageOrBase64Rule.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?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.");
|
||||
}
|
||||
}
|
||||
24
app/Shared/Rules/ValidTimezone.php
Normal file
24
app/Shared/Rules/ValidTimezone.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Shared\Rules;
|
||||
|
||||
use Closure;
|
||||
use DateTimeZone;
|
||||
use Exception;
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
|
||||
class ValidTimezone implements ValidationRule
|
||||
{
|
||||
public function validate(string $attribute, mixed $value, Closure $fail): void
|
||||
{
|
||||
if (! is_string($value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
new DateTimeZone($value);
|
||||
} catch (Exception) {
|
||||
$fail(__('validation.timezone'));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user