@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\SchoolYearModel;
|
||||
use DateTimeImmutable;
|
||||
use InvalidArgumentException;
|
||||
|
||||
final class SchoolYearValidationService
|
||||
{
|
||||
public function __construct(
|
||||
private readonly SchoolYearModel $schoolYearModel,
|
||||
) {
|
||||
}
|
||||
|
||||
public function validateMetadata(array $payload, ?int $exceptId = null): void
|
||||
{
|
||||
$name = trim((string) ($payload['name'] ?? ''));
|
||||
|
||||
if (! $this->isValidYearName($name)) {
|
||||
throw new InvalidArgumentException('School year must use YYYY-YYYY with consecutive years.');
|
||||
}
|
||||
|
||||
$existing = $this->schoolYearModel->where('name', $name);
|
||||
if ($exceptId !== null) {
|
||||
$existing->where('id !=', $exceptId);
|
||||
}
|
||||
if ($existing->first() !== null) {
|
||||
throw new InvalidArgumentException('That school year already exists.');
|
||||
}
|
||||
|
||||
$startsOn = $this->dateOrNull($payload['starts_on'] ?? null);
|
||||
$endsOn = $this->dateOrNull($payload['ends_on'] ?? null);
|
||||
if ($startsOn !== null && $endsOn !== null && $startsOn >= $endsOn) {
|
||||
throw new InvalidArgumentException('School year start date must be before the end date.');
|
||||
}
|
||||
|
||||
$registrationStarts = $this->dateOrNull($payload['registration_starts_on'] ?? null);
|
||||
$registrationEnds = $this->dateOrNull($payload['registration_ends_on'] ?? null);
|
||||
if ($registrationStarts !== null && $registrationEnds !== null && $registrationStarts > $registrationEnds) {
|
||||
throw new InvalidArgumentException('Registration start date must be on or before the registration end date.');
|
||||
}
|
||||
}
|
||||
|
||||
public function isValidYearName(string $value): bool
|
||||
{
|
||||
if (! preg_match('/^(\d{4})-(\d{4})$/', $value, $matches)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (int) $matches[2] === (int) $matches[1] + 1;
|
||||
}
|
||||
|
||||
private function dateOrNull(mixed $value): ?DateTimeImmutable
|
||||
{
|
||||
$value = trim((string) $value);
|
||||
if ($value === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
$date = DateTimeImmutable::createFromFormat('!Y-m-d', $value);
|
||||
if (! $date instanceof DateTimeImmutable || $date->format('Y-m-d') !== $value) {
|
||||
throw new InvalidArgumentException('Dates must use YYYY-MM-DD.');
|
||||
}
|
||||
|
||||
return $date;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user