PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.33.1
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.33.1
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
formidable / classes / models / FrmMigrate.php

FrmMigrate.php in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More 6.33.1, at classes/models/FrmMigrate.php

916 lines 24.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 die( 'You are not allowed to call this page directly.' );
4 }
5
6 class FrmMigrate {
7
8 /**
9 * @var string
10 */
11 public $fields;
12
13 /**
14 * @var string
15 */
16 public $forms;
17
18 /**
19 * @var string
20 */
21 public $entries;
22
23 /**
24 * @var string
25 */
26 public $entry_metas;
27
28 /**
29 * @var string
30 */
31 public $gated_tokens;
32
33 public function __construct() {
34 global $wpdb;
35 $this->fields = $wpdb->prefix . 'frm_fields';
36 $this->forms = $wpdb->prefix . 'frm_forms';
37 $this->entries = $wpdb->prefix . 'frm_items';
38 $this->entry_metas = $wpdb->prefix . 'frm_item_metas';
39 $this->gated_tokens = $wpdb->prefix . 'frm_gated_tokens';
40 }
41
42 /**
43 * @return void
44 */
45 public function upgrade() {
46 do_action( 'frm_before_install' );
47
48 global $wpdb, $frm_vars;
49
50 $frm_vars['doing_upgrade'] = true;
51
52 $needs_upgrade = FrmAppController::compare_for_update(
53 array(
54 'option' => 'frm_db_version',
55 'new_db_version' => FrmAppHelper::$db_version,
56 'new_plugin_version' => FrmAppHelper::plugin_version(),
57 )
58 );
59
60 if ( $needs_upgrade ) {
61 $this->maybe_delete_htaccess_file();
62
63 // Update rewrite rules for views and other custom post types
64 flush_rewrite_rules();
65
66 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
67
68 $old_db_version = get_option( 'frm_db_version' );
69
70 $this->create_tables();
71 $this->migrate_data( $old_db_version );
72 $this->check_that_tables_exist();
73
74 // SAVE DB VERSION.
75 update_option( 'frm_db_version', FrmAppHelper::plugin_version() . '-' . FrmAppHelper::$db_version );
76
77 if ( ! $old_db_version ) {
78 $this->maybe_create_contact_form();
79
80 if ( false === get_option( 'frm_first_activation' ) ) {
81 update_option( 'frm_first_activation', time(), false );
82 }
83
84 $this->update_settings_for_new_install();
85 }
86 }//end if
87
88 do_action( 'frm_after_install' );
89
90 $frm_vars['doing_upgrade'] = false;
91
92 FrmAppHelper::save_combined_js();
93
94 // Update the styling settings
95 if ( ! function_exists( 'get_filesystem_method' ) ) {
96 return;
97 }
98
99 $frm_style = new FrmStyle();
100 $frm_style->update( 'default' );
101 }
102
103 /**
104 * Check if the .htaccess file should be deleted based on server response.
105 * If a server has AllowOverride FileInfo but not AllowOverride AuthConfig, JS and CSS files
106 * will result in a 500 error.
107 *
108 * @since 6.27
109 *
110 * @return void
111 */
112 private function maybe_delete_htaccess_file() {
113 $css_file_request = wp_remote_get( FrmAppHelper::plugin_url() . '/css/frm_fonts.css' );
114
115 if ( 200 === wp_remote_retrieve_response_code( $css_file_request ) ) {
116 return;
117 }
118
119 $htaccess_path = FrmAppHelper::plugin_path() . '/.htaccess';
120
121 if ( file_exists( $htaccess_path ) ) {
122 wp_delete_file( $htaccess_path );
123 }
124 }
125
126 /**
127 * Updates some settings for new installs.
128 *
129 * @since 6.23
130 *
131 * @return void
132 */
133 private function update_settings_for_new_install() {
134 $settings = FrmAppHelper::get_settings();
135
136 $settings->denylist_check = 1;
137 $settings->installed_after_welcome_tour_update = 1;
138 $settings->store();
139 }
140
141 /**
142 * If we fail to create the database tables, add an inbox notice.
143 * This informs the user that they need to correct the issue and try again.
144 *
145 * @since 6.19
146 *
147 * @return void
148 */
149 private function check_that_tables_exist() {
150 // Check the DB that the table $this->forms exists.
151 global $wpdb;
152 $exists = $wpdb->get_results( $wpdb->prepare( 'SHOW TABLES LIKE %s', $this->forms ) );
153
154 if ( $exists ) {
155 $inbox = new FrmInbox();
156 $inbox->dismiss( 'failed-to-create-tables' );
157 return;
158 }
159
160 $message = array(
161 'key' => 'failed-to-create-tables',
162 'subject' => 'Something went wrong setting up the database',
163 'message' => 'For steps to continue, see our <a href="https://formidableforms.com/knowledgebase/install-formidable-forms/#kb-missing-database-tables">documentation</a>. If you need assistance, we recommend that you reach out to your hosting provider. Then <a href="' . esc_url( admin_url( 'admin.php?page=formidable&frm_add_tables=1' ) ) . '">click here</a> to try again.', // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
164 'cta' => '<a href="https://formidableforms.com/knowledgebase/install-formidable-forms/#kb-missing-database-tables">Learn More</a>',
165 'type' => 'error',
166 );
167
168 $inbox = new FrmInbox();
169 $inbox->add_message( $message );
170 }
171
172 /**
173 * @return string
174 */
175 public function collation() {
176 global $wpdb;
177 return $wpdb->has_cap( 'collation' ) ? $wpdb->get_charset_collate() : '';
178 }
179
180 /**
181 * @return void
182 */
183 private function create_tables() {
184 $charset_collate = $this->collation();
185 $sql = array();
186
187 /* Create/Upgrade Fields Table */
188 $sql[] = 'CREATE TABLE ' . $this->fields . ' (
189 id BIGINT(20) NOT NULL auto_increment,
190 field_key varchar(100) default NULL,
191 name text default NULL,
192 description longtext default NULL,
193 type text default NULL,
194 default_value longtext default NULL,
195 options longtext default NULL,
196 field_order int(11) default 0,
197 required int(1) default NULL,
198 field_options longtext default NULL,
199 form_id int(11) default NULL,
200 created_at datetime NOT NULL,
201 PRIMARY KEY (id),
202 KEY form_id (form_id),
203 UNIQUE KEY field_key (field_key)
204 )';
205
206 /* Create/Upgrade Forms Table */
207 $sql[] = 'CREATE TABLE ' . $this->forms . ' (
208 id int(11) NOT NULL auto_increment,
209 form_key varchar(100) default NULL,
210 name varchar(255) default NULL,
211 description text default NULL,
212 parent_form_id int(11) default 0,
213 logged_in tinyint(1) default NULL,
214 editable tinyint(1) default NULL,
215 is_template tinyint(1) default 0,
216 default_template tinyint(1) default 0,
217 status varchar(255) default NULL,
218 options longtext default NULL,
219 created_at datetime NOT NULL,
220 PRIMARY KEY (id),
221 UNIQUE KEY form_key (form_key)
222 )';
223
224 /* Create/Upgrade Items Table */
225 $sql[] = 'CREATE TABLE ' . $this->entries . ' (
226 id BIGINT(20) NOT NULL auto_increment,
227 item_key varchar(100) default NULL,
228 name varchar(255) default NULL,
229 description text default NULL,
230 ip text default NULL,
231 form_id BIGINT(20) default NULL,
232 post_id BIGINT(20) default NULL,
233 user_id BIGINT(20) default NULL,
234 parent_item_id BIGINT(20) default 0,
235 is_draft tinyint(1) default 0,
236 updated_by BIGINT(20) default NULL,
237 created_at datetime NOT NULL,
238 updated_at datetime NOT NULL,
239 PRIMARY KEY (id),
240 KEY form_id (form_id),
241 KEY post_id (post_id),
242 KEY user_id (user_id),
243 KEY parent_item_id (parent_item_id),
244 UNIQUE KEY item_key (item_key)
245 )';
246
247 /* Create/Upgrade Meta Table */
248 $sql[] = 'CREATE TABLE ' . $this->entry_metas . ' (
249 id BIGINT(20) NOT NULL auto_increment,
250 meta_value longtext default NULL,
251 field_id BIGINT(20) NOT NULL,
252 item_id BIGINT(20) NOT NULL,
253 created_at datetime NOT NULL,
254 PRIMARY KEY (id),
255 KEY field_id (field_id),
256 KEY item_id (item_id)
257 )';
258
259 /* Create/Upgrade Gated Tokens Table */
260 $sql[] = 'CREATE TABLE ' . $this->gated_tokens . ' (
261 id BIGINT UNSIGNED NOT NULL auto_increment,
262 token_hash varchar(64) NOT NULL,
263 action_id BIGINT UNSIGNED NOT NULL,
264 entry_id BIGINT UNSIGNED NOT NULL,
265 user_id BIGINT UNSIGNED default NULL,
266 ip_address varchar(255) default NULL,
267 created_at int UNSIGNED NOT NULL,
268 expired_at int UNSIGNED default NULL,
269 PRIMARY KEY (id),
270 UNIQUE KEY token_hash (token_hash),
271 KEY action_id (action_id),
272 KEY user_id (user_id),
273 KEY expired_at (expired_at)
274 )';
275
276 foreach ( $sql as $q ) {
277 if ( function_exists( 'dbDelta' ) ) {
278 dbDelta( $q . $charset_collate . ';' );
279 } else {
280 global $wpdb;
281 $wpdb->query( $q . $charset_collate ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
282 }
283 unset( $q );
284 }
285
286 $this->add_composite_indexes_for_entries();
287 }
288
289 /**
290 * These indexes help optimize database queries for entries.
291 *
292 * @since 6.6
293 * @since 6.16.3 idx_form_id_is_draft was also added to frm_items.
294 * @since 6.17 idx_form_id_type was also added to frm_fields.
295 *
296 * @return void
297 */
298 private function add_composite_indexes_for_entries() {
299 global $wpdb;
300
301 $table_name = "{$wpdb->prefix}frm_items";
302 $index_name = 'idx_is_draft_created_at';
303
304 if ( ! self::index_exists( $table_name, $index_name ) ) {
305 $wpdb->query( "CREATE INDEX idx_is_draft_created_at ON `{$wpdb->prefix}frm_items` (is_draft, created_at)" );
306 }
307
308 $table_name = "{$wpdb->prefix}frm_item_metas";
309 $index_name = 'idx_field_id_item_id';
310
311 if ( ! self::index_exists( $table_name, $index_name ) ) {
312 $wpdb->query( "CREATE INDEX idx_field_id_item_id ON `{$wpdb->prefix}frm_item_metas` (field_id, item_id)" );
313 }
314
315 $table_name = "{$wpdb->prefix}frm_items";
316 $index_name = 'idx_form_id_is_draft';
317
318 if ( ! self::index_exists( $table_name, $index_name ) ) {
319 $wpdb->query( "CREATE INDEX idx_form_id_is_draft ON `{$wpdb->prefix}frm_items` (form_id, is_draft)" );
320 }
321
322 $table_name = "{$wpdb->prefix}frm_fields";
323 $index_name = 'idx_form_id_type';
324
325 if ( ! self::index_exists( $table_name, $index_name ) ) {
326 $wpdb->query( "CREATE INDEX idx_form_id_type ON `{$wpdb->prefix}frm_fields` (form_id, type(30))" );
327 }
328 }
329
330 /**
331 * Check that an index exists in a database table before trying to add it (which results in an error).
332 *
333 * @since 6.6
334 *
335 * @param string $table_name
336 * @param string $index_name
337 *
338 * @return bool
339 */
340 private static function index_exists( $table_name, $index_name ) {
341 global $wpdb;
342 $row = $wpdb->get_row(
343 $wpdb->prepare(
344 'SELECT 1 FROM information_schema.statistics
345 WHERE table_schema = database()
346 AND table_name = %s
347 AND index_name = %s
348 LIMIT 1',
349 array( $table_name, $index_name )
350 )
351 );
352 return (bool) $row;
353 }
354
355 /**
356 * @return void
357 */
358 private function maybe_create_contact_form() {
359 $form_exists = FrmForm::get_id_by_key( 'contact-form' );
360
361 if ( ! $form_exists ) {
362 $this->add_default_template();
363 }
364 }
365
366 /**
367 * Create the default contact form
368 *
369 * @since 3.06
370 *
371 * @return void
372 */
373 private function add_default_template() {
374 if ( FrmXMLHelper::check_if_libxml_disable_entity_loader_exists() ) {
375 // XML import is not enabled on your server.
376 return;
377 }
378
379 $set_err = libxml_use_internal_errors( true );
380 $loader = FrmXMLHelper::maybe_libxml_disable_entity_loader( true );
381 $file = FrmAppHelper::plugin_path() . '/classes/views/xml/default-templates.xml';
382 FrmXMLHelper::import_xml( $file );
383
384 libxml_use_internal_errors( $set_err );
385 FrmXMLHelper::maybe_libxml_disable_entity_loader( $loader );
386 }
387
388 /**
389 * @param int|string $old_db_version
390 *
391 * @return void
392 */
393 private function migrate_data( $old_db_version ) {
394 if ( ! $old_db_version ) {
395 $old_db_version = get_option( 'frm_db_version' );
396 }
397
398 if ( str_contains( $old_db_version, '-' ) ) {
399 $last_upgrade = explode( '-', $old_db_version );
400 $old_db_version = intval( end( $last_upgrade ) );
401 }
402
403 if ( ! is_numeric( $old_db_version ) ) {
404 // Bail if we don't know the previous version
405 return;
406 }
407
408 $migrations = array( 16, 11, 16, 17, 23, 25, 86, 90, 97, 98, 101, 104, 105 );
409
410 foreach ( $migrations as $migration ) {
411 if ( FrmAppHelper::$db_version < $migration || $old_db_version >= $migration ) {
412 continue;
413 }
414
415 $function_name = 'migrate_to_' . $migration;
416 $this->$function_name();
417 }
418 }
419
420 /**
421 * @return bool
422 */
423 public function uninstall() {
424 if ( ! current_user_can( 'administrator' ) ) {
425 $frm_settings = FrmAppHelper::get_settings();
426 wp_die( esc_html( $frm_settings->admin_permission ) );
427 }
428
429 global $wpdb, $wp_roles;
430
431 $wpdb->query( 'DROP TABLE IF EXISTS ' . $this->fields ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
432 $wpdb->query( 'DROP TABLE IF EXISTS ' . $this->forms ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
433 $wpdb->query( 'DROP TABLE IF EXISTS ' . $this->entries ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
434 $wpdb->query( 'DROP TABLE IF EXISTS ' . $this->entry_metas ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
435 $wpdb->query( 'DROP TABLE IF EXISTS ' . $this->gated_tokens ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
436
437 delete_option( 'frm_options' );
438 delete_option( 'frm_db_version' );
439 delete_option( 'frm_install_running' );
440 delete_option( 'frm_lite_settings_upgrade' );
441 delete_option( 'frm-usage-uuid' );
442 delete_option( 'frm_inbox' );
443 delete_option( 'frmpro_css' );
444 delete_option( FrmOnboardingWizardController::REDIRECT_STATUS_OPTION );
445 delete_option( FrmEmailSummaryHelper::$option_name );
446
447 // Delete roles.
448 $frm_roles = FrmAppHelper::frm_capabilities();
449 $roles = get_editable_roles();
450
451 foreach ( $frm_roles as $frm_role => $frm_role_description ) {
452 foreach ( $roles as $role => $details ) {
453 $wp_roles->remove_cap( $role, $frm_role );
454 unset( $role, $details );
455 }
456 unset( $frm_role, $frm_role_description );
457 }
458 unset( $roles, $frm_roles );
459
460 // Delete actions, views, and styles
461
462 // Prevent the post deletion from triggering entries to be deleted
463 remove_action( 'before_delete_post', 'FrmProDisplaysController::before_delete_post' );
464 remove_action( 'deleted_post', 'FrmProEntriesController::delete_entry' );
465
466 $post_ids = $wpdb->get_col( $wpdb->prepare( 'SELECT ID FROM ' . $wpdb->posts . ' WHERE post_type in (%s, %s, %s)', FrmFormActionsController::$action_post_type, FrmStylesController::$post_type, 'frm_display' ) ); // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
467
468 foreach ( $post_ids as $post_id ) {
469 // Delete's each post.
470 wp_delete_post( $post_id, true );
471 }
472 unset( $post_ids );
473
474 // Delete transients
475 delete_transient( 'frmpro_css' );
476 delete_transient( 'frm_options' );
477 delete_transient( 'frmpro_options' );
478 delete_transient( FrmOnboardingWizardController::TRANSIENT_NAME );
479
480 $wpdb->query( $wpdb->prepare( 'DELETE FROM ' . $wpdb->options . ' WHERE option_name LIKE %s OR option_name LIKE %s', '_transient_timeout_frm_form_fields_%', '_transient_frm_form_fields_%' ) ); // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
481
482 do_action( 'frm_after_uninstall' );
483
484 return true;
485 }
486
487 /**
488 * In older versions of Lite, it's possible we've saved the wrong location ID.
489 * So force it to get valid values again.
490 *
491 * @since 6.25
492 *
493 * @return void
494 */
495 private function migrate_to_104() {
496 if ( FrmSquareLiteConnectHelper::get_merchant_id( 'test' ) ) {
497 FrmSquareLiteConnectHelper::get_location_id( true, 'test' );
498 }
499
500 if ( FrmSquareLiteConnectHelper::get_merchant_id( 'live' ) ) {
501 FrmSquareLiteConnectHelper::get_location_id( true, 'live' );
502 }
503 }
504
505 /**
506 * Add new wp_options row for custom setting.
507 *
508 * @since 6.26
509 *
510 * @return void
511 */
512 private function migrate_to_105() {
513 if ( ! FrmAppHelper::pro_is_installed() ) {
514 update_option( 'frm_show_pricing_fields_modal', 1, false );
515 }
516 }
517
518 /**
519 * Disables summary email for multisite (not the main site) if recipient setting isn't changed.
520 *
521 * @since 6.8
522 *
523 * @return void
524 */
525 private function migrate_to_101() {
526 if ( ! is_multisite() || get_main_site_id() === get_current_blog_id() ) {
527 return;
528 }
529
530 $frm_settings = FrmAppHelper::get_settings();
531
532 if ( empty( $frm_settings->summary_emails ) || '[admin_email]' !== $frm_settings->summary_emails_recipients ) {
533 // User changed it.
534 return;
535 }
536
537 $frm_settings->summary_emails = 0;
538 $frm_settings->store();
539 }
540
541 /**
542 * Clear frmpro_css transient.
543 *
544 * @since 4.10.02
545 *
546 * @return void
547 */
548 private function migrate_to_98() {
549 delete_transient( 'frmpro_css' );
550 }
551
552 /**
553 * Move default_blank and clear_on_focus to placeholder.
554 *
555 * @since 4.0
556 *
557 * @return void
558 */
559 private function migrate_to_97() {
560 $this->migrate_to_placeholder( 'clear_on_focus' );
561 $this->migrate_to_placeholder( 'default_blank' );
562 }
563
564 /**
565 * Move clear_on_focus or default_blank to placeholder.
566 *
567 * @since 4.0
568 *
569 * @param string $type Field option key to migrate.
570 *
571 * @return void
572 */
573 private function migrate_to_placeholder( $type = 'clear_on_focus' ) {
574 $query = array(
575 'field_options like' => '"' . $type . '";s:1:"1";',
576 );
577
578 $fields = FrmDb::get_results( $this->fields, $query, 'id, default_value, field_options, options' );
579
580 foreach ( $fields as $field ) {
581 FrmAppHelper::unserialize_or_decode( $field->field_options );
582 FrmAppHelper::unserialize_or_decode( $field->options );
583 $update_values = FrmXMLHelper::migrate_field_placeholder( $field, $type );
584
585 if ( ! $update_values ) {
586 continue;
587 }
588
589 FrmField::update( $field->id, $update_values );
590 unset( $field );
591 }
592 }
593
594 /**
595 * Delete unneeded default templates
596 *
597 * @since 3.06
598 *
599 * @return void
600 */
601 private function migrate_to_90() {
602 $form = FrmForm::getOne( 'contact' );
603
604 // phpcs:ignore Universal.Operators.StrictComparisons
605 if ( $form && $form->default_template == 1 ) {
606 FrmForm::destroy( 'contact' );
607 }
608 }
609
610 /**
611 * Reverse migration 17 -- Divide by 9
612 *
613 * @since 3.0.05
614 *
615 * @return void
616 */
617 private function migrate_to_86() {
618 $fields = $this->get_fields_with_size();
619
620 foreach ( $fields as $f ) {
621 FrmAppHelper::unserialize_or_decode( $f->field_options );
622 $size = $f->field_options['size'];
623 $this->maybe_convert_migrated_size( $size );
624
625 if ( $size === $f->field_options['size'] ) {
626 continue;
627 }
628
629 $f->field_options['size'] = $size;
630 FrmField::update( $f->id, array( 'field_options' => $f->field_options ) );
631 unset( $f );
632 }
633
634 // Reverse the extra size changes in widgets
635 $widgets = get_option( 'widget_frm_show_form' );
636
637 if ( ! $widgets ) {
638 return;
639 }
640
641 $this->revert_widget_field_size();
642 }
643
644 /**
645 * @return array
646 */
647 private function get_fields_with_size() {
648 $field_types = array(
649 'textarea',
650 'text',
651 'number',
652 'email',
653 'url',
654 'rte',
655 'date',
656 'phone',
657 'password',
658 'image',
659 'tag',
660 'file',
661 );
662
663 $query = array(
664 'type' => $field_types,
665 'field_options like' => 's:4:"size";',
666 'field_options not like' => 's:4:"size";s:0:',
667 );
668
669 return FrmDb::get_results( $this->fields, $query, 'id, field_options' );
670 }
671
672 /**
673 * Reverse the extra size changes in widgets
674 *
675 * @since 3.0.05
676 *
677 * @return void
678 */
679 private function revert_widget_field_size() {
680 $widgets = get_option( 'widget_frm_show_form' );
681
682 if ( ! $widgets ) {
683 return;
684 }
685
686 FrmAppHelper::unserialize_or_decode( $widgets );
687
688 foreach ( $widgets as $k => $widget ) {
689 if ( ! is_array( $widget ) || ! isset( $widget['size'] ) ) {
690 continue;
691 }
692
693 $this->maybe_convert_migrated_size( $widgets[ $k ]['size'] );
694 }
695
696 update_option( 'widget_frm_show_form', $widgets );
697 }
698
699 /**
700 * Divide by 9 to reverse the multiplication
701 *
702 * @since 3.0.05
703 *
704 * @param string $size Size string to maybe convert, passed by reference.
705 *
706 * @return void
707 */
708 private function maybe_convert_migrated_size( &$size ) {
709 $has_px_size = $size && str_contains( $size, 'px' );
710
711 if ( ! $has_px_size ) {
712 return;
713 }
714
715 $int_size = str_replace( 'px', '', $size );
716
717 if ( ! is_numeric( $int_size ) || (int) $int_size < 900 ) {
718 return;
719 }
720
721 $pixel_conversion = 9;
722 $size = round( (int) $int_size / $pixel_conversion );
723 }
724
725 /**
726 * Migrate old styling settings. If sites are using the old
727 * default 400px field width, switch it to 100%
728 *
729 * @since 2.0.4
730 *
731 * @return void
732 */
733 private function migrate_to_25() {
734 // Get the style that was created with the style migration
735 $frm_style = new FrmStyle();
736 $styles = $frm_style->get_all( 'post_date', 'ASC', 1 );
737
738 if ( ! $styles ) {
739 return;
740 }
741
742 foreach ( $styles as $style ) {
743 if ( $style->post_content['field_width'] === '400px' ) {
744 $style->post_content['field_width'] = '100%';
745 $frm_style->save( (array) $style );
746
747 return;
748 }
749 }
750 }
751
752 /**
753 * Check if the parent_form_id columns exists.
754 * If not, try and add it again
755 *
756 * @since 2.0.2
757 *
758 * @return void
759 */
760 private function migrate_to_23() {
761 global $wpdb;
762 $exists = $wpdb->get_row( 'SHOW COLUMNS FROM ' . $this->forms . ' LIKE "parent_form_id"' ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
763
764 if ( ! $exists ) {
765 $wpdb->query( 'ALTER TABLE ' . $this->forms . ' ADD parent_form_id int(11) default 0' ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
766 }
767 }
768
769 /**
770 * Change field size from character to pixel -- Multiply by 9
771 *
772 * @return void
773 */
774 private function migrate_to_17() {
775 $fields = $this->get_fields_with_size();
776
777 foreach ( $fields as $f ) {
778 FrmAppHelper::unserialize_or_decode( $f->field_options );
779
780 if ( empty( $f->field_options['size'] ) || ! is_numeric( $f->field_options['size'] ) ) {
781 continue;
782 }
783
784 $this->convert_character_to_px( $f->field_options['size'] );
785
786 FrmField::update( $f->id, array( 'field_options' => $f->field_options ) );
787 unset( $f );
788 }
789
790 $this->adjust_widget_size();
791 }
792
793 /**
794 * Change the characters in widgets to pixels
795 *
796 * @return void
797 */
798 private function adjust_widget_size() {
799 $widgets = get_option( 'widget_frm_show_form' );
800
801 if ( ! $widgets ) {
802 return;
803 }
804
805 FrmAppHelper::unserialize_or_decode( $widgets );
806
807 foreach ( $widgets as $k => $widget ) {
808 if ( ! is_array( $widget ) || ! isset( $widget['size'] ) ) {
809 continue;
810 }
811 $this->convert_character_to_px( $widgets[ $k ]['size'] );
812 }
813
814 update_option( 'widget_frm_show_form', $widgets );
815 }
816
817 /**
818 * @param string $size
819 *
820 * @return void
821 */
822 private function convert_character_to_px( &$size ) {
823 $pixel_conversion = 9;
824
825 $size = round( $pixel_conversion * (int) $size );
826 $size .= 'px';
827 }
828
829 /**
830 * Migrate post and email notification settings into actions
831 */
832 private function migrate_to_16() {
833 $forms = FrmDb::get_results( $this->forms, array(), 'id, options, is_template, default_template' );
834
835 /**
836 * Old email settings format:
837 * email_to: Email or field id
838 * also_email_to: array of fields ids
839 * reply_to: Email, field id, 'custom'
840 * cust_reply_to: string
841 * reply_to_name: field id, 'custom'
842 * cust_reply_to_name: string
843 * plain_text: 0|1
844 * email_message: string or ''
845 * email_subject: string or ''
846 * inc_user_info: 0|1
847 * update_email: 0, 1, 2
848 *
849 * Old autoresponder settings format:
850 * auto_responder: 0|1
851 * ar_email_message: string or ''
852 * ar_email_to: field id
853 * ar_plain_text: 0|1
854 * ar_reply_to_name: string
855 * ar_reply_to: string
856 * ar_email_subject: string
857 * ar_update_email: 0, 1, 2
858 *
859 * New email settings:
860 * post_content: json settings
861 * post_title: form id
862 * post_excerpt: message
863 */
864 foreach ( $forms as $form ) {
865 if ( $form->is_template && $form->default_template ) {
866 // Don't migrate the default templates since the email will be added anyway
867 continue;
868 }
869
870 // Format form options
871 $form_options = $form->options;
872 FrmAppHelper::unserialize_or_decode( $form_options );
873
874 // Migrate settings to actions
875 FrmXMLHelper::migrate_form_settings_to_actions( $form_options, $form->id );
876 }
877 }
878
879 private function migrate_to_11() {
880 global $wpdb;
881
882 $forms = FrmDb::get_results( $this->forms, array(), 'id, options' );
883 $sending = __( 'Sending', 'formidable' );
884 $img = FrmAppHelper::plugin_url() . '/images/ajax_loader.gif';
885 $old_default_html = <<<DEFAULT_HTML
886 <div class="frm_submit">
887 [if back_button]<input type="submit" value="[back_label]" name="frm_prev_page" formnovalidate="formnovalidate" [back_hook] />[/if back_button]
888 <input type="submit" value="[button_label]" [button_action] />
889 <img class="frm_ajax_loading" src="$img" alt="$sending" style="visibility:hidden;" />
890 </div>
891 DEFAULT_HTML;
892 unset( $sending, $img );
893
894 $new_default_html = FrmFormsHelper::get_default_html( 'submit' );
895 $draft_link = FrmFormsHelper::get_draft_link();
896
897 foreach ( $forms as $form ) {
898 FrmAppHelper::unserialize_or_decode( $form->options );
899
900 if ( empty( $form->options['submit_html'] ) ) {
901 continue;
902 }
903
904 // phpcs:ignore Universal.Operators.StrictComparisons
905 if ( $form->options['submit_html'] != $new_default_html && $form->options['submit_html'] == $old_default_html ) {
906 $form->options['submit_html'] = $new_default_html;
907 $wpdb->update( $this->forms, array( 'options' => serialize( $form->options ) ), array( 'id' => $form->id ) );
908 } elseif ( ! str_contains( $form->options['submit_html'], 'save_draft' ) ) {
909 $form->options['submit_html'] = preg_replace( '~\<\/div\>(?!.*\<\/div\>)~', $draft_link . "\r\n</div>", $form->options['submit_html'] );
910 $wpdb->update( $this->forms, array( 'options' => serialize( $form->options ) ), array( 'id' => $form->id ) );
911 }
912 unset( $form );
913 }
914 }
915 }
916