PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.2.8
Yatra – Travel Booking & Tour Operator Software v3.0.2.8
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
yatra / app / Services / InstallerService.php

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

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