Completed
Push — master ( 60e79e...f15df2 )
by Stephanie
03:00
created

FrmMigrate::migrate_data()   C

Complexity

Conditions 7
Paths 16

Size

Total Lines 22
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 13
nc 16
nop 1
dl 0
loc 22
rs 6.9811
c 0
b 0
f 0
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( $old_db_version = false ) {
22
		do_action( 'frm_before_install' );
23
24
		global $wpdb, $frm_vars;
25
26
		$frm_vars['doing_upgrade'] = true;
27
28
		$needs_upgrade = FrmAppHelper::compare_for_update( array(
0 ignored issues
show
Bug introduced by
The method compare_for_update() does not seem to exist on object<FrmAppHelper>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
29
			'option'             => 'frm_db_version',
30
			'new_db_version'     => FrmAppHelper::$db_version,
31
			'new_plugin_version' => FrmAppHelper::plugin_version(),
32
		) );
33
34
		if ( $needs_upgrade ) {
35
			// update rewrite rules for views and other custom post types
36
			flush_rewrite_rules();
37
38
			require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
39
40
			$this->create_tables();
41
			$this->migrate_data( $old_db_version );
42
43
			/***** SAVE DB VERSION *****/
44
			update_option( 'frm_db_version', FrmAppHelper::plugin_version() . '-' . FrmAppHelper::$db_version );
45
46
			/**** ADD/UPDATE DEFAULT TEMPLATES ****/
47
			FrmXMLController::add_default_templates();
48
49
			if ( ! $old_db_version ) {
50
				$this->maybe_create_contact_form();
51
			}
52
		}
53
54
		do_action('frm_after_install');
55
56
		$frm_vars['doing_upgrade'] = false;
57
58
		FrmAppHelper::save_combined_js();
59
60
		/**** update the styling settings ****/
61
		if ( function_exists( 'get_filesystem_method' ) ) {
62
			$frm_style = new FrmStyle();
63
			$frm_style->update( 'default' );
64
		}
65
	}
66
67
	public function collation() {
68
		global $wpdb;
69
		if ( ! $wpdb->has_cap( 'collation' ) ) {
70
			return '';
71
		}
72
73
		$charset_collate = '';
74
		if ( ! empty( $wpdb->charset ) ) {
75
			$charset_collate .= ' DEFAULT CHARACTER SET ' . $wpdb->charset;
76
		}
77
78
		if ( ! empty( $wpdb->collate ) ) {
79
			$charset_collate .= ' COLLATE ' . $wpdb->collate;
80
		}
81
82
		return $charset_collate;
83
	}
84
85
    private function create_tables() {
86
        $charset_collate = $this->collation();
87
        $sql = array();
88
89
        /* Create/Upgrade Fields Table */
90
		$sql[] = 'CREATE TABLE ' . $this->fields . ' (
91
				id BIGINT(20) NOT NULL auto_increment,
92
				field_key varchar(100) default NULL,
93
                name text default NULL,
94
                description longtext default NULL,
95
                type text default NULL,
96
                default_value longtext default NULL,
97
                options longtext default NULL,
98
                field_order int(11) default 0,
99
                required int(1) default NULL,
100
                field_options longtext default NULL,
101
                form_id int(11) default NULL,
102
                created_at datetime NOT NULL,
103
                PRIMARY KEY  (id),
104
                KEY form_id (form_id),
105
                UNIQUE KEY field_key (field_key)
106
        )';
107
108
        /* Create/Upgrade Forms Table */
109
		$sql[] = 'CREATE TABLE ' . $this->forms . ' (
110
                id int(11) NOT NULL auto_increment,
111
				form_key varchar(100) default NULL,
112
                name varchar(255) default NULL,
113
                description text default NULL,
114
                parent_form_id int(11) default 0,
115
                logged_in tinyint(1) default NULL,
116
                editable tinyint(1) default NULL,
117
                is_template tinyint(1) default 0,
118
                default_template tinyint(1) default 0,
119
                status varchar(255) default NULL,
120
                options longtext default NULL,
121
                created_at datetime NOT NULL,
122
                PRIMARY KEY  (id),
123
                UNIQUE KEY form_key (form_key)
124
        )';
125
126
        /* Create/Upgrade Items Table */
127
		$sql[] = 'CREATE TABLE ' . $this->entries . ' (
128
				id BIGINT(20) NOT NULL auto_increment,
129
				item_key varchar(100) default NULL,
130
                name varchar(255) default NULL,
131
                description text default NULL,
132
                ip text default NULL,
133
				form_id BIGINT(20) default NULL,
134
				post_id BIGINT(20) default NULL,
135
				user_id BIGINT(20) default NULL,
136
				parent_item_id BIGINT(20) default 0,
137
				is_draft tinyint(1) default 0,
138
				updated_by BIGINT(20) default NULL,
139
                created_at datetime NOT NULL,
140
                updated_at datetime NOT NULL,
141
                PRIMARY KEY  (id),
142
                KEY form_id (form_id),
143
                KEY post_id (post_id),
144
                KEY user_id (user_id),
145
                KEY parent_item_id (parent_item_id),
146
                UNIQUE KEY item_key (item_key)
147
        )';
148
149
        /* Create/Upgrade Meta Table */
150
		$sql[] = 'CREATE TABLE ' . $this->entry_metas . ' (
151
				id BIGINT(20) NOT NULL auto_increment,
152
				meta_value longtext default NULL,
153
				field_id BIGINT(20) NOT NULL,
154
				item_id BIGINT(20) NOT NULL,
155
                created_at datetime NOT NULL,
156
                PRIMARY KEY  (id),
157
                KEY field_id (field_id),
158
                KEY item_id (item_id)
159
        )';
160
161
        foreach ( $sql as $q ) {
162
			if ( function_exists( 'dbDelta' ) ) {
163
				dbDelta( $q . $charset_collate . ';' );
164
			} else {
165
				global $wpdb;
166
				$wpdb->query( $q . $charset_collate );
167
			}
168
            unset($q);
169
        }
170
    }
171
172
	private function maybe_create_contact_form() {
173
		$template_id = FrmForm::get_id_by_key( 'contact' );
174
		if ( $template_id ) {
175
			$form_id = FrmForm::duplicate( $template_id, false, true );
176
			if ( $form_id ) {
177
				$values = array(
178
					'status'   => 'published',
179
					'form_key' => 'contact-form',
180
				);
181
				FrmForm::update( $form_id, $values );
182
			}
183
		}
184
	}
185
186
    /**
187
     * @param integer $frm_db_version
0 ignored issues
show
Bug introduced by
There is no parameter named $frm_db_version. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
188
	 * @param int $old_db_version
189
     */
190
	private function migrate_data( $old_db_version ) {
191
		if ( ! $old_db_version ) {
192
			$old_db_version = get_option( 'frm_db_version' );
193
		}
194
		if ( strpos( $old_db_version, '-' ) ) {
195
			$last_upgrade = explode( '-', $old_db_version );
196
			$old_db_version = (int) $last_upgrade[1];
197
		}
198
199
		if ( ! is_numeric( $old_db_version ) ) {
200
			// bail if we don't know the previous version
201
			return;
202
		}
203
204
		$migrations = array( 4, 6, 11, 16, 17, 23, 25 );
205
		foreach ( $migrations as $migration ) {
206
			if ( FrmAppHelper::$db_version >= $migration && $old_db_version < $migration ) {
207
				$function_name = 'migrate_to_' . $migration;
208
				$this->$function_name();
209
			}
210
		}
211
	}
212
213
    public function uninstall() {
214
		if ( ! current_user_can( 'administrator' ) ) {
215
            $frm_settings = FrmAppHelper::get_settings();
216
            wp_die($frm_settings->admin_permission);
217
        }
218
219
        global $wpdb, $wp_roles;
220
221
		$wpdb->query( 'DROP TABLE IF EXISTS ' . $this->fields );
222
		$wpdb->query( 'DROP TABLE IF EXISTS ' . $this->forms );
223
		$wpdb->query( 'DROP TABLE IF EXISTS ' . $this->entries );
224
		$wpdb->query( 'DROP TABLE IF EXISTS ' . $this->entry_metas );
225
226
        delete_option('frm_options');
227
        delete_option('frm_db_version');
228
229
        //delete roles
230
        $frm_roles = FrmAppHelper::frm_capabilities();
231
        $roles = get_editable_roles();
232
        foreach ( $frm_roles as $frm_role => $frm_role_description ) {
233
            foreach ( $roles as $role => $details ) {
234
                $wp_roles->remove_cap( $role, $frm_role );
235
                unset($role, $details);
236
    		}
237
    		unset($frm_role, $frm_role_description);
238
		}
239
		unset($roles, $frm_roles);
240
241
		// delete actions, views, and styles
242
243
		// prevent the post deletion from triggering entries to be deleted
244
		remove_action( 'before_delete_post', 'FrmProDisplaysController::before_delete_post' );
245
		remove_action( 'deleted_post', 'FrmProEntriesController::delete_entry' );
246
247
		$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' ) );
248
		foreach ( $post_ids as $post_id ) {
249
			// Delete's each post.
250
			wp_delete_post( $post_id, true );
251
		}
252
		unset( $post_ids );
253
254
		// delete transients
255
		delete_transient( 'frmpro_css' );
256
		delete_transient( 'frm_options' );
257
		delete_transient( 'frmpro_options' );
258
259
		$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_%' ) );
260
261
        do_action('frm_after_uninstall');
262
        return true;
263
    }
264
265
	/**
266
	 * Migrate old styling settings. If sites are using the old
267
	 * default 400px field width, switch it to 100%
268
	 *
269
	 * @since 2.0.4
270
	 */
271
	private function migrate_to_25() {
272
		// get the style that was created with the style migration
273
		$frm_style = new FrmStyle();
274
		$styles = $frm_style->get_all( 'post_date', 'ASC', 1 );
275
		if ( empty( $styles ) ) {
276
			return;
277
		}
278
279
		foreach ( $styles as $style ) {
280
			if ( $style->post_content['field_width'] == '400px' ) {
281
				$style->post_content['field_width'] = '100%';
282
				$frm_style->save( (array) $style );
283
				return;
284
			}
285
		}
286
	}
287
288
	/**
289
	 * Check if the parent_form_id columns exists.
290
	 * If not, try and add it again
291
	 *
292
	 * @since 2.0.2
293
	 */
294
	private function migrate_to_23() {
295
		global $wpdb;
296
		$exists = $wpdb->get_row( 'SHOW COLUMNS FROM ' . $this->forms . ' LIKE "parent_form_id"' );
297
		if ( empty( $exists ) ) {
298
			$wpdb->query( 'ALTER TABLE ' . $this->forms . ' ADD parent_form_id int(11) default 0' );
299
		}
300
	}
301
302
    /**
303
     * Change field size from character to pixel -- Multiply by 9
304
     */
305
    private function migrate_to_17() {
306
        global $wpdb;
307
		$pixel_conversion = 9;
308
309
        // Get query arguments
310
		$field_types = array( 'textarea', 'text', 'number', 'email', 'url', 'rte', 'date', 'phone', 'password', 'image', 'tag', 'file' );
311
		$query = array(
312
			'type' => $field_types,
313
			'field_options like' => 's:4:"size";',
314
			'field_options not like' => 's:4:"size";s:0:',
315
		);
316
317
        // Get results
318
		$fields = FrmDb::get_results( $this->fields, $query, 'id, field_options' );
319
320
        $updated = 0;
321
        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...
322
            $f->field_options = maybe_unserialize($f->field_options);
323
            if ( empty($f->field_options['size']) || ! is_numeric($f->field_options['size']) ) {
324
                continue;
325
            }
326
327
			$f->field_options['size'] = round( $pixel_conversion * (int) $f->field_options['size'] );
328
            $f->field_options['size'] .= 'px';
329
            $u = FrmField::update( $f->id, array( 'field_options' => $f->field_options ) );
330
            if ( $u ) {
331
                $updated++;
332
            }
333
            unset($f);
334
        }
335
336
        // Change the characters in widgets to pixels
337
        $widgets = get_option('widget_frm_show_form');
338
        if ( empty($widgets) ) {
339
            return;
340
        }
341
342
        $widgets = maybe_unserialize($widgets);
343
        foreach ( $widgets as $k => $widget ) {
344
            if ( ! is_array($widget) || ! isset($widget['size']) ) {
345
                continue;
346
            }
347
			$size = round( $pixel_conversion * (int) $widget['size'] );
348
            $size .= 'px';
349
			$widgets[ $k ]['size'] = $size;
350
        }
351
        update_option('widget_frm_show_form', $widgets);
352
    }
353
354
    /**
355
     * Migrate post and email notification settings into actions
356
     */
357
    private function migrate_to_16() {
358
        $forms = FrmDb::get_results( $this->forms, array(), 'id, options, is_template, default_template' );
359
360
        /**
361
        * Old email settings format:
362
        * email_to: Email or field id
363
        * also_email_to: array of fields ids
364
        * reply_to: Email, field id, 'custom'
365
        * cust_reply_to: string
366
        * reply_to_name: field id, 'custom'
367
        * cust_reply_to_name: string
368
        * plain_text: 0|1
369
        * email_message: string or ''
370
        * email_subject: string or ''
371
        * inc_user_info: 0|1
372
        * update_email: 0, 1, 2
373
        *
374
        * Old autoresponder settings format:
375
        * auto_responder: 0|1
376
        * ar_email_message: string or ''
377
        * ar_email_to: field id
378
        * ar_plain_text: 0|1
379
        * ar_reply_to_name: string
380
        * ar_reply_to: string
381
        * ar_email_subject: string
382
        * ar_update_email: 0, 1, 2
383
        *
384
        * New email settings:
385
        * post_content: json settings
386
        * post_title: form id
387
        * post_excerpt: message
388
        *
389
        */
390
391
        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...
392
			if ( $form->is_template && $form->default_template ) {
393
				// don't migrate the default templates since the email will be added anyway
394
				continue;
395
			}
396
397
            // Format form options
398
            $form_options = maybe_unserialize($form->options);
399
400
            // Migrate settings to actions
401
            FrmXMLHelper::migrate_form_settings_to_actions( $form_options, $form->id );
402
        }
403
    }
404
405
    private function migrate_to_11() {
406
        global $wpdb;
407
408
        $forms = FrmDb::get_results( $this->forms, array(), 'id, options');
409
410
        $sending = __( 'Sending', 'formidable' );
411
		$img = FrmAppHelper::plugin_url() . '/images/ajax_loader.gif';
412
        $old_default_html = <<<DEFAULT_HTML
413
<div class="frm_submit">
414
[if back_button]<input type="submit" value="[back_label]" name="frm_prev_page" formnovalidate="formnovalidate" [back_hook] />[/if back_button]
415
<input type="submit" value="[button_label]" [button_action] />
416
<img class="frm_ajax_loading" src="$img" alt="$sending" style="visibility:hidden;" />
417
</div>
418
DEFAULT_HTML;
419
        unset($sending, $img);
420
421
        $new_default_html = FrmFormsHelper::get_default_html('submit');
422
        $draft_link = FrmFormsHelper::get_draft_link();
423
		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...
424
            $form->options = maybe_unserialize($form->options);
425
            if ( ! isset($form->options['submit_html']) || empty($form->options['submit_html']) ) {
426
                continue;
427
            }
428
429
            if ( $form->options['submit_html'] != $new_default_html && $form->options['submit_html'] == $old_default_html ) {
430
                $form->options['submit_html'] = $new_default_html;
431
				$wpdb->update( $this->forms, array( 'options' => serialize( $form->options ) ), array( 'id' => $form->id ) );
432
			} else if ( ! strpos( $form->options['submit_html'], 'save_draft' ) ) {
433
				$form->options['submit_html'] = preg_replace( '~\<\/div\>(?!.*\<\/div\>)~', $draft_link . "\r\n</div>", $form->options['submit_html'] );
434
				$wpdb->update( $this->forms, array( 'options' => serialize( $form->options ) ), array( 'id' => $form->id ) );
435
            }
436
            unset($form);
437
        }
438
        unset($forms);
439
    }
440
441
    private function migrate_to_6() {
442
        global $wpdb;
443
444
		$no_save = array_merge( FrmField::no_save_fields(), array( 'form', 'hidden', 'user_id' ) );
445
		$fields = FrmDb::get_results( $this->fields, array( 'type NOT' => $no_save ), 'id, field_options' );
446
447
        $default_html = <<<DEFAULT_HTML
448
<div id="frm_field_[id]_container" class="form-field [required_class] [error_class]">
449
    <label class="frm_pos_[label_position]">[field_name]
450
        <span class="frm_required">[required_label]</span>
451
    </label>
452
    [input]
453
    [if description]<div class="frm_description">[description]</div>[/if description]
454
</div>
455
DEFAULT_HTML;
456
457
        $old_default_html = <<<DEFAULT_HTML
458
<div id="frm_field_[id]_container" class="form-field [required_class] [error_class]">
459
    <label class="frm_pos_[label_position]">[field_name]
460
        <span class="frm_required">[required_label]</span>
461
    </label>
462
    [input]
463
    [if description]<p class="frm_description">[description]</p>[/if description]
464
</div>
465
DEFAULT_HTML;
466
467
        $new_default_html = FrmFieldsHelper::get_default_html('text');
468
        foreach ( $fields as $field ) {
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...
469
            $field->field_options = maybe_unserialize($field->field_options);
470
			$html = FrmField::get_option( $field, 'custom_html' );
471
			if ( $html == $default_html || $html == $old_default_html ) {
472
                $field->field_options['custom_html'] = $new_default_html;
473
				$wpdb->update( $this->fields, array( 'field_options' => maybe_serialize( $field->field_options ) ), array( 'id' => $field->id ) );
474
            }
475
            unset($field);
476
        }
477
        unset($default_html, $old_default_html, $fields);
478
    }
479
480
    private function migrate_to_4() {
481
        global $wpdb;
482
		$user_ids = FrmEntryMeta::getAll( array( 'fi.type' => 'user_id' ) );
483
        foreach ( $user_ids as $user_id ) {
484
			$wpdb->update( $this->entries, array( 'user_id' => $user_id->meta_value ), array( 'id' => $user_id->item_id ) );
485
        }
486
    }
487
}
488