PluginProbe ʕ •ᴥ•ʔ
WP Mail SMTP by WPForms – The Most Popular SMTP and Email Log Plugin / 3.5.2
WP Mail SMTP by WPForms – The Most Popular SMTP and Email Log Plugin v3.5.2
0.9.6 1.0.0 1.0.1 1.0.2 1.1.0 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.6.0 1.6.2 1.7.0 1.7.1 1.8.0 1.8.1 1.9.0 2.0.0 2.0.1 2.1.1 2.2.1 2.3.1 2.4.0 2.5.0 2.5.1 2.6.0 2.7.0 2.8.0 2.9.0 3.0.1 3.0.2 3.0.3 3.1.0 3.10.0 3.11.0 3.11.1 3.2.0 3.2.1 3.3.0 3.4.0 3.5.0 3.5.1 3.5.2 3.6.1 3.7.0 3.8.0 3.8.2 3.9.0 4.0.1 4.1.0 4.1.1 4.2.0 4.3.0 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.8.0 trunk 0.10.0 0.10.1 0.11.1 0.11.2 0.3.1 0.3.2 0.4 0.4.1 0.4.2 0.5.0 0.5.1 0.5.2 0.6 0.7 0.8 0.8.2 0.8.3 0.8.4 0.8.5 0.8.6 0.8.7 0.9.0 0.9.1 0.9.2 0.9.3 0.9.4 0.9.5
wp-mail-smtp / src / Migration.php
wp-mail-smtp / src Last commit date
Admin 3 years ago Compatibility 3 years ago Helpers 3 years ago Providers 3 years ago Reports 3 years ago Tasks 3 years ago UsageTracking 3 years ago Conflicts.php 3 years ago Connect.php 3 years ago Core.php 3 years ago Debug.php 3 years ago Geo.php 3 years ago MailCatcher.php 3 years ago MailCatcherInterface.php 3 years ago MailCatcherV6.php 3 years ago Migration.php 3 years ago MigrationAbstract.php 3 years ago Options.php 3 years ago Processor.php 3 years ago SiteHealth.php 3 years ago Upgrade.php 3 years ago Uploads.php 3 years ago WP.php 3 years ago
Migration.php
518 lines
1 <?php
2
3 namespace WPMailSMTP;
4
5 use WPMailSMTP\Reports\Emails\Summary as SummaryReportEmail;
6 use WPMailSMTP\Tasks\Meta;
7 use WPMailSMTP\Tasks\Reports\SummaryEmailTask as SummaryReportEmailTask;
8 use WPMailSMTP\Tasks\Tasks;
9
10 /**
11 * Class Migration helps migrate plugin options, DB tables and more.
12 *
13 * @since 1.0.0 Migrate all plugin options saved from separate WP options into one.
14 * @since 2.1.0 Major overhaul of this class to use DB migrations (or any other migrations per version).
15 * @since 3.0.0 Extends MigrationAbstract.
16 */
17 class Migration extends MigrationAbstract {
18
19 /**
20 * Version of the latest migration.
21 *
22 * @since 2.1.0
23 */
24 const VERSION = 5;
25
26 /**
27 * Option key where we save the current migration version.
28 *
29 * @since 2.1.0
30 */
31 const OPTION_NAME = 'wp_mail_smtp_migration_version';
32
33 /**
34 * Current migration version, received from static::OPTION_NAME WP option.
35 *
36 * @since 2.1.0
37 *
38 * @var int
39 */
40 protected $cur_ver;
41
42 /**
43 * All old values for pre 1.0 version of a plugin.
44 *
45 * @since 1.0.0
46 *
47 * @var array
48 */
49 protected $old_keys = array(
50 'pepipost_ssl',
51 'pepipost_port',
52 'pepipost_pass',
53 'pepipost_user',
54 'smtp_pass',
55 'smtp_user',
56 'smtp_auth',
57 'smtp_ssl',
58 'smtp_port',
59 'smtp_host',
60 'mail_set_return_path',
61 'mailer',
62 'mail_from_name',
63 'mail_from',
64 'wp_mail_smtp_am_notifications_hidden',
65 );
66
67 /**
68 * Old values, taken from $old_keys options.
69 *
70 * @since 1.0.0
71 *
72 * @var array
73 */
74 protected $old_values = array();
75
76 /**
77 * Converted array of data from previous option values.
78 *
79 * @since 1.0.0
80 *
81 * @var array
82 */
83 protected $new_values = array();
84
85 /**
86 * Initialize migration.
87 *
88 * @since 3.0.0
89 */
90 public function init() {
91
92 $this->maybe_migrate();
93 }
94
95 /**
96 * Static on purpose, to get current migration version without __construct() and validation.
97 *
98 * @since 2.1.0
99 *
100 * @return int
101 */
102 public static function get_cur_version() {
103
104 return (int) get_option( static::OPTION_NAME, 0 );
105 }
106
107 /**
108 * Run the migration if needed.
109 *
110 * @since 2.1.0
111 */
112 protected function maybe_migrate() {
113
114 if ( version_compare( $this->cur_ver, static::VERSION, '<' ) ) {
115 $this->run( static::VERSION );
116 }
117 }
118
119 /**
120 * Actual migration launcher.
121 *
122 * @since 2.1.0
123 *
124 * @param int $version The version of migration to run.
125 */
126 protected function run( $version ) {
127
128 $function_version = (int) $version;
129
130 if ( method_exists( $this, 'migrate_to_' . $function_version ) ) {
131 $this->{'migrate_to_' . $function_version}();
132 } else {
133 if ( WP::in_wp_admin() ) {
134 $message = sprintf( /* translators: %1$s - WP Mail SMTP, %2$s - error message. */
135 esc_html__( 'There was an error while upgrading the database. Please contact %1$s support with this information: %2$s.', 'wp-mail-smtp' ),
136 '<strong>WP Mail SMTP</strong>',
137 '<code>migration from v' . static::get_cur_version() . ' to v' . static::VERSION . ' failed. Plugin version: v' . WPMS_PLUGIN_VER . '</code>'
138 );
139
140 WP::add_admin_notice( $message, WP::ADMIN_NOTICE_ERROR );
141 }
142 }
143 }
144
145 /**
146 * Update migration version in options table.
147 *
148 * @since 2.1.0
149 *
150 * @param int $version Migration version.
151 */
152 protected function update_db_ver( $version = 0 ) {
153
154 if ( empty( $version ) ) {
155 $version = static::VERSION;
156 }
157
158 // Autoload it, because this value is checked all the time
159 // and no need to request it separately from all autoloaded options.
160 update_option( static::OPTION_NAME, $version, true );
161 }
162
163 /**
164 * Prevent running the same migration twice.
165 * Run migration only when required.
166 *
167 * @since 2.1.0
168 *
169 * @param string $version The version of migration to check for potential execution.
170 */
171 protected function maybe_required_older_migrations( $version ) {
172
173 if ( version_compare( $this->cur_ver, $version, '<' ) ) {
174 $this->run( $version );
175 }
176 }
177
178 /**
179 * Migration from 0.x to 1.0.0.
180 * Move separate plugin WP options to one main plugin WP option setting.
181 *
182 * @since 2.1.0
183 */
184 private function migrate_to_1() {
185
186 if ( $this->is_migrated() ) {
187 return;
188 }
189
190 $this->old_values = $this->get_old_values();
191 $this->new_values = $this->get_converted_options();
192
193 Options::init()->set( $this->new_values, true );
194
195 $this->update_db_ver( 1 );
196 }
197
198 /**
199 * Migration from 1.x to 2.1.0.
200 * Create Tasks\Meta table, if it does not exist.
201 *
202 * @since 2.1.0
203 */
204 private function migrate_to_2() {
205
206 $this->maybe_required_older_migrations( 1 );
207
208 $meta = new Meta();
209
210 // Create the table if it doesn't exist.
211 if ( $meta && ! $meta->table_exists() ) {
212 $meta->create_table();
213 }
214
215 $this->update_db_ver( 2 );
216 }
217
218 /**
219 * Migration to 2.6.0.
220 * Cancel all recurring ActionScheduler tasks, so they will be newly created and no longer
221 * cause PHP fatal error on PHP 8 (because of the named parameter 'tasks_meta_id').
222 *
223 * @since 2.6.0
224 */
225 private function migrate_to_3() {
226
227 $this->maybe_required_older_migrations( 2 );
228
229 $tasks = [];
230 $ut = new UsageTracking\UsageTracking();
231
232 if ( $ut->is_enabled() ) {
233 $tasks[] = '\WPMailSMTP\UsageTracking\SendUsageTask';
234 }
235
236 $recurring_tasks = apply_filters( 'wp_mail_smtp_migration_cancel_recurring_tasks', $tasks );
237
238 foreach ( $recurring_tasks as $task ) {
239 ( new $task() )->cancel();
240 }
241
242 $this->update_db_ver( 3 );
243 }
244
245 /**
246 * Migration to 3.0.0.
247 * Disable summary report email for Lite users and Multisite installations after update.
248 * For new installations we have default values in Options::get_defaults.
249 *
250 * @since 3.0.0
251 */
252 protected function migrate_to_4() {
253
254 $this->maybe_required_older_migrations( 3 );
255
256 $options = Options::init();
257
258 $value = $options->get( 'general', SummaryReportEmail::SETTINGS_SLUG );
259
260 // If option was not already set, then plugin was updated from lower version.
261 if (
262 ( $value === '' || $value === null ) &&
263 ( is_multisite() || ! wp_mail_smtp()->is_pro() )
264 ) {
265 $data = [
266 'general' => [
267 SummaryReportEmail::SETTINGS_SLUG => true,
268 ],
269 ];
270
271 $options->set( $data, false, false );
272
273 // Just to be safe cancel summary report email task.
274 ( new SummaryReportEmailTask() )->cancel();
275 }
276
277 $this->update_db_ver( 4 );
278 }
279
280 /**
281 * Cleanup scheduled actions meta table.
282 *
283 * @since 3.5.0
284 */
285 protected function migrate_to_5() {
286
287 $this->maybe_required_older_migrations( 4 );
288
289 global $wpdb;
290
291 $meta = new Meta();
292
293 if (
294 $meta->table_exists() &&
295 $meta->table_exists( $wpdb->prefix . 'actionscheduler_actions' ) &&
296 $meta->table_exists( $wpdb->prefix . 'actionscheduler_groups' )
297 ) {
298 $group = Tasks::GROUP;
299 $sql = "SELECT DISTINCT a.args FROM {$wpdb->prefix}actionscheduler_actions a
300 JOIN {$wpdb->prefix}actionscheduler_groups g ON g.group_id = a.group_id
301 WHERE g.slug = '$group' AND a.status IN ('pending', 'in-progress')";
302
303 // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
304 $results = $wpdb->get_results( $sql, 'ARRAY_A' );
305 // phpcs:enable WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
306
307 $results = $results ? $results : [];
308 $meta_ids = [];
309
310 foreach ( $results as $result ) {
311 $args = isset( $result['args'] ) ? json_decode( $result['args'], true ) : null;
312
313 if ( $args && isset( $args[0] ) && is_numeric( $args[0] ) ) {
314 $meta_ids[] = $args[0];
315 }
316 }
317
318 $table = Meta::get_table_name();
319 $not_in = 0;
320
321 if ( ! empty( $meta_ids ) ) {
322 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
323 $not_in = $wpdb->prepare( implode( ',', array_fill( 0, count( $meta_ids ), '%d' ) ), $meta_ids );
324 }
325
326 // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching
327 $wpdb->query( "DELETE FROM $table WHERE id NOT IN ($not_in)" );
328 // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching
329 }
330
331 // Save the current version to DB.
332 $this->update_db_ver( 5 );
333 }
334
335 /**
336 * Whether we already migrated or not.
337 *
338 * @since 1.0.0
339 *
340 * @return bool
341 */
342 protected function is_migrated() {
343
344 $is_migrated = false;
345 $new_values = get_option( Options::META_KEY, array() );
346
347 if ( ! empty( $new_values ) ) {
348 $is_migrated = true;
349 }
350
351 return $is_migrated;
352 }
353
354 /**
355 * Get all old values from DB.
356 *
357 * @since 1.0.0
358 *
359 * @return array
360 */
361 protected function get_old_values() {
362
363 $old_values = array();
364
365 foreach ( $this->old_keys as $old_key ) {
366 $value = get_option( $old_key, '' );
367
368 if ( ! empty( $value ) ) {
369 $old_values[ $old_key ] = $value;
370 }
371 }
372
373 return $old_values;
374 }
375
376 /**
377 * Convert old values from key=>value to a multidimensional array of data.
378 *
379 * @since 1.0.0
380 */
381 protected function get_converted_options() {
382
383 $converted = array();
384
385 foreach ( $this->old_keys as $old_key ) {
386
387 $old_value = isset( $this->old_values[ $old_key ] ) ? $this->old_values[ $old_key ] : '';
388
389 switch ( $old_key ) {
390 case 'pepipost_user':
391 case 'pepipost_pass':
392 case 'pepipost_port':
393 case 'pepipost_ssl':
394 // Do not migrate pepipost options if it's not activated at the moment.
395 if ( isset( $this->old_values['mailer'] ) && $this->old_values['mailer'] === 'pepipost' ) {
396 $shortcut = explode( '_', $old_key );
397
398 if ( $old_key === 'pepipost_ssl' ) {
399 $converted[ $shortcut[0] ]['encryption'] = $old_value;
400 } else {
401 $converted[ $shortcut[0] ][ $shortcut[1] ] = $old_value;
402 }
403 }
404 break;
405
406 case 'smtp_host':
407 case 'smtp_port':
408 case 'smtp_ssl':
409 case 'smtp_auth':
410 case 'smtp_user':
411 case 'smtp_pass':
412 $shortcut = explode( '_', $old_key );
413
414 if ( $old_key === 'smtp_ssl' ) {
415 $converted[ $shortcut[0] ]['encryption'] = $old_value;
416 } elseif ( $old_key === 'smtp_auth' ) {
417 $converted[ $shortcut[0] ][ $shortcut[1] ] = ( $old_value === 'true' ? 'yes' : 'no' );
418 } else {
419 $converted[ $shortcut[0] ][ $shortcut[1] ] = $old_value;
420 }
421
422 break;
423
424 case 'mail_from':
425 $converted['mail']['from_email'] = $old_value;
426 break;
427 case 'mail_from_name':
428 $converted['mail']['from_name'] = $old_value;
429 break;
430 case 'mail_set_return_path':
431 $converted['mail']['return_path'] = ( $old_value === 'true' );
432 break;
433 case 'mailer':
434 $converted['mail']['mailer'] = ! empty( $old_value ) ? $old_value : 'mail';
435 break;
436 case 'wp_mail_smtp_am_notifications_hidden':
437 $converted['general']['am_notifications_hidden'] = ( isset( $old_value ) && $old_value === 'true' );
438 break;
439 }
440 }
441
442 $converted = $this->get_converted_constants_options( $converted );
443
444 return $converted;
445 }
446
447 /**
448 * Some users use constants in wp-config.php to define values.
449 * We need to prioritize them and reapply data to options.
450 * Use only those that are actually defined.
451 *
452 * @since 1.0.0
453 *
454 * @param array $converted
455 *
456 * @return array
457 */
458 protected function get_converted_constants_options( $converted ) {
459
460 // Are we configured via constants?
461 if ( ! defined( 'WPMS_ON' ) || ! WPMS_ON ) {
462 return $converted;
463 }
464
465 /*
466 * Mail settings.
467 */
468 if ( defined( 'WPMS_MAIL_FROM' ) ) {
469 $converted['mail']['from_email'] = WPMS_MAIL_FROM;
470 }
471 if ( defined( 'WPMS_MAIL_FROM_NAME' ) ) {
472 $converted['mail']['from_name'] = WPMS_MAIL_FROM_NAME;
473 }
474 if ( defined( 'WPMS_MAILER' ) ) {
475 $converted['mail']['mailer'] = WPMS_MAILER;
476 }
477 if ( defined( 'WPMS_SET_RETURN_PATH' ) ) {
478 $converted['mail']['return_path'] = WPMS_SET_RETURN_PATH;
479 }
480
481 /*
482 * SMTP settings.
483 */
484 if ( defined( 'WPMS_SMTP_HOST' ) ) {
485 $converted['smtp']['host'] = WPMS_SMTP_HOST;
486 }
487 if ( defined( 'WPMS_SMTP_PORT' ) ) {
488 $converted['smtp']['port'] = WPMS_SMTP_PORT;
489 }
490 if ( defined( 'WPMS_SSL' ) ) {
491 $converted['smtp']['ssl'] = WPMS_SSL;
492 }
493 if ( defined( 'WPMS_SMTP_AUTH' ) ) {
494 $converted['smtp']['auth'] = WPMS_SMTP_AUTH;
495 }
496 if ( defined( 'WPMS_SMTP_USER' ) ) {
497 $converted['smtp']['user'] = WPMS_SMTP_USER;
498 }
499 if ( defined( 'WPMS_SMTP_PASS' ) ) {
500 $converted['smtp']['pass'] = WPMS_SMTP_PASS;
501 }
502
503 return $converted;
504 }
505
506 /**
507 * Delete all old values that are stored separately each.
508 *
509 * @since 1.0.0
510 */
511 protected function clean_deprecated_data() {
512
513 foreach ( $this->old_keys as $old_key ) {
514 delete_option( $old_key );
515 }
516 }
517 }
518