src/Controller/MondeController.php line 212

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  4. use Symfony\Component\HttpFoundation\Response;
  5. use Symfony\Component\Routing\Annotation\Route;
  6. use Symfony\Component\HttpClient\HttpClient;
  7. use Symfony\Contracts\HttpClient\HttpClientInterface;
  8. use Symfony\Component\HttpFoundation\Request; // Add this import
  9. use Symfony\Component\HttpFoundation\JsonResponse; // Also add this if not present
  10. class MondeController extends AbstractController
  11. {
  12. #[Route('/monde', name: 'blt_monde_all')]
  13. public function monde(): Response
  14. {
  15. $apiUrlCountries = 'https://static-api.didatravel.com/api/v1/region/countries';
  16. $apiUrlDestinations = 'https://static-api.didatravel.com/api/v1/region/destinations';
  17. $username = 'DidaApiTestID';
  18. $password = 'TestKey';
  19. $httpClient = HttpClient::create();
  20. // Step 1: Get all countries
  21. $response = $httpClient->request('GET', $apiUrlCountries, [
  22. 'auth_basic' => [$username, $password],
  23. ]);
  24. $countriesData = [];
  25. $allDestinations = [];
  26. if ($response->getStatusCode() === 200) {
  27. $data = $response->toArray();
  28. // Check if data is in the 'data' key or directly in response
  29. $countries = isset($data['data']) ? $data['data'] : $data;
  30. // Step 2: For each country, get its destinations
  31. foreach ($countries as $country) {
  32. $countryCode = $country['code'];
  33. // Make API call for destinations of this specific country
  34. $destResponse = $httpClient->request('GET', $apiUrlDestinations, [
  35. 'query' => [
  36. 'countryCode' => $countryCode,
  37. 'language' => 'en-US'
  38. ],
  39. 'auth_basic' => [$username, $password],
  40. ]);
  41. $countryDestinations = [];
  42. if ($destResponse->getStatusCode() === 200) {
  43. $destData = $destResponse->toArray();
  44. $countryDestinations = isset($destData['data']) ? $destData['data'] : $destData;
  45. }
  46. // Store country with its destinations
  47. $countriesData[] = [
  48. 'country_code' => $countryCode,
  49. 'country_name' => $country['name'],
  50. 'destinations' => $countryDestinations,
  51. 'destination_count' => count($countryDestinations)
  52. ];
  53. // Add all destinations to the combined list
  54. foreach ($countryDestinations as $destination) {
  55. $destination['country_code'] = $countryCode;
  56. $destination['country_name'] = $country['name'];
  57. $allDestinations[] = $destination;
  58. }
  59. }
  60. }
  61. //dd($countriesData);
  62. return $this->render('blt/monde.html.twig', [
  63. 'countries' => $countriesData,
  64. 'all_destinations' => $allDestinations,
  65. 'total_countries' => count($countriesData),
  66. 'total_destinations' => count($allDestinations)
  67. ]);
  68. }
  69. #[Route('/monde/pays', name: 'blt_monde')]
  70. public function pays(): Response
  71. {
  72. $apiUrlCountries = 'https://static-api.didatravel.com/api/v1/region/countries';
  73. $username = 'DidaApiTestID';
  74. $password = 'TestKey';
  75. $httpClient = HttpClient::create();
  76. // Get all countries
  77. $response = $httpClient->request('GET', $apiUrlCountries, [
  78. 'auth_basic' => [$username, $password],
  79. ]);
  80. $countriesData = [];
  81. if ($response->getStatusCode() === 200) {
  82. $data = $response->toArray();
  83. $countriesData = isset($data['data']) ? $data['data'] : $data;
  84. }
  85. return $this->render('blt/pays.html.twig', [
  86. 'countries' => $countriesData,
  87. 'total_countries' => count($countriesData)
  88. ]);
  89. }
  90. #[Route('/monde/pays/{code}', name: 'blt_monde_pays_details')]
  91. public function paysDetails(string $code): Response
  92. {
  93. $apiUrlCountries = 'https://static-api.didatravel.com/api/v1/region/countries';
  94. $apiUrlDestinations = 'https://static-api.didatravel.com/api/v1/region/destinations';
  95. $username = 'DidaApiTestID';
  96. $password = 'TestKey';
  97. $httpClient = HttpClient::create();
  98. $countryData = null;
  99. $countryDestinations = [];
  100. // First, try to get the specific country if you want to verify it exists
  101. // (The API might not have a single country endpoint, so we'll get all and filter)
  102. $response = $httpClient->request('GET', $apiUrlCountries, [
  103. 'auth_basic' => [$username, $password],
  104. ]);
  105. if ($response->getStatusCode() === 200) {
  106. $data = $response->toArray();
  107. $allCountries = isset($data['data']) ? $data['data'] : $data;
  108. // Find the specific country
  109. foreach ($allCountries as $country) {
  110. if ($country['code'] === strtoupper($code)) {
  111. $countryData = $country;
  112. break;
  113. }
  114. }
  115. }
  116. // If country not found, show 404
  117. if (!$countryData) {
  118. throw $this->createNotFoundException('Pays non trouvé: ' . $code);
  119. }
  120. // Get destinations for this specific country
  121. $destResponse = $httpClient->request('GET', $apiUrlDestinations, [
  122. 'query' => [
  123. 'countryCode' => strtoupper($code),
  124. 'language' => 'en-US'
  125. ],
  126. 'auth_basic' => [$username, $password],
  127. ]);
  128. if ($destResponse->getStatusCode() === 200) {
  129. $destData = $destResponse->toArray();
  130. $countryDestinations = isset($destData['data']) ? $destData['data'] : $destData;
  131. }
  132. //dd($countryDestinations);
  133. return $this->render('blt/pays_details.html.twig', [
  134. 'country' => $countryData,
  135. 'destinations' => $countryDestinations,
  136. 'destination_count' => count($countryDestinations)
  137. ]);
  138. }
  139. #[Route('/monde/hotel/details/{id}', name: 'blt_monde_hotel_details')]
  140. public function hotelDetails(int $id): Response
  141. {
  142. $apiUrlHotelDetails = 'https://static-api.didatravel.com/api/v1/hotel/details';
  143. $username = 'DidaApiTestID';
  144. $password = 'TestKey';
  145. $httpClient = HttpClient::create();
  146. // Prepare the POST request body
  147. $requestData = [
  148. 'language' => 'en-US',
  149. 'hotelIds' => [$id]
  150. ];
  151. // Make POST request to get hotel details
  152. $response = $httpClient->request('POST', $apiUrlHotelDetails, [
  153. 'auth_basic' => [$username, $password],
  154. 'headers' => [
  155. 'Content-Type' => 'application/json',
  156. ],
  157. 'json' => $requestData,
  158. ]);
  159. $hotelDetails = null;
  160. if ($response->getStatusCode() === 200) {
  161. $data = $response->toArray();
  162. $hotelDetails = isset($data['data']) ? $data['data'] : $data;
  163. // If it's an array with one hotel, extract it
  164. if (is_array($hotelDetails) && count($hotelDetails) === 1 && isset($hotelDetails[0])) {
  165. $hotelDetails = $hotelDetails[0];
  166. }
  167. }
  168. if (!$hotelDetails) {
  169. throw $this->createNotFoundException('Détails de l\'hôtel non trouvés pour ID: ' . $id);
  170. }
  171. //dd($hotelDetails);
  172. return $this->render('blt/hotel_details.html.twig', [
  173. 'hotel' => $hotelDetails,
  174. 'hotel_id' => $id
  175. ]);
  176. }
  177. #[Route('/monde/hotel/{code}', name: 'blt_monde_hotel')]
  178. public function hotelParPays(string $code): Response
  179. {
  180. $apiUrlCountries = 'https://static-api.didatravel.com/api/v1/region/countries';
  181. $apiUrlHotels = 'https://static-api.didatravel.com/api/v1/hotel/list';
  182. $username = 'DidaApiTestID';
  183. $password = 'TestKey';
  184. $httpClient = HttpClient::create();
  185. $countryData = null;
  186. $hotelIds = [];
  187. $hotelDetails = [];
  188. $hotelPrices = [];
  189. // First, verify the country exists
  190. $response = $httpClient->request('GET', $apiUrlCountries, [
  191. 'auth_basic' => [$username, $password],
  192. ]);
  193. if ($response->getStatusCode() === 200) {
  194. $data = $response->toArray();
  195. $allCountries = isset($data['data']) ? $data['data'] : $data;
  196. // Find the specific country
  197. foreach ($allCountries as $country) {
  198. if ($country['code'] === strtoupper($code)) {
  199. $countryData = $country;
  200. break;
  201. }
  202. }
  203. }
  204. // If country not found, show 404
  205. if (!$countryData) {
  206. throw $this->createNotFoundException('Pays non trouvé: ' . $code);
  207. }
  208. // Get hotel list for this specific country
  209. $hotelResponse = $httpClient->request('GET', $apiUrlHotels, [
  210. 'query' => [
  211. 'countryCode' => strtoupper($code),
  212. 'language' => 'en-US'
  213. ],
  214. 'auth_basic' => [$username, $password],
  215. ]);
  216. if ($hotelResponse->getStatusCode() === 200) {
  217. $hotelData = $hotelResponse->toArray();
  218. $hotelIds = isset($hotelData['data']) ? $hotelData['data'] : $hotelData;
  219. }
  220. // Limit hotel IDs for testing (API may have rate limits)
  221. //dd($hotelIds);
  222. // Fetch hotel details for limited hotel IDs
  223. if (!empty($hotelIds)) {
  224. $hotelDetails = $this->fetchHotelDetails($hotelIds, $httpClient, $username, $password);
  225. $hotelPrices = $this->fetchHotelPrices($hotelIds, $httpClient, $username, $password);
  226. }
  227. //dd($hotelDetails, $hotelPrices,$hotelIds);
  228. return $this->render('blt/hotelListMonde.html.twig', [
  229. 'country' => $countryData,
  230. 'hotel_ids' => $hotelIds,
  231. 'hotel_details' => $hotelDetails,
  232. 'hotel_prices' => $hotelPrices,
  233. 'hotel_count' => count($hotelIds)
  234. ]);
  235. }
  236. #[Route('/monde/destinations/{destinationId}', name: 'blt_monde_destination_hotels')]
  237. public function hotelsParDestination(int $destinationId): Response
  238. {
  239. $apiUrlPriceSearch = 'https://apiint.didatravel.com/api/rate/pricesearch?$format=json';
  240. $username = 'DidaApiTestID';
  241. $password = 'TestKey';
  242. $httpClient = HttpClient::create();
  243. // Use default dates (next 2 days)
  244. $checkInDate = (new \DateTime('+1 day'))->format('Y-m-d');
  245. $checkOutDate = (new \DateTime('+2 days'))->format('Y-m-d');
  246. // Prepare the POST request body for destination search
  247. $requestData = [
  248. 'Header' => [
  249. 'ClientID' => $username,
  250. 'LicenseKey' => $password
  251. ],
  252. 'CheckInDate' => $checkInDate,
  253. 'CheckOutDate' => $checkOutDate,
  254. 'Destination' => [
  255. 'CityCode' => (string)$destinationId
  256. ],
  257. 'LowestPriceOnly' => true,
  258. 'Nationality' => 'FR',
  259. 'Currency' => 'EUR'
  260. ];
  261. try {
  262. $response = $httpClient->request('POST', $apiUrlPriceSearch, [
  263. 'headers' => [
  264. 'Content-Type' => 'application/json',
  265. ],
  266. 'json' => $requestData,
  267. 'timeout' => 30
  268. ]);
  269. $hotelIds = [];
  270. $hotelPrices = [];
  271. if ($response->getStatusCode() === 200) {
  272. $data = $response->toArray();
  273. if (isset($data['Success']) && isset($data['Success']['PriceDetails']) && isset($data['Success']['PriceDetails']['HotelList'])) {
  274. $hotelsData = $data['Success']['PriceDetails']['HotelList'];
  275. // Extract hotel IDs and organize prices
  276. foreach ($hotelsData as $hotel) {
  277. if (isset($hotel['HotelID'])) {
  278. $hotelId = $hotel['HotelID'];
  279. $hotelIds[] = $hotelId;
  280. // Store price information
  281. $hotelPrices[$hotelId] = [
  282. 'LowestPrice' => $hotel['LowestPrice']['Value'] ?? null,
  283. 'Currency' => $hotel['LowestPrice']['Currency'] ?? 'EUR',
  284. 'CheckInDate' => $checkInDate,
  285. 'CheckOutDate' => $checkOutDate,
  286. 'HotelName' => $hotel['HotelName'] ?? null,
  287. 'ExcludedFeeList' => $hotel['ExcludedFeeList'] ?? []
  288. ];
  289. }
  290. }
  291. }
  292. }
  293. // Fetch hotel details for limited hotel IDs
  294. $hotelDetails = [];
  295. if (!empty($hotelIds)) {
  296. $hotelDetails = $this->fetchHotelDetails($hotelIds, $httpClient, $username, $password);
  297. //dd($hotelIds,$hotelDetails,$hotelPrices);
  298. }
  299. // Create a dummy country object for the template
  300. $countryData = [
  301. 'name' => 'Destination #' . $destinationId,
  302. 'code' => 'DEST' . $destinationId
  303. ];
  304. return $this->render('blt/hotelListMonde.html.twig', [
  305. 'country' => $countryData,
  306. 'hotel_ids' => $hotelIds,
  307. 'hotel_details' => $hotelDetails,
  308. 'hotel_prices' => $hotelPrices, // This already has prices from the first API call!
  309. 'hotel_count' => count($hotelIds)
  310. ]);
  311. } catch (\Exception $e) {
  312. // Handle error
  313. error_log('Error fetching hotels for destination: ' . $e->getMessage());
  314. // Create a dummy country object for the template
  315. $countryData = [
  316. 'name' => 'Destination #' . $destinationId,
  317. 'code' => 'DEST' . $destinationId
  318. ];
  319. return $this->render('blt/hotelListMonde.html.twig', [
  320. 'country' => $countryData,
  321. 'hotel_ids' => [],
  322. 'hotel_details' => [],
  323. 'hotel_prices' => [],
  324. 'hotel_count' => 0,
  325. 'error' => $e->getMessage()
  326. ]);
  327. }
  328. }
  329. #[Route('/monde/test', name: 'monde_test')]
  330. public function test(): Response
  331. {
  332. return new Response('Monde controller is working!');
  333. }
  334. /**
  335. * Fetch hotel details from DidaTravel API
  336. */
  337. private function fetchHotelDetails(array $hotelIds, HttpClientInterface $httpClient, string $username, string $password): array
  338. {
  339. $apiUrlHotelDetails = 'https://static-api.didatravel.com/api/v1/hotel/details';
  340. // Prepare the POST request body
  341. $requestData = [
  342. 'language' => 'en-US',
  343. 'hotelIds' => $hotelIds
  344. ];
  345. try {
  346. $response = $httpClient->request('POST', $apiUrlHotelDetails, [
  347. 'auth_basic' => [$username, $password],
  348. 'headers' => [
  349. 'Content-Type' => 'application/json',
  350. ],
  351. 'json' => $requestData,
  352. 'timeout' => 30 // Increase timeout for multiple hotels
  353. ]);
  354. if ($response->getStatusCode() === 200) {
  355. $data = $response->toArray();
  356. $hotelDetails = isset($data['data']) ? $data['data'] : $data;
  357. // Organize by hotel ID for easy access
  358. $organizedDetails = [];
  359. foreach ($hotelDetails as $detail) {
  360. if (isset($detail['id'])) {
  361. $organizedDetails[$detail['id']] = $detail;
  362. }
  363. }
  364. return $organizedDetails;
  365. }
  366. } catch (\Exception $e) {
  367. // Log error and return empty array
  368. // error_log('Error fetching hotel details: ' . $e->getMessage());
  369. }
  370. return [];
  371. }
  372. /**
  373. * Fetch hotel prices from DidaTravel API
  374. */
  375. /**
  376. * Fetch hotel prices from DidaTravel API
  377. */
  378. private function fetchHotelPrices(array $hotelIds, HttpClientInterface $httpClient, string $username, string $password): array
  379. {
  380. $apiUrlPriceSearch = 'https://apiint.didatravel.com/api/rate/pricesearch?$format=json';
  381. // Use default dates (next 2 days)
  382. $checkInDate = (new \DateTime('+1 day'))->format('Y-m-d');
  383. $checkOutDate = (new \DateTime('+2 days'))->format('Y-m-d');
  384. // Prepare the POST request body
  385. $requestData = [
  386. 'Header' => [
  387. 'ClientID' => $username,
  388. 'LicenseKey' => $password
  389. ],
  390. 'CheckInDate' => $checkInDate,
  391. 'CheckOutDate' => $checkOutDate,
  392. 'HotelIDList' => $hotelIds,
  393. 'LowestPriceOnly' => true,
  394. 'Nationality' => 'FR', // Default to France
  395. 'Currency' => 'EUR' // Default to Euro
  396. ];
  397. try {
  398. $response = $httpClient->request('POST', $apiUrlPriceSearch, [
  399. 'headers' => [
  400. 'Content-Type' => 'application/json',
  401. ],
  402. 'json' => $requestData,
  403. 'timeout' => 30
  404. ]);
  405. if ($response->getStatusCode() === 200) {
  406. $data = $response->toArray();
  407. // Debug: Check the actual response structure
  408. // dd($data);
  409. // Organize by hotel ID for easy access
  410. $organizedPrices = [];
  411. // Check the actual response structure
  412. if (isset($data['Success']) && isset($data['Success']['PriceDetails']) && isset($data['Success']['PriceDetails']['HotelList'])) {
  413. foreach ($data['Success']['PriceDetails']['HotelList'] as $hotelRate) {
  414. if (isset($hotelRate['HotelID'])) {
  415. $organizedPrices[$hotelRate['HotelID']] = [
  416. 'HotelID' => $hotelRate['HotelID'],
  417. 'HotelName' => $hotelRate['HotelName'] ?? null,
  418. 'LowestPrice' => $hotelRate['LowestPrice']['Value'] ?? null,
  419. 'Currency' => $hotelRate['LowestPrice']['Currency'] ?? 'EUR',
  420. 'CheckInDate' => $checkInDate,
  421. 'CheckOutDate' => $checkOutDate,
  422. 'ExcludedFeeList' => $hotelRate['ExcludedFeeList'] ?? []
  423. ];
  424. }
  425. }
  426. }
  427. return $organizedPrices;
  428. }
  429. } catch (\Exception $e) {
  430. // Log error and return empty array
  431. error_log('Error fetching hotel prices: ' . $e->getMessage());
  432. }
  433. return [];
  434. }
  435. #[Route('/monde/recherche-hotels', name: 'blt_monde_hotel_search')]
  436. public function hotelSearch(): Response
  437. {
  438. $apiUrlCountries = 'https://static-api.didatravel.com/api/v1/region/countries';
  439. $username = 'DidaApiTestID';
  440. $password = 'TestKey';
  441. $httpClient = HttpClient::create();
  442. // Get all countries for the dropdown
  443. $response = $httpClient->request('GET', $apiUrlCountries, [
  444. 'auth_basic' => [$username, $password],
  445. ]);
  446. $countriesData = [];
  447. if ($response->getStatusCode() === 200) {
  448. $data = $response->toArray();
  449. $countriesData = isset($data['data']) ? $data['data'] : $data;
  450. }
  451. return $this->render('blt/hotel_search.html.twig', [
  452. 'countries' => $countriesData,
  453. 'total_countries' => count($countriesData),
  454. 'total_destinations' => 0 // You can calculate this if needed
  455. ]);
  456. }
  457. #[Route('/monde/destinationssearch/{countryCode}', name: 'blt_monde_destinations_ajax')]
  458. public function getDestinationsByCountry(string $countryCode): JsonResponse
  459. {
  460. $apiUrlDestinations = 'https://static-api.didatravel.com/api/v1/region/destinations';
  461. $username = 'DidaApiTestID';
  462. $password = 'TestKey';
  463. $httpClient = HttpClient::create();
  464. try {
  465. $response = $httpClient->request('GET', $apiUrlDestinations, [
  466. 'query' => [
  467. 'countryCode' => strtoupper($countryCode),
  468. 'language' => 'en-US'
  469. ],
  470. 'auth_basic' => [$username, $password],
  471. ]);
  472. if ($response->getStatusCode() === 200) {
  473. $data = $response->toArray();
  474. // Check the actual structure of the response
  475. if (isset($data['Header'])) {
  476. // This seems to be an error response format
  477. return $this->json([
  478. 'success' => false,
  479. 'message' => 'API returned unexpected format',
  480. 'data' => []
  481. ]);
  482. }
  483. $destinations = isset($data['data']) ? $data['data'] : $data;
  484. // Format for JSON response
  485. $formattedDestinations = [];
  486. foreach ($destinations as $destination) {
  487. $formattedDestinations[] = [
  488. 'id' => $destination['id'] ?? null,
  489. 'name' => $destination['name'] ?? 'Unknown Destination',
  490. 'type' => $destination['type'] ?? null,
  491. 'code' => $destination['code'] ?? null
  492. ];
  493. }
  494. return $this->json([
  495. 'success' => true,
  496. 'data' => $formattedDestinations
  497. ]);
  498. }
  499. return $this->json([
  500. 'success' => false,
  501. 'message' => 'Failed to fetch destinations',
  502. 'data' => []
  503. ]);
  504. } catch (\Exception $e) {
  505. return $this->json([
  506. 'success' => false,
  507. 'message' => 'Error: ' . $e->getMessage(),
  508. 'data' => []
  509. ]);
  510. }
  511. }
  512. #[Route('/monde/recherche-hotels/resultats', name: 'blt_monde_hotel_search_results')]
  513. public function hotelSearchResults(Request $request): Response
  514. {
  515. $searchType = $request->query->get('searchType', 'country');
  516. $countryCode = $request->query->get('countryCode');
  517. $destinationId = $request->query->get('destinationId');
  518. $checkInDate = $request->query->get('checkInDate');
  519. $checkOutDate = $request->query->get('checkOutDate');
  520. $nationality = $request->query->get('nationality', 'FR');
  521. $currency = $request->query->get('currency', 'EUR');
  522. $username = 'DidaApiTestID';
  523. $password = 'TestKey';
  524. $httpClient = HttpClient::create();
  525. $hotelIds = [];
  526. $hotelDetails = [];
  527. $hotelPrices = [];
  528. $countryData = null;
  529. $destinationData = null;
  530. // If searching by country
  531. if ($searchType === 'country' && $countryCode) {
  532. // First get country info
  533. $apiUrlCountries = 'https://static-api.didatravel.com/api/v1/region/countries';
  534. $countryResponse = $httpClient->request('GET', $apiUrlCountries, [
  535. 'auth_basic' => [$username, $password],
  536. ]);
  537. if ($countryResponse->getStatusCode() === 200) {
  538. $data = $countryResponse->toArray();
  539. $allCountries = isset($data['data']) ? $data['data'] : $data;
  540. foreach ($allCountries as $country) {
  541. if ($country['code'] === strtoupper($countryCode)) {
  542. $countryData = $country;
  543. break;
  544. }
  545. }
  546. }
  547. // Get hotel IDs for country
  548. $apiUrlHotels = 'https://static-api.didatravel.com/api/v1/hotel/list';
  549. $hotelResponse = $httpClient->request('GET', $apiUrlHotels, [
  550. 'query' => [
  551. 'countryCode' => strtoupper($countryCode),
  552. 'language' => 'en-US'
  553. ],
  554. 'auth_basic' => [$username, $password],
  555. ]);
  556. if ($hotelResponse->getStatusCode() === 200) {
  557. $hotelData = $hotelResponse->toArray();
  558. $hotelIds = isset($hotelData['data']) ? $hotelData['data'] : $hotelData;
  559. }
  560. }
  561. // If searching by destination
  562. elseif ($searchType === 'destination' && $destinationId) {
  563. // Get destination details first
  564. $apiUrlDestinations = 'https://static-api.didatravel.com/api/v1/region/destinations';
  565. $destResponse = $httpClient->request('GET', $apiUrlDestinations, [
  566. 'query' => [
  567. 'countryCode' => 'ALL', // Or you might need to pass specific country
  568. 'language' => 'en-US'
  569. ],
  570. 'auth_basic' => [$username, $password],
  571. ]);
  572. if ($destResponse->getStatusCode() === 200) {
  573. $destData = $destResponse->toArray();
  574. $allDestinations = isset($destData['data']) ? $destData['data'] : $destData;
  575. // Find the specific destination
  576. foreach ($allDestinations as $dest) {
  577. if (isset($dest['id']) && $dest['id'] == $destinationId) {
  578. $destinationData = $dest;
  579. break;
  580. }
  581. }
  582. }
  583. // Get hotels by destination using price search API
  584. $apiUrlPriceSearch = 'https://apiint.didatravel.com/api/rate/pricesearch?$format=json';
  585. $requestData = [
  586. 'Header' => [
  587. 'ClientID' => $username,
  588. 'LicenseKey' => $password
  589. ],
  590. 'CheckInDate' => $checkInDate,
  591. 'CheckOutDate' => $checkOutDate,
  592. 'Destination' => [
  593. 'CityCode' => (string)$destinationId
  594. ],
  595. 'LowestPriceOnly' => true,
  596. 'Nationality' => $nationality,
  597. 'Currency' => $currency
  598. ];
  599. try {
  600. $response = $httpClient->request('POST', $apiUrlPriceSearch, [
  601. 'headers' => [
  602. 'Content-Type' => 'application/json',
  603. ],
  604. 'json' => $requestData,
  605. 'timeout' => 30
  606. ]);
  607. if ($response->getStatusCode() === 200) {
  608. $data = $response->toArray();
  609. if (isset($data['Success']) && isset($data['Success']['PriceDetails']) && isset($data['Success']['PriceDetails']['HotelList'])) {
  610. $hotelsData = $data['Success']['PriceDetails']['HotelList'];
  611. foreach ($hotelsData as $hotel) {
  612. if (isset($hotel['HotelID'])) {
  613. $hotelId = $hotel['HotelID'];
  614. $hotelIds[] = $hotelId;
  615. // Store price information
  616. $hotelPrices[$hotelId] = [
  617. 'HotelID' => $hotelId,
  618. 'LowestPrice' => $hotel['LowestPrice']['Value'] ?? null,
  619. 'Currency' => $hotel['LowestPrice']['Currency'] ?? $currency,
  620. 'CheckInDate' => $checkInDate,
  621. 'CheckOutDate' => $checkOutDate,
  622. 'HotelName' => $hotel['HotelName'] ?? null,
  623. 'ExcludedFeeList' => $hotel['ExcludedFeeList'] ?? []
  624. ];
  625. }
  626. }
  627. }
  628. }
  629. } catch (\Exception $e) {
  630. // Handle error
  631. error_log('Error in destination search: ' . $e->getMessage());
  632. }
  633. // Create dummy country data for destination
  634. if ($destinationData) {
  635. $countryData = [
  636. 'name' => $destinationData['name'] ?? 'Destination #' . $destinationId,
  637. 'code' => 'DEST' . $destinationId
  638. ];
  639. } else {
  640. $countryData = [
  641. 'name' => 'Destination #' . $destinationId,
  642. 'code' => 'DEST' . $destinationId
  643. ];
  644. }
  645. }
  646. // Fetch hotel details and prices (if not already fetched for destination search)
  647. if (!empty($hotelIds)) {
  648. if (empty($hotelPrices)) {
  649. // Only fetch prices if not already done (for destination search)
  650. $hotelPrices = $this->fetchHotelPricesWithDates(
  651. $hotelIds,
  652. $httpClient,
  653. $username,
  654. $password,
  655. $checkInDate,
  656. $checkOutDate,
  657. $nationality,
  658. $currency
  659. );
  660. }
  661. $hotelDetails = $this->fetchHotelDetails($hotelIds, $httpClient, $username, $password);
  662. }
  663. return $this->render('blt/hotel_search_results.html.twig', [
  664. 'search_type' => $searchType,
  665. 'country' => $countryData,
  666. 'destination' => $destinationData,
  667. 'hotel_ids' => $hotelIds,
  668. 'hotel_details' => $hotelDetails,
  669. 'hotel_prices' => $hotelPrices,
  670. 'hotel_count' => count($hotelIds),
  671. 'check_in_date' => $checkInDate,
  672. 'check_out_date' => $checkOutDate,
  673. 'nationality' => $nationality,
  674. 'currency' => $currency,
  675. 'search_params' => $request->query->all()
  676. ]);
  677. }
  678. /**
  679. * Fetch hotel prices with specific dates
  680. */
  681. private function fetchHotelPricesWithDates(
  682. array $hotelIds,
  683. HttpClientInterface $httpClient,
  684. string $username,
  685. string $password,
  686. string $checkInDate,
  687. string $checkOutDate,
  688. string $nationality = 'FR',
  689. string $currency = 'EUR'
  690. ): array {
  691. $apiUrlPriceSearch = 'https://apiint.didatravel.com/api/rate/pricesearch?$format=json';
  692. // Limit hotel IDs to avoid timeout (API might have limits)
  693. $limitedHotelIds = array_slice($hotelIds, 0, 10);
  694. $requestData = [
  695. 'Header' => [
  696. 'ClientID' => $username,
  697. 'LicenseKey' => $password
  698. ],
  699. 'CheckInDate' => $checkInDate,
  700. 'CheckOutDate' => $checkOutDate,
  701. 'HotelIDList' => $limitedHotelIds,
  702. 'LowestPriceOnly' => true,
  703. 'Nationality' => $nationality,
  704. 'Currency' => $currency
  705. ];
  706. try {
  707. $response = $httpClient->request('POST', $apiUrlPriceSearch, [
  708. 'headers' => [
  709. 'Content-Type' => 'application/json',
  710. ],
  711. 'json' => $requestData,
  712. 'timeout' => 30
  713. ]);
  714. if ($response->getStatusCode() === 200) {
  715. $data = $response->toArray();
  716. $organizedPrices = [];
  717. if (isset($data['Success']) && isset($data['Success']['PriceDetails']) && isset($data['Success']['PriceDetails']['HotelList'])) {
  718. foreach ($data['Success']['PriceDetails']['HotelList'] as $hotelRate) {
  719. if (isset($hotelRate['HotelID'])) {
  720. $organizedPrices[$hotelRate['HotelID']] = [
  721. 'HotelID' => $hotelRate['HotelID'],
  722. 'HotelName' => $hotelRate['HotelName'] ?? null,
  723. 'LowestPrice' => $hotelRate['LowestPrice']['Value'] ?? null,
  724. 'Currency' => $hotelRate['LowestPrice']['Currency'] ?? $currency,
  725. 'CheckInDate' => $checkInDate,
  726. 'CheckOutDate' => $checkOutDate,
  727. 'ExcludedFeeList' => $hotelRate['ExcludedFeeList'] ?? [],
  728. 'Nationality' => $nationality
  729. ];
  730. }
  731. }
  732. }
  733. return $organizedPrices;
  734. }
  735. } catch (\Exception $e) {
  736. error_log('Error fetching hotel prices with dates: ' . $e->getMessage());
  737. }
  738. return [];
  739. }
  740. }