resolveDto($request, false); if ($dto instanceof Response) { return $dto; } $accommodation = $this->loadAccommodationOrFail($dto); $services = $this->bookingService->loadAvailableServices($dto, $accommodation); if ($request->isMethod(Request::METHOD_POST)) { $inquiryForm = $this->createForm(AccommodationInquiryConfirmationType::class); $inquiryForm->handleRequest($request); if (!$inquiryForm->isSubmitted() || !$inquiryForm->isValid()) { throw $this->createAccessDeniedException('Invalid CSRF token.'); } $dto->forceInquiry = true; $this->persistBooking($request, $dto, $accommodation, $services); return $this->redirectToRoute('app_groups_booking_success'); } $ctx = new AccommodationBookingContext( accommodation: $accommodation, hotelCmsData: $this->bookingService->loadHotelCmsData($accommodation), boardServices: $services['boardServices'], additionalServices: $services['additionalServices'], priceBreakdown: $dto->priceBreakdown ?: null, ); return $this->render('groups/booking/step_4.html.twig', [ 'dto' => $dto, 'ctx' => $ctx, ]); } #[Route('/groups/booking/step-4/confirm-inquiry', name: 'app_groups_booking_step_4_confirm_inquiry', methods: ['GET'])] public function confirmInquiry(Request $request): Response { $dto = $this->resolveDto($request, true); if ($dto instanceof Response) { return $dto; } $inquiryForm = $this->createForm(AccommodationInquiryConfirmationType::class); return $this->render('groups/booking/_step4_inquiry_confirmation_modal.html.twig', [ 'inquiryForm' => $inquiryForm, ]); } #[Route('/groups/booking/step-4/confirm', name: 'app_groups_booking_step_4_confirm', methods: ['GET', 'POST'])] public function confirm(Request $request): Response { $dto = $this->resolveDto($request, true); if ($dto instanceof Response) { return $dto; } $accommodation = $this->loadAccommodationOrFail($dto); $confirmationForm = $this->createForm(AccommodationBookingConfirmationType::class, $dto, [ 'terms_url' => $this->termsUrlProvider->forAccommodation($accommodation), ]); $confirmationForm->handleRequest($request); if ($confirmationForm->isSubmitted() && $confirmationForm->isValid()) { $services = $this->bookingService->loadAvailableServices($dto, $accommodation); $this->persistBooking($request, $dto, $accommodation, $services); return $this->htmxRedirect($request, $this->generateUrl('app_groups_booking_success')); } return $this->render('groups/booking/_step4_booking_confirmation_modal.html.twig', [ 'confirmationForm' => $confirmationForm, ]); } /** * Loads the session DTO and checks step access, returning an early * response (session failure or step-access redirect) if either fails. */ private function resolveDto(Request $request, bool $htmx): AccommodationBookingDto|Response { try { $dto = $this->sessionManager->getOrFail($request); } catch (AccommodationSessionNotFoundException $e) { return $this->createFailureResponse($e, $htmx); } if ($redirect = $this->validateStepAccess($dto, 4)) { return $redirect; } return $dto; } private function loadAccommodationOrFail(AccommodationBookingDto $dto): Accommodation { $accommodation = $this->bookingService->loadAccommodation($dto->accommodationId); if (null === $accommodation) { throw $this->createNotFoundException(); } return $accommodation; } /** * @param array{ * boardServices: BoardService[], * additionalServices: AdditionalService[], * groupedAdditionalServices: array, * ungroupedAdditionalServices: AdditionalService[] * } $services */ private function persistBooking(Request $request, AccommodationBookingDto $dto, Accommodation $accommodation, array $services): void { $prices = $this->bookingService->loadPrices($dto, $accommodation); $booking = $this->bookingService->finalizeBooking($dto, $accommodation, $prices, $services); $this->addFlash('groups_booking_result', $booking->getType()->value); $this->sessionManager->clear($request); } }