PluginProbe
Yatra – Travel Booking & Tour Operator Software / trunk
Yatra – Travel Booking & Tour Operator Software vtrunk
3.0.15 3.0.14 3.0.14.1 3.0.14.2 3.0.12 3.0.13 3.0.11 3.0.10 3.0.9 3.0.8 3.0.7 3.0.6 3.0.5 3.0.5.1 3.0.4 3.0.3 3.0.2.9 3.0.2.7 3.0.2.8 3.0.2.6 trunk 1.0.0 2.0.0 2.0.1 2.0.10 All 83 releases
← All changes | app/Controllers/TripAvailabilityController.php +63 -5 3.0.14.2trunk View file →
@@ -197,8 +197,26 @@
197 197 // DEPARTURES ENDPOINTS
198 198 // =========================================================================
199 199
200 200 /**
201 + * Sanitised pagination for the departure list endpoints.
202 + *
203 + * Returns [page, per_page]. per_page is 0 when the caller did not ask for
204 + * pagination, so the list keeps returning every matching row for
205 + * consumers that never sent it (the previous behaviour); page is always
206 + * >= 1. Only when per_page > 0 is a LIMIT / OFFSET window applied.
207 + *
208 + * @return array{0: int, 1: int}
209 + */
210 + private function paginationParams(WP_REST_Request $request): array
211 + {
212 + $perPage = max(0, (int) $request->get_param('per_page'));
213 + $page = max(1, (int) $request->get_param('page'));
214 +
215 + return [$page, $perPage];
216 + }
217 +
218 + /**
201 219 * GET /trips/{trip_id}/departures
202 220 */
203 221 public function get_departures(WP_REST_Request $request): WP_REST_Response
204 222 {
@@ -203,15 +221,21 @@
203 221 public function get_departures(WP_REST_Request $request): WP_REST_Response
204 222 {
205 223 $tripId = (int) $request->get_param('trip_id');
206 224 $status = $request->get_param('status');
225 + $availability = $request->get_param('availability');
226 + $search = $request->get_param('search');
207 227 $source = $request->get_param('source');
208 228 $dateFrom = $request->get_param('date_from');
209 229 $dateTo = $request->get_param('date_to');
210 230 $includePast = $request->get_param('include_past') !== 'false';
211 -
231 +
212 232 $filters = [];
213 233 if ($status) $filters['status'] = $status;
234 + // Capacity is filtered independently of status (see DepartureRepository::applyAvailabilityClause).
235 + if ($availability && in_array($availability, ['available', 'partial', 'full'], true)) $filters['availability'] = $availability;
236 + // Free-text search on date / notes (see DepartureRepository::applySearchClause).
237 + if (is_string($search) && trim($search) !== '') $filters['search'] = trim($search);
214 238 if ($source) $filters['source'] = $source;
215 239 if ($dateFrom && trim($dateFrom) !== '') $filters['date_from'] = $dateFrom;
216 240 if ($dateTo && trim($dateTo) !== '') $filters['date_to'] = $dateTo;
217 241 $filters['include_past'] = $includePast;
@@ -216,8 +240,17 @@
216 240 if ($dateTo && trim($dateTo) !== '') $filters['date_to'] = $dateTo;
217 241 $filters['include_past'] = $includePast;
218 242
219 243 try {
244 + // Server-side pagination, only when the caller asks for it.
245 + [$page, $perPage] = $this->paginationParams($request);
246 + if ($perPage > 0) {
247 + $filters['per_page'] = $perPage;
248 + $filters['page'] = $page;
249 + }
250 + // True total for the SAME filters, independent of the page window —
251 + // count($departures) was the size of the returned page, not the total.
252 + $total = $this->departureService->countByTripId($tripId, $filters);
220 253 $departures = $this->departureService->getByTripId($tripId, $filters);
221 254
222 255 // Get trip information
223 256 $tripRepository = new \Yatra\Repositories\TripRepository();
@@ -345,9 +378,12 @@
345 378 // Debug: Log time and revenue values
346 379 return $departureArray;
347 380 }, $departures),
348 381 'meta' => [
349 - 'total' => count($departures),
382 + 'total' => $total,
383 + 'page' => $page,
384 + 'per_page' => $perPage > 0 ? $perPage : $total,
385 + 'total_pages' => $perPage > 0 ? max(1, (int) ceil($total / $perPage)) : 1,
350 386 ],
351 387 ]);
352 388 } catch (\Exception $e) {
353 389 return new WP_REST_Response([
@@ -605,15 +641,21 @@
605 641 */
606 642 public function get_all_departures(WP_REST_Request $request): WP_REST_Response
607 643 {
608 644 $status = $request->get_param('status');
645 + $availability = $request->get_param('availability');
646 + $search = $request->get_param('search');
609 647 $source = $request->get_param('source');
610 648 $dateFrom = $request->get_param('date_from');
611 649 $dateTo = $request->get_param('date_to');
612 650 $includePast = $request->get_param('include_past') !== 'false';
613 -
651 +
614 652 $filters = [];
615 653 if ($status) $filters['status'] = $status;
654 + // Capacity is filtered independently of status (see DepartureRepository::applyAvailabilityClause).
655 + if ($availability && in_array($availability, ['available', 'partial', 'full'], true)) $filters['availability'] = $availability;
656 + // Free-text search on date / notes (see DepartureRepository::applySearchClause).
657 + if (is_string($search) && trim($search) !== '') $filters['search'] = trim($search);
616 658 if ($source) $filters['source'] = $source;
617 659 if ($dateFrom && trim($dateFrom) !== '') $filters['date_from'] = $dateFrom;
618 660 if ($dateTo && trim($dateTo) !== '') $filters['date_to'] = $dateTo;
619 661 $filters['include_past'] = $includePast;
@@ -618,8 +660,17 @@
618 660 if ($dateTo && trim($dateTo) !== '') $filters['date_to'] = $dateTo;
619 661 $filters['include_past'] = $includePast;
620 662
621 663 try {
664 + // Server-side pagination, only when the caller asks for it.
665 + [$page, $perPage] = $this->paginationParams($request);
666 + if ($perPage > 0) {
667 + $filters['per_page'] = $perPage;
668 + $filters['page'] = $page;
669 + }
670 + // True total for the SAME filters, independent of the page window —
671 + // count($processed) was the size of the returned page, not the total.
672 + $total = $this->departureService->countAllDepartures($filters);
622 673 // Get all departures (no trip filter)
623 674 $departures = $this->departureService->getAllDepartures($filters);
624 675
625 676 // Get repository for additional data
@@ -763,9 +814,12 @@
763 814 return new WP_REST_Response([
764 815 'success' => true,
765 816 'data' => $processed,
766 817 'meta' => [
767 - 'total' => count($processed),
818 + 'total' => $total,
819 + 'page' => $page,
820 + 'per_page' => $perPage > 0 ? $perPage : $total,
821 + 'total_pages' => $perPage > 0 ? max(1, (int) ceil($total / $perPage)) : 1,
768 822 ],
769 823 ]);
770 824 } catch (\Exception $e) {
771 825 return new WP_REST_Response([
@@ -806,9 +860,13 @@
806 860 public function get_available_dates(WP_REST_Request $request): WP_REST_Response
807 861 {
808 862 $tripId = (int) $request->get_param('trip_id');
809 863 $fromDate = $request->get_param('from_date') ?: date('Y-m-d');
810 - $toDate = $request->get_param('to_date') ?: date('Y-m-d', strtotime('+12 months'));
864 + // An explicit to_date always wins; only the default follows the
865 + // configurable booking horizon (12 months unless changed). The default
866 + // is counted from TODAY — not from from_date — exactly as before, so a
867 + // client that sends only from_date gets the same window it always did.
868 + $toDate = $request->get_param('to_date') ?: yatra_get_availability_horizon_date();
811 869
812 870 try {
813 871 $dates = $this->departureService->getAvailableDates($tripId, $fromDate, $toDate);
814 872