169 lines
4.8 KiB
PHP
169 lines
4.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Service;
|
|
|
|
use App\Exception\BookingSessionNotFoundException;
|
|
use App\Form\Model\BookingDto;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
|
|
/**
|
|
* Owns booking-flow session state.
|
|
*
|
|
* This service keeps the HTTP session concerns separate from booking
|
|
* orchestration and pricing logic. It handles DTO persistence, baseline
|
|
* room snapshots, and return URL storage for the booking create/edit flows.
|
|
*/
|
|
class BookingSessionService
|
|
{
|
|
public const BOOKING_CREATE_KEY = 'booking_create';
|
|
public const BOOKING_CREATE_BASELINE_KEY = 'booking_create_baseline_snapshot';
|
|
public const BOOKING_EDIT_KEY = 'booking_edit';
|
|
public const RETURN_URL_KEY = 'booking_return_url';
|
|
public const DEFAULT_RETURN_URL = 'https://www.ep-reisen.de';
|
|
|
|
public function __construct(
|
|
private readonly TravelDataService $travelDataService,
|
|
) {
|
|
}
|
|
|
|
/**
|
|
* Retrieves the booking creation DTO from the session.
|
|
*
|
|
* @throws BookingSessionNotFoundException
|
|
*/
|
|
public function getOrCreateBookingCreateDto(Request $request): BookingDto
|
|
{
|
|
$bookingDto = $this->getBookingDto($request, BookingDto::MODE_CREATE);
|
|
|
|
if (null !== $bookingDto) {
|
|
return $bookingDto;
|
|
}
|
|
|
|
throw new BookingSessionNotFoundException();
|
|
}
|
|
|
|
/**
|
|
* Gets or creates the baseline room selection snapshot for change detection.
|
|
*/
|
|
public function getOrCreateBaselineSnapshot(Request $request, BookingDto $bookingCreateDto): array
|
|
{
|
|
$baselineKey = self::BOOKING_CREATE_BASELINE_KEY;
|
|
|
|
if (!$request->getSession()->has($baselineKey) || $request->query->has('reset_baseline')) {
|
|
$baseline = $bookingCreateDto->createRoomSelectionSnapshot();
|
|
$request->getSession()->set($baselineKey, $baseline);
|
|
|
|
return $baseline;
|
|
}
|
|
|
|
return $request->getSession()->get($baselineKey);
|
|
}
|
|
|
|
/**
|
|
* Clears the baseline snapshot from the session.
|
|
*/
|
|
public function clearBaselineSnapshot(Request $request): void
|
|
{
|
|
$request->getSession()->remove(self::BOOKING_CREATE_BASELINE_KEY);
|
|
}
|
|
|
|
/**
|
|
* Saves the booking DTO to the session.
|
|
*/
|
|
public function saveBookingDto(Request $request, BookingDto $bookingDto, string $mode): void
|
|
{
|
|
$sessionKey = $this->getSessionKey($mode);
|
|
$request->getSession()->set($sessionKey, $bookingDto);
|
|
}
|
|
|
|
/**
|
|
* Retrieves the booking DTO from the session and restores the Travel object.
|
|
*/
|
|
public function getBookingDto(Request $request, string $mode): ?BookingDto
|
|
{
|
|
$sessionKey = $this->getSessionKey($mode);
|
|
$session = $request->getSession();
|
|
|
|
if (false === $session->has($sessionKey)) {
|
|
return null;
|
|
}
|
|
|
|
$bookingDto = $session->get($sessionKey);
|
|
$this->hydrate($bookingDto);
|
|
|
|
return $bookingDto;
|
|
}
|
|
|
|
/**
|
|
* Clears the booking DTO from the session.
|
|
*/
|
|
public function clearBookingDto(Request $request, string $mode): void
|
|
{
|
|
$sessionKey = $this->getSessionKey($mode);
|
|
$request->getSession()->remove($sessionKey);
|
|
}
|
|
|
|
/**
|
|
* Clears all booking-related session data except the return URL.
|
|
*/
|
|
public function clearBookingSession(Request $request): void
|
|
{
|
|
$session = $request->getSession();
|
|
$session->remove(self::BOOKING_CREATE_KEY);
|
|
$session->remove(self::BOOKING_CREATE_BASELINE_KEY);
|
|
}
|
|
|
|
/**
|
|
* Stores the return URL in the session.
|
|
*/
|
|
public function storeReturnUrl(Request $request, ?string $returnUrl): void
|
|
{
|
|
$url = self::DEFAULT_RETURN_URL;
|
|
|
|
if (null !== $returnUrl && '' !== trim($returnUrl)) {
|
|
if (false !== filter_var($returnUrl, \FILTER_VALIDATE_URL)
|
|
&& 1 === preg_match('#^https?://#i', $returnUrl)) {
|
|
$url = $returnUrl;
|
|
}
|
|
}
|
|
|
|
$request->getSession()->set(self::RETURN_URL_KEY, $url);
|
|
}
|
|
|
|
/**
|
|
* Retrieves the return URL from the session.
|
|
*/
|
|
public function getReturnUrl(Request $request): string
|
|
{
|
|
return $request->getSession()->get(self::RETURN_URL_KEY, self::DEFAULT_RETURN_URL);
|
|
}
|
|
|
|
private function getSessionKey(string $mode): string
|
|
{
|
|
return BookingDto::MODE_EDIT === $mode ? self::BOOKING_EDIT_KEY : self::BOOKING_CREATE_KEY;
|
|
}
|
|
|
|
/**
|
|
* Restores the full Travel object after session deserialization.
|
|
*/
|
|
private function hydrate(BookingDto $bookingDto): void
|
|
{
|
|
$travel = $this->travelDataService->getTravelData(
|
|
$bookingDto->travel->id,
|
|
$bookingDto->hotelId
|
|
);
|
|
|
|
if (null === $travel) {
|
|
return;
|
|
}
|
|
|
|
$bookingDto->travel = $travel;
|
|
|
|
if (null !== $bookingDto->booking) {
|
|
$bookingDto->booking->travelData = $travel;
|
|
}
|
|
}
|
|
}
|