Completed
Push — master ( 3a55aa...28641d )
by Stephanie
02:48
created

FrmDb::maybe_create_contact_form()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 9
nc 3
nop 0
dl 0
loc 13
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
class FrmDb {
4
    var $fields;
5
    var $forms;
6
    var $entries;
7
    var $entry_metas;
8
9
    public function __construct() {
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
    /**
195
     * Change array into format $wpdb->prepare can use
196
	 *
197
	 * @param array $args
198
	 * @param string $starts_with
199
     */
200
    public static function get_where_clause_and_values( &$args, $starts_with = ' WHERE ' ) {
201
        if ( empty($args) ) {
202
			// add an arg to prevent prepare from failing
203
			$args = array( 'where' => $starts_with . '1=%d', 'values' => array( 1 ) );
204
			return;
205
        }
206
207
		$where = '';
208
		$values = array();
209
210
		if ( is_array( $args ) ) {
211
			$base_where = $starts_with;
212
			self::parse_where_from_array( $args, $base_where, $where, $values );
213
		}
214
215
		$args = compact( 'where', 'values' );
216
    }
217
218
    /**
219
	 * @param array $args
220
     * @param string $base_where
221
     * @param string $where
222
	 * @param array $values
223
     */
224
    public static function parse_where_from_array( $args, $base_where, &$where, &$values ) {
225
        $condition = ' AND';
226
        if ( isset( $args['or'] ) ) {
227
            $condition = ' OR';
228
            unset( $args['or'] );
229
        }
230
231
        foreach ( $args as $key => $value ) {
232
            $where .= empty( $where ) ? $base_where : $condition;
233
            $array_inc_null = ( ! is_numeric( $key ) && is_array( $value ) && in_array( null, $value ) );
234
            if ( is_numeric( $key ) || $array_inc_null ) {
235
                $where .= ' ( ';
236
                $nested_where = '';
237
                if ( $array_inc_null ) {
238
                    foreach ( $value as $val ) {
239
                        self::parse_where_from_array( array( $key => $val, 'or' => 1 ), '', $nested_where, $values );
240
                    }
241
                } else {
242
                    self::parse_where_from_array( $value, '', $nested_where, $values );
243
                }
244
                $where .= $nested_where;
245
                $where .= ' ) ';
246
            } else {
247
                self::interpret_array_to_sql( $key, $value, $where, $values );
248
            }
249
        }
250
    }
251
252
    /**
253
     * @param string $key
254
	 * @param string|array $value
255
     * @param string $where
256
	 * @param array $values
257
     */
258
    private static function interpret_array_to_sql( $key, $value, &$where, &$values ) {
259
		$key = trim( $key );
260
261
		if ( strpos( $key, 'created_at' ) !== false || strpos( $key, 'updated_at' ) !== false ) {
262
            $k = explode(' ', $key);
263
            $where .= ' DATE_FORMAT(' . reset( $k ) . ', %s) ' . str_replace( reset( $k ), '', $key );
264
            $values[] = '%Y-%m-%d %H:%i:%s';
265
        } else {
266
			$where .= ' ' . $key;
267
        }
268
269
		$lowercase_key = explode( ' ', strtolower( $key ) );
270
		$lowercase_key = end( $lowercase_key );
271
272
        if ( is_array( $value ) ) {
273
            // translate array of values to "in"
274
			if ( strpos( $lowercase_key, 'like' ) !== false ) {
275
				$where = preg_replace('/' . $key . '$/', '', $where);
276
				$where .= '(';
277
				$start = true;
278
				foreach ( $value as $v ) {
279
					if ( ! $start ) {
280
						$where .= ' OR ';
281
					}
282
					$start = false;
283
					$where .= $key . ' %s';
284
					$values[] = '%' . FrmAppHelper::esc_like( $v ) . '%';
285
				}
286
				$where .= ')';
287
			} else if ( ! empty( $value ) ) {
288
				$where .= ' in (' . FrmAppHelper::prepare_array_values( $value, '%s' ) . ')';
289
				$values = array_merge( $values, $value );
290
			}
291
        } else if ( strpos( $lowercase_key, 'like' ) !== false ) {
292
			/**
293
			 * Allow string to start or end with the value
294
			 * If the key is like% then skip the first % for starts with
295
			 * If the key is %like then skip the last % for ends with
296
			 */
297
			$start = '%';
298
			$end = '%';
299
			if ( $lowercase_key == 'like%' ) {
300
				$start = '';
301
				$where = rtrim( $where, '%' );
302
			} else if ( $lowercase_key == '%like' ) {
303
				$end = '';
304
				$where = rtrim( rtrim( $where, '%like' ), '%LIKE' );
305
				$where .= 'like';
306
			}
307
308
			$where .= ' %s';
309
			$values[] = $start . FrmAppHelper::esc_like( $value ) . $end;
310
311
        } else if ( $value === null ) {
312
            $where .= ' IS NULL';
313
        } else {
314
			// allow a - to prevent = from being added
315
			if ( substr( $key, -1 ) == '-' ) {
316
				$where = rtrim( $where, '-' );
317
			} else {
318
				$where .= '=';
319
			}
320
321
			self::add_query_placeholder( $key, $value, $where );
322
323
            $values[] = $value;
324
        }
325
    }
326
327
	/**
328
	 * Add %d, or %s to query
329
	 *
330
	 * @since 2.02.05
331
	 * @param string $key
332
	 * @param int|string $value
333
	 * @param string $where
334
	 */
335
    private static function add_query_placeholder( $key, $value, &$where ) {
336
		if ( is_numeric( $value ) && strpos( $key, 'meta_value' ) === false ) {
337
			$where .= '%d';
338
		} else {
339
			$where .= '%s';
340
		}
341
	}
342
343
    /**
344
     * @param string $table
345
	 * @param array $where
346
	 * @param array $args
347
	 * @return int
348
     */
349
    public static function get_count( $table, $where = array(), $args = array() ) {
350
        $count = self::get_var( $table, $where, 'COUNT(*)', $args );
351
        return $count;
352
    }
353
354
	/**
355
	 * @param string $table
356
	 * @param array $where
357
	 * @param string $field
358
	 * @param array $args
359
	 * @param string $limit
360
	 * @param string $type
361
	 * @return array|null|string|object
362
	 */
363
    public static function get_var( $table, $where = array(), $field = 'id', $args = array(), $limit = '', $type = 'var' ) {
364
        $group = '';
365
        self::get_group_and_table_name( $table, $group );
366
		self::convert_options_to_array( $args, '', $limit );
367
368
		$query = self::generate_query_string_from_pieces( $field, $table, $where, $args );
369
370
		$cache_key = self::generate_cache_key( $where, $args, $field, $type );
371
		$results = FrmAppHelper::check_cache( $cache_key, $group, $query, 'get_' . $type );
372
        return $results;
373
    }
374
375
	/**
376
	 * Generate a cache key from the where query, field, type, and other arguments
377
	 *
378
	 * @since 2.03.07
379
	 *
380
	 * @param array $where
381
	 * @param array $args
382
	 * @param string $field
383
	 * @param string $type
384
	 *
385
	 * @return string
386
	 */
387
	private static function generate_cache_key( $where, $args, $field, $type ) {
388
		$cache_key = '';
389
		$where = FrmAppHelper::array_flatten( $where );
390
		foreach ( $where as $key => $value ) {
391
			$cache_key .= $key . '_' . $value;
392
		}
393
		$cache_key .= implode( '_', $args ) . $field . '_' . $type;
394
		$cache_key = str_replace( array( ' ', ',' ), '_', $cache_key );
395
396
		return $cache_key;
397
	}
398
399
    /**
400
     * @param string $table
401
     * @param array $where
402
	 * @param string $field
403
	 * @param array $args
404
	 * @param string $limit
405
	 * @return mixed
406
     */
407
    public static function get_col( $table, $where = array(), $field = 'id', $args = array(), $limit = '' ) {
408
        return self::get_var( $table, $where, $field, $args, $limit, 'col' );
409
    }
410
411
    /**
412
     * @since 2.0
413
     * @param string $table
414
	 * @param array $where
415
	 * @param string $fields
416
	 * @param array $args
417
	 * @return mixed
418
     */
419
    public static function get_row( $table, $where = array(), $fields = '*', $args = array() ) {
420
        $args['limit'] = 1;
421
        return self::get_var( $table, $where, $fields, $args, '', 'row' );
422
    }
423
424
    /**
425
     * Prepare a key/value array before DB call
426
	 *
427
     * @since 2.0
428
     * @param string $table
429
	 * @param array $where
430
	 * @param string $fields
431
	 * @param array $args
432
	 * @return mixed
433
     */
434
    public static function get_results( $table, $where = array(), $fields = '*', $args = array() ) {
435
        return self::get_var( $table, $where, $fields, $args, '', 'results' );
436
    }
437
438
	/**
439
	 * Check for like, not like, in, not in, =, !=, >, <, <=, >=
440
	 * Return a value to append to the where array key
441
	 *
442
	 * @param string $where_is
443
	 * @return string
444
	 */
445
	public static function append_where_is( $where_is ) {
446
		$switch_to = array(
447
			'='		=> '',
448
			'!=' 	=> '!',
449
			'<='	=> '<',
450
			'>='	=> '>',
451
			'like'	=> 'like',
452
			'not like' => 'not like',
453
			'in'	=> '',
454
			'not in' => 'not',
455
			'like%'	=> 'like%',
456
			'%like'	=> '%like',
457
		);
458
459
		$where_is = strtolower( $where_is );
460
		if ( isset( $switch_to[ $where_is ] ) ) {
461
			return ' ' . $switch_to[ $where_is ];
462
		}
463
464
		// > and < need a little more work since we don't want them switched to >= and <=
465
		if ( $where_is == '>' || $where_is == '<' ) {
466
			return ' ' . $where_is . '-'; // the - indicates that the = should not be added later
467
		}
468
469
		// fallback to = if the query is none of these
470
		return '';
471
	}
472
473
    /**
474
     * Get 'frm_forms' from wp_frm_forms or a longer table param that includes a join
475
     * Also add the wpdb->prefix to the table if it's missing
476
     *
477
     * @param string $table
478
     * @param string $group
479
     */
480
    private static function get_group_and_table_name( &$table, &$group ) {
481
		global $wpdb, $wpmuBaseTablePrefix;
482
483
        $table_parts = explode(' ', $table);
484
        $group = reset($table_parts);
485
        $group = str_replace( $wpdb->prefix, '', $group );
486
487
		$prefix = $wpmuBaseTablePrefix ? $wpmuBaseTablePrefix : $wpdb->base_prefix;
488
		$group = str_replace( $prefix, '', $group );
489
490
        if ( $group == $table ) {
491
            $table = $wpdb->prefix . $table;
492
        }
493
494
		// switch to singular group name
495
		$group = rtrim( $group, 's' );
496
    }
497
498
    private static function convert_options_to_array( &$args, $order_by = '', $limit = '' ) {
499
        if ( ! is_array($args) ) {
500
			$args = array( 'order_by' => $args );
501
        }
502
503
        if ( ! empty( $order_by ) ) {
504
            $args['order_by'] = $order_by;
505
        }
506
507
        if ( ! empty( $limit ) ) {
508
            $args['limit'] = $limit;
509
        }
510
511
        $temp_args = $args;
512
        foreach ( $temp_args as $k => $v ) {
513
            if ( $v == '' ) {
514
				unset( $args[ $k ] );
515
                continue;
516
            }
517
518
            if ( $k == 'limit' ) {
519
				$args[ $k ] = FrmAppHelper::esc_limit( $v );
520
            }
521
            $db_name = strtoupper( str_replace( '_', ' ', $k ) );
522
            if ( strpos( $v, $db_name ) === false ) {
523
				$args[ $k ] = $db_name . ' ' . $v;
524
            }
525
        }
526
527
		// Make sure LIMIT is the last argument
528
		if ( isset( $args['order_by'] ) && isset( $args['limit'] ) ) {
529
			$temp_limit = $args['limit'];
530
			unset( $args['limit'] );
531
			$args['limit'] = $temp_limit;
532
		}
533
    }
534
535
	/**
536
	 * Get the associative array results for the given columns, table, and where query
537
	 *
538
	 * @since 2.02.05
539
	 * @param string $columns
540
	 * @param string $table
541
	 * @param array $where
542
	 * @return mixed
543
	 */
544
	public static function get_associative_array_results( $columns, $table, $where ) {
545
		$group = '';
546
		self::get_group_and_table_name( $table, $group );
547
548
		$query = self::generate_query_string_from_pieces( $columns, $table, $where );
549
550
		$cache_key = str_replace( array( ' ', ',' ), '_', trim( implode( '_', FrmAppHelper::array_flatten( $where ) ) . $columns . '_results_ARRAY_A' , ' WHERE' ) );
551
		$results = FrmAppHelper::check_cache( $cache_key, $group, $query, 'get_associative_results' );
552
553
		return $results;
554
	}
555
556
	/**
557
	 * Combine the pieces of a query to form a full, prepared query
558
	 *
559
	 * @since 2.02.05
560
	 *
561
	 * @param string $columns
562
	 * @param string $table
563
	 * @param mixed $where
564
	 * @param array $args
565
	 * @return string
566
	 */
567
	private static function generate_query_string_from_pieces( $columns, $table, $where, $args = array() ) {
568
		$query = 'SELECT ' . $columns . ' FROM ' . $table;
569
570
		if ( is_array( $where ) || empty( $where ) ) {
571
			self::get_where_clause_and_values( $where );
572
			global $wpdb;
573
			$query = $wpdb->prepare( $query . $where['where'] . ' ' . implode( ' ', $args ), $where['values'] );
574
		} else {
575
			/**
576
			 * Allow the $where to be prepared before we recieve it here.
577
			 * This is a fallback for reverse compatability, but is not recommended
578
			 */
579
			_deprecated_argument( 'where', '2.0', __( 'Use the query in an array format so it can be properly prepared.', 'formidable' ) );
580
			$query .= $where . ' ' . implode( ' ', $args );
581
		}
582
583
		return $query;
584
	}
585
586
    public function uninstall() {
587
		if ( ! current_user_can( 'administrator' ) ) {
588
            $frm_settings = FrmAppHelper::get_settings();
589
            wp_die($frm_settings->admin_permission);
590
        }
591
592
        global $wpdb, $wp_roles;
593
594
		$wpdb->query( 'DROP TABLE IF EXISTS ' . $this->fields );
595
		$wpdb->query( 'DROP TABLE IF EXISTS ' . $this->forms );
596
		$wpdb->query( 'DROP TABLE IF EXISTS ' . $this->entries );
597
		$wpdb->query( 'DROP TABLE IF EXISTS ' . $this->entry_metas );
598
599
        delete_option('frm_options');
600
        delete_option('frm_db_version');
601
602
        //delete roles
603
        $frm_roles = FrmAppHelper::frm_capabilities();
604
        $roles = get_editable_roles();
605
        foreach ( $frm_roles as $frm_role => $frm_role_description ) {
606
            foreach ( $roles as $role => $details ) {
607
                $wp_roles->remove_cap( $role, $frm_role );
608
                unset($role, $details);
609
    		}
610
    		unset($frm_role, $frm_role_description);
611
		}
612
		unset($roles, $frm_roles);
613
614
		// delete actions, views, and styles
615
616
		// prevent the post deletion from triggering entries to be deleted
617
		remove_action( 'before_delete_post', 'FrmProDisplaysController::before_delete_post' );
618
		remove_action( 'deleted_post', 'FrmProEntriesController::delete_entry' );
619
620
		$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' ) );
621
		foreach ( $post_ids as $post_id ) {
622
			// Delete's each post.
623
			wp_delete_post( $post_id, true );
624
		}
625
		unset( $post_ids );
626
627
		// delete transients
628
		delete_transient( 'frmpro_css' );
629
		delete_transient( 'frm_options' );
630
		delete_transient( 'frmpro_options' );
631
632
		$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_%' ) );
633
634
        do_action('frm_after_uninstall');
635
        return true;
636
    }
637
638
	/**
639
	 * Migrate old styling settings. If sites are using the old
640
	 * default 400px field width, switch it to 100%
641
	 *
642
	 * @since 2.0.4
643
	 */
644
	private function migrate_to_25() {
645
		// get the style that was created with the style migration
646
		$frm_style = new FrmStyle();
647
		$styles = $frm_style->get_all( 'post_date', 'ASC', 1 );
648
		if ( empty( $styles ) ) {
649
			return;
650
		}
651
652
		foreach ( $styles as $style ) {
653
			if ( $style->post_content['field_width'] == '400px' ) {
654
				$style->post_content['field_width'] = '100%';
655
				$frm_style->save( (array) $style );
656
				return;
657
			}
658
		}
659
	}
660
661
	/**
662
	 * Check if the parent_form_id columns exists.
663
	 * If not, try and add it again
664
	 *
665
	 * @since 2.0.2
666
	 */
667
	private function migrate_to_23() {
668
		global $wpdb;
669
		$exists = $wpdb->get_row( 'SHOW COLUMNS FROM ' . $this->forms . ' LIKE "parent_form_id"' );
670
		if ( empty( $exists ) ) {
671
			$wpdb->query( 'ALTER TABLE ' . $this->forms . ' ADD parent_form_id int(11) default 0' );
672
		}
673
	}
674
675
    /**
676
     * Change field size from character to pixel -- Multiply by 9
677
     */
678
    private function migrate_to_17() {
679
        global $wpdb;
680
		$pixel_conversion = 9;
681
682
        // Get query arguments
683
		$field_types = array( 'textarea', 'text', 'number', 'email', 'url', 'rte', 'date', 'phone', 'password', 'image', 'tag', 'file' );
684
		$query = array( 'type' => $field_types, 'field_options like' => 's:4:"size";', 'field_options not like' => 's:4:"size";s:0:' );
685
686
        // Get results
687
		$fields = FrmDb::get_results( $this->fields, $query, 'id, field_options' );
688
689
        $updated = 0;
690
        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...
691
            $f->field_options = maybe_unserialize($f->field_options);
692
            if ( empty($f->field_options['size']) || ! is_numeric($f->field_options['size']) ) {
693
                continue;
694
            }
695
696
			$f->field_options['size'] = round( $pixel_conversion * (int) $f->field_options['size'] );
697
            $f->field_options['size'] .= 'px';
698
            $u = FrmField::update( $f->id, array( 'field_options' => $f->field_options ) );
699
            if ( $u ) {
700
                $updated++;
701
            }
702
            unset($f);
703
        }
704
705
        // Change the characters in widgets to pixels
706
        $widgets = get_option('widget_frm_show_form');
707
        if ( empty($widgets) ) {
708
            return;
709
        }
710
711
        $widgets = maybe_unserialize($widgets);
712
        foreach ( $widgets as $k => $widget ) {
713
            if ( ! is_array($widget) || ! isset($widget['size']) ) {
714
                continue;
715
            }
716
			$size = round( $pixel_conversion * (int) $widget['size'] );
717
            $size .= 'px';
718
			$widgets[ $k ]['size'] = $size;
719
        }
720
        update_option('widget_frm_show_form', $widgets);
721
    }
722
723
    /**
724
     * Migrate post and email notification settings into actions
725
     */
726
    private function migrate_to_16() {
727
        global $wpdb;
728
729
        $forms = FrmDb::get_results( $this->forms, array(), 'id, options, is_template, default_template' );
730
731
        /**
732
        * Old email settings format:
733
        * email_to: Email or field id
734
        * also_email_to: array of fields ids
735
        * reply_to: Email, field id, 'custom'
736
        * cust_reply_to: string
737
        * reply_to_name: field id, 'custom'
738
        * cust_reply_to_name: string
739
        * plain_text: 0|1
740
        * email_message: string or ''
741
        * email_subject: string or ''
742
        * inc_user_info: 0|1
743
        * update_email: 0, 1, 2
744
        *
745
        * Old autoresponder settings format:
746
        * auto_responder: 0|1
747
        * ar_email_message: string or ''
748
        * ar_email_to: field id
749
        * ar_plain_text: 0|1
750
        * ar_reply_to_name: string
751
        * ar_reply_to: string
752
        * ar_email_subject: string
753
        * ar_update_email: 0, 1, 2
754
        *
755
        * New email settings:
756
        * post_content: json settings
757
        * post_title: form id
758
        * post_excerpt: message
759
        *
760
        */
761
762
        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...
763
			if ( $form->is_template && $form->default_template ) {
764
				// don't migrate the default templates since the email will be added anyway
765
				continue;
766
			}
767
768
            // Format form options
769
            $form_options = maybe_unserialize($form->options);
770
771
            // Migrate settings to actions
772
            FrmXMLHelper::migrate_form_settings_to_actions( $form_options, $form->id );
773
        }
774
    }
775
776
    private function migrate_to_11() {
777
        global $wpdb;
778
779
        $forms = FrmDb::get_results( $this->forms, array(), 'id, options');
780
781
        $sending = __( 'Sending', 'formidable' );
782
		$img = FrmAppHelper::plugin_url() . '/images/ajax_loader.gif';
783
        $old_default_html = <<<DEFAULT_HTML
784
<div class="frm_submit">
785
[if back_button]<input type="submit" value="[back_label]" name="frm_prev_page" formnovalidate="formnovalidate" [back_hook] />[/if back_button]
786
<input type="submit" value="[button_label]" [button_action] />
787
<img class="frm_ajax_loading" src="$img" alt="$sending" style="visibility:hidden;" />
788
</div>
789
DEFAULT_HTML;
790
        unset($sending, $img);
791
792
        $new_default_html = FrmFormsHelper::get_default_html('submit');
793
        $draft_link = FrmFormsHelper::get_draft_link();
794
		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...
795
            $form->options = maybe_unserialize($form->options);
796
            if ( ! isset($form->options['submit_html']) || empty($form->options['submit_html']) ) {
797
                continue;
798
            }
799
800
            if ( $form->options['submit_html'] != $new_default_html && $form->options['submit_html'] == $old_default_html ) {
801
                $form->options['submit_html'] = $new_default_html;
802
				$wpdb->update( $this->forms, array( 'options' => serialize( $form->options ) ), array( 'id' => $form->id ) );
803
			} else if ( ! strpos( $form->options['submit_html'], 'save_draft' ) ) {
804
				$form->options['submit_html'] = preg_replace( '~\<\/div\>(?!.*\<\/div\>)~', $draft_link . "\r\n</div>", $form->options['submit_html'] );
805
				$wpdb->update( $this->forms, array( 'options' => serialize( $form->options ) ), array( 'id' => $form->id ) );
806
            }
807
            unset($form);
808
        }
809
        unset($forms);
810
    }
811
812
    private function migrate_to_6() {
813
        global $wpdb;
814
815
		$no_save = array_merge( FrmField::no_save_fields(), array( 'form', 'hidden', 'user_id' ) );
816
		$fields = FrmDb::get_results( $this->fields, array( 'type NOT' => $no_save ), 'id, field_options' );
817
818
        $default_html = <<<DEFAULT_HTML
819
<div id="frm_field_[id]_container" class="form-field [required_class] [error_class]">
820
    <label class="frm_pos_[label_position]">[field_name]
821
        <span class="frm_required">[required_label]</span>
822
    </label>
823
    [input]
824
    [if description]<div class="frm_description">[description]</div>[/if description]
825
</div>
826
DEFAULT_HTML;
827
828
        $old_default_html = <<<DEFAULT_HTML
829
<div id="frm_field_[id]_container" class="form-field [required_class] [error_class]">
830
    <label class="frm_pos_[label_position]">[field_name]
831
        <span class="frm_required">[required_label]</span>
832
    </label>
833
    [input]
834
    [if description]<p class="frm_description">[description]</p>[/if description]
835
</div>
836
DEFAULT_HTML;
837
838
        $new_default_html = FrmFieldsHelper::get_default_html('text');
839
        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...
840
            $field->field_options = maybe_unserialize($field->field_options);
841
			if ( ! FrmField::is_option_empty( $field, 'custom_html' ) || $field->field_options['custom_html'] == $default_html || $field->field_options['custom_html'] == $old_default_html ) {
842
                $field->field_options['custom_html'] = $new_default_html;
843
				$wpdb->update( $this->fields, array( 'field_options' => maybe_serialize( $field->field_options ) ), array( 'id' => $field->id ) );
844
            }
845
            unset($field);
846
        }
847
        unset($default_html, $old_default_html, $fields);
848
    }
849
850
    private function migrate_to_4() {
851
        global $wpdb;
852
		$user_ids = FrmEntryMeta::getAll( array( 'fi.type' => 'user_id' ) );
853
        foreach ( $user_ids as $user_id ) {
854
			$wpdb->update( $this->entries, array( 'user_id' => $user_id->meta_value ), array( 'id' => $user_id->item_id ) );
855
        }
856
    }
857
}
858