Completed
Push — master ( b3ff26...a88860 )
by Stephanie
02:55
created

FrmMigrate::migrate_to_17()   C

Complexity

Conditions 9
Paths 16

Size

Total Lines 48
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 31
nc 16
nop 0
dl 0
loc 48
rs 5.5102
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;
25
		//$frm_db_version is the version of the database we're moving to
26
		$frm_db_version = FrmAppHelper::$db_version;
27
		$old_db_version = (float) $old_db_version;
28
		if ( ! $old_db_version ) {
29
			$old_db_version = get_option('frm_db_version');
30
		}
31
32
		if ( $frm_db_version != $old_db_version ) {
33
			// update rewrite rules for views and other custom post types
34
			flush_rewrite_rules();
35
36
			require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
37
38
			$this->create_tables();
39
			$this->migrate_data($frm_db_version, $old_db_version);
40
41
			/***** SAVE DB VERSION *****/
42
			update_option('frm_db_version', $frm_db_version);
43
44
			/**** ADD/UPDATE DEFAULT TEMPLATES ****/
45
			FrmXMLController::add_default_templates();
46
47
			if ( ! $old_db_version ) {
48
				$this->maybe_create_contact_form();
49
			}
50
		}
51
52
		do_action('frm_after_install');
53
54
		/**** update the styling settings ****/
55
		if ( is_admin() && function_exists( 'get_filesystem_method' ) ) {
56
			$frm_style = new FrmStyle();
57
			$frm_style->update( 'default' );
58
		}
59
	}
60
61
	public function collation() {
62
		global $wpdb;
63
		if ( ! $wpdb->has_cap( 'collation' ) ) {
64
			return '';
65
		}
66
67
		$charset_collate = '';
68
		if ( ! empty( $wpdb->charset ) ) {
69
			$charset_collate .= ' DEFAULT CHARACTER SET ' . $wpdb->charset;
70
		}
71
72
		if ( ! empty( $wpdb->collate ) ) {
73
			$charset_collate .= ' COLLATE ' . $wpdb->collate;
74
		}
75
76
		return $charset_collate;
77
	}
78
79
    private function create_tables() {
80
        $charset_collate = $this->collation();
81
        $sql = array();
82
83
        /* Create/Upgrade Fields Table */
84
		$sql[] = 'CREATE TABLE ' . $this->fields . ' (
85
				id BIGINT(20) NOT NULL auto_increment,
86
				field_key varchar(100) default NULL,
87
                name text default NULL,
88
                description longtext default NULL,
89
                type text default NULL,
90
                default_value longtext default NULL,
91
                options longtext default NULL,
92
                field_order int(11) default 0,
93
                required int(1) default NULL,
94
                field_options longtext default NULL,
95
                form_id int(11) default NULL,
96
                created_at datetime NOT NULL,
97
                PRIMARY KEY  (id),
98
                KEY form_id (form_id),
99
                UNIQUE KEY field_key (field_key)
100
        )';
101
102
        /* Create/Upgrade Forms Table */
103
		$sql[] = 'CREATE TABLE ' . $this->forms . ' (
104
                id int(11) NOT NULL auto_increment,
105
				form_key varchar(100) default NULL,
106
                name varchar(255) default NULL,
107
                description text default NULL,
108
                parent_form_id int(11) default 0,
109
                logged_in tinyint(1) default NULL,
110
                editable tinyint(1) default NULL,
111
                is_template tinyint(1) default 0,
112
                default_template tinyint(1) default 0,
113
                status varchar(255) default NULL,
114
                options longtext default NULL,
115
                created_at datetime NOT NULL,
116
                PRIMARY KEY  (id),
117
                UNIQUE KEY form_key (form_key)
118
        )';
119
120
        /* Create/Upgrade Items Table */
121
		$sql[] = 'CREATE TABLE ' . $this->entries . ' (
122
				id BIGINT(20) NOT NULL auto_increment,
123
				item_key varchar(100) default NULL,
124
                name varchar(255) default NULL,
125
                description text default NULL,
126
                ip text default NULL,
127
				form_id BIGINT(20) default NULL,
128
				post_id BIGINT(20) default NULL,
129
				user_id BIGINT(20) default NULL,
130
				parent_item_id BIGINT(20) default 0,
131
				is_draft tinyint(1) default 0,
132
				updated_by BIGINT(20) default NULL,
133
                created_at datetime NOT NULL,
134
                updated_at datetime NOT NULL,
135
                PRIMARY KEY  (id),
136
                KEY form_id (form_id),
137
                KEY post_id (post_id),
138
                KEY user_id (user_id),
139
                KEY parent_item_id (parent_item_id),
140
                UNIQUE KEY item_key (item_key)
141
        )';
142
143
        /* Create/Upgrade Meta Table */
144
		$sql[] = 'CREATE TABLE ' . $this->entry_metas . ' (
145
				id BIGINT(20) NOT NULL auto_increment,
146
				meta_value longtext default NULL,
147
				field_id BIGINT(20) NOT NULL,
148
				item_id BIGINT(20) NOT NULL,
149
                created_at datetime NOT NULL,
150
                PRIMARY KEY  (id),
151
                KEY field_id (field_id),
152
                KEY item_id (item_id)
153
        )';
154
155
        foreach ( $sql as $q ) {
156
			if ( function_exists( 'dbDelta' ) ) {
157
				dbDelta( $q . $charset_collate . ';' );
158
			} else {
159
				global $wpdb;
160
				$wpdb->query( $q . $charset_collate );
161
			}
162
            unset($q);
163
        }
164
    }
165
166
	private function maybe_create_contact_form() {
167
		$template_id = FrmForm::getIdByKey( 'contact' );
168
		if ( $template_id ) {
169
			$form_id = FrmForm::duplicate( $template_id, false, true );
170
			if ( $form_id ) {
171
				$values = array(
172
					'status'   => 'published',
173
					'form_key' => 'contact-form',
174
				);
175
				FrmForm::update( $form_id, $values );
176
			}
177
		}
178
	}
179
180
    /**
181
     * @param integer $frm_db_version
182
	 * @param int $old_db_version
183
     */
184
	private function migrate_data( $frm_db_version, $old_db_version ) {
185
		$migrations = array( 4, 6, 11, 16, 17, 23, 25 );
186
        foreach ( $migrations as $migration ) {
187
            if ( $frm_db_version >= $migration && $old_db_version < $migration ) {
188
				$function_name = 'migrate_to_' . $migration;
189
                $this->$function_name();
190
            }
191
        }
192
    }
193
194
    public function uninstall() {
195
		if ( ! current_user_can( 'administrator' ) ) {
196
            $frm_settings = FrmAppHelper::get_settings();
197
            wp_die($frm_settings->admin_permission);
198
        }
199
200
        global $wpdb, $wp_roles;
201
202
		$wpdb->query( 'DROP TABLE IF EXISTS ' . $this->fields );
203
		$wpdb->query( 'DROP TABLE IF EXISTS ' . $this->forms );
204
		$wpdb->query( 'DROP TABLE IF EXISTS ' . $this->entries );
205
		$wpdb->query( 'DROP TABLE IF EXISTS ' . $this->entry_metas );
206
207
        delete_option('frm_options');
208
        delete_option('frm_db_version');
209
210
        //delete roles
211
        $frm_roles = FrmAppHelper::frm_capabilities();
212
        $roles = get_editable_roles();
213
        foreach ( $frm_roles as $frm_role => $frm_role_description ) {
214
            foreach ( $roles as $role => $details ) {
215
                $wp_roles->remove_cap( $role, $frm_role );
216
                unset($role, $details);
217
    		}
218
    		unset($frm_role, $frm_role_description);
219
		}
220
		unset($roles, $frm_roles);
221
222
		// delete actions, views, and styles
223
224
		// prevent the post deletion from triggering entries to be deleted
225
		remove_action( 'before_delete_post', 'FrmProDisplaysController::before_delete_post' );
226
		remove_action( 'deleted_post', 'FrmProEntriesController::delete_entry' );
227
228
		$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' ) );
229
		foreach ( $post_ids as $post_id ) {
230
			// Delete's each post.
231
			wp_delete_post( $post_id, true );
232
		}
233
		unset( $post_ids );
234
235
		// delete transients
236
		delete_transient( 'frmpro_css' );
237
		delete_transient( 'frm_options' );
238
		delete_transient( 'frmpro_options' );
239
240
		$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_%' ) );
241
242
        do_action('frm_after_uninstall');
243
        return true;
244
    }
245
246
	/**
247
	 * Migrate old styling settings. If sites are using the old
248
	 * default 400px field width, switch it to 100%
249
	 *
250
	 * @since 2.0.4
251
	 */
252
	private function migrate_to_25() {
253
		// get the style that was created with the style migration
254
		$frm_style = new FrmStyle();
255
		$styles = $frm_style->get_all( 'post_date', 'ASC', 1 );
256
		if ( empty( $styles ) ) {
257
			return;
258
		}
259
260
		foreach ( $styles as $style ) {
261
			if ( $style->post_content['field_width'] == '400px' ) {
262
				$style->post_content['field_width'] = '100%';
263
				$frm_style->save( (array) $style );
264
				return;
265
			}
266
		}
267
	}
268
269
	/**
270
	 * Check if the parent_form_id columns exists.
271
	 * If not, try and add it again
272
	 *
273
	 * @since 2.0.2
274
	 */
275
	private function migrate_to_23() {
276
		global $wpdb;
277
		$exists = $wpdb->get_row( 'SHOW COLUMNS FROM ' . $this->forms . ' LIKE "parent_form_id"' );
278
		if ( empty( $exists ) ) {
279
			$wpdb->query( 'ALTER TABLE ' . $this->forms . ' ADD parent_form_id int(11) default 0' );
280
		}
281
	}
282
283
    /**
284
     * Change field size from character to pixel -- Multiply by 9
285
     */
286
    private function migrate_to_17() {
287
        global $wpdb;
288
		$pixel_conversion = 9;
289
290
        // Get query arguments
291
		$field_types = array( 'textarea', 'text', 'number', 'email', 'url', 'rte', 'date', 'phone', 'password', 'image', 'tag', 'file' );
292
		$query = array(
293
			'type' => $field_types,
294
			'field_options like' => 's:4:"size";',
295
			'field_options not like' => 's:4:"size";s:0:',
296
		);
297
298
        // Get results
299
		$fields = FrmDb::get_results( $this->fields, $query, 'id, field_options' );
300
301
        $updated = 0;
302
        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...
303
            $f->field_options = maybe_unserialize($f->field_options);
304
            if ( empty($f->field_options['size']) || ! is_numeric($f->field_options['size']) ) {
305
                continue;
306
            }
307
308
			$f->field_options['size'] = round( $pixel_conversion * (int) $f->field_options['size'] );
309
            $f->field_options['size'] .= 'px';
310
            $u = FrmField::update( $f->id, array( 'field_options' => $f->field_options ) );
311
            if ( $u ) {
312
                $updated++;
313
            }
314
            unset($f);
315
        }
316
317
        // Change the characters in widgets to pixels
318
        $widgets = get_option('widget_frm_show_form');
319
        if ( empty($widgets) ) {
320
            return;
321
        }
322
323
        $widgets = maybe_unserialize($widgets);
324
        foreach ( $widgets as $k => $widget ) {
325
            if ( ! is_array($widget) || ! isset($widget['size']) ) {
326
                continue;
327
            }
328
			$size = round( $pixel_conversion * (int) $widget['size'] );
329
            $size .= 'px';
330
			$widgets[ $k ]['size'] = $size;
331
        }
332
        update_option('widget_frm_show_form', $widgets);
333
    }
334
335
    /**
336
     * Migrate post and email notification settings into actions
337
     */
338
    private function migrate_to_16() {
339
        global $wpdb;
340
341
        $forms = FrmDb::get_results( $this->forms, array(), 'id, options, is_template, default_template' );
342
343
        /**
344
        * Old email settings format:
345
        * email_to: Email or field id
346
        * also_email_to: array of fields ids
347
        * reply_to: Email, field id, 'custom'
348
        * cust_reply_to: string
349
        * reply_to_name: field id, 'custom'
350
        * cust_reply_to_name: string
351
        * plain_text: 0|1
352
        * email_message: string or ''
353
        * email_subject: string or ''
354
        * inc_user_info: 0|1
355
        * update_email: 0, 1, 2
356
        *
357
        * Old autoresponder settings format:
358
        * auto_responder: 0|1
359
        * ar_email_message: string or ''
360
        * ar_email_to: field id
361
        * ar_plain_text: 0|1
362
        * ar_reply_to_name: string
363
        * ar_reply_to: string
364
        * ar_email_subject: string
365
        * ar_update_email: 0, 1, 2
366
        *
367
        * New email settings:
368
        * post_content: json settings
369
        * post_title: form id
370
        * post_excerpt: message
371
        *
372
        */
373
374
        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...
375
			if ( $form->is_template && $form->default_template ) {
376
				// don't migrate the default templates since the email will be added anyway
377
				continue;
378
			}
379
380
            // Format form options
381
            $form_options = maybe_unserialize($form->options);
382
383
            // Migrate settings to actions
384
            FrmXMLHelper::migrate_form_settings_to_actions( $form_options, $form->id );
385
        }
386
    }
387
388
    private function migrate_to_11() {
389
        global $wpdb;
390
391
        $forms = FrmDb::get_results( $this->forms, array(), 'id, options');
392
393
        $sending = __( 'Sending', 'formidable' );
394
		$img = FrmAppHelper::plugin_url() . '/images/ajax_loader.gif';
395
        $old_default_html = <<<DEFAULT_HTML
396
<div class="frm_submit">
397
[if back_button]<input type="submit" value="[back_label]" name="frm_prev_page" formnovalidate="formnovalidate" [back_hook] />[/if back_button]
398
<input type="submit" value="[button_label]" [button_action] />
399
<img class="frm_ajax_loading" src="$img" alt="$sending" style="visibility:hidden;" />
400
</div>
401
DEFAULT_HTML;
402
        unset($sending, $img);
403
404
        $new_default_html = FrmFormsHelper::get_default_html('submit');
405
        $draft_link = FrmFormsHelper::get_draft_link();
406
		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...
407
            $form->options = maybe_unserialize($form->options);
408
            if ( ! isset($form->options['submit_html']) || empty($form->options['submit_html']) ) {
409
                continue;
410
            }
411
412
            if ( $form->options['submit_html'] != $new_default_html && $form->options['submit_html'] == $old_default_html ) {
413
                $form->options['submit_html'] = $new_default_html;
414
				$wpdb->update( $this->forms, array( 'options' => serialize( $form->options ) ), array( 'id' => $form->id ) );
415
			} else if ( ! strpos( $form->options['submit_html'], 'save_draft' ) ) {
416
				$form->options['submit_html'] = preg_replace( '~\<\/div\>(?!.*\<\/div\>)~', $draft_link . "\r\n</div>", $form->options['submit_html'] );
417
				$wpdb->update( $this->forms, array( 'options' => serialize( $form->options ) ), array( 'id' => $form->id ) );
418
            }
419
            unset($form);
420
        }
421
        unset($forms);
422
    }
423
424
    private function migrate_to_6() {
425
        global $wpdb;
426
427
		$no_save = array_merge( FrmField::no_save_fields(), array( 'form', 'hidden', 'user_id' ) );
428
		$fields = FrmDb::get_results( $this->fields, array( 'type NOT' => $no_save ), 'id, field_options' );
429
430
        $default_html = <<<DEFAULT_HTML
431
<div id="frm_field_[id]_container" class="form-field [required_class] [error_class]">
432
    <label class="frm_pos_[label_position]">[field_name]
433
        <span class="frm_required">[required_label]</span>
434
    </label>
435
    [input]
436
    [if description]<div class="frm_description">[description]</div>[/if description]
437
</div>
438
DEFAULT_HTML;
439
440
        $old_default_html = <<<DEFAULT_HTML
441
<div id="frm_field_[id]_container" class="form-field [required_class] [error_class]">
442
    <label class="frm_pos_[label_position]">[field_name]
443
        <span class="frm_required">[required_label]</span>
444
    </label>
445
    [input]
446
    [if description]<p class="frm_description">[description]</p>[/if description]
447
</div>
448
DEFAULT_HTML;
449
450
        $new_default_html = FrmFieldsHelper::get_default_html('text');
451
        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...
452
            $field->field_options = maybe_unserialize($field->field_options);
453
			$html = FrmField::get_option( $field, 'custom_html' );
454
			if ( $html == $default_html || $html == $old_default_html ) {
455
                $field->field_options['custom_html'] = $new_default_html;
456
				$wpdb->update( $this->fields, array( 'field_options' => maybe_serialize( $field->field_options ) ), array( 'id' => $field->id ) );
457
            }
458
            unset($field);
459
        }
460
        unset($default_html, $old_default_html, $fields);
461
    }
462
463
    private function migrate_to_4() {
464
        global $wpdb;
465
		$user_ids = FrmEntryMeta::getAll( array( 'fi.type' => 'user_id' ) );
466
        foreach ( $user_ids as $user_id ) {
467
			$wpdb->update( $this->entries, array( 'user_id' => $user_id->meta_value ), array( 'id' => $user_id->item_id ) );
468
        }
469
    }
470
}
471