PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.13
Yatra – Travel Booking & Tour Operator Software v3.0.13
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
yatra / app / Models / RecurringRule.php

RecurringRule.php in Yatra – Travel Booking & Tour Operator Software 3.0.13, at app/Models/RecurringRule.php

203 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\Models;
6
7 /**
8 * Recurring Rule Model
9 * Represents a recurring rule that generates departure dates dynamically
10 *
11 * Rules do NOT generate dates automatically in the database.
12 * They only act as rules for dynamic date generation on the frontend.
13 */
14 class RecurringRule
15 {
16 public int $id = 0;
17 public int $trip_id = 0;
18 public string $name = '';
19 public string $status = 'active'; // active | inactive | paused
20 public string $recurrence_type = 'weekly'; // daily | weekly | monthly | yearly | custom
21 public ?string $recurrence_pattern = null;
22 public ?string $start_date = null; // Start date for the rule
23 public ?string $end_date = null; // Optional end date for the rule
24 public ?array $days_of_week = null; // JSON array: [0,1,2,3,4,5,6] (Sun-Sat)
25 public ?int $day_of_month = null;
26 public ?int $month_of_year = null;
27 public int $interval = 1;
28 public string $availability_status = 'available';
29 /** @var int[]|null Months 1–12 when rule is limited to specific months; null = all months */
30 public ?array $allowed_months = null;
31 public ?int $max_bookings = null;
32 public ?float $price_override = null;
33 public string $price_type = 'fixed';
34 public ?string $departure_time = null;
35 public ?string $arrival_time = null;
36 public ?float $duration_hours = null;
37 public ?string $from_location = null;
38 public ?string $to_location = null;
39 public ?string $from_latitude = null;
40 public ?string $from_longitude = null;
41 public ?string $to_latitude = null;
42 public ?string $to_longitude = null;
43 public ?array $exceptions = null;
44 public string $exception_type = 'exclude';
45 public string $capacity_type = 'fixed';
46 public ?int $capacity_value = null;
47 // The rule editor persists the seat cap here; `capacity_value` is only written
48 // by the legacy `/trips/{id}/recurring-rules` path. Both are read (seats_total
49 // first) so rules created by either path resolve to the same capacity.
50 public ?int $seats_total = null;
51 public float $pricing_adjustment = 0.00;
52 public string $pricing_adjustment_type = 'amount';
53 public ?int $cutoff_hours = null;
54 public ?int $cutoff_days = null;
55 public ?int $advance_booking_days = null;
56 public ?int $minimum_participants = null;
57 public ?int $maximum_participants = null;
58 public ?array $age_restrictions = null;
59 public ?string $skill_level = null;
60 public string $season_type = 'all';
61 public bool $holiday_only = false;
62 public bool $weekend_only = false;
63 public bool $weekday_only = false;
64 public ?string $notes = null;
65 public int $priority = 10;
66 public bool $auto_generate = true;
67 public ?string $last_generated = null;
68 public string $created_at = '';
69 public string $updated_at = '';
70 public ?int $created_by = null;
71 public ?int $updated_by = null;
72
73 /**
74 * Create from array (database row)
75 */
76 public static function fromArray(array $data): self
77 {
78 $rule = new self();
79
80 $rule->id = (int) ($data['id'] ?? 0);
81 $rule->trip_id = (int) ($data['trip_id'] ?? 0);
82 $rule->name = sanitize_text_field($data['name'] ?? '');
83 $rule->status = sanitize_text_field($data['status'] ?? 'active');
84 $rule->recurrence_type = sanitize_text_field($data['recurrence_type'] ?? 'weekly');
85 $rule->start_date = !empty($data['start_date']) ? sanitize_text_field($data['start_date']) : null;
86 $rule->end_date = !empty($data['end_date']) ? sanitize_text_field($data['end_date']) : null;
87 $rule->capacity_value = (int) ($data['capacity_value'] ?? 0);
88 $rule->seats_total = isset($data['seats_total']) && $data['seats_total'] !== null && $data['seats_total'] !== ''
89 ? (int) $data['seats_total']
90 : null;
91 $rule->price_override = !empty($data['price_override']) ? (float) $data['price_override'] : null;
92 $rule->created_at = $data['created_at'] ?? '';
93 $rule->updated_at = $data['updated_at'] ?? '';
94 $rule->availability_status = sanitize_text_field($data['availability_status'] ?? 'available');
95
96 $allowedMonths = null;
97 if (isset($data['months']) && $data['months'] !== '' && $data['months'] !== null) {
98 $mRaw = $data['months'];
99 if (is_string($mRaw)) {
100 $decodedM = json_decode($mRaw, true);
101 $allowedMonths = is_array($decodedM) ? array_values(array_unique(array_map('intval', $decodedM))) : null;
102 } elseif (is_array($mRaw)) {
103 $allowedMonths = array_values(array_unique(array_map('intval', $mRaw)));
104 }
105 }
106 if (($allowedMonths === null || $allowedMonths === []) && !empty($data['recurrence_pattern'])) {
107 $rp = $data['recurrence_pattern'];
108 if (is_string($rp)) {
109 $rp = json_decode($rp, true);
110 }
111 if (is_array($rp) && !empty($rp['months']) && is_array($rp['months'])) {
112 $allowedMonths = array_values(array_unique(array_map('intval', $rp['months'])));
113 }
114 }
115 $rule->allowed_months = ($allowedMonths !== null && $allowedMonths !== []) ? $allowedMonths : null;
116
117 // Handle days_of_week as JSON or comma-separated string
118 if (isset($data['days_of_week'])) {
119 if (is_string($data['days_of_week'])) {
120 // Try JSON first, then comma-separated
121 $decoded = json_decode($data['days_of_week'], true);
122 if (is_array($decoded)) {
123 $rule->days_of_week = array_map('intval', $decoded);
124 } else {
125 $rule->days_of_week = array_map('intval', explode(',', $data['days_of_week']));
126 }
127 } elseif (is_array($data['days_of_week'])) {
128 $rule->days_of_week = array_map('intval', $data['days_of_week']);
129 } else {
130 $rule->days_of_week = [];
131 }
132 }
133
134 // Handle exceptions as JSON
135 if (isset($data['exceptions'])) {
136 if (is_string($data['exceptions'])) {
137 $rule->exceptions = json_decode($data['exceptions'], true) ?: [];
138 } elseif (is_array($data['exceptions'])) {
139 $rule->exceptions = $data['exceptions'];
140 } else {
141 $rule->exceptions = [];
142 }
143 }
144
145 return $rule;
146 }
147
148 /**
149 * Convert to array
150 */
151 public function toArray(): array
152 {
153 return [
154 'id' => $this->id,
155 'trip_id' => $this->trip_id,
156 'recurrence_type' => $this->recurrence_type,
157 'weekdays' => $this->weekdays,
158 'start_date' => $this->start_date,
159 'end_date' => $this->end_date,
160 'max_capacity' => $this->max_capacity,
161 'pricing_by_traveler_type' => $this->pricing_by_traveler_type,
162 'base_price' => $this->base_price,
163 'is_active' => $this->is_active,
164 'created_at' => $this->created_at,
165 'updated_at' => $this->updated_at,
166 ];
167 }
168
169 /**
170 * Check if rule is active for a given date
171 */
172 public function isActiveForDate(string $date): bool
173 {
174 if ($this->status !== 'active') {
175 return false;
176 }
177
178 if ($this->availability_status === 'unavailable') {
179 return false;
180 }
181
182 // Check start date
183 if ($this->start_date && $date < $this->start_date) {
184 return false;
185 }
186
187 // Check end date
188 if ($this->end_date && $date > $this->end_date) {
189 return false;
190 }
191
192 if ($this->allowed_months !== null && $this->allowed_months !== []) {
193 $month = (int) date('n', strtotime($date . ' 00:00:00'));
194 if (!in_array($month, $this->allowed_months, true)) {
195 return false;
196 }
197 }
198
199 return true;
200 }
201 }
202
203