wip: booking process
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace App\Controller\Api;
|
||||
|
||||
use App\BusProNet\ApiClient;
|
||||
use App\BusProNet\Exception\ApiClientException;
|
||||
use App\BusProNet\Model\Travel;
|
||||
use App\BusProNet\Utility\TravelCodeUtility;
|
||||
use App\BusProNet\XmlLoader\HotelLoader;
|
||||
@@ -11,6 +13,7 @@ use Psr\Cache\InvalidArgumentException;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Attribute\MapDateTime;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
use Symfony\Contracts\Cache\CacheInterface;
|
||||
@@ -24,6 +27,7 @@ class TravelController extends AbstractController
|
||||
private readonly TravelLoader $travelXmlLoader,
|
||||
private readonly HotelLoader $hotelXmlLoader,
|
||||
private readonly PickupLoader $pickupXmlLoader,
|
||||
private readonly ApiClient $apiClient,
|
||||
private readonly CacheInterface $cache,
|
||||
) {
|
||||
}
|
||||
@@ -49,6 +53,38 @@ class TravelController extends AbstractController
|
||||
return $this->json($travel, Response::HTTP_OK, [], ['groups' => ['api:list', 'api:single']]);
|
||||
}
|
||||
|
||||
#[Route(
|
||||
path: '/travels/{travelId}/remote',
|
||||
name: 'api_travel_single_id_remote',
|
||||
requirements: ['travelId' => '\d+'],
|
||||
)]
|
||||
public function singleByIdRemote(int $travelId): JsonResponse
|
||||
{
|
||||
$cacheKey = sprintf('bpn_travel_remote_%d', $travelId);
|
||||
|
||||
try {
|
||||
$result = $this->cache->get($cacheKey, function (ItemInterface $item) use ($travelId) {
|
||||
$item->expiresAfter(300); // 5 minutes cache for remote API calls
|
||||
|
||||
try {
|
||||
return $this->apiClient->getTravelData($travelId);
|
||||
} catch (ApiClientException $e) {
|
||||
// Return error info instead of throwing to avoid cache wrapping issues
|
||||
return ['error' => $e->getMessage(), 'type' => 'api_error'];
|
||||
}
|
||||
});
|
||||
|
||||
// Check if result is an error
|
||||
if (is_array($result) && isset($result['error'], $result['type'])) {
|
||||
return $this->json($result['error'], Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
return $this->json($result, Response::HTTP_OK, [], ['groups' => ['api:list', 'api:single']]);
|
||||
} catch (InvalidArgumentException) {
|
||||
return $this->json('Cache error occurred', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
#[Route(
|
||||
path: '/travels/{travelCode}/{hotelCode}',
|
||||
name: 'api_travel_single_code',
|
||||
@@ -63,7 +99,7 @@ class TravelController extends AbstractController
|
||||
$hotelId = $hotelCode ? $this->hotelXmlLoader->mapCodeToId($travelCode) : null;
|
||||
|
||||
if (null === $travelId) {
|
||||
return new JsonResponse(['message' => 'Not found'], Response::HTTP_NOT_FOUND);
|
||||
return $this->json(['message' => 'Not found'], Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$travel = $this->loadCached($travelId, $hotelId);
|
||||
@@ -71,29 +107,47 @@ class TravelController extends AbstractController
|
||||
return $this->json($travel, Response::HTTP_OK, [], ['groups' => ['api:list', 'api:single']]);
|
||||
}
|
||||
|
||||
#[Route('/travels/{travelId}/{hotelId}/{dateTo}/availability', name: 'api_travel_hotel_availability')]
|
||||
public function hotelAvailability(
|
||||
int $travelId,
|
||||
int $hotelId,
|
||||
#[MapDateTime(format: 'Y-m-d')] \DateTimeImmutable $dateTo
|
||||
): JsonResponse {
|
||||
try {
|
||||
$result = $this->apiClient->getHotelAvailability($travelId, $hotelId, $dateTo);
|
||||
|
||||
return $this->json($result);
|
||||
} catch (ApiClientException $e) {
|
||||
return $this->json(['error' => $e->getMessage(), 'type' => 'api_error']);
|
||||
}
|
||||
}
|
||||
|
||||
private function loadCached(int $travelId, ?int $hotelId = null): ?Travel
|
||||
{
|
||||
$cacheKey = sprintf('bpn_travel_%d_%d', $travelId, $hotelId ?? 0);
|
||||
|
||||
try {
|
||||
$travel = $this->cache->get($cacheKey, function (ItemInterface $item) use ($travelId, $hotelId) {
|
||||
return $this->cache->get($cacheKey, function (ItemInterface $item) use ($travelId, $hotelId) {
|
||||
$item->expiresAfter(60);
|
||||
|
||||
$travel = $this->travelXmlLoader->loadById($travelId, $hotelId);
|
||||
try {
|
||||
$travel = $this->travelXmlLoader->loadById($travelId, $hotelId);
|
||||
|
||||
if (null === $travel) {
|
||||
return new JsonResponse(['message' => 'Not found'], Response::HTTP_NOT_FOUND);
|
||||
if (null === $travel) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->pickupXmlLoader->patchPickupsDetails($travel);
|
||||
$this->hotelXmlLoader->patchHotelDetails($travel);
|
||||
|
||||
return $travel;
|
||||
} catch (\Exception) {
|
||||
// Return null for any loader exceptions to avoid cache wrapping issues
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->pickupXmlLoader->patchPickupsDetails($travel);
|
||||
$this->hotelXmlLoader->patchHotelDetails($travel);
|
||||
|
||||
return $travel;
|
||||
});
|
||||
} catch (InvalidArgumentException $e) {
|
||||
$travel = null;
|
||||
} catch (InvalidArgumentException) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $travel;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user