createNotFoundException('Invalid booking parameters provided'); } $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); // Store theme for consistent styling throughout the booking flow $this->bookingService->storeTheme($request, $params->theme); // 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->redirectToRoute('app_login'); } catch (TravelNotFoundException) { throw $this->createNotFoundException(sprintf('Travel not found for date ID %d', $dateId)); } catch (HotelNotFoundException) { throw $this->createNotFoundException(sprintf('Hotel not found for hotel ID %d', $hotelId)); } catch (HotelNotInTravelException) { throw $this->createNotFoundException(sprintf('Hotel ID %d is not available for travel ID %d', $hotelId, $dateId)); } catch (NoRoomsAvailableException) { throw $this->createNotFoundException('No rooms available for this travel.'); } } /** * 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), ]); } }