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 / Repositories / RecurringRuleRepository.php

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

254 lines 7.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare(strict_types=1);
4
5 namespace Yatra\Repositories;
6
7 use Yatra\Models\RecurringRule;
8 use Yatra\Database\Tables\TripAvailabilityRulesTable;
9
10 /**
11 * Recurring Rule Repository
12 * Handles database operations for recurring departure rules
13 *
14 * Table: yatra_trip_availability_rules
15 *
16 * Fields:
17 * - id (primary key)
18 * - trip_id
19 * - recurrence_type (daily|weekly|monthly|custom_days)
20 * - weekdays (JSON array: [0,1,2,3,4,5,6])
21 * - start_date (nullable)
22 * - end_date (nullable)
23 * - max_capacity
24 * - base_price (nullable)
25 * - pricing_by_traveler_type (JSON)
26 * - is_active
27 * - created_at
28 * - updated_at
29 */
30 class RecurringRuleRepository extends BaseRepository
31 {
32 /**
33 * Get table name
34 */
35 protected function getTableName(): string
36 {
37 return TripAvailabilityRulesTable::getTableName();
38 }
39
40 /**
41 * Find by ID
42 */
43 public function find(int $id, bool $includeDeleted = false): ?\stdClass
44 {
45 $result = parent::find($id, $includeDeleted);
46 return $result ? (object) RecurringRule::fromArray((array) $result)->toArray() : null;
47 }
48
49 /**
50 * Find by ID and return RecurringRule model
51 */
52 public function findModel(int $id): ?RecurringRule
53 {
54 $result = parent::find($id);
55 return $result ? RecurringRule::fromArray((array) $result) : null;
56 }
57
58 /**
59 * Find all rules by trip ID
60 */
61 public function findByTripId(int $tripId, bool $activeOnly = false): array
62 {
63 $table = esc_sql($this->table);
64 $where = ['trip_id = %d'];
65 $params = [$tripId];
66
67 if ($activeOnly) {
68 $where[] = "status = 'active'";
69 }
70
71 $query = "SELECT * FROM `{$table}` WHERE " . implode(' AND ', $where);
72 $query .= " ORDER BY created_at DESC";
73
74 $results = $this->wpdb->get_results(
75 $this->wpdb->prepare($query, ...$params),
76 ARRAY_A
77 );
78
79 return array_map(function ($row) {
80 return RecurringRule::fromArray($row);
81 }, $results ?: []);
82 }
83
84 /**
85 * Find active rules for a trip within a date range
86 */
87 public function findActiveForDateRange(int $tripId, string $fromDate, string $toDate): array
88 {
89 $table = esc_sql($this->table);
90
91 $query = $this->wpdb->prepare(
92 "SELECT * FROM `{$table}`
93 WHERE trip_id = %d
94 AND status = 'active'
95 AND (start_date IS NULL OR start_date <= %s)
96 AND (end_date IS NULL OR end_date >= %s)
97 ORDER BY created_at DESC",
98 $tripId,
99 $toDate,
100 $fromDate
101 );
102
103 $results = $this->wpdb->get_results($query, ARRAY_A);
104
105 return array_map(function ($row) {
106 return RecurringRule::fromArray($row);
107 }, $results ?: []);
108 }
109
110 /**
111 * Create a recurring rule
112 */
113 public function create(array $data): int
114 {
115 $table = esc_sql($this->table);
116
117 $maxCap = (int) ($data['max_capacity'] ?? 0);
118
119 $insertData = [
120 'trip_id' => (int) ($data['trip_id'] ?? 0),
121 'name' => sanitize_text_field($data['name'] ?? 'Recurring Rule'),
122 'status' => sanitize_text_field($data['status'] ?? 'active'),
123 'recurrence_type' => sanitize_text_field($data['recurrence_type'] ?? 'weekly'),
124 'start_date' => !empty($data['start_date']) ? sanitize_text_field($data['start_date']) : current_time('Y-m-d'),
125 'end_date' => !empty($data['end_date']) ? sanitize_text_field($data['end_date']) : null,
126 'capacity_value' => $maxCap > 0 ? $maxCap : null,
127 'capacity_type' => 'fixed',
128 'price_override' => !empty($data['base_price']) ? (float) $data['base_price'] : null,
129 'seats_total' => $maxCap > 0 ? $maxCap : null,
130 'created_at' => current_time('mysql'),
131 'updated_at' => current_time('mysql'),
132 ];
133
134 // Schema column is days_of_week (JSON), not weekdays
135 if (!empty($data['weekdays'])) {
136 if (is_array($data['weekdays'])) {
137 $insertData['days_of_week'] = wp_json_encode(array_map('intval', $data['weekdays']));
138 } else {
139 $insertData['days_of_week'] = $data['weekdays'];
140 }
141 } else {
142 $insertData['days_of_week'] = null;
143 }
144
145 if (!empty($data['pricing_by_traveler_type'])) {
146 $insertData['pricing_by_traveler_type'] = is_array($data['pricing_by_traveler_type'])
147 ? wp_json_encode($data['pricing_by_traveler_type'])
148 : $data['pricing_by_traveler_type'];
149 } else {
150 $insertData['pricing_by_traveler_type'] = null;
151 }
152
153 $formats = [];
154 foreach ($insertData as $value) {
155 if (is_int($value)) {
156 $formats[] = '%d';
157 } elseif (is_float($value)) {
158 $formats[] = '%f';
159 } else {
160 $formats[] = '%s';
161 }
162 }
163
164 $this->wpdb->insert($table, $insertData, $formats);
165
166 return (int) $this->wpdb->insert_id;
167 }
168
169 /**
170 * Update a recurring rule
171 */
172 public function update(int $id, array $data): bool
173 {
174 $table = esc_sql($this->table);
175
176 $updateData = [];
177
178 if (isset($data['trip_id'])) $updateData['trip_id'] = (int) $data['trip_id'];
179 if (isset($data['recurrence_type'])) $updateData['recurrence_type'] = sanitize_text_field($data['recurrence_type']);
180 if (isset($data['start_date'])) $updateData['start_date'] = !empty($data['start_date']) ? sanitize_text_field($data['start_date']) : null;
181 if (isset($data['end_date'])) $updateData['end_date'] = !empty($data['end_date']) ? sanitize_text_field($data['end_date']) : null;
182 if (isset($data['max_capacity'])) {
183 $mc = (int) $data['max_capacity'];
184 $updateData['capacity_value'] = $mc;
185 $updateData['seats_total'] = $mc > 0 ? $mc : null;
186 }
187 if (isset($data['base_price'])) {
188 $updateData['price_override'] = !empty($data['base_price']) ? (float) $data['base_price'] : null;
189 }
190 if (isset($data['is_active'])) {
191 $updateData['status'] = !empty($data['is_active']) ? 'active' : 'inactive';
192 }
193
194 if (isset($data['weekdays'])) {
195 if (is_array($data['weekdays'])) {
196 $updateData['days_of_week'] = wp_json_encode(array_map('intval', $data['weekdays']));
197 } else {
198 $updateData['days_of_week'] = $data['weekdays'];
199 }
200 }
201
202 if (isset($data['pricing_by_traveler_type'])) {
203 $updateData['pricing_by_traveler_type'] = is_array($data['pricing_by_traveler_type'])
204 ? wp_json_encode($data['pricing_by_traveler_type'])
205 : $data['pricing_by_traveler_type'];
206 }
207
208 $updateData['updated_at'] = current_time('mysql');
209
210 if (empty($updateData)) {
211 return false;
212 }
213
214 $formats = [];
215 foreach ($updateData as $value) {
216 if (is_int($value)) {
217 $formats[] = '%d';
218 } elseif (is_float($value)) {
219 $formats[] = '%f';
220 } elseif (is_bool($value)) {
221 $formats[] = '%d';
222 } else {
223 $formats[] = '%s';
224 }
225 }
226
227 return (bool) $this->wpdb->update(
228 $table,
229 $updateData,
230 ['id' => $id],
231 $formats,
232 ['%d']
233 );
234 }
235
236 /**
237 * Delete a recurring rule
238 */
239 public function delete(int $id): bool
240 {
241 $table = esc_sql($this->table);
242 return (bool) $this->wpdb->delete($table, ['id' => $id], ['%d']);
243 }
244
245 /**
246 * Check if table supports soft delete
247 */
248 protected function hasSoftDelete(): bool
249 {
250 return false;
251 }
252 }
253
254