PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.6
Yatra – Travel Booking & Tour Operator Software v3.0.6
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 / Repositories / TravellerRepository.php

TravellerRepository.php in Yatra – Travel Booking & Tour Operator Software 3.0.6, at app/Repositories/TravellerRepository.php

813 lines 25.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Yatra\Repositories;
4
5 use Yatra\Database\Tables\BookingTravellersTable;
6 use Yatra\Database\Tables\BookingTravellerMetaTable;
7 use Yatra\Database\Tables\BookingsTable;
8 use Yatra\Database\Tables\TripsTable;
9
10 /**
11 * Traveller Repository
12 *
13 * Handles CRUD operations for booking travellers using normalized tables:
14 * - yatra_booking_travellers: Core traveller data
15 * - yatra_booking_traveller_meta: Dynamic key-value fields
16 *
17 * @package Yatra
18 */
19 class TravellerRepository
20 {
21 /**
22 * @var \wpdb WordPress database instance
23 */
24 private \wpdb $wpdb;
25
26 /**
27 * @var string Travellers table name
28 */
29 private string $travellers_table;
30
31 /**
32 * @var string Traveller meta table name
33 */
34 private string $meta_table;
35
36 /**
37 * Constructor
38 */
39 public function __construct()
40 {
41 global $wpdb;
42 $this->wpdb = $wpdb;
43
44 // Use proper table classes
45 $this->travellers_table = BookingTravellersTable::getTableName();
46 $this->meta_table = BookingTravellerMetaTable::getTableName();
47 }
48
49 /**
50 * Create a new traveller for a booking
51 *
52 * @param int $booking_id Booking ID
53 * @param int $traveller_index Position in the booking (0-based)
54 * @param bool $is_lead Whether this is the lead/primary traveller
55 * @param array $fields Dynamic fields as key-value pairs
56 * @return int|false Traveller ID on success, false on failure
57 */
58 public function create(int $booking_id, int $traveller_index, bool $is_lead = false, array $fields = [])
59 {
60 // Insert traveller record
61 $result = $this->wpdb->insert(
62 $this->travellers_table,
63 [
64 'booking_id' => $booking_id,
65 'traveller_index' => $traveller_index,
66 'is_lead' => $is_lead ? 1 : 0,
67 'created_at' => current_time('mysql'),
68 'updated_at' => current_time('mysql'),
69 ],
70 ['%d', '%d', '%d', '%s', '%s']
71 );
72
73 if ($result === false) {
74 return false;
75 }
76
77 $traveller_id = $this->wpdb->insert_id;
78
79 // Save all dynamic fields to meta table
80 if (!empty($fields)) {
81 $this->saveMeta($traveller_id, $fields);
82 }
83
84 return $traveller_id;
85 }
86
87 /**
88 * Update a traveller's core data
89 *
90 * @param int $traveller_id Traveller ID
91 * @param array $data Data to update (is_lead, traveller_index)
92 * @return bool Success
93 */
94 public function update(int $traveller_id, array $data): bool
95 {
96 $update_data = [];
97 $update_format = [];
98
99 if (isset($data['is_lead'])) {
100 $update_data['is_lead'] = $data['is_lead'] ? 1 : 0;
101 $update_format[] = '%d';
102 }
103
104 if (isset($data['traveller_index'])) {
105 $update_data['traveller_index'] = (int) $data['traveller_index'];
106 $update_format[] = '%d';
107 }
108
109 if (empty($update_data)) {
110 return true;
111 }
112
113 $update_data['updated_at'] = current_time('mysql');
114 $update_format[] = '%s';
115
116 $result = $this->wpdb->update(
117 $this->travellers_table,
118 $update_data,
119 ['id' => $traveller_id],
120 $update_format,
121 ['%d']
122 );
123
124 return $result !== false;
125 }
126
127 /**
128 * Update traveller fields (meta data)
129 *
130 * @param int $traveller_id Traveller ID
131 * @param array $fields Fields to update/create
132 * @return bool Success
133 */
134 public function updateFields(int $traveller_id, array $fields): bool
135 {
136 // Update timestamp on main record
137 $this->wpdb->update(
138 $this->travellers_table,
139 ['updated_at' => current_time('mysql')],
140 ['id' => $traveller_id],
141 ['%s'],
142 ['%d']
143 );
144
145 return $this->saveMeta($traveller_id, $fields);
146 }
147
148 /**
149 * Delete a traveller and all their meta data
150 *
151 * @param int $traveller_id Traveller ID
152 * @return bool Success
153 */
154 public function delete(int $traveller_id): bool
155 {
156 // Delete meta first
157 $this->wpdb->delete(
158 $this->meta_table,
159 ['traveller_id' => $traveller_id],
160 ['%d']
161 );
162
163 // Delete traveller record
164 $result = $this->wpdb->delete(
165 $this->travellers_table,
166 ['id' => $traveller_id],
167 ['%d']
168 );
169
170 return $result !== false;
171 }
172
173 /**
174 * Delete all travellers for a booking
175 *
176 * @param int $booking_id Booking ID
177 * @return bool Success
178 */
179 public function deleteByBookingId(int $booking_id): bool
180 {
181 // Get all traveller IDs for this booking
182 $traveller_ids = $this->wpdb->get_col($this->wpdb->prepare(
183 "SELECT id FROM {$this->travellers_table} WHERE booking_id = %d",
184 $booking_id
185 ));
186
187 if (!empty($traveller_ids)) {
188 // Delete meta for all travellers
189 $placeholders = implode(',', array_fill(0, count($traveller_ids), '%d'));
190 $this->wpdb->query($this->wpdb->prepare(
191 "DELETE FROM {$this->meta_table} WHERE traveller_id IN ($placeholders)",
192 ...$traveller_ids
193 ));
194 }
195
196 // Delete traveller records
197 $result = $this->wpdb->delete(
198 $this->travellers_table,
199 ['booking_id' => $booking_id],
200 ['%d']
201 );
202
203 return $result !== false;
204 }
205
206 /**
207 * Get a single traveller by ID with all meta fields
208 *
209 * @param int $traveller_id Traveller ID
210 * @return array|null Traveller data with fields, or null if not found
211 */
212 public function getById(int $traveller_id): ?array
213 {
214 $traveller = $this->wpdb->get_row($this->wpdb->prepare(
215 "SELECT * FROM {$this->travellers_table} WHERE id = %d",
216 $traveller_id
217 ), ARRAY_A);
218
219 if (!$traveller) {
220 return null;
221 }
222
223 // Get all meta fields
224 $traveller['fields'] = $this->getMeta($traveller_id);
225 $traveller['is_lead'] = (bool) $traveller['is_lead'];
226
227 return $traveller;
228 }
229
230 /**
231 * Get all travellers for a booking with their meta fields
232 *
233 * @param int $booking_id Booking ID
234 * @return array Array of travellers with their fields
235 */
236 public function getByBookingId(int $booking_id): array
237 {
238 $travellers = $this->wpdb->get_results($this->wpdb->prepare(
239 "SELECT * FROM {$this->travellers_table}
240 WHERE booking_id = %d
241 ORDER BY traveller_index ASC",
242 $booking_id
243 ), ARRAY_A);
244
245 if (empty($travellers)) {
246 return [];
247 }
248
249 // Get all traveller IDs
250 $traveller_ids = array_column($travellers, 'id');
251
252 // Batch fetch all meta for these travellers
253 $all_meta = $this->getMetaBatch($traveller_ids);
254
255 // Merge meta into travellers
256 foreach ($travellers as &$traveller) {
257 $traveller['is_lead'] = (bool) $traveller['is_lead'];
258 $traveller['fields'] = $all_meta[$traveller['id']] ?? [];
259 }
260
261 return $travellers;
262 }
263
264 /**
265 * Get the lead traveller for a booking
266 *
267 * @param int $booking_id Booking ID
268 * @return array|null Lead traveller data, or null if not found
269 */
270 public function getLeadTraveller(int $booking_id): ?array
271 {
272 $traveller = $this->wpdb->get_row($this->wpdb->prepare(
273 "SELECT * FROM {$this->travellers_table}
274 WHERE booking_id = %d AND is_lead = 1
275 LIMIT 1",
276 $booking_id
277 ), ARRAY_A);
278
279 if (!$traveller) {
280 // Fallback to first traveller
281 $traveller = $this->wpdb->get_row($this->wpdb->prepare(
282 "SELECT * FROM {$this->travellers_table}
283 WHERE booking_id = %d
284 ORDER BY traveller_index ASC
285 LIMIT 1",
286 $booking_id
287 ), ARRAY_A);
288 }
289
290 if (!$traveller) {
291 return null;
292 }
293
294 $traveller['is_lead'] = (bool) $traveller['is_lead'];
295 $traveller['fields'] = $this->getMeta((int) $traveller['id']);
296
297 return $traveller;
298 }
299
300 /**
301 * Count travellers for a booking
302 *
303 * @param int $booking_id Booking ID
304 * @return int Count
305 */
306 public function countByBookingId(int $booking_id): int
307 {
308 return (int) $this->wpdb->get_var($this->wpdb->prepare(
309 "SELECT COUNT(*) FROM {$this->travellers_table} WHERE booking_id = %d",
310 $booking_id
311 ));
312 }
313
314 /**
315 * Save meta fields for a traveller (insert or update)
316 *
317 * @param int $traveller_id Traveller ID
318 * @param array $fields Key-value pairs of fields
319 * @return bool Success
320 */
321 public function saveMeta(int $traveller_id, array $fields): bool
322 {
323 foreach ($fields as $meta_key => $meta_value) {
324 // Sanitize key
325 $meta_key = sanitize_key($meta_key);
326
327 if (empty($meta_key)) {
328 continue;
329 }
330
331 // Sanitize value based on type
332 if (is_array($meta_value)) {
333 $meta_value = wp_json_encode($meta_value);
334 } else {
335 $meta_value = sanitize_text_field((string) $meta_value);
336 }
337
338 // Check if meta exists
339 $existing = $this->wpdb->get_var($this->wpdb->prepare(
340 "SELECT id FROM {$this->meta_table}
341 WHERE traveller_id = %d AND meta_key = %s",
342 $traveller_id,
343 $meta_key
344 ));
345
346 if ($existing) {
347 // Update existing meta
348 $this->wpdb->update(
349 $this->meta_table,
350 ['meta_value' => $meta_value],
351 [
352 'traveller_id' => $traveller_id,
353 'meta_key' => $meta_key,
354 ],
355 ['%s'],
356 ['%d', '%s']
357 );
358 } else {
359 // Insert new meta
360 $this->wpdb->insert(
361 $this->meta_table,
362 [
363 'traveller_id' => $traveller_id,
364 'meta_key' => $meta_key,
365 'meta_value' => $meta_value,
366 ],
367 ['%d', '%s', '%s']
368 );
369 }
370 }
371
372 return true;
373 }
374
375 /**
376 * Get all meta fields for a traveller
377 *
378 * @param int $traveller_id Traveller ID
379 * @return array Key-value pairs of fields
380 */
381 public function getMeta(int $traveller_id): array
382 {
383 $meta = $this->wpdb->get_results($this->wpdb->prepare(
384 "SELECT meta_key, meta_value FROM {$this->meta_table}
385 WHERE traveller_id = %d",
386 $traveller_id
387 ), ARRAY_A);
388
389 $fields = [];
390 foreach ($meta as $row) {
391 $value = $row['meta_value'];
392
393 // Try to decode JSON arrays/objects
394 $decoded = json_decode($value, true);
395 if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
396 $value = $decoded;
397 }
398
399 $fields[$row['meta_key']] = $value;
400 }
401
402 return $fields;
403 }
404
405 /**
406 * Get a specific meta value for a traveller
407 *
408 * @param int $traveller_id Traveller ID
409 * @param string $meta_key Meta key
410 * @param mixed $default Default value if not found
411 * @return mixed Meta value or default
412 */
413 public function getMetaValue(int $traveller_id, string $meta_key, $default = null)
414 {
415 $value = $this->wpdb->get_var($this->wpdb->prepare(
416 "SELECT meta_value FROM {$this->meta_table}
417 WHERE traveller_id = %d AND meta_key = %s",
418 $traveller_id,
419 $meta_key
420 ));
421
422 if ($value === null) {
423 return $default;
424 }
425
426 // Try to decode JSON
427 $decoded = json_decode($value, true);
428 if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
429 return $decoded;
430 }
431
432 return $value;
433 }
434
435 /**
436 * Delete a specific meta field
437 *
438 * @param int $traveller_id Traveller ID
439 * @param string $meta_key Meta key
440 * @return bool Success
441 */
442 public function deleteMeta(int $traveller_id, string $meta_key): bool
443 {
444 $result = $this->wpdb->delete(
445 $this->meta_table,
446 [
447 'traveller_id' => $traveller_id,
448 'meta_key' => $meta_key,
449 ],
450 ['%d', '%s']
451 );
452
453 return $result !== false;
454 }
455
456 /**
457 * Batch fetch meta for multiple travellers
458 *
459 * @param array $traveller_ids Array of traveller IDs
460 * @return array Associative array of traveller_id => fields
461 */
462 private function getMetaBatch(array $traveller_ids): array
463 {
464 if (empty($traveller_ids)) {
465 return [];
466 }
467
468 $placeholders = implode(',', array_fill(0, count($traveller_ids), '%d'));
469
470 $meta = $this->wpdb->get_results($this->wpdb->prepare(
471 "SELECT traveller_id, meta_key, meta_value FROM {$this->meta_table}
472 WHERE traveller_id IN ($placeholders)",
473 ...$traveller_ids
474 ), ARRAY_A);
475
476 $result = [];
477 foreach ($meta as $row) {
478 $traveller_id = $row['traveller_id'];
479 $value = $row['meta_value'];
480
481 // Try to decode JSON
482 $decoded = json_decode($value, true);
483 if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
484 $value = $decoded;
485 }
486
487 if (!isset($result[$traveller_id])) {
488 $result[$traveller_id] = [];
489 }
490 $result[$traveller_id][$row['meta_key']] = $value;
491 }
492
493 return $result;
494 }
495
496 /**
497 * Search travellers across all bookings
498 *
499 * @param string $search Search term
500 * @param int $trip_id Optional trip ID filter
501 * @param int $page Page number
502 * @param int $per_page Items per page
503 * @return array Array with 'data' and 'total'
504 */
505 public function search(string $search = '', int $trip_id = 0, int $page = 1, int $per_page = 20): array
506 {
507 // Use Table classes for table names
508 $bookings_table = BookingsTable::getTableName();
509 $trips_table = TripsTable::getTableName();
510
511 // Base query to get travellers with booking info
512 $query = "SELECT t.*, b.reference as booking_reference, b.travel_date, b.contact_email, b.contact_phone,
513 tr.title as trip_title, tr.id as trip_id
514 FROM {$this->travellers_table} t
515 INNER JOIN {$bookings_table} b ON t.booking_id = b.id
516 LEFT JOIN {$trips_table} tr ON b.trip_id = tr.id";
517
518 $where_clauses = [];
519 $where_values = [];
520
521 if ($trip_id > 0) {
522 $where_clauses[] = "b.trip_id = %d";
523 $where_values[] = $trip_id;
524 }
525
526 if (!empty($where_clauses)) {
527 $query .= " WHERE " . implode(' AND ', $where_clauses);
528 }
529
530 $query .= " ORDER BY b.created_at DESC, t.traveller_index ASC";
531
532 if (!empty($where_values)) {
533 $query = $this->wpdb->prepare($query, ...$where_values);
534 }
535
536 $travellers = $this->wpdb->get_results($query, ARRAY_A);
537
538 if (empty($travellers)) {
539 return ['data' => [], 'total' => 0];
540 }
541
542 // Get all meta
543 $traveller_ids = array_column($travellers, 'id');
544 $all_meta = $this->getMetaBatch($traveller_ids);
545
546 // Merge meta and apply search filter
547 $filtered = [];
548 $search_lower = strtolower($search);
549
550 foreach ($travellers as $traveller) {
551 $traveller['is_lead'] = (bool) $traveller['is_lead'];
552 $traveller['fields'] = $all_meta[$traveller['id']] ?? [];
553
554 // Add lead traveller contact info
555 if ($traveller['is_lead']) {
556 if (empty($traveller['fields']['email']) && !empty($traveller['contact_email'])) {
557 $traveller['fields']['email'] = $traveller['contact_email'];
558 }
559 if (empty($traveller['fields']['phone']) && !empty($traveller['contact_phone'])) {
560 $traveller['fields']['phone'] = $traveller['contact_phone'];
561 }
562 }
563
564 // Apply search filter
565 if (!empty($search)) {
566 $searchable = strtolower(implode(' ', array_merge(
567 [$traveller['booking_reference'] ?? ''],
568 array_values($traveller['fields'])
569 )));
570
571 if (strpos($searchable, $search_lower) === false) {
572 continue;
573 }
574 }
575
576 // Clean up unnecessary fields
577 unset($traveller['contact_email'], $traveller['contact_phone']);
578
579 $filtered[] = $traveller;
580 }
581
582 $total = count($filtered);
583
584 // Apply pagination
585 $offset = ($page - 1) * $per_page;
586 $paginated = array_slice($filtered, $offset, $per_page);
587
588 return [
589 'data' => $paginated,
590 'total' => $total,
591 ];
592 }
593
594 /**
595 * Save multiple travellers for a booking (bulk operation)
596 * Replaces all existing travellers for the booking
597 *
598 * @param int $booking_id Booking ID
599 * @param array $travellers Array of traveller data with 'is_lead' and 'fields'
600 * @return array Array of created traveller IDs
601 */
602 public function saveTravellersForBooking(int $booking_id, array $travellers): array
603 {
604 // Delete existing travellers for this booking
605 $this->deleteByBookingId($booking_id);
606
607 $created_ids = [];
608
609 foreach ($travellers as $index => $traveller_data) {
610 $is_lead = !empty($traveller_data['is_lead']) || $index === 0;
611 $fields = $traveller_data['fields'] ?? $traveller_data;
612
613 // Remove non-field keys
614 unset($fields['is_lead'], $fields['traveller_index']);
615
616 $traveller_id = $this->create($booking_id, $index, $is_lead, $fields);
617
618 if ($traveller_id) {
619 $created_ids[] = $traveller_id;
620 }
621 }
622
623 return $created_ids;
624 }
625
626 /**
627 * Get travellers formatted for API response (backward compatible with JSON format)
628 *
629 * @param int $booking_id Booking ID
630 * @return array Array of traveller fields (flat structure like old JSON)
631 */
632 public function getTravellersAsArray(int $booking_id): array
633 {
634 $travellers = $this->getByBookingId($booking_id);
635
636 $result = [];
637 foreach ($travellers as $traveller) {
638 $data = $traveller['fields'];
639 $data['_traveller_id'] = $traveller['id'];
640 $data['_is_lead'] = $traveller['is_lead'];
641 $data['_traveller_index'] = $traveller['traveller_index'];
642 $result[] = $data;
643 }
644
645 return $result;
646 }
647
648 /**
649 * Get paginated travelers with filters
650 *
651 * @param array $filters Filter options
652 * @return array {data: array, meta: array}
653 */
654 public function paginate(array $filters = []): array
655 {
656 // Use Table classes for table names
657 $bookings_table = BookingsTable::getTableName();
658 $trips_table = TripsTable::getTableName();
659
660 // Pagination
661 $page = max(1, (int) ($filters['page'] ?? 1));
662 $per_page = max(1, min(100, (int) ($filters['per_page'] ?? 20)));
663 $offset = ($page - 1) * $per_page;
664
665 // Build WHERE clause
666 $where_clauses = ['1=1'];
667 $where_values = [];
668
669 if (!empty($filters['trip_id'])) {
670 $where_clauses[] = 'b.trip_id = %d';
671 $where_values[] = (int) $filters['trip_id'];
672 }
673
674 if (!empty($filters['search'])) {
675 // Search in meta values
676 $search_like = '%' . $this->wpdb->esc_like(sanitize_text_field($filters['search'])) . '%';
677 $where_clauses[] = "EXISTS (
678 SELECT 1 FROM {$this->meta_table} m
679 WHERE m.traveller_id = t.id
680 AND m.meta_value LIKE %s
681 )";
682 $where_values[] = $search_like;
683 }
684
685 $where_sql = implode(' AND ', $where_clauses);
686
687 // Get total count
688 $count_query = "SELECT COUNT(DISTINCT t.id)
689 FROM {$this->travellers_table} t
690 INNER JOIN {$bookings_table} b ON t.booking_id = b.id
691 WHERE {$where_sql}";
692
693 if (!empty($where_values)) {
694 $count_query = $this->wpdb->prepare($count_query, ...$where_values);
695 }
696 $total = (int) $this->wpdb->get_var($count_query);
697
698 // Get travellers with booking info
699 $query = "SELECT t.id, t.booking_id, t.traveller_index, t.is_lead, t.created_at,
700 b.reference as booking_reference, b.trip_id, b.travel_date,
701 tr.title as trip_title
702 FROM {$this->travellers_table} t
703 INNER JOIN {$bookings_table} b ON t.booking_id = b.id
704 LEFT JOIN {$trips_table} tr ON b.trip_id = tr.id
705 WHERE {$where_sql}
706 ORDER BY t.created_at DESC
707 LIMIT %d OFFSET %d";
708
709 $query_values = array_merge($where_values, [$per_page, $offset]);
710 $travellers = $this->wpdb->get_results($this->wpdb->prepare($query, ...$query_values));
711
712 // Get meta for each traveller
713 $data = [];
714 foreach ($travellers as $traveller) {
715 $meta = $this->getMeta((int) $traveller->id);
716
717 $data[] = array_merge([
718 'id' => (int) $traveller->id,
719 'booking_id' => (int) $traveller->booking_id,
720 'booking_reference' => $traveller->booking_reference,
721 'trip_id' => (int) $traveller->trip_id,
722 'trip_title' => $traveller->trip_title,
723 'travel_date' => $traveller->travel_date,
724 'traveler_index' => (int) $traveller->traveller_index,
725 'is_lead' => (bool) $traveller->is_lead,
726 ], $meta);
727 }
728
729 // Get unique trips for filter dropdown (only on first page with no search)
730 $available_trips = [];
731 if ($page === 1 && empty($filters['search'])) {
732 $trips_query = "SELECT DISTINCT tr.id, tr.title
733 FROM {$this->travellers_table} t
734 INNER JOIN {$bookings_table} b ON t.booking_id = b.id
735 INNER JOIN {$trips_table} tr ON b.trip_id = tr.id
736 WHERE tr.id IS NOT NULL
737 ORDER BY tr.title ASC";
738 $trips = $this->wpdb->get_results($trips_query);
739
740 foreach ($trips as $trip) {
741 $available_trips[] = [
742 'id' => (int) $trip->id,
743 'title' => $trip->title,
744 ];
745 }
746 }
747
748 return [
749 'data' => $data,
750 'meta' => [
751 'total' => $total,
752 'page' => $page,
753 'per_page' => $per_page,
754 'total_pages' => (int) ceil($total / $per_page),
755 'available_trips' => $available_trips,
756 ],
757 ];
758 }
759
760 /**
761 * Bulk delete travellers and their meta
762 *
763 * @param int[] $ids Traveller IDs
764 * @return array {success: bool, deleted: int, message: string}
765 */
766 public function bulkDelete(array $ids): array
767 {
768 $ids = array_values(array_filter(array_map('intval', $ids)));
769
770 if (empty($ids)) {
771 return [
772 'success' => false,
773 'deleted' => 0,
774 'message' => __('No travelers selected.', 'yatra'),
775 ];
776 }
777
778 $placeholders = implode(',', array_fill(0, count($ids), '%d'));
779
780 // Delete meta first
781 $metaDeleted = 0;
782 if (!empty($this->meta_table)) {
783 $metaSql = "DELETE FROM {$this->meta_table} WHERE traveller_id IN ($placeholders)";
784 $metaDeleted = $this->wpdb->query($this->wpdb->prepare($metaSql, ...$ids));
785 }
786
787 // Delete travellers
788 $travellerSql = "DELETE FROM {$this->travellers_table} WHERE id IN ($placeholders)";
789 $travellersDeleted = $this->wpdb->query($this->wpdb->prepare($travellerSql, ...$ids));
790
791 $deletedCount = (int) $travellersDeleted;
792
793 if ($deletedCount <= 0) {
794 return [
795 'success' => false,
796 'deleted' => 0,
797 'message' => __('Failed to delete travelers.', 'yatra'),
798 ];
799 }
800
801 return [
802 'success' => true,
803 'deleted' => $deletedCount,
804 'message' => sprintf(
805 /* translators: %d: number of travelers deleted. */
806 _n('%d traveler deleted.', '%d travelers deleted.', $deletedCount, 'yatra'),
807 $deletedCount
808 ),
809 ];
810 }
811 }
812
813