Completed
Push — master ( 64c78a...31a8b8 )
by Stephanie
02:36
created

FrmMigrate   F

Complexity

Total Complexity 72

Size/Duplication

Total Lines 533
Duplicated Lines 7.88 %

Coupling/Cohesion

Components 1
Dependencies 11

Importance

Changes 0
Metric Value
dl 42
loc 533
rs 2.64
c 0
b 0
f 0
wmc 72
lcom 1
cbo 11

20 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 11 11 2
A upgrade() 0 46 4
A collation() 0 8 2
B create_tables() 0 86 3
A maybe_create_contact_form() 0 6 2
A add_default_template() 0 15 2
B migrate_data() 0 22 7
B uninstall() 0 53 5
A migrate_to_90() 0 6 3
A migrate_to_86() 0 26 4
A get_fields_with_size() 0 10 1
A revert_widget_field_size() 16 16 5
A maybe_convert_migrated_size() 0 14 5
A migrate_to_25() 0 16 4
A migrate_to_23() 0 7 2
A migrate_to_17() 0 17 4
A adjust_widget_size() 15 15 5
A convert_character_to_px() 0 5 1
A migrate_to_16() 0 45 4
B migrate_to_11() 0 34 7

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like FrmMigrate often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use FrmMigrate, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
class FrmMigrate {
4
	public $fields;
5
	public $forms;
6
	public $entries;
7
	public $entry_metas;
8
9 View Code Duplication
	public function __construct() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
10
		if ( ! defined( 'ABSPATH' ) ) {
11
			die( 'You are not allowed to call this page directly.' );
12
		}
13
14
		global $wpdb;
15
		$this->fields         = $wpdb->prefix . 'frm_fields';
16
		$this->forms          = $wpdb->prefix . 'frm_forms';
17
		$this->entries        = $wpdb->prefix . 'frm_items';
18
		$this->entry_metas    = $wpdb->prefix . 'frm_item_metas';
19
	}
20
21
	public function upgrade() {
22
		do_action( 'frm_before_install' );
23
24
		global $wpdb, $frm_vars;
25
26
		$frm_vars['doing_upgrade'] = true;
27
28
		$needs_upgrade = FrmAppController::compare_for_update(
29
			array(
30
				'option'             => 'frm_db_version',
31
				'new_db_version'     => FrmAppHelper::$db_version,
32
				'new_plugin_version' => FrmAppHelper::plugin_version(),
33
			)
34
		);
35
36
		if ( $needs_upgrade ) {
37
			// update rewrite rules for views and other custom post types
38
			flush_rewrite_rules();
39
40
			require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
41
42
			$old_db_version = get_option( 'frm_db_version' );
43
44
			$this->create_tables();
45
			$this->migrate_data( $old_db_version );
46
47
			/***** SAVE DB VERSION *****/
48
			update_option( 'frm_db_version', FrmAppHelper::plugin_version() . '-' . FrmAppHelper::$db_version );
49
50
			if ( ! $old_db_version ) {
51
				$this->maybe_create_contact_form();
52
			}
53
		}
54
55
		do_action( 'frm_after_install' );
56
57
		$frm_vars['doing_upgrade'] = false;
58
59
		FrmAppHelper::save_combined_js();
60
61
		// update the styling settings
62
		if ( function_exists( 'get_filesystem_method' ) ) {
63
			$frm_style = new FrmStyle();
64
			$frm_style->update( 'default' );
65
		}
66
	}
67
68
	public function collation() {
69
		global $wpdb;
70
		if ( ! $wpdb->has_cap( 'collation' ) ) {
71
			return '';
72
		}
73
74
		return $wpdb->get_charset_collate();
75
	}
76
77
    private function create_tables() {
78
        $charset_collate = $this->collation();
79
        $sql = array();
80
81
        /* Create/Upgrade Fields Table */
82
		$sql[] = 'CREATE TABLE ' . $this->fields . ' (
83
				id BIGINT(20) NOT NULL auto_increment,
84
				field_key varchar(100) default NULL,
85
                name text default NULL,
86
                description longtext default NULL,
87
                type text default NULL,
88
                default_value longtext default NULL,
89
                options longtext default NULL,
90
                field_order int(11) default 0,
91
                required int(1) default NULL,
92
                field_options longtext default NULL,
93
                form_id int(11) default NULL,
94
                created_at datetime NOT NULL,
95
                PRIMARY KEY  (id),
96
                KEY form_id (form_id),
97
                UNIQUE KEY field_key (field_key)
98
        )';
99
100
        /* Create/Upgrade Forms Table */
101
		$sql[] = 'CREATE TABLE ' . $this->forms . ' (
102
                id int(11) NOT NULL auto_increment,
103
				form_key varchar(100) default NULL,
104
                name varchar(255) default NULL,
105
                description text default NULL,
106
                parent_form_id int(11) default 0,
107
                logged_in tinyint(1) default NULL,
108
                editable tinyint(1) default NULL,
109
                is_template tinyint(1) default 0,
110
                default_template tinyint(1) default 0,
111
                status varchar(255) default NULL,
112
                options longtext default NULL,
113
                created_at datetime NOT NULL,
114
                PRIMARY KEY  (id),
115
                UNIQUE KEY form_key (form_key)
116
        )';
117
118
        /* Create/Upgrade Items Table */
119
		$sql[] = 'CREATE TABLE ' . $this->entries . ' (
120
				id BIGINT(20) NOT NULL auto_increment,
121
				item_key varchar(100) default NULL,
122
                name varchar(255) default NULL,
123
                description text default NULL,
124
                ip text default NULL,
125
				form_id BIGINT(20) default NULL,
126
				post_id BIGINT(20) default NULL,
127
				user_id BIGINT(20) default NULL,
128
				parent_item_id BIGINT(20) default 0,
129
				is_draft tinyint(1) default 0,
130
				updated_by BIGINT(20) default NULL,
131
                created_at datetime NOT NULL,
132
                updated_at datetime NOT NULL,
133
                PRIMARY KEY  (id),
134
                KEY form_id (form_id),
135
                KEY post_id (post_id),
136
                KEY user_id (user_id),
137
                KEY parent_item_id (parent_item_id),
138
                UNIQUE KEY item_key (item_key)
139
        )';
140
141
        /* Create/Upgrade Meta Table */
142
		$sql[] = 'CREATE TABLE ' . $this->entry_metas . ' (
143
				id BIGINT(20) NOT NULL auto_increment,
144
				meta_value longtext default NULL,
145
				field_id BIGINT(20) NOT NULL,
146
				item_id BIGINT(20) NOT NULL,
147
                created_at datetime NOT NULL,
148
                PRIMARY KEY  (id),
149
                KEY field_id (field_id),
150
                KEY item_id (item_id)
151
        )';
152
153
        foreach ( $sql as $q ) {
154
			if ( function_exists( 'dbDelta' ) ) {
155
				dbDelta( $q . $charset_collate . ';' );
156
			} else {
157
				global $wpdb;
158
				$wpdb->query( $q . $charset_collate ); // WPCS: unprepared SQL ok.
159
			}
160
			unset( $q );
161
        }
162
    }
163
164
	private function maybe_create_contact_form() {
165
		$form_exists = FrmForm::get_id_by_key( 'contact-form' );
166
		if ( ! $form_exists ) {
167
			$this->add_default_template();
168
		}
169
	}
170
171
	/**
172
	 * Create the default contact form
173
	 *
174
	 * @since 3.06
175
	 */
176
	private function add_default_template() {
177
		if ( ! function_exists( 'libxml_disable_entity_loader' ) ) {
178
			// XML import is not enabled on your server.
179
			return;
180
		}
181
182
		$set_err = libxml_use_internal_errors( true );
183
		$loader  = libxml_disable_entity_loader( true );
184
185
		$file = FrmAppHelper::plugin_path() . '/classes/views/xml/default-templates.xml';
186
		FrmXMLHelper::import_xml( $file );
187
188
		libxml_use_internal_errors( $set_err );
189
		libxml_disable_entity_loader( $loader );
190
	}
191
192
	/**
193
	 * @param int|string $old_db_version
194
	 */
195
	private function migrate_data( $old_db_version ) {
196
		if ( ! $old_db_version ) {
197
			$old_db_version = get_option( 'frm_db_version' );
198
		}
199
		if ( strpos( $old_db_version, '-' ) ) {
200
			$last_upgrade = explode( '-', $old_db_version );
201
			$old_db_version = (int) $last_upgrade[1];
202
		}
203
204
		if ( ! is_numeric( $old_db_version ) ) {
205
			// bail if we don't know the previous version
206
			return;
207
		}
208
209
		$migrations = array( 16, 11, 16, 17, 23, 25, 86, 90 );
210
		foreach ( $migrations as $migration ) {
211
			if ( FrmAppHelper::$db_version >= $migration && $old_db_version < $migration ) {
212
				$function_name = 'migrate_to_' . $migration;
213
				$this->$function_name();
214
			}
215
		}
216
	}
217
218
    public function uninstall() {
219
		if ( ! current_user_can( 'administrator' ) ) {
220
            $frm_settings = FrmAppHelper::get_settings();
221
			wp_die( esc_html( $frm_settings->admin_permission ) );
222
        }
223
224
        global $wpdb, $wp_roles;
225
226
		$wpdb->query( 'DROP TABLE IF EXISTS ' . $this->fields ); // WPCS: unprepared SQL ok.
227
		$wpdb->query( 'DROP TABLE IF EXISTS ' . $this->forms ); // WPCS: unprepared SQL ok.
228
		$wpdb->query( 'DROP TABLE IF EXISTS ' . $this->entries ); // WPCS: unprepared SQL ok.
229
		$wpdb->query( 'DROP TABLE IF EXISTS ' . $this->entry_metas ); // WPCS: unprepared SQL ok.
230
231
		delete_option( 'frm_options' );
232
		delete_option( 'frm_db_version' );
233
		delete_option( 'frm_install_running' );
234
		delete_option( 'frm_lite_settings_upgrade' );
235
236
        //delete roles
237
        $frm_roles = FrmAppHelper::frm_capabilities();
238
        $roles = get_editable_roles();
239
        foreach ( $frm_roles as $frm_role => $frm_role_description ) {
240
            foreach ( $roles as $role => $details ) {
241
                $wp_roles->remove_cap( $role, $frm_role );
242
				unset( $role, $details );
243
			}
244
			unset( $frm_role, $frm_role_description );
245
		}
246
		unset( $roles, $frm_roles );
247
248
		// delete actions, views, and styles
249
250
		// prevent the post deletion from triggering entries to be deleted
251
		remove_action( 'before_delete_post', 'FrmProDisplaysController::before_delete_post' );
252
		remove_action( 'deleted_post', 'FrmProEntriesController::delete_entry' );
253
254
		$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' ) );
255
		foreach ( $post_ids as $post_id ) {
256
			// Delete's each post.
257
			wp_delete_post( $post_id, true );
258
		}
259
		unset( $post_ids );
260
261
		// delete transients
262
		delete_transient( 'frmpro_css' );
263
		delete_transient( 'frm_options' );
264
		delete_transient( 'frmpro_options' );
265
266
		$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_%' ) );
267
268
		do_action( 'frm_after_uninstall' );
269
        return true;
270
    }
271
272
	/**
273
	 * Delete uneeded default templates
274
	 *
275
	 * @since 3.06
276
	 */
277
	private function migrate_to_90() {
278
		$form = FrmForm::getOne( 'contact' );
279
		if ( $form && $form->default_template == 1 ) {
280
			FrmForm::destroy( 'contact' );
281
		}
282
	}
283
284
	/**
285
	 * Reverse migration 17 -- Divide by 9
286
	 *
287
	 * @since 3.0.05
288
	 */
289
	private function migrate_to_86() {
290
291
		$fields = $this->get_fields_with_size();
292
293
		foreach ( (array) $fields as $f ) {
294
			$f->field_options = maybe_unserialize( $f->field_options );
295
			$size = $f->field_options['size'];
296
			$this->maybe_convert_migrated_size( $size );
297
298
			if ( $size === $f->field_options['size'] ) {
299
				continue;
300
			}
301
302
			$f->field_options['size'] = $size;
303
			FrmField::update( $f->id, array( 'field_options' => $f->field_options ) );
304
			unset( $f );
305
		}
306
307
		// reverse the extra size changes in widgets
308
		$widgets = get_option( 'widget_frm_show_form' );
309
		if ( empty( $widgets ) ) {
310
			return;
311
		}
312
313
		$this->revert_widget_field_size();
314
	}
315
316
	private function get_fields_with_size() {
317
		$field_types = array( 'textarea', 'text', 'number', 'email', 'url', 'rte', 'date', 'phone', 'password', 'image', 'tag', 'file' );
318
		$query = array(
319
			'type' => $field_types,
320
			'field_options like' => 's:4:"size";',
321
			'field_options not like' => 's:4:"size";s:0:',
322
		);
323
324
		return FrmDb::get_results( $this->fields, $query, 'id, field_options' );
325
	}
326
327
	/**
328
	 * Reverse the extra size changes in widgets
329
	 *
330
	 * @since 3.0.05
331
	 */
332 View Code Duplication
	private function revert_widget_field_size() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
333
		$widgets = get_option( 'widget_frm_show_form' );
334
		if ( empty( $widgets ) ) {
335
			return;
336
		}
337
338
		$widgets = maybe_unserialize( $widgets );
339
		foreach ( $widgets as $k => $widget ) {
340
			if ( ! is_array( $widget ) || ! isset( $widget['size'] ) ) {
341
				continue;
342
			}
343
344
			$this->maybe_convert_migrated_size( $widgets[ $k ]['size'] );
345
		}
346
		update_option( 'widget_frm_show_form', $widgets );
347
	}
348
349
	/**
350
	 * Divide by 9 to reverse the multiplication
351
	 *
352
	 * @since 3.0.05
353
	 */
354
	private function maybe_convert_migrated_size( &$size ) {
355
		$has_px_size = ! empty( $size ) && strpos( $size, 'px' );
356
		if ( ! $has_px_size ) {
357
			return;
358
		}
359
360
		$int_size = str_replace( 'px', '', $size );
361
		if ( ! is_numeric( $int_size ) || (int) $int_size < 900 ) {
362
			return;
363
		}
364
365
		$pixel_conversion = 9;
366
		$size = round( (int) $int_size / $pixel_conversion );
367
	}
368
369
	/**
370
	 * Migrate old styling settings. If sites are using the old
371
	 * default 400px field width, switch it to 100%
372
	 *
373
	 * @since 2.0.4
374
	 */
375
	private function migrate_to_25() {
376
		// get the style that was created with the style migration
377
		$frm_style = new FrmStyle();
378
		$styles = $frm_style->get_all( 'post_date', 'ASC', 1 );
379
		if ( empty( $styles ) ) {
380
			return;
381
		}
382
383
		foreach ( $styles as $style ) {
384
			if ( $style->post_content['field_width'] == '400px' ) {
385
				$style->post_content['field_width'] = '100%';
386
				$frm_style->save( (array) $style );
387
				return;
388
			}
389
		}
390
	}
391
392
	/**
393
	 * Check if the parent_form_id columns exists.
394
	 * If not, try and add it again
395
	 *
396
	 * @since 2.0.2
397
	 */
398
	private function migrate_to_23() {
399
		global $wpdb;
400
		$exists = $wpdb->get_row( 'SHOW COLUMNS FROM ' . $this->forms . ' LIKE "parent_form_id"' ); // WPCS: unprepared SQL ok.
401
		if ( empty( $exists ) ) {
402
			$wpdb->query( 'ALTER TABLE ' . $this->forms . ' ADD parent_form_id int(11) default 0' ); // WPCS: unprepared SQL ok.
403
		}
404
	}
405
406
	/**
407
	 * Change field size from character to pixel -- Multiply by 9
408
	 */
409
	private function migrate_to_17() {
410
		$fields = $this->get_fields_with_size();
411
412
		foreach ( $fields as $f ) {
0 ignored issues
show
Bug introduced by
The expression $fields of type array|null|string|object is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
413
			$f->field_options = maybe_unserialize( $f->field_options );
414
			if ( empty( $f->field_options['size'] ) || ! is_numeric( $f->field_options['size'] ) ) {
415
				continue;
416
			}
417
418
			$this->convert_character_to_px( $f->field_options['size'] );
419
420
			FrmField::update( $f->id, array( 'field_options' => $f->field_options ) );
421
			unset( $f );
422
		}
423
424
		$this->adjust_widget_size();
425
	}
426
427
	/**
428
	 * Change the characters in widgets to pixels
429
	 */
430 View Code Duplication
	private function adjust_widget_size() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
431
		$widgets = get_option( 'widget_frm_show_form' );
432
		if ( empty( $widgets ) ) {
433
			return;
434
		}
435
436
		$widgets = maybe_unserialize( $widgets );
437
		foreach ( $widgets as $k => $widget ) {
438
			if ( ! is_array( $widget ) || ! isset( $widget['size'] ) ) {
439
				continue;
440
			}
441
			$this->convert_character_to_px( $widgets[ $k ]['size'] );
442
		}
443
		update_option( 'widget_frm_show_form', $widgets );
444
	}
445
446
	private function convert_character_to_px( &$size ) {
447
		$pixel_conversion = 9;
448
		$size = round( $pixel_conversion * (int) $size );
449
		$size .= 'px';
450
	}
451
452
    /**
453
     * Migrate post and email notification settings into actions
454
     */
455
    private function migrate_to_16() {
456
        $forms = FrmDb::get_results( $this->forms, array(), 'id, options, is_template, default_template' );
457
458
        /**
459
        * Old email settings format:
460
        * email_to: Email or field id
461
        * also_email_to: array of fields ids
462
        * reply_to: Email, field id, 'custom'
463
        * cust_reply_to: string
464
        * reply_to_name: field id, 'custom'
465
        * cust_reply_to_name: string
466
        * plain_text: 0|1
467
        * email_message: string or ''
468
        * email_subject: string or ''
469
        * inc_user_info: 0|1
470
        * update_email: 0, 1, 2
471
        *
472
        * Old autoresponder settings format:
473
        * auto_responder: 0|1
474
        * ar_email_message: string or ''
475
        * ar_email_to: field id
476
        * ar_plain_text: 0|1
477
        * ar_reply_to_name: string
478
        * ar_reply_to: string
479
        * ar_email_subject: string
480
        * ar_update_email: 0, 1, 2
481
        *
482
        * New email settings:
483
        * post_content: json settings
484
        * post_title: form id
485
        * post_excerpt: message
486
        */
487
        foreach ( $forms as $form ) {
0 ignored issues
show
Bug introduced by
The expression $forms of type array|null|string|object is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
488
			if ( $form->is_template && $form->default_template ) {
489
				// don't migrate the default templates since the email will be added anyway
490
				continue;
491
			}
492
493
			// Format form options
494
			$form_options = maybe_unserialize( $form->options );
495
496
            // Migrate settings to actions
497
            FrmXMLHelper::migrate_form_settings_to_actions( $form_options, $form->id );
498
        }
499
    }
500
501
    private function migrate_to_11() {
502
        global $wpdb;
503
504
		$forms = FrmDb::get_results( $this->forms, array(), 'id, options' );
505
506
        $sending = __( 'Sending', 'formidable' );
507
		$img = FrmAppHelper::plugin_url() . '/images/ajax_loader.gif';
508
        $old_default_html = <<<DEFAULT_HTML
509
<div class="frm_submit">
510
[if back_button]<input type="submit" value="[back_label]" name="frm_prev_page" formnovalidate="formnovalidate" [back_hook] />[/if back_button]
511
<input type="submit" value="[button_label]" [button_action] />
512
<img class="frm_ajax_loading" src="$img" alt="$sending" style="visibility:hidden;" />
513
</div>
514
DEFAULT_HTML;
515
		unset( $sending, $img );
516
517
		$new_default_html = FrmFormsHelper::get_default_html( 'submit' );
518
        $draft_link = FrmFormsHelper::get_draft_link();
519
		foreach ( $forms as $form ) {
0 ignored issues
show
Bug introduced by
The expression $forms of type array|null|string|object is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
520
			$form->options = maybe_unserialize( $form->options );
521
			if ( ! isset( $form->options['submit_html'] ) || empty( $form->options['submit_html'] ) ) {
522
                continue;
523
            }
524
525
            if ( $form->options['submit_html'] != $new_default_html && $form->options['submit_html'] == $old_default_html ) {
526
                $form->options['submit_html'] = $new_default_html;
527
				$wpdb->update( $this->forms, array( 'options' => serialize( $form->options ) ), array( 'id' => $form->id ) );
528
			} else if ( ! strpos( $form->options['submit_html'], 'save_draft' ) ) {
529
				$form->options['submit_html'] = preg_replace( '~\<\/div\>(?!.*\<\/div\>)~', $draft_link . "\r\n</div>", $form->options['submit_html'] );
530
				$wpdb->update( $this->forms, array( 'options' => serialize( $form->options ) ), array( 'id' => $form->id ) );
531
            }
532
			unset( $form );
533
        }
534
    }
535
}
536