PluginProbe
Yatra – Travel Booking & Tour Operator Software / trunk
Yatra – Travel Booking & Tour Operator Software vtrunk
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 2.0.11 All 82 releases
yatra / app / Controllers / AvailabilitySpecificDatesController.php

AvailabilitySpecificDatesController.php in Yatra – Travel Booking & Tour Operator Software trunk, at app/Controllers/AvailabilitySpecificDatesController.php

585 lines 18.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Yatra\Controllers;
4
5 use Yatra\Services\AvailabilitySpecificDatesService;
6 use Yatra\Helpers\FormatHelper;
7 use Yatra\Helpers\ValidationHelper;
8
9 /**
10 * Availability Specific Dates Controller Class
11 *
12 * Handles HTTP requests for specific date availability management.
13 * Provides REST API endpoints for CRUD operations.
14 *
15 * @package Yatra\Controllers
16 * @since 2.0.0
17 */
18 class AvailabilitySpecificDatesController
19 {
20 /**
21 * @var AvailabilitySpecificDatesService Service instance
22 */
23 private $service;
24
25 /**
26 * Constructor
27 */
28 public function __construct()
29 {
30 $this->service = new AvailabilitySpecificDatesService();
31 }
32
33 /**
34 * Register REST API routes
35 */
36 public function registerRoutes()
37 {
38 register_rest_route('yatra/v1', '/availability/specific-dates', [
39 [
40 'methods' => 'GET',
41 'callback' => [$this, 'getItems'],
42 'permission_callback' => [$this, 'checkPermission'],
43 ],
44 [
45 'methods' => 'POST',
46 'callback' => [$this, 'createItem'],
47 'permission_callback' => [$this, 'checkPermission'],
48 ],
49 ]);
50
51 register_rest_route('yatra/v1', '/availability/specific-dates/(?P<id>\d+)', [
52 [
53 'methods' => 'GET',
54 'callback' => [$this, 'getItem'],
55 'permission_callback' => [$this, 'checkPermission'],
56 ],
57 [
58 'methods' => 'PUT',
59 'callback' => [$this, 'updateItem'],
60 'permission_callback' => [$this, 'checkPermission'],
61 ],
62 [
63 'methods' => 'DELETE',
64 'callback' => [$this, 'deleteItem'],
65 'permission_callback' => [$this, 'checkPermission'],
66 ],
67 ]);
68
69 register_rest_route('yatra/v1', '/availability/specific-dates/trip/(?P<tripId>\d+)', [
70 [
71 'methods' => 'GET',
72 'callback' => [$this, 'getDatesForTrip'],
73 'permission_callback' => [$this, 'checkPermission'],
74 ],
75 ]);
76
77 register_rest_route('yatra/v1', '/availability/specific-dates/trip/(?P<tripId>\d+)/available', [
78 [
79 'methods' => 'GET',
80 'callback' => [$this, 'getAvailableDates'],
81 'permission_callback' => [$this, 'checkPermission'],
82 ],
83 ]);
84
85 register_rest_route('yatra/v1', '/availability/specific-dates/trip/(?P<tripId>\d+)/check/(?P<date>[^/]+)', [
86 [
87 'methods' => 'GET',
88 'callback' => [$this, 'checkDateAvailability'],
89 'permission_callback' => [$this, 'checkPermission'],
90 ],
91 ]);
92
93 register_rest_route('yatra/v1', '/availability/specific-dates/trip/(?P<tripId>\d+)/booking-count', [
94 [
95 'methods' => 'POST',
96 'callback' => [$this, 'updateBookingCount'],
97 'permission_callback' => [$this, 'checkPermission'],
98 ],
99 ]);
100
101 register_rest_route('yatra/v1', '/availability/specific-dates/trip/(?P<tripId>\d+)/increment', [
102 [
103 'methods' => 'POST',
104 'callback' => [$this, 'incrementBookingCount'],
105 'permission_callback' => [$this, 'checkPermission'],
106 ],
107 ]);
108
109 register_rest_route('yatra/v1', '/availability/specific-dates/trip/(?P<tripId>\d+)/decrement', [
110 [
111 'methods' => 'POST',
112 'callback' => [$this, 'decrementBookingCount'],
113 'permission_callback' => [$this, 'checkPermission'],
114 ],
115 ]);
116
117 register_rest_route('yatra/v1', '/availability/specific-dates/trip/(?P<tripId>\d+)/price-overrides', [
118 [
119 'methods' => 'GET',
120 'callback' => [$this, 'getPriceOverrides'],
121 'permission_callback' => [$this, 'checkPermission'],
122 ],
123 ]);
124
125 register_rest_route('yatra/v1', '/availability/specific-dates/trip/(?P<tripId>\d+)/delete-range', [
126 [
127 'methods' => 'DELETE',
128 'callback' => [$this, 'deleteDateRange'],
129 'permission_callback' => [$this, 'checkPermission'],
130 ],
131 ]);
132 }
133
134 /**
135 * Get specific dates list
136 *
137 * @param \WP_REST_Request $request REST request object
138 * @return \WP_REST_Response REST response
139 */
140 public function getItems(\WP_REST_Request $request): \WP_REST_Response
141 {
142 try {
143 $tripId = $request->get_param('trip_id');
144 $startDate = $request->get_param('start_date');
145 $endDate = $request->get_param('end_date');
146 $page = $request->get_param('page') ?: 1;
147 $perPage = $request->get_param('per_page') ?: 20;
148
149 $args = [];
150 if ($tripId) {
151 $args['trip_id'] = (int) $tripId;
152 }
153 if ($startDate) {
154 $args['start_date'] = $startDate;
155 }
156 if ($endDate) {
157 $args['end_date'] = $endDate;
158 }
159 $args['page'] = $page;
160 $args['per_page'] = $perPage;
161
162 $result = $this->service->getAll($args);
163
164 return new \WP_REST_Response([
165 'success' => true,
166 'data' => $result['data'],
167 'pagination' => $result['pagination'],
168 ], 200);
169
170 } catch (\Exception $e) {
171 return new \WP_REST_Response([
172 'success' => false,
173 'message' => $e->getMessage(),
174 ], 400);
175 }
176 }
177
178 /**
179 * Get specific date by ID
180 *
181 * @param \WP_REST_Request $request REST request object
182 * @return \WP_REST_Response REST response
183 */
184 public function getItem(\WP_REST_Request $request): \WP_REST_Response
185 {
186 try {
187 $id = (int) $request->get_param('id');
188 $item = $this->service->getById($id);
189
190 if (!$item) {
191 return new \WP_REST_Response([
192 'success' => false,
193 'message' => 'Specific date record not found.',
194 ], 404);
195 }
196
197 return new \WP_REST_Response([
198 'success' => true,
199 'data' => $item,
200 ], 200);
201
202 } catch (\Exception $e) {
203 return new \WP_REST_Response([
204 'success' => false,
205 'message' => $e->getMessage(),
206 ], 400);
207 }
208 }
209
210 /**
211 * Create new specific date record
212 *
213 * @param \WP_REST_Request $request REST request object
214 * @return \WP_REST_Response REST response
215 */
216 public function createItem(\WP_REST_Request $request): \WP_REST_Response
217 {
218 try {
219 $data = $request->get_json_params();
220
221 if (empty($data)) {
222 throw new \InvalidArgumentException('No data provided.');
223 }
224
225 $id = $this->service->create($data);
226
227 if (!$id) {
228 throw new \RuntimeException('Failed to create specific date record.');
229 }
230
231 $item = $this->service->getById($id);
232
233 return new \WP_REST_Response([
234 'success' => true,
235 'data' => $item,
236 'message' => 'Specific date record created successfully.',
237 ], 201);
238
239 } catch (\Exception $e) {
240 return new \WP_REST_Response([
241 'success' => false,
242 'message' => $e->getMessage(),
243 ], 400);
244 }
245 }
246
247 /**
248 * Update specific date record
249 *
250 * @param \WP_REST_Request $request REST request object
251 * @return \WP_REST_Response REST response
252 */
253 public function updateItem(\WP_REST_Request $request): \WP_REST_Response
254 {
255 try {
256 $id = (int) $request->get_param('id');
257 $data = $request->get_json_params();
258
259 if (empty($data)) {
260 throw new \InvalidArgumentException('No data provided.');
261 }
262
263 $success = $this->service->update($id, $data);
264
265 if (!$success) {
266 throw new \RuntimeException('Failed to update specific date record.');
267 }
268
269 $item = $this->service->getById($id);
270
271 return new \WP_REST_Response([
272 'success' => true,
273 'data' => $item,
274 'message' => 'Specific date record updated successfully.',
275 ], 200);
276
277 } catch (\Exception $e) {
278 return new \WP_REST_Response([
279 'success' => false,
280 'message' => $e->getMessage(),
281 ], 400);
282 }
283 }
284
285 /**
286 * Delete specific date record
287 *
288 * @param \WP_REST_Request $request REST request object
289 * @return \WP_REST_Response REST response
290 */
291 public function deleteItem(\WP_REST_Request $request): \WP_REST_Response
292 {
293 try {
294 $id = (int) $request->get_param('id');
295 $success = $this->service->delete($id);
296
297 if (!$success) {
298 throw new \RuntimeException('Failed to delete specific date record.');
299 }
300
301 return new \WP_REST_Response([
302 'success' => true,
303 'message' => 'Specific date record deleted successfully.',
304 ], 200);
305
306 } catch (\Exception $e) {
307 return new \WP_REST_Response([
308 'success' => false,
309 'message' => $e->getMessage(),
310 ], 400);
311 }
312 }
313
314 /**
315 * Get dates for a trip
316 *
317 * @param \WP_REST_Request $request REST request object
318 * @return \WP_REST_Response REST response
319 */
320 public function getDatesForTrip(\WP_REST_Request $request): \WP_REST_Response
321 {
322 try {
323 $tripId = (int) $request->get_param('tripId');
324 $startDate = $request->get_param('start_date') ?: date('Y-m-d');
325 $endDate = $request->get_param('end_date') ?: date('Y-m-d', strtotime('+1 year'));
326
327 $dates = $this->service->getDatesForTrip($tripId, $startDate, $endDate);
328
329 return new \WP_REST_Response([
330 'success' => true,
331 'data' => $dates,
332 ], 200);
333
334 } catch (\Exception $e) {
335 return new \WP_REST_Response([
336 'success' => false,
337 'message' => $e->getMessage(),
338 ], 400);
339 }
340 }
341
342 /**
343 * Get available dates for a trip
344 *
345 * @param \WP_REST_Request $request REST request object
346 * @return \WP_REST_Response REST response
347 */
348 public function getAvailableDates(\WP_REST_Request $request): \WP_REST_Response
349 {
350 try {
351 $tripId = (int) $request->get_param('tripId');
352 $startDate = $request->get_param('start_date') ?: date('Y-m-d');
353 $endDate = $request->get_param('end_date') ?: date('Y-m-d', strtotime('+1 year'));
354
355 $dates = $this->service->getAvailableDates($tripId, $startDate, $endDate);
356
357 return new \WP_REST_Response([
358 'success' => true,
359 'data' => $dates,
360 ], 200);
361
362 } catch (\Exception $e) {
363 return new \WP_REST_Response([
364 'success' => false,
365 'message' => $e->getMessage(),
366 ], 400);
367 }
368 }
369
370 /**
371 * Check date availability
372 *
373 * @param \WP_REST_Request $request REST request object
374 * @return \WP_REST_Response REST response
375 */
376 public function checkDateAvailability(\WP_REST_Request $request): \WP_REST_Response
377 {
378 try {
379 $tripId = (int) $request->get_param('tripId');
380 $date = $request->get_param('date');
381
382 $isAvailable = $this->service->isDateAvailable($tripId, $date);
383 $availableSlots = $this->service->getAvailableSlots($tripId, $date);
384
385 return new \WP_REST_Response([
386 'success' => true,
387 'data' => [
388 'is_available' => $isAvailable,
389 'available_slots' => $availableSlots,
390 'date' => $date,
391 'trip_id' => $tripId,
392 ],
393 ], 200);
394
395 } catch (\Exception $e) {
396 return new \WP_REST_Response([
397 'success' => false,
398 'message' => $e->getMessage(),
399 ], 400);
400 }
401 }
402
403 /**
404 * Update booking count
405 *
406 * @param \WP_REST_Request $request REST request object
407 * @return \WP_REST_Response REST response
408 */
409 public function updateBookingCount(\WP_REST_Request $request): \WP_REST_Response
410 {
411 try {
412 $tripId = (int) $request->get_param('tripId');
413 $data = $request->get_json_params();
414
415 if (!isset($data['date']) || !isset($data['booking_count'])) {
416 throw new \InvalidArgumentException('Date and booking_count are required.');
417 }
418
419 $success = $this->service->updateBookingCount($tripId, $data['date'], (int) $data['booking_count']);
420
421 if (!$success) {
422 throw new \RuntimeException('Failed to update booking count.');
423 }
424
425 return new \WP_REST_Response([
426 'success' => true,
427 'message' => 'Booking count updated successfully.',
428 ], 200);
429
430 } catch (\Exception $e) {
431 return new \WP_REST_Response([
432 'success' => false,
433 'message' => $e->getMessage(),
434 ], 400);
435 }
436 }
437
438 /**
439 * Increment booking count
440 *
441 * @param \WP_REST_Request $request REST request object
442 * @return \WP_REST_Response REST response
443 */
444 public function incrementBookingCount(\WP_REST_Request $request): \WP_REST_Response
445 {
446 try {
447 $tripId = (int) $request->get_param('tripId');
448 $data = $request->get_json_params();
449
450 if (!isset($data['date'])) {
451 throw new \InvalidArgumentException('Date is required.');
452 }
453
454 $increment = $data['increment'] ?? 1;
455 $success = $this->service->incrementBookingCount($tripId, $data['date'], (int) $increment);
456
457 if (!$success) {
458 throw new \RuntimeException('Failed to increment booking count.');
459 }
460
461 return new \WP_REST_Response([
462 'success' => true,
463 'message' => 'Booking count incremented successfully.',
464 ], 200);
465
466 } catch (\Exception $e) {
467 return new \WP_REST_Response([
468 'success' => false,
469 'message' => $e->getMessage(),
470 ], 400);
471 }
472 }
473
474 /**
475 * Decrement booking count
476 *
477 * @param \WP_REST_Request $request REST request object
478 * @return \WP_REST_Response REST response
479 */
480 public function decrementBookingCount(\WP_REST_Request $request): \WP_REST_Response
481 {
482 try {
483 $tripId = (int) $request->get_param('tripId');
484 $data = $request->get_json_params();
485
486 if (!isset($data['date'])) {
487 throw new \InvalidArgumentException('Date is required.');
488 }
489
490 $decrement = $data['decrement'] ?? 1;
491 $success = $this->service->decrementBookingCount($tripId, $data['date'], (int) $decrement);
492
493 if (!$success) {
494 throw new \RuntimeException('Failed to decrement booking count.');
495 }
496
497 return new \WP_REST_Response([
498 'success' => true,
499 'message' => 'Booking count decremented successfully.',
500 ], 200);
501
502 } catch (\Exception $e) {
503 return new \WP_REST_Response([
504 'success' => false,
505 'message' => $e->getMessage(),
506 ], 400);
507 }
508 }
509
510 /**
511 * Get price overrides for a trip
512 *
513 * @param \WP_REST_Request $request REST request object
514 * @return \WP_REST_Response REST response
515 */
516 public function getPriceOverrides(\WP_REST_Request $request): \WP_REST_Response
517 {
518 try {
519 $tripId = (int) $request->get_param('tripId');
520 $startDate = $request->get_param('start_date') ?: date('Y-m-d');
521 $endDate = $request->get_param('end_date') ?: date('Y-m-d', strtotime('+1 year'));
522
523 $overrides = $this->service->getDatesWithPriceOverrides($tripId, $startDate, $endDate);
524
525 return new \WP_REST_Response([
526 'success' => true,
527 'data' => $overrides,
528 ], 200);
529
530 } catch (\Exception $e) {
531 return new \WP_REST_Response([
532 'success' => false,
533 'message' => $e->getMessage(),
534 ], 400);
535 }
536 }
537
538 /**
539 * Delete date range for a trip
540 *
541 * @param \WP_REST_Request $request REST request object
542 * @return \WP_REST_Response REST response
543 */
544 public function deleteDateRange(\WP_REST_Request $request): \WP_REST_Response
545 {
546 try {
547 $tripId = (int) $request->get_param('tripId');
548 $data = $request->get_json_params();
549
550 if (!isset($data['start_date']) || !isset($data['end_date'])) {
551 throw new \InvalidArgumentException('Start date and end date are required.');
552 }
553
554 $deletedCount = $this->service->deleteDatesInRange($tripId, $data['start_date'], $data['end_date']);
555
556 return new \WP_REST_Response([
557 'success' => true,
558 'message' => "Deleted {$deletedCount} specific date records.",
559 'deleted_count' => $deletedCount,
560 ], 200);
561
562 } catch (\Exception $e) {
563 return new \WP_REST_Response([
564 'success' => false,
565 'message' => $e->getMessage(),
566 ], 400);
567 }
568 }
569
570 /**
571 * Check user permissions
572 *
573 * @param \WP_REST_Request $request REST request object
574 * @return bool Permission status
575 */
576 public function checkPermission(\WP_REST_Request $request): bool
577 {
578 // Trip-writes cap covers every endpoint on this controller —
579 // managing specific override dates, price overrides, and booking
580 // counts all mutate trip availability. WP admins pass via the
581 // Team module's admin-fallback filter.
582 return current_user_can('yatra_edit_trips');
583 }
584 }
585