PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.2.9
Yatra – Travel Booking & Tour Operator Software v3.0.2.9
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 / Services / InstallerService.php

InstallerService.php in Yatra – Travel Booking & Tour Operator Software 3.0.2.9, at app/Services/InstallerService.php

382 lines 15.0 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\Services;
6
7 /**
8 * Installer Service
9 *
10 * Handles plugin installation and default settings setup
11 * Ensures proper default configuration on fresh installation
12 */
13 class InstallerService
14 {
15 /**
16 * Run installation tasks
17 *
18 * @return void
19 */
20 public static function install(): void
21 {
22 // Create all database tables (one-time action)
23 self::createDatabaseTables();
24
25 // Set all default options for fresh installation
26 self::setDefaultOptions();
27 }
28
29 /**
30 * Create all database tables (centralized table creation)
31 *
32 * @return void
33 */
34 public static function createDatabaseTables(): void
35 {
36 if (class_exists('\Yatra\Core\Database')) {
37 \Yatra\Core\Database::createTables();
38 }
39
40 }
41
42 /**
43 * Set all default options for fresh installation
44 * Only Book Now Pay Later should be enabled by default
45 * Uses SettingsService keys to ensure consistency
46 *
47 * @return void
48 */
49 private static function setDefaultOptions(): void
50 {
51 // Payment Gateway Settings - Only enable Pay Later by default
52 // These match SettingsService defaults exactly
53 update_option('yatra_payment_gateways', ['pay_later']);
54 update_option('yatra_payment_methods', []);
55 update_option('yatra_payment_test_mode', true);
56 update_option('yatra_auto_confirm_pay_later', true);
57 update_option('yatra_partial_payment', false);
58 // Set gateway configs with proper structure - only enable pay_later by default
59 $gateway_configs = [
60 'pay_later' => [
61 'enabled' => true,
62 'title' => 'Book Now, Pay Later',
63 'description' => 'Allow customers to reserve now and pay before the trip',
64 ],
65 // Explicitly disable all other gateways
66 'stripe' => [
67 'enabled' => false,
68 'title' => 'Stripe',
69 'description' => 'Accept credit and debit cards',
70 'api_key' => '',
71 'api_secret' => '',
72 'webhook_secret' => '',
73 ],
74 'paypal' => [
75 'enabled' => false,
76 'title' => 'PayPal',
77 'description' => 'Accept PayPal payments',
78 'api_key' => '',
79 'api_secret' => '',
80 ],
81 'razorpay' => [
82 'enabled' => false,
83 'title' => 'Razorpay',
84 'description' => 'Accept payments via Razorpay',
85 'api_key' => '',
86 'api_secret' => '',
87 ],
88 'square' => [
89 'enabled' => false,
90 'title' => 'Square',
91 'description' => 'Accept payments via Square',
92 'api_key' => '',
93 'api_secret' => '',
94 ],
95 'authorize_net' => [
96 'enabled' => false,
97 'title' => 'Authorize.net',
98 'description' => 'Accept payments via Authorize.net',
99 'api_key' => '',
100 'api_secret' => '',
101 ],
102 'bank_transfer' => [
103 'enabled' => false,
104 'title' => 'Bank Transfer',
105 'description' => 'Accept manual bank transfer payments',
106 'api_key' => '',
107 'api_secret' => '',
108 ]
109 ];
110 update_option('yatra_gateway_configs', $gateway_configs);
111 update_option('yatra_gateway_order', []);
112
113 // Currency Settings - Match SettingsService defaults
114 update_option('yatra_currency', 'USD');
115 update_option('yatra_currency_position', 'before');
116 update_option('yatra_thousand_separator', ',');
117 update_option('yatra_decimal_separator', '.');
118 update_option('yatra_decimal_places', 2);
119
120 // Flexible Payment Settings - Match SettingsService defaults
121 update_option('yatra_enable_deposit', false);
122 update_option('yatra_deposit_type', 'percentage');
123 update_option('yatra_deposit_amount', 20);
124 update_option('yatra_deposit_required', false);
125 update_option('yatra_deposit_percentage', 20);
126 update_option('yatra_partial_payment_percentage', 30);
127
128 // Scheduled Payment Settings - Match SettingsService defaults
129 update_option('yatra_enable_scheduled_payments', false);
130 update_option('yatra_scheduled_payment_type', 'single');
131 update_option('yatra_scheduled_payment_days', 15);
132 update_option('yatra_scheduled_payment_installments', 1);
133 update_option('yatra_scheduled_payment_interval', 30);
134 update_option('yatra_scheduled_payment_reminder_days', 3);
135 update_option('yatra_allow_save_payment_methods', false);
136
137 // Trip Settings - Match SettingsService defaults
138 update_option('yatra_trip_base', 'trip');
139 update_option('yatra_trips_per_page', 12);
140 update_option('yatra_enable_wishlist', false);
141 update_option('yatra_enable_comparison', false);
142 update_option('yatra_show_sold_out', true);
143
144 // Customer Settings - Match SettingsService defaults
145 update_option('yatra_enable_customer_accounts', true);
146 update_option('yatra_enable_customer_registration', true);
147
148 // Booking Settings - Match SettingsService defaults
149 update_option('yatra_booking_base', 'book');
150 update_option('yatra_use_booking_page', false);
151 update_option('yatra_booking_page_id', 0);
152 update_option('yatra_enable_guest_booking', true);
153 update_option('yatra_booking_confirmation', true);
154 update_option('yatra_auto_confirm_bookings', false);
155 update_option('yatra_require_login', false);
156 update_option('yatra_allow_guest_checkout', true);
157 update_option('yatra_cancellation_policy', 'full_refund');
158 update_option('yatra_cancellation_days', 7);
159 update_option('yatra_refund_policy', '');
160 update_option('yatra_booking_expiry_hours', 24);
161 update_option('yatra_booking_reminder_days', 3);
162 update_option('yatra_allow_waitlist', true);
163
164 // Email identity: canonical keys (REST / EmailService) + legacy keys for older code paths
165 $wpAdminEmail = (string) get_option('admin_email', '');
166 $blogName = (string) get_bloginfo('name');
167 update_option('yatra_from_email', $wpAdminEmail);
168 update_option('yatra_from_name', $blogName);
169 update_option('yatra_admin_email', $wpAdminEmail);
170 update_option('yatra_email_from_name', $blogName);
171 update_option('yatra_email_from_address', $wpAdminEmail);
172 update_option('yatra_enable_admin_notifications', true);
173 update_option('yatra_enable_customer_notifications', true);
174
175 // Default transactional template HTML + subjects (Email → Templates / settings API)
176 foreach (EmailTemplateDefaults::settingsOptionDefaults() as $optionKey => $value) {
177 update_option('yatra_' . $optionKey, $value);
178 }
179 update_option('yatra_email_template_booking', true);
180 update_option('yatra_email_template_confirmation', true);
181 update_option('yatra_email_template_cancellation', true);
182 update_option('yatra_email_template_reminder', true);
183 update_option('yatra_email_template_admin_new_booking', true);
184 update_option('yatra_email_template_admin_payment', true);
185 update_option('yatra_email_template_admin_cancellation', true);
186
187 // Clear any existing Stripe/PayPal settings that might exist
188 delete_option('yatra_stripe_settings');
189 delete_option('yatra_paypal_settings');
190
191 // Set installation tracking (not in SettingsService but needed for tracking)
192 update_option('yatra_installation_date', current_time('mysql'));
193 update_option('yatra_version', defined('YATRA_VERSION') ? YATRA_VERSION : '3.0.2.4');
194
195
196 }
197
198 /**
199 * Get all required database tables using Table classes
200 *
201 * @return array
202 */
203 public static function getRequiredTables(): array
204 {
205 // Must match \Yatra\Core\Database::createTables() — used for activation, migrations, and targeted checks.
206 $table_classes = [
207 \Yatra\Database\Tables\TripsTable::class,
208 \Yatra\Database\Tables\BookingsTable::class,
209 \Yatra\Database\Tables\BookingPaymentsTable::class,
210 \Yatra\Database\Tables\ScheduledPaymentsTable::class,
211 \Yatra\Database\Tables\PaymentTokensTable::class,
212 \Yatra\Database\Tables\CustomersTable::class,
213 \Yatra\Database\Tables\BookingTravellersTable::class,
214 \Yatra\Database\Tables\BookingTravellerMetaTable::class,
215 \Yatra\Database\Tables\BookingDeparturesTable::class,
216 \Yatra\Database\Tables\ReviewsTable::class,
217 \Yatra\Database\Tables\DiscountsTable::class,
218 \Yatra\Database\Tables\EnquiriesTable::class,
219 \Yatra\Database\Tables\TripAvailabilityDatesTable::class,
220 \Yatra\Database\Tables\TripAvailabilityRulesTable::class,
221 \Yatra\Database\Tables\TripRevisionsTable::class,
222 \Yatra\Database\Tables\DeparturesTable::class,
223 \Yatra\Database\Tables\TripItineraryDaysTable::class,
224 \Yatra\Database\Tables\TripItineraryDayEntryTable::class,
225 \Yatra\Database\Tables\ClassificationsTable::class,
226 \Yatra\Database\Tables\TripClassificationsTable::class,
227 \Yatra\Database\Tables\TripContentTable::class,
228 ];
229
230 $table_names = [];
231 foreach ($table_classes as $table_class) {
232 if (class_exists($table_class)) {
233 $table_names[] = $table_class::getTableName();
234 }
235 }
236
237 return $table_names;
238 }
239
240 /**
241 * Whether a prefixed table exists. Uses esc_like() because SQL LIKE treats "_" as a wildcard.
242 */
243 public static function databaseTableExists(string $fullTableName): bool
244 {
245 global $wpdb;
246 if ($fullTableName === '') {
247 return false;
248 }
249 $pattern = $wpdb->esc_like($fullTableName);
250 $found = $wpdb->get_var($wpdb->prepare('SHOW TABLES LIKE %s', $pattern));
251
252 return $found === $fullTableName;
253 }
254
255 /**
256 * Check if this is a fresh installation
257 *
258 * @return bool
259 */
260 public static function isFreshInstallation(): bool
261 {
262 // Check if Yatra version exists in database
263 $installed_version = get_option('yatra_version');
264
265 // If no version is set, it's a fresh installation
266 if ($installed_version === false) {
267 return true;
268 }
269
270 // Check installation date
271 $installation_date = get_option('yatra_installation_date');
272 if ($installation_date === false) {
273 return true;
274 }
275
276 // Additional check: if core tables don't exist, it's fresh
277 $required_tables = self::getRequiredTables();
278 if (!empty($required_tables)) {
279 $trips_table = $required_tables[0]; // Use first table (already has prefix)
280 if (!self::databaseTableExists($trips_table)) {
281 return true;
282 }
283 }
284
285 return false;
286 }
287
288 /**
289 * One-time: coupon migration incorrectly stored status "active"; 3.x uses "publish" (admin + checkout).
290 */
291 public static function maybeNormalizeMigratedCouponDiscountStatuses(): void
292 {
293 if (get_option('yatra_discount_active_status_normalized_v1')) {
294 return;
295 }
296
297 if (!class_exists('Yatra\\Database\\Tables\\DiscountsTable')) {
298 return;
299 }
300
301 $table = \Yatra\Database\Tables\DiscountsTable::getTableName();
302 if (!self::databaseTableExists($table)) {
303 return;
304 }
305
306 global $wpdb;
307 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- table name from schema helper
308 $wpdb->query("UPDATE `{$table}` SET `status` = 'publish' WHERE `status` = 'active'");
309
310 update_option('yatra_discount_active_status_normalized_v1', '1', false);
311 }
312
313 /**
314 * Fill canonical + legacy email identity options when empty (upgrades, partial installs, or empty strings in DB).
315 * Idempotent; safe to run on each admin load via maybeBackfillEmailTemplateDefaults().
316 */
317 public static function maybeBackfillEmailDeliveryIdentity(): void
318 {
319 $wpAdmin = trim((string) get_option('admin_email', ''));
320 $wpName = trim((string) get_bloginfo('name'));
321
322 $isUnsetOrEmpty = static function ($v): bool {
323 return $v === false || $v === null || $v === '' || (is_string($v) && trim($v) === '');
324 };
325
326 if ($wpAdmin !== '') {
327 foreach (['yatra_admin_email', 'yatra_from_email', 'yatra_email_from_address'] as $opt) {
328 if ($isUnsetOrEmpty(get_option($opt, false))) {
329 update_option($opt, $wpAdmin);
330 }
331 }
332 }
333 if ($wpName !== '') {
334 foreach (['yatra_from_name', 'yatra_email_from_name'] as $opt) {
335 if ($isUnsetOrEmpty(get_option($opt, false))) {
336 update_option($opt, $wpName);
337 }
338 }
339 }
340 }
341
342 /**
343 * One-time: persist default HTML subjects/bodies when options exist but are empty (pre-template-defaults installs).
344 */
345 public static function maybeBackfillEmailTemplateDefaults(): void
346 {
347 self::maybeBackfillEmailDeliveryIdentity();
348
349 // Default-on for new option on existing sites (add_option no-ops if already present).
350 add_option('yatra_email_template_admin_new_booking', 1);
351 add_option('yatra_email_template_admin_payment', 1);
352 add_option('yatra_email_template_admin_cancellation', 1);
353
354 if (!get_option('yatra_email_identity_synced_v1')) {
355 $from = get_option('yatra_from_email', '');
356 if (($from === false || $from === '') && ($legacy = get_option('yatra_email_from_address', '')) && is_string($legacy) && $legacy !== '') {
357 update_option('yatra_from_email', $legacy);
358 }
359 $fname = get_option('yatra_from_name', '');
360 if (($fname === false || $fname === '') && ($legacy = get_option('yatra_email_from_name', '')) && is_string($legacy) && $legacy !== '') {
361 update_option('yatra_from_name', $legacy);
362 }
363 update_option('yatra_email_identity_synced_v1', '1');
364 }
365
366 if (get_option('yatra_email_tpl_defaults_backfill_1')) {
367 return;
368 }
369
370 foreach (EmailTemplateDefaults::settingsOptionDefaults() as $key => $defaultValue) {
371 $name = 'yatra_' . $key;
372 $current = get_option($name, false);
373 $isEmpty = $current === false || $current === '' || (is_string($current) && trim($current) === '');
374 if ($isEmpty) {
375 update_option($name, $defaultValue);
376 }
377 }
378
379 update_option('yatra_email_tpl_defaults_backfill_1', '1');
380 }
381 }
382