Files
myep/src/Validator/Constraints/MandatoryAdditionalServicesSelectedValidator.php
T
2026-04-16 13:34:54 +02:00

86 lines
2.9 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Validator\Constraints;
use App\BusProNet\Constants;
use App\BusProNet\Model\Service;
use App\Form\Model\ParticipantEditDto;
use App\Form\Service\ServiceAgeEvaluator;
use App\Service\ParticipantEligibilityChecker;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* Enforces selection of age-eligible mandatory additional services.
*/
class MandatoryAdditionalServicesSelectedValidator extends ConstraintValidator
{
public function __construct(
private readonly ParticipantEligibilityChecker $participantEligibilityService,
private readonly ServiceAgeEvaluator $serviceAgeEvaluator,
) {
}
public function validate(mixed $value, Constraint $constraint): void
{
if (false === $constraint instanceof MandatoryAdditionalServicesSelected) {
throw new UnexpectedTypeException($constraint, MandatoryAdditionalServicesSelected::class);
}
if (false === $value instanceof ParticipantEditDto) {
throw new UnexpectedTypeException($value, ParticipantEditDto::class);
}
$participant = $value->participant;
if (true === $participant->isCanceled()) {
return;
}
$participantIndex = $participant->index ?? 0;
if (false === $this->participantEligibilityService->isParticipantEligible($value->bookingContext, $participantIndex)) {
return;
}
$mandatoryAdditionalServices = array_filter(
$value->bookingContext->travel->getAdditionalServicesBySubTypes(Constants::TOKEN_ADDITIONAL),
function (Service $service) use ($value, $participantIndex): bool {
if (true !== $service->mandatory) {
return false;
}
if (true === $this->serviceAgeEvaluator->canEvaluate($service)) {
return $this->serviceAgeEvaluator->isServiceAvailableForParticipant(
$service,
$value->bookingContext,
$participantIndex
);
}
return true;
}
);
if (true === empty($mandatoryAdditionalServices)) {
return;
}
$selectedAdditionalServiceIds = array_map(
static fn (Service $service): int => $service->id,
$participant->additionalServices
);
foreach ($mandatoryAdditionalServices as $mandatoryService) {
if (false === in_array($mandatoryService->id, $selectedAdditionalServiceIds, true)) {
$this->context->buildViolation($constraint->message)
->atPath('participant.additionalServices')
->addViolation();
return;
}
}
}
}