diff --git a/src/Controller/Booking/Create/IndexController.php b/src/Controller/Booking/Create/IndexController.php
index f62d596..fef1626 100644
--- a/src/Controller/Booking/Create/IndexController.php
+++ b/src/Controller/Booking/Create/IndexController.php
@@ -138,7 +138,8 @@ class IndexController extends AbstractController
return $this->redirectToRoute('app_account');
}
- return $this->redirect($returnUrl);
+ // Use htmxRedirect for cross-origin safety (returnUrl may be external)
+ return $this->htmxRedirect($request, $returnUrl);
}
return $this->render('booking/modal_cancel.html.twig');
diff --git a/src/Controller/Booking/Create/Step2Controller.php b/src/Controller/Booking/Create/Step2Controller.php
index e155796..b31c178 100644
--- a/src/Controller/Booking/Create/Step2Controller.php
+++ b/src/Controller/Booking/Create/Step2Controller.php
@@ -108,6 +108,7 @@ class Step2Controller extends AbstractController
'bookingDto' => $bookingCreateDto,
'cardsData' => $cardsData,
'summaryData' => $summaryData,
+ 'isSubmitted' => $form->isSubmitted(),
];
return $this->render('booking/create/step_2.html.twig', $templateData);
@@ -123,7 +124,11 @@ class Step2Controller extends AbstractController
)]
public function editParticipant(int $index, Request $request): Response
{
- $bookingDto = $this->loadBookingDtoOrFail($request, BookingDto::MODE_CREATE);
+ $result = $this->loadBookingDtoOrRedirect($request, BookingDto::MODE_CREATE);
+ if ($result instanceof Response) {
+ return $result;
+ }
+ $bookingDto = $result;
// Validate participant index
if (false === isset($bookingDto->participants[$index])) {
@@ -178,7 +183,11 @@ class Step2Controller extends AbstractController
)]
public function refreshParticipantForm(int $index, Request $request): Response
{
- $bookingDto = $this->loadBookingDtoOrFail($request, BookingDto::MODE_CREATE);
+ $result = $this->loadBookingDtoOrRedirect($request, BookingDto::MODE_CREATE);
+ if ($result instanceof Response) {
+ return $result;
+ }
+ $bookingDto = $result;
// Validate participant index
if (false === isset($bookingDto->participants[$index])) {
diff --git a/src/Controller/Booking/Traits/BookingExceptionHandlerTrait.php b/src/Controller/Booking/Traits/BookingExceptionHandlerTrait.php
index 15f369b..40f3e0a 100644
--- a/src/Controller/Booking/Traits/BookingExceptionHandlerTrait.php
+++ b/src/Controller/Booking/Traits/BookingExceptionHandlerTrait.php
@@ -34,7 +34,7 @@ trait BookingExceptionHandlerTrait
try {
return $bookingService->getOrCreateBookingCreateDto($request);
} catch (BookingSessionNotFoundException $e) {
- $this->addFlash('error', 'Ihre Buchungssitzung ist abgelaufen. Bitte starten Sie eine neue Buchung.');
+ $this->addFlash('error', 'Deine Buchungssitzung ist abgelaufen. Bitte starte eine neue Buchung.');
return $this->redirectToRoute('app_booking_create_error');
} catch (TravelNotFoundException $e) {
diff --git a/src/Controller/Booking/Traits/ParticipantCardFlowTrait.php b/src/Controller/Booking/Traits/ParticipantCardFlowTrait.php
index 97b43be..403a1a5 100644
--- a/src/Controller/Booking/Traits/ParticipantCardFlowTrait.php
+++ b/src/Controller/Booking/Traits/ParticipantCardFlowTrait.php
@@ -8,6 +8,7 @@ use App\Form\BookingParticipantType;
use App\Form\Model\BookingDto;
use App\Form\Model\ParticipantEditDto;
use Symfony\Component\Form\FormInterface;
+use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
@@ -20,16 +21,18 @@ use Symfony\Component\HttpFoundation\Response;
trait ParticipantCardFlowTrait
{
/**
- * Load BookingDto from session or throw exception.
+ * Load BookingDto from session or return redirect to login.
*
- * @throws \RuntimeException When booking data not found in session
+ * Returns RedirectResponse when session data is missing (e.g., after cancel or session expiry).
*/
- private function loadBookingDtoOrFail(Request $request, string $mode): BookingDto
+ private function loadBookingDtoOrRedirect(Request $request, string $mode): BookingDto|RedirectResponse
{
$bookingDto = $this->bookingService->getBookingDto($request, $mode);
if (null === $bookingDto) {
- throw new \RuntimeException(sprintf('Booking data not found in session for mode: %s', $mode));
+ $this->addFlash('info', 'Deine Sitzung ist abgelaufen. Bitte starte eine neue Buchung.');
+
+ return $this->redirectToRoute('app_login');
}
return $bookingDto;
@@ -183,4 +186,6 @@ trait ParticipantCardFlowTrait
abstract private function render(string $view, array $parameters = [], ?Response $response = null): Response;
abstract protected function addFlash(string $type, mixed $message): void;
+
+ abstract protected function redirectToRoute(string $route, array $parameters = [], int $status = 302): RedirectResponse;
}
diff --git a/src/Htmx/HxTrait.php b/src/Htmx/HxTrait.php
index 0e3fcf5..616a372 100644
--- a/src/Htmx/HxTrait.php
+++ b/src/Htmx/HxTrait.php
@@ -4,10 +4,11 @@ declare(strict_types=1);
namespace App\Htmx;
+use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
/**
- * Trait providing HTMX Out-of-Band swap functionality for controllers.
+ * Trait providing HTMX functionality for controllers.
*/
trait HxTrait
{
@@ -46,4 +47,23 @@ trait HxTrait
return $response;
}
+
+ /**
+ * Creates a redirect response that works correctly with HTMX requests.
+ *
+ * For HTMX requests, returns a 200 response with HX-Redirect header,
+ * which triggers a full page navigation (avoiding CORS issues with cross-origin redirects).
+ * For regular requests, returns a standard HTTP redirect.
+ */
+ protected function htmxRedirect(Request $request, string $url): Response
+ {
+ if ($request->headers->has('HX-Request')) {
+ $response = new Response('', Response::HTTP_OK);
+ $response->headers->set('HX-Redirect', $url);
+
+ return $response;
+ }
+
+ return $this->redirect($url);
+ }
}
diff --git a/templates/booking/create/error.html.twig b/templates/booking/create/error.html.twig
index 7b5b9b4..540cf6a 100644
--- a/templates/booking/create/error.html.twig
+++ b/templates/booking/create/error.html.twig
@@ -12,7 +12,8 @@
messages: errorMessages
} %}
-
+ {# hx-boost disabled for cross-origin #}
+
Zurück
diff --git a/templates/booking/create/success.html.twig b/templates/booking/create/success.html.twig
index 85f03a2..664d679 100644
--- a/templates/booking/create/success.html.twig
+++ b/templates/booking/create/success.html.twig
@@ -47,8 +47,8 @@
{% else %}
- {# Guest user - show simple homepage link #}
-
+ {# Guest user - show simple homepage link (hx-boost disabled for cross-origin) #}
+
Zurück
{% endif %}