createNotFoundException('Invalid booking parameters provided'); } $user = $this->getUser(); if ($user instanceof User && false === $user->isProfileComplete()) { $request->getSession()->set(PersonalDataController::SESSION_REDIRECT_KEY, $request->getUri()); return $this->redirectToRoute('app_personal_data'); } return $this->render('booking/create/index.html.twig', [ 'params' => $params, ]); } /** * Initializes a fresh booking session and redirects to the login page. * * This endpoint is triggered via HTMX from the loading page. It clears any * existing booking session, creates a fresh BookingDto, and redirects to * the login page where users can authenticate or continue as guest. * * Optionally accepts an agency code parameter. If provided and valid, the * corresponding agency ID is stored in the booking. If not provided or invalid, * defaults to agency code '0001'. */ #[Route( path: '/bookings/create/init', name: 'app_booking_create_init', )] public function init(Request $request, #[MapQueryString] ?BookingQueryParams $params): Response { if (null === $params) { return $this->htmxRedirect($request, $this->generateUrl('app_booking_create_error')); } $dateId = $params->dateId; $hotelId = $params->hotelId; try { // Clear any existing booking session to ensure fresh start $this->bookingService->clearBookingSession($request); // Determine agency ID from optional query parameter $agencyId = $this->resolveAgencyId($params->agency); // Store optional return URL in session (defaults to main EP site) $this->bookingService->storeReturnUrl($request, $params->returnUrl); // Create fresh booking session with the provided parameters $bookingDto = $this->bookingService->startFreshBooking($request, $dateId, $hotelId, $agencyId); // Warm the CMS cache early so data is available on the login page $this->summaryDataService->getCmsDataForProduct( $bookingDto->travel->productCode, $bookingDto->travel->hotel?->code ); // Redirect to login page (optional authentication before Step 1) return $this->htmxRedirect($request, $this->generateUrl('app_login')); } catch (TravelNotFoundException|HotelNotFoundException|HotelNotInTravelException|NoRoomsAvailableException $e) { $this->addFlash('error', $e->getMessage()); return $this->htmxRedirect($request, $this->generateUrl('app_booking_create_error')); } } /** * Resolves the agency ID from the provided agency code. * * If the code is null or the agency is not found, returns the default agency ID. * * @param string|null $agencyCode The agency code from the request parameter * * @return int|null The agency ID, or null if default agency not found */ private function resolveAgencyId(?string $agencyCode): ?int { // Use default agency if no code provided if (null === $agencyCode || '' === trim($agencyCode)) { $defaultAgency = $this->agencyLoader->loadDefault(); return $defaultAgency?->id; } // Try to find agency by provided code $agency = $this->agencyLoader->loadByCode($agencyCode); // Fall back to default agency if code not found if (null === $agency) { $defaultAgency = $this->agencyLoader->loadDefault(); return $defaultAgency?->id; } return $agency->id; } /** * Cancels the active booking session and returns to the appropriate page. * * This endpoint allows users to exit the booking flow at any time by * clearing the booking session data and redirecting them appropriately: * - Logged-in users: redirected to account dashboard * - Guest users: redirected to the return URL (stored during booking init) */ #[Route('/bookings/cancel', name: 'app_booking_cancel')] public function cancel(Request $request): Response { if (Request::METHOD_POST === $request->getMethod()) { // Get return URL before clearing session (for guest users) $returnUrl = $this->bookingService->getReturnUrl($request); // Clear the booking session $this->bookingService->clearBookingSession($request); // Clear the security target path to prevent redirect loop after login // Without this, logging in after cancel would redirect back to a stale booking URL $request->getSession()->remove('_security.main.target_path'); // Redirect to account dashboard if logged in, otherwise to return URL // Use htmxRedirect to ensure full page navigation so flash messages are displayed if (null !== $this->getUser()) { $this->addFlash('info', 'Buchung abgebrochen.'); return $this->htmxRedirect($request, $this->generateUrl('app_account')); } // Use htmxRedirect for cross-origin safety (returnUrl may be external) return $this->htmxRedirect($request, $returnUrl); } return $this->render('booking/create/modal_cancel.html.twig'); } /** * Displays user-friendly error messages for booking initialization failures. * * This endpoint provides a centralized location for displaying booking errors * with appropriate error messages and guidance for users. */ #[Route('/bookings/create/error', name: 'app_booking_create_error')] public function error(Request $request): Response { return $this->render('booking/create/error.html.twig', [ 'returnUrl' => $this->bookingService->getReturnUrl($request), ]); } }