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
yatra / uninstall.php

uninstall.php in Yatra – Travel Booking & Tour Operator Software 3.0.17, at uninstall.php

200 lines 6.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Runs when Yatra is deleted from the Plugins screen.
4 *
5 * Deleting a plugin is not the same as deactivating it, and WordPress only
6 * loads this one file — the plugin itself is never bootstrapped, so nothing
7 * here may assume an autoloader, a class or a helper exists.
8 *
9 * Nothing is removed unless the operator has switched on
10 * "Delete all data on uninstall" (Yatra → Settings → Uninstall). Left off,
11 * which is the default, every table and option survives so the plugin can be
12 * reinstalled with its bookings and customers intact.
13 *
14 * @package Yatra
15 */
16
17 defined('WP_UNINSTALL_PLUGIN') || exit;
18
19 /**
20 * Table suffixes owned by the free plugin.
21 *
22 * Mirrors \Yatra\Services\InstallerService::getRequiredTables(). Hard-coded
23 * on purpose: that class is not loaded during uninstall, and a missing
24 * autoloader must not leave data half-removed. Yatra Pro removes its own
25 * tables from its own uninstall.php.
26 */
27 function yatra_uninstall_free_table_suffixes(): array
28 {
29 return [
30 'yatra_trips',
31 'yatra_bookings',
32 'yatra_booking_payments',
33 'yatra_customers',
34 'yatra_booking_travellers',
35 'yatra_booking_traveller_meta',
36 'yatra_booking_departures',
37 'yatra_reviews',
38 'yatra_discounts',
39 'yatra_enquiries',
40 'yatra_trip_availability_dates',
41 'yatra_trip_availability_rules',
42 'yatra_trip_revisions',
43 'yatra_trip_departures',
44 'yatra_trip_itinerary_days',
45 'yatra_trip_itinerary_day_entry',
46 'yatra_classifications',
47 'yatra_trip_classifications',
48 'yatra_trip_content',
49 'yatra_tour_dates',
50 ];
51 }
52
53 /**
54 * Is Yatra Pro still installed on this site?
55 *
56 * Deleting the free plugin must not take Pro's settings and scheduled work with
57 * it while Pro is still sitting there: Pro keeps its own tables through its own
58 * uninstall.php, so wiping its configuration here would leave it half removed.
59 * Once Pro has gone too, there is nothing left to protect and the sweep below
60 * takes everything, so nothing is orphaned either way.
61 */
62 function yatra_uninstall_pro_still_installed(): bool
63 {
64 return file_exists(WP_PLUGIN_DIR . '/yatra-pro/yatra-pro.php');
65 }
66
67 /**
68 * Pro-owned options that do not carry the `yatra_pro_` prefix.
69 *
70 * Mirrors yatra_pro_uninstall_extra_option_names() in Yatra Pro. Repeated here
71 * because uninstall.php runs with no autoloader and cannot read the other
72 * plugin, the same reason both files hard-code their table lists.
73 */
74 function yatra_uninstall_pro_owned_options(): array
75 {
76 return [
77 'yatra_license',
78 'yatra_abandoned_last_seen_id',
79 'yatra_abandoned_recovery_settings',
80 'yatra_ai_chat_limits',
81 'yatra_ai_trip_chat_enabled',
82 'yatra_dynamic_pricing_settings',
83 'yatra_facebook_pixel_event_log',
84 'yatra_facebook_pixel_settings',
85 'yatra_google_analytics_event_log',
86 'yatra_google_analytics_settings',
87 'yatra_mailchimp_settings',
88 'yatra_mailchimp_sync_log',
89 'yatra_team_keep_access_on_module_disable',
90 ];
91 }
92
93 /**
94 * Pro cron hooks registered under the plain `yatra_` prefix.
95 *
96 * Mirrors yatra_pro_uninstall_cron_hooks(). Without this the free plugin's
97 * prefix test matched all of them and unscheduled Pro's queue, demand scores,
98 * reminders and consent runs while Pro was still installed and relying on them.
99 */
100 function yatra_uninstall_pro_owned_cron_hooks(): array
101 {
102 return [
103 'yatra_ai_audit_retention_tick',
104 'yatra_calculate_demand_scores',
105 'yatra_cleanup_abandoned_bookings',
106 'yatra_consent_daily_cron',
107 'yatra_process_email_queue',
108 'yatra_process_recovery_emails',
109 'yatra_send_payment_reminders',
110 'yatra_sync_scheduled_payments',
111 ];
112 }
113
114 /**
115 * Remove Yatra's data for the current site.
116 */
117 function yatra_uninstall_cleanup_site(): void
118 {
119 global $wpdb;
120
121 if (!get_option('yatra_delete_data_on_uninstall')) {
122 return;
123 }
124
125 // Several of these tables are the target of a foreign key held by another
126 // (availability and revisions both point at trips), so a plain DROP fails
127 // for whichever one is reached first and that table survives the uninstall.
128 // Order should not decide whether data is removed, so the constraints are
129 // lifted for the duration.
130 $wpdb->query('SET FOREIGN_KEY_CHECKS = 0');
131
132 foreach (yatra_uninstall_free_table_suffixes() as $suffix) {
133 $table = $wpdb->prefix . $suffix;
134 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
135 $wpdb->query("DROP TABLE IF EXISTS `{$table}`");
136 }
137
138 $wpdb->query('SET FOREIGN_KEY_CHECKS = 1');
139
140 // Scheduled work must go too, or WordPress keeps firing hooks for a plugin
141 // that is no longer installed.
142 $protectPro = yatra_uninstall_pro_still_installed();
143 $proHooks = yatra_uninstall_pro_owned_cron_hooks();
144 foreach ((array) _get_cron_array() as $timestamp => $hooks) {
145 foreach ((array) $hooks as $hook => $events) {
146 $hook = (string) $hook;
147 if (strpos($hook, 'yatra') !== 0) {
148 continue;
149 }
150 if ($protectPro && (strpos($hook, 'yatra_pro') === 0 || in_array($hook, $proHooks, true))) {
151 continue;
152 }
153 foreach ((array) $events as $event) {
154 wp_unschedule_event($timestamp, $hook, $event['args'] ?? []);
155 }
156 }
157 }
158
159 // Options and transients. `yatra_pro_` is left alone: those belong to Yatra
160 // Pro, which removes them from its own uninstall.php, and deleting them
161 // here would wipe Pro's settings whenever the free plugin is removed first.
162 $options = $wpdb->get_col(
163 "SELECT option_name FROM {$wpdb->options}
164 WHERE option_name LIKE 'yatra\\_%'
165 AND option_name NOT LIKE 'yatra\\_pro\\_%'"
166 );
167 $proOptions = $protectPro ? yatra_uninstall_pro_owned_options() : [];
168 foreach ((array) $options as $option) {
169 if ($proOptions && in_array($option, $proOptions, true)) {
170 continue;
171 }
172 delete_option($option);
173 }
174
175 $transients = $wpdb->get_col(
176 "SELECT option_name FROM {$wpdb->options}
177 WHERE option_name LIKE '\\_transient\\_yatra\\_%'
178 OR option_name LIKE '\\_transient\\_timeout\\_yatra\\_%'"
179 );
180 foreach ((array) $transients as $transient) {
181 delete_option($transient);
182 }
183
184 // User meta Yatra set on customers and staff.
185 $wpdb->query("DELETE FROM {$wpdb->usermeta} WHERE meta_key LIKE 'yatra\\_%'");
186 }
187
188 // Network-wide installs keep a separate set of tables and options per site, so
189 // each one has to be cleaned on its own.
190 if (is_multisite()) {
191 $sites = get_sites(['fields' => 'ids', 'number' => 0]);
192 foreach ((array) $sites as $siteId) {
193 switch_to_blog((int) $siteId);
194 yatra_uninstall_cleanup_site();
195 restore_current_blog();
196 }
197 } else {
198 yatra_uninstall_cleanup_site();
199 }
200