59 lines
1.8 KiB
PHP
59 lines
1.8 KiB
PHP
<?php
|
|||
|
|
declare(strict_types=1);
|
||
|
|
|
||
|
|
namespace App\Domain\Jobcard;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Validates and normalizes the command used to replace a jobcard's technician assignments.
|
||
|
|
*/
|
||
|
|
final class AssignmentValidator
|
||
|
|
{
|
||
|
|
/**
|
||
|
|
* @return array{valid: bool, jobcard_id: ?int, user_ids: list<int>, errors: array<string, string>}
|
||
|
|
*/
|
||
|
|
public function validate(array $payload): array
|
||
|
|
{
|
||
|
|
$errors = [];
|
||
|
|
$jobcardId = $this->positiveInteger($payload['jobcard_id'] ?? null);
|
||
|
|
if ($jobcardId === null) {
|
||
|
|
$errors['jobcard_id'] = 'Jobcard ID must be a positive integer.';
|
||
|
|
}
|
||
|
|
|
||
|
|
$userIds = [];
|
||
|
|
$assignments = $payload['user_ids'] ?? null;
|
||
|
|
if (!is_array($assignments) || $assignments === []) {
|
||
|
|
$errors['user_ids'] = 'At least one technician ID is required.';
|
||
|
|
} else {
|
||
|
|
foreach ($assignments as $userId) {
|
||
|
|
$normalized = $this->positiveInteger($userId);
|
||
|
|
if ($normalized === null) {
|
||
|
|
$errors['user_ids'] = 'Technician IDs must be positive integers.';
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
if (!in_array($normalized, $userIds, true)) {
|
||
|
|
$userIds[] = $normalized;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return [
|
||
|
|
'valid' => $errors === [],
|
||
|
|
'jobcard_id' => $jobcardId,
|
||
|
|
'user_ids' => $userIds,
|
||
|
|
'errors' => $errors,
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
private function positiveInteger(mixed $value): ?int
|
||
|
|
{
|
||
|
|
if (is_int($value)) {
|
||
|
|
return $value > 0 ? $value : null;
|
||
|
|
}
|
||
|
|
if (is_string($value) && preg_match('/^[1-9]\d*$/', $value) === 1) {
|
||
|
|
$integer = filter_var($value, FILTER_VALIDATE_INT);
|
||
|
|
return $integer !== false ? $integer : null;
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
}
|