PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.17
Yatra – Travel Booking & Tour Operator Software v3.0.17
3.0.17 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 All 85 releases
← All changes | app/Services/InstallerService.php +162 -74 3.0.6 → 3.0.17 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,109 @@
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 + // Off on a fresh install — see SettingsService::$defaults for why.
211 + $seed('yatra_email_template_review_request', false);
212 + $seed('yatra_email_template_abandoned_booking_recovery_first', true);
213 + $seed('yatra_email_template_abandoned_booking_recovery_second', true);
214 + $seed('yatra_email_template_abandoned_booking_recovery_final', true);
198 215
199 - // Clear any existing Stripe/PayPal settings that might exist
200 - delete_option('yatra_stripe_settings');
201 - delete_option('yatra_paypal_settings');
216 + // Clear pre-existing legacy Stripe/PayPal settings, but only on a
217 + // brand-new install. On a reactivation these may hold the operator's
218 + // configured gateway data, so deleting them would be destructive.
219 + if ($isFreshInstall) {
220 + delete_option('yatra_stripe_settings');
221 + delete_option('yatra_paypal_settings');
222 + }
202 223
203 - // Set installation tracking (not in SettingsService but needed for tracking)
204 - update_option('yatra_installation_date', current_time('mysql'));
224 + // Installation tracking: stamp the date once (seed); keep the
225 + // version current so upgrade routines can detect version changes.
226 + $seed('yatra_installation_date', current_time('mysql'));
205 227 update_option('yatra_version', defined('YATRA_VERSION') ? YATRA_VERSION : '3.0.3');
206 228
207 229
208 230 }
@@ -492,8 +514,74 @@
492 514 . "WHERE `status` = '' AND `payment_status` = 'pending'"
493 515 );
494 516
495 517 update_option('yatra_booking_status_pending_verification_v1', '1', false);
518 + }
519 +
520 + /**
521 + * Add the `duration_hours` column to the trips table for hour-based
522 + * (single-day) tours. Purely additive and nullable — existing trips get
523 + * NULL and behave exactly as before (day-based via `duration_days`). Only
524 + * tours that later set a positive `duration_hours` change behaviour.
525 + *
526 + * Idempotent: guarded by a one-shot option AND an INFORMATION_SCHEMA check,
527 + * so it runs its ALTER at most once and is a no-op when the column already
528 + * exists (fresh installs get it from TripsTable::getSchema()).
529 + */
530 + public static function maybeAddTripDurationHoursColumn(): void
531 + {
532 + if (get_option('yatra_trip_duration_hours_v1')) {
533 + return;
534 + }
535 +
536 + if (!class_exists('Yatra\\Database\\Tables\\TripsTable')) {
537 + return;
538 + }
539 +
540 + $table = \Yatra\Database\Tables\TripsTable::getTableName();
541 + if (!self::databaseTableExists($table)) {
542 + return;
543 + }
544 +
545 + global $wpdb;
546 +
547 + $columnExists = $wpdb->get_var(
548 + $wpdb->prepare(
549 + "SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
550 + WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s AND COLUMN_NAME = %s",
551 + DB_NAME,
552 + $table,
553 + 'duration_hours'
554 + )
555 + );
556 +
557 + if (!$columnExists) {
558 + // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- table name escaped, static column definition.
559 + $wpdb->query(
560 + 'ALTER TABLE `' . esc_sql($table) . '` '
561 + . "ADD COLUMN `duration_hours` smallint(5) UNSIGNED DEFAULT NULL "
562 + . "COMMENT 'Duration in hours for hour-based single-day tours, NULL means day-based' "
563 + . 'AFTER `duration_nights`'
564 + );
565 +
566 + // Re-check so we only mark this done when the column really exists.
567 + // If the ALTER failed (e.g. a restrictive host), leave the one-shot
568 + // flag unset so it retries on the next admin load rather than
569 + // disabling the feature permanently.
570 + $columnExists = $wpdb->get_var(
571 + $wpdb->prepare(
572 + "SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
573 + WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s AND COLUMN_NAME = %s",
574 + DB_NAME,
575 + $table,
576 + 'duration_hours'
577 + )
578 + );
579 + }
580 +
581 + if ($columnExists) {
582 + update_option('yatra_trip_duration_hours_v1', '1', false);
583 + }
496 584 }
497 585
498 586 /**
499 587 * Fill canonical + legacy email identity options when empty (upgrades, partial installs, or empty strings in DB).