$submittedData The submitted participant form data * @param int $participantIndex The index of the participant being processed * * @return bool Always returns true for insurance selection fields */ public function shouldProcess(array $submittedData, int $participantIndex): bool { return true; // Always process to handle deselection cases } /** * Processes the insurance field for a specific participant. * * This method handles both explicit insurance selection from form data and automatic * reassignment when the participant's travel price changes. It distinguishes between: * 1. New selection: User explicitly changed their insurance choice * 2. Resubmission: Form resubmitted with existing insurance (e.g., after adding rentals) * * For resubmissions, it checks if the current insurance is still eligible with updated * participant data and automatically reassigns to the correct price tier if needed. * * @param array $submittedData The submitted participant form data * @param BookingDtoInterface $bookingDto The booking DTO to update (create or edit) * @param int $participantIndex The index of the participant being processed */ public function processField(array $submittedData, BookingDtoInterface $bookingDto, int $participantIndex): void { $participant = $bookingDto->getParticipant($participantIndex); if (null === $participant || !$bookingDto instanceof BookingCreateDto) { return; } $selectedInsuranceId = $this->getFieldValue($submittedData, $this->getFieldName()); $currentInsurance = $participant->insurance; $availableInsurances = $bookingDto->travel->insurances ?? []; // Determine if this is a new user selection or just form resubmission $isNewSelection = null !== $selectedInsuranceId && (null === $currentInsurance || !$this->isSameInsurance($selectedInsuranceId, $currentInsurance)); // Handle explicit new insurance selection from user if ($isNewSelection) { $selectedInsurance = $this->findInsuranceById($availableInsurances, $selectedInsuranceId); if (null !== $selectedInsurance) { $eligibleInsurances = $this->insuranceMatchingService->getEligibleInsurances($availableInsurances, $participant, $bookingDto); $isSelectedInsuranceEligible = $this->isInsuranceInList($selectedInsurance, $eligibleInsurances); if ($isSelectedInsuranceEligible) { // New selection is eligible - use it $participant->insurance = $selectedInsurance; } else { // New selection is not eligible - try to find alternative in same type $reassignedInsurance = $this->insuranceMatchingService->reassignInsuranceForPriceChange( $availableInsurances, $selectedInsurance, $participant, $bookingDto ); $participant->insurance = $reassignedInsurance; } } else { // Insurance not found - clear selection $participant->insurance = null; } return; } // Handle form resubmission with existing insurance (automatic reassignment check) if (null !== $currentInsurance && null !== $selectedInsuranceId) { // Check if current insurance is still eligible with updated participant data $eligibleInsurances = $this->insuranceMatchingService->getEligibleInsurances($availableInsurances, $participant, $bookingDto); $isCurrentInsuranceStillEligible = $this->isInsuranceInList($currentInsurance, $eligibleInsurances); if (!$isCurrentInsuranceStillEligible) { // Current insurance no longer eligible - try to reassign to same type with new price tier $reassignedInsurance = $this->insuranceMatchingService->reassignInsuranceForPriceChange( $availableInsurances, $currentInsurance, $participant, $bookingDto ); $participant->insurance = $reassignedInsurance; // null if no suitable match found } return; } // Handle explicit deselection (user removed insurance) if (null === $selectedInsuranceId) { $participant->insurance = null; } } /** * Returns field state modifications that should be applied after processing. * * Currently no field state modifications are needed for insurance selection. * * @param array $submittedData The submitted participant form data * @param BookingDtoInterface $bookingDto The booking DTO (potentially modified by processing) * @param int $participantIndex The participant index being processed * * @return array> Empty array - no field state modifications */ public function getFieldStateModifications(array $submittedData, BookingDtoInterface $bookingDto, int $participantIndex): array { return []; } /** * Returns field names whose state is affected by this handler's processing. * * Currently no other fields are affected by insurance selection. * * @return string[] Empty array - no other fields are affected */ public function getAffectedFieldNames(): array { return []; } /** * Finds an insurance by ID from the available insurances array. * * @param array $insurances Array of available insurances * @param string|int $insuranceId The insurance ID to find * * @return Insurance|null The found insurance or null if not found */ private function findInsuranceById(array $insurances, string|int $insuranceId): ?Insurance { foreach ($insurances as $insurance) { if ($insurance->id === $insuranceId || (string) $insurance->id === (string) $insuranceId) { return $insurance; } } return null; } /** * Checks if a specific insurance exists in a list of insurances. * * @param Insurance $targetInsurance The insurance to find * @param array $insuranceList The list to search in * * @return bool True if the insurance is found in the list */ private function isInsuranceInList(Insurance $targetInsurance, array $insuranceList): bool { foreach ($insuranceList as $insurance) { if ($insurance->id === $targetInsurance->id || (string) $insurance->id === (string) $targetInsurance->id) { return true; } } return false; } /** * Checks if the submitted insurance ID matches the current insurance. * * This is used to distinguish between a new user selection and a form resubmission * with the existing insurance selection (e.g., when user adds rentals that change travel price). * * @param string|int $selectedInsuranceId The insurance ID from form submission * @param Insurance $currentInsurance The currently assigned insurance from DTO * * @return bool True if they represent the same insurance */ private function isSameInsurance(string|int $selectedInsuranceId, Insurance $currentInsurance): bool { return (string) $currentInsurance->id === (string) $selectedInsuranceId; } }