PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.16
Yatra – Travel Booking & Tour Operator Software v3.0.16
3.0.16 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 All 84 releases
← All changes | app/Services/InstallerService.php +161 -74 3.0.9 → 3.0.16 View file →
@@ -47,15 +47,31 @@
47 47 * @return void
48 48 */
49 49 private static function setDefaultOptions(): void
50 50 {
51 + // Whether this is a brand-new install vs. a reactivation/upgrade.
52 + // Captured before version/date are stamped below so it reflects the
53 + // pre-activation state.
54 + $isFreshInstall = self::isFreshInstallation();
55 +
56 + // Seed a default only when the option is absent. add_option() is a
57 + // no-op when the option already exists (existence is keyed on the
58 + // option NAME, so values legitimately stored as false/0/'' are still
59 + // preserved). This makes activation idempotent: a deactivate ->
60 + // reactivate, or a plugin update, can never overwrite an operator's
61 + // saved settings, while a fresh install (and any newly-introduced
62 + // default on upgrade) is still seeded.
63 + $seed = static function (string $name, $value): void {
64 + add_option($name, $value);
65 + };
66 +
51 67 // Payment Gateway Settings - Only enable Pay Later by default
52 68 // 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);
69 + $seed('yatra_payment_gateways', ['pay_later']);
70 + $seed('yatra_payment_methods', []);
71 + $seed('yatra_payment_test_mode', true);
72 + $seed('yatra_auto_confirm_pay_later', true);
73 + $seed('yatra_partial_payment', false);
58 74 // Set gateway configs with proper structure - only enable pay_later by default
59 75 $gateway_configs = [
60 76 'pay_later' => [
61 77 'enabled' => true,
@@ -106,103 +122,108 @@
106 122 'api_key' => '',
107 123 'api_secret' => '',
108 124 ]
109 125 ];
110 - update_option('yatra_gateway_configs', $gateway_configs);
111 - update_option('yatra_gateway_order', []);
126 + $seed('yatra_gateway_configs', $gateway_configs);
127 + $seed('yatra_gateway_order', []);
112 128
113 129 // 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);
130 + $seed('yatra_currency', 'USD');
131 + $seed('yatra_currency_position', 'before');
132 + $seed('yatra_thousand_separator', ',');
133 + $seed('yatra_decimal_separator', '.');
134 + $seed('yatra_decimal_places', 2);
119 135
120 136 // 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);
137 + $seed('yatra_enable_deposit', false);
138 + $seed('yatra_deposit_type', 'percentage');
139 + $seed('yatra_deposit_amount', 20);
140 + $seed('yatra_deposit_required', false);
141 + $seed('yatra_deposit_percentage', 20);
142 + $seed('yatra_partial_payment_percentage', 30);
127 143
128 - update_option('yatra_allow_save_payment_methods', false);
144 + $seed('yatra_allow_save_payment_methods', false);
129 145
130 146 // Trip Settings - Match SettingsService defaults
131 - update_option('yatra_trip_base', 'trip');
132 - update_option('yatra_trips_per_page', 12);
133 - update_option('yatra_enable_wishlist', false);
134 - update_option('yatra_enable_comparison', false);
135 - update_option('yatra_show_sold_out', true);
147 + $seed('yatra_trip_base', 'trip');
148 + $seed('yatra_trips_per_page', 12);
149 + $seed('yatra_enable_wishlist', false);
150 + $seed('yatra_enable_comparison', false);
151 + $seed('yatra_show_sold_out', true);
136 152
137 153 // Customer Settings - Match SettingsService defaults
138 - update_option('yatra_enable_customer_accounts', true);
139 - update_option('yatra_enable_customer_registration', true);
154 + $seed('yatra_enable_customer_accounts', true);
155 + $seed('yatra_enable_customer_registration', true);
140 156
141 157 // Booking Settings - Match SettingsService defaults
142 - update_option('yatra_booking_base', 'book');
143 - update_option('yatra_use_booking_page', false);
144 - update_option('yatra_booking_page_id', 0);
145 - update_option('yatra_enable_guest_booking', true);
146 - update_option('yatra_booking_confirmation', true);
147 - update_option('yatra_auto_confirm_bookings', false);
148 - update_option('yatra_require_login', false);
149 - update_option('yatra_allow_guest_checkout', true);
158 + $seed('yatra_booking_base', 'book');
159 + $seed('yatra_use_booking_page', false);
160 + $seed('yatra_booking_page_id', 0);
161 + $seed('yatra_enable_guest_booking', true);
162 + $seed('yatra_booking_confirmation', true);
163 + $seed('yatra_auto_confirm_bookings', false);
164 + $seed('yatra_require_login', false);
165 + $seed('yatra_allow_guest_checkout', true);
150 166 // cancellation_policy / cancellation_days / refund_policy
151 167 // intentionally not seeded — these are removed settings (see
152 168 // SettingsController::$default_settings comment). Existing
153 169 // sites that already have orphan values stored will keep
154 170 // them in wp_options; new sites won't acquire them.
155 - update_option('yatra_booking_expiry_hours', 24);
156 - update_option('yatra_booking_reminder_days', 3);
157 - update_option('yatra_allow_waitlist', true);
171 + $seed('yatra_booking_expiry_hours', 24);
172 + $seed('yatra_booking_reminder_days', 3);
173 + $seed('yatra_allow_waitlist', true);
158 174
159 175 // Email identity: canonical keys (REST / EmailService) + legacy keys for older code paths
160 176 $wpAdminEmail = (string) get_option('admin_email', '');
161 177 $blogName = (string) get_bloginfo('name');
162 - update_option('yatra_from_email', $wpAdminEmail);
163 - update_option('yatra_from_name', $blogName);
164 - update_option('yatra_admin_email', $wpAdminEmail);
165 - update_option('yatra_email_from_name', $blogName);
166 - update_option('yatra_email_from_address', $wpAdminEmail);
167 - update_option('yatra_enable_admin_notifications', true);
168 - update_option('yatra_enable_customer_notifications', true);
178 + $seed('yatra_from_email', $wpAdminEmail);
179 + $seed('yatra_from_name', $blogName);
180 + $seed('yatra_admin_email', $wpAdminEmail);
181 + $seed('yatra_email_from_name', $blogName);
182 + $seed('yatra_email_from_address', $wpAdminEmail);
183 + $seed('yatra_enable_admin_notifications', true);
184 + $seed('yatra_enable_customer_notifications', true);
169 185
170 186 // Default transactional template HTML + subjects (Email → Templates / settings API)
171 187 foreach (EmailTemplateDefaults::settingsOptionDefaults() as $optionKey => $value) {
172 - update_option('yatra_' . $optionKey, $value);
188 + $seed('yatra_' . $optionKey, $value);
173 189 }
174 - update_option('yatra_email_template_booking', true);
175 - update_option('yatra_email_template_confirmation', true);
176 - update_option('yatra_email_template_cancellation', true);
177 - update_option('yatra_email_template_reminder', true);
178 - update_option('yatra_email_template_admin_new_booking', true);
179 - update_option('yatra_email_template_admin_payment', true);
180 - update_option('yatra_email_template_admin_cancellation', true);
181 - update_option('yatra_email_template_trip_consent', true);
182 - update_option('yatra_email_template_customer_verification', true);
183 - update_option('yatra_email_template_guest_verification', true);
184 - update_option('yatra_email_template_booking_completed', true);
185 - update_option('yatra_email_template_booking_expired_customer', true);
186 - update_option('yatra_email_template_admin_booking_expired', true);
187 - update_option('yatra_email_template_scheduled_payment_reminder', true);
188 - update_option('yatra_email_template_scheduled_payment_succeeded', true);
189 - update_option('yatra_email_template_scheduled_payment_failed', true);
190 - update_option('yatra_email_template_admin_scheduled_payment_failed', true);
191 - update_option('yatra_email_template_enquiry_received', true);
192 - update_option('yatra_email_template_enquiry_admin', true);
193 - update_option('yatra_email_template_enquiry_response', true);
194 - update_option('yatra_email_template_review_request', true);
195 - update_option('yatra_email_template_abandoned_booking_recovery_first', true);
196 - update_option('yatra_email_template_abandoned_booking_recovery_second', true);
197 - update_option('yatra_email_template_abandoned_booking_recovery_final', true);
190 + $seed('yatra_email_template_booking', true);
191 + $seed('yatra_email_template_confirmation', true);
192 + $seed('yatra_email_template_cancellation', true);
193 + $seed('yatra_email_template_reminder', true);
194 + $seed('yatra_email_template_admin_new_booking', true);
195 + $seed('yatra_email_template_admin_payment', true);
196 + $seed('yatra_email_template_admin_cancellation', true);
197 + $seed('yatra_email_template_trip_consent', true);
198 + $seed('yatra_email_template_customer_verification', true);
199 + $seed('yatra_email_template_guest_verification', true);
200 + $seed('yatra_email_template_booking_completed', true);
201 + $seed('yatra_email_template_booking_expired_customer', true);
202 + $seed('yatra_email_template_admin_booking_expired', true);
203 + $seed('yatra_email_template_scheduled_payment_reminder', true);
204 + $seed('yatra_email_template_scheduled_payment_succeeded', true);
205 + $seed('yatra_email_template_scheduled_payment_failed', true);
206 + $seed('yatra_email_template_admin_scheduled_payment_failed', true);
207 + $seed('yatra_email_template_enquiry_received', true);
208 + $seed('yatra_email_template_enquiry_admin', true);
209 + $seed('yatra_email_template_enquiry_response', true);
210 + $seed('yatra_email_template_review_request', true);
211 + $seed('yatra_email_template_abandoned_booking_recovery_first', true);
212 + $seed('yatra_email_template_abandoned_booking_recovery_second', true);
213 + $seed('yatra_email_template_abandoned_booking_recovery_final', true);
198 214
199 - // Clear any existing Stripe/PayPal settings that might exist
200 - delete_option('yatra_stripe_settings');
201 - delete_option('yatra_paypal_settings');
215 + // Clear pre-existing legacy Stripe/PayPal settings, but only on a
216 + // brand-new install. On a reactivation these may hold the operator's
217 + // configured gateway data, so deleting them would be destructive.
218 + if ($isFreshInstall) {
219 + delete_option('yatra_stripe_settings');
220 + delete_option('yatra_paypal_settings');
221 + }
202 222
203 - // Set installation tracking (not in SettingsService but needed for tracking)
204 - update_option('yatra_installation_date', current_time('mysql'));
223 + // Installation tracking: stamp the date once (seed); keep the
224 + // version current so upgrade routines can detect version changes.
225 + $seed('yatra_installation_date', current_time('mysql'));
205 226 update_option('yatra_version', defined('YATRA_VERSION') ? YATRA_VERSION : '3.0.3');
206 227
207 228
208 229 }
@@ -492,8 +513,74 @@
492 513 . "WHERE `status` = '' AND `payment_status` = 'pending'"
493 514 );
494 515
495 516 update_option('yatra_booking_status_pending_verification_v1', '1', false);
517 + }
518 +
519 + /**
520 + * Add the `duration_hours` column to the trips table for hour-based
521 + * (single-day) tours. Purely additive and nullable — existing trips get
522 + * NULL and behave exactly as before (day-based via `duration_days`). Only
523 + * tours that later set a positive `duration_hours` change behaviour.
524 + *
525 + * Idempotent: guarded by a one-shot option AND an INFORMATION_SCHEMA check,
526 + * so it runs its ALTER at most once and is a no-op when the column already
527 + * exists (fresh installs get it from TripsTable::getSchema()).
528 + */
529 + public static function maybeAddTripDurationHoursColumn(): void
530 + {
531 + if (get_option('yatra_trip_duration_hours_v1')) {
532 + return;
533 + }
534 +
535 + if (!class_exists('Yatra\\Database\\Tables\\TripsTable')) {
536 + return;
537 + }
538 +
539 + $table = \Yatra\Database\Tables\TripsTable::getTableName();
540 + if (!self::databaseTableExists($table)) {
541 + return;
542 + }
543 +
544 + global $wpdb;
545 +
546 + $columnExists = $wpdb->get_var(
547 + $wpdb->prepare(
548 + "SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
549 + WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s AND COLUMN_NAME = %s",
550 + DB_NAME,
551 + $table,
552 + 'duration_hours'
553 + )
554 + );
555 +
556 + if (!$columnExists) {
557 + // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- table name escaped, static column definition.
558 + $wpdb->query(
559 + 'ALTER TABLE `' . esc_sql($table) . '` '
560 + . "ADD COLUMN `duration_hours` smallint(5) UNSIGNED DEFAULT NULL "
561 + . "COMMENT 'Duration in hours for hour-based single-day tours, NULL means day-based' "
562 + . 'AFTER `duration_nights`'
563 + );
564 +
565 + // Re-check so we only mark this done when the column really exists.
566 + // If the ALTER failed (e.g. a restrictive host), leave the one-shot
567 + // flag unset so it retries on the next admin load rather than
568 + // disabling the feature permanently.
569 + $columnExists = $wpdb->get_var(
570 + $wpdb->prepare(
571 + "SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
572 + WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s AND COLUMN_NAME = %s",
573 + DB_NAME,
574 + $table,
575 + 'duration_hours'
576 + )
577 + );
578 + }
579 +
580 + if ($columnExists) {
581 + update_option('yatra_trip_duration_hours_v1', '1', false);
582 + }
496 583 }
497 584
498 585 /**
499 586 * Fill canonical + legacy email identity options when empty (upgrades, partial installs, or empty strings in DB).