Completed
Push — master ( bf42a4...e5ea0d )
by Jamie
03:56
created

FrmXMLHelper::remove_invalid_characters_from_xml()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
if ( ! defined('ABSPATH') ) {
3
	die( 'You are not allowed to call this page directly.' );
4
}
5
6
class FrmXMLHelper {
7
8
	public static function get_xml_values( $opt, $padding ) {
9
		if ( is_array( $opt ) ) {
10
			foreach ( $opt as $ok => $ov ) {
11
				echo "\n" . $padding;
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$padding'
Loading history...
12
				$tag = ( is_numeric( $ok ) ? 'key:' : '' ) . $ok;
13
				echo '<' . $tag . '>';
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$tag'
Loading history...
14
				self::get_xml_values( $ov, $padding .'    ' );
15
				if ( is_array( $ov ) ) {
16
					echo "\n" . $padding;
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$padding'
Loading history...
17
				}
18
				echo '</' . $tag . '>';
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$tag'
Loading history...
19
			}
20
		} else {
21
			echo self::cdata( $opt );
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not 'self'
Loading history...
22
		}
23
	}
24
25
	public static function import_xml( $file ) {
26
        $defaults = array(
27
            'forms' => 0, 'fields' => 0, 'terms' => 0,
28
            'posts' => 0, 'views' => 0, 'actions' => 0,
29
            'styles' => 0,
30
        );
31
32
        $imported = array(
33
            'imported' => $defaults,
34
			'updated'  => $defaults,
35
			'forms'    => array(),
36
			'terms'    => array(),
37
        );
38
39
        unset($defaults);
40
41
		if ( ! defined( 'WP_IMPORTING' ) ) {
42
            define('WP_IMPORTING', true);
43
        }
44
45
		if ( ! class_exists( 'DOMDocument' ) ) {
46
            return new WP_Error( 'SimpleXML_parse_error', __( 'Your server does not have XML enabled', 'formidable' ), libxml_get_errors() );
47
        }
48
49
        $dom = new DOMDocument;
50
		$success = $dom->loadXML( file_get_contents( $file ) );
0 ignored issues
show
introduced by
file_get_contents is highly discouraged, please use wpcom_vip_file_get_contents() instead.
Loading history...
51
		if ( ! $success ) {
52
			return new WP_Error( 'SimpleXML_parse_error', __( 'There was an error when reading this XML file', 'formidable' ), libxml_get_errors() );
53
		}
54
55
		if ( ! function_exists('simplexml_import_dom') ) {
56
			return new WP_Error( 'SimpleXML_parse_error', __( 'Your server is missing the simplexml_import_dom function', 'formidable' ), libxml_get_errors() );
57
		}
58
59
		$xml = simplexml_import_dom( $dom );
60
		unset( $dom );
61
62
		// halt if loading produces an error
63
		if ( ! $xml ) {
64
			return new WP_Error( 'SimpleXML_parse_error', __( 'There was an error when reading this XML file', 'formidable' ), libxml_get_errors() );
65
		}
66
67
        // add terms, forms (form and field ids), posts (post ids), and entries to db, in that order
68
		foreach ( array( 'term', 'form', 'view' ) as $item_type ) {
69
            // grab cats, tags, and terms, or forms or posts
70
            if ( isset($xml->{$item_type} ) ) {
71
				$function_name = 'import_xml_' . $item_type . 's';
72
				$imported = self::$function_name( $xml->{$item_type}, $imported );
73
				unset( $function_name, $xml->{$item_type} );
74
            }
75
        }
76
77
	    $return = apply_filters('frm_importing_xml', $imported, $xml );
78
79
	    return $return;
80
    }
81
82
	public static function import_xml_terms( $terms, $imported ) {
83
        foreach ( $terms as $t ) {
84
			if ( term_exists((string) $t->term_slug, (string) $t->term_taxonomy) ) {
0 ignored issues
show
introduced by
No space before opening casting parenthesis is prohibited
Loading history...
85
			    continue;
86
			}
87
88
			$parent = self::get_term_parent_id( $t );
89
90
			$term = wp_insert_term( (string) $t->term_name, (string) $t->term_taxonomy, array(
91
                'slug'          => (string) $t->term_slug,
92
                'description'   => (string) $t->term_description,
93
				'parent'        => empty( $parent ) ? 0 : $parent,
94
            ));
95
96
			if ( $term && is_array( $term ) ) {
97
                $imported['imported']['terms']++;
98
				$imported['terms'][ (int) $t->term_id ] = $term['term_id'];
99
            }
100
101
			unset( $term, $t );
102
		}
103
104
		return $imported;
105
    }
106
107
	/**
108
	 * @since 2.0.8
109
	 */
110
	private static function get_term_parent_id( $t ) {
111
		$parent = (string) $t->term_parent;
112
		if ( ! empty( $parent ) ) {
113
			$parent = term_exists( (string) $t->term_parent, (string) $t->term_taxonomy );
114
			if ( $parent ) {
115
				$parent = $parent['term_id'];
116
			} else {
117
				$parent = 0;
118
			}
119
		}
120
		return $parent;
121
	}
122
123
	public static function import_xml_forms( $forms, $imported ) {
124
		$child_forms = array();
125
126
		// Import child forms first
127
		self::put_child_forms_first( $forms );
128
129
		foreach ( $forms as $item ) {
130
            $form = array(
131
                'id'            => (int) $item->id,
132
                'form_key'      => (string) $item->form_key,
133
                'name'          => (string) $item->name,
134
                'description'   => (string) $item->description,
135
                'options'       => (string) $item->options,
136
                'logged_in'     => (int) $item->logged_in,
137
                'is_template'   => (int) $item->is_template,
138
                'default_template' => (int) $item->default_template,
139
                'editable'      => (int) $item->editable,
140
                'status'        => (string) $item->status,
141
                'parent_form_id' => isset($item->parent_form_id) ? (int) $item->parent_form_id : 0,
142
                'created_at'    => date('Y-m-d H:i:s', strtotime((string) $item->created_at)),
0 ignored issues
show
introduced by
No space before opening casting parenthesis is prohibited
Loading history...
143
            );
144
145
            $form['options'] = FrmAppHelper::maybe_json_decode($form['options']);
146
147
			self::update_custom_style_setting_on_import( $form );
148
149
            // if template, allow to edit if form keys match, otherwise, creation date must also match
150
			$edit_query = array( 'form_key' => $form['form_key'], 'is_template' => $form['is_template'] );
151
            if ( ! $form['is_template'] ) {
152
                $edit_query['created_at'] = $form['created_at'];
153
            }
154
155
            $edit_query = apply_filters('frm_match_xml_form', $edit_query, $form);
156
157
            $this_form = FrmForm::getAll($edit_query, '', 1);
158
            unset($edit_query);
159
160
            if ( ! empty( $this_form ) ) {
161
                $old_id = $form_id = $this_form->id;
162
                FrmForm::update($form_id, $form );
163
                $imported['updated']['forms']++;
164
                // Keep track of whether this specific form was updated or not
165
				$imported['form_status'][ $form_id ] = 'updated';
166
167
				$form_fields = FrmField::get_all_for_form( $form_id, '', 'exclude', 'exclude' );
168
                $old_fields = array();
169
                foreach ( $form_fields as $f ) {
170
					$old_fields[ $f->id ] = $f;
171
					$old_fields[ $f->field_key ] = $f->id;
172
                    unset($f);
173
                }
174
                $form_fields = $old_fields;
175
                unset($old_fields);
176
            } else {
177
                $old_id = false;
178
                //form does not exist, so create it
179
				$form_id = FrmForm::create( $form );
180
                if ( $form_id ) {
181
                    $imported['imported']['forms']++;
182
                    // Keep track of whether this specific form was updated or not
183
					$imported['form_status'][ $form_id ] = 'imported';
184
					self::track_imported_child_forms( (int) $form_id, $form['parent_form_id'], $child_forms );
185
                }
186
            }
187
188
    		self::import_xml_fields( $item->field, $form_id, $this_form, $form_fields, $imported );
189
190
    		// Delete any fields attached to this form that were not included in the template
191
    		if ( isset( $form_fields ) && ! empty( $form_fields ) ) {
192
				foreach ( $form_fields as $field ) {
193
                    if ( is_object($field) ) {
194
                        FrmField::destroy($field->id);
195
                    }
196
                    unset($field);
197
                }
198
                unset($form_fields);
199
            }
200
201
		    // Update field ids/keys to new ones
202
			do_action( 'frm_after_duplicate_form', $form_id, $form, array( 'old_id' => $old_id ) );
203
204
			$imported['forms'][ (int) $item->id ] = $form_id;
205
206
            // Send pre 2.0 form options through function that creates actions
207
            self::migrate_form_settings_to_actions( $form['options'], $form_id, $imported, $switch = true );
208
209
		    unset($form, $item);
210
		}
211
212
		self::maybe_update_child_form_parent_id( $imported['forms'], $child_forms );
213
214
		return $imported;
215
    }
216
217
	/**
218
	* Put child forms first so they will be imported before parents
219
	*
220
	* @since 2.0.16
221
	* @param array $forms
222
	*/
223
	private static function put_child_forms_first( &$forms ) {
224
		$child_forms = array();
225
		$regular_forms = array();
226
227
		foreach ( $forms as $form ) {
228
			$parent_form_id = isset( $form->parent_form_id) ? (int) $form->parent_form_id : 0;
229
230
			if ( $parent_form_id ) {
231
				$child_forms[] = $form;
232
			} else {
233
				$regular_forms[] = $form;
234
			}
235
		}
236
237
		$forms = array_merge( $child_forms, $regular_forms );
238
	}
239
240
	/**
241
	* Keep track of all imported child forms
242
	*
243
	* @since 2.0.16
244
	* @param int $form_id
245
	* @param int $parent_form_id
246
	* @param array $child_forms
247
	*/
248
	private static function track_imported_child_forms( $form_id, $parent_form_id, &$child_forms ) {
249
		if ( $parent_form_id ) {
250
			$child_forms[ $form_id ] = $parent_form_id;
251
		}
252
	}
253
254
	/**
255
	* Update the parent_form_id on imported child forms
256
	* Child forms are imported first so their parent_form_id will need to be updated after the parent is imported
257
	*
258
	* @since 2.0.6
259
	* @param array $imported_forms
260
	* @param array $child_forms
261
	*/
262
	private static function maybe_update_child_form_parent_id( $imported_forms, $child_forms ) {
263
		foreach ( $child_forms as $child_form_id => $old_parent_form_id ) {
264
265
			if ( isset( $imported_forms[ $old_parent_form_id ] ) && $imported_forms[ $old_parent_form_id ] != $old_parent_form_id ) {
266
				// Update all children with this old parent_form_id
267
				$new_parent_form_id = (int) $imported_forms[ $old_parent_form_id ];
268
269
				FrmForm::update( $child_form_id, array( 'parent_form_id' => $new_parent_form_id ) );
270
			}
271
		}
272
	}
273
274
	/**
275
	* Import all fields for a form
276
	* @since 2.0.13
277
	*
278
	* TODO: Cut down on params
279
	*/
280
	private static function import_xml_fields( $xml_fields, $form_id, $this_form, &$form_fields, &$imported ) {
281
		foreach ( $xml_fields as $field ) {
282
		    $f = array(
283
		        'id'            => (int) $field->id,
284
		        'field_key'     => (string) $field->field_key,
285
		        'name'          => (string) $field->name,
286
		        'description'   => (string) $field->description,
287
		        'type'          => (string) $field->type,
288
		        'default_value' => FrmAppHelper::maybe_json_decode( (string) $field->default_value),
289
		        'field_order'   => (int) $field->field_order,
290
		        'form_id'       => (int) $form_id,
291
		        'required'      => (int) $field->required,
292
		        'options'       => FrmAppHelper::maybe_json_decode( (string) $field->options),
293
				'field_options' => FrmAppHelper::maybe_json_decode( (string) $field->field_options ),
294
		    );
295
296
		    if ( is_array($f['default_value']) && in_array($f['type'], array(
297
		        'text', 'email', 'url', 'textarea',
298
		        'number','phone', 'date', 'time',
299
		        'hidden', 'password', 'tag', 'image',
300
		    )) ) {
301
		        if ( count($f['default_value']) === 1 ) {
302
		            $f['default_value'] = '['. reset($f['default_value']) .']';
303
		        } else {
304
		            $f['default_value'] = reset($f['default_value']);
305
		        }
306
		    }
307
308
		    $f = apply_filters('frm_duplicated_field', $f);
309
310
			self::maybe_update_form_select( $f, $imported );
311
312
		    if ( ! empty($this_form) ) {
313
		        // check for field to edit by field id
314
				if ( isset( $form_fields[ $f['id'] ] ) ) {
315
		            FrmField::update( $f['id'], $f );
316
		            $imported['updated']['fields']++;
317
318
					unset( $form_fields[ $f['id'] ] );
319
320
		            //unset old field key
321
					if ( isset( $form_fields[ $f['field_key'] ] ) ) {
322
						unset( $form_fields[ $f['field_key'] ] );
323
					}
324
				} else if ( isset( $form_fields[ $f['field_key'] ] ) ) {
325
		            // check for field to edit by field key
326
		            unset($f['id']);
327
328
					FrmField::update( $form_fields[ $f['field_key'] ], $f );
329
		            $imported['updated']['fields']++;
330
331
					unset( $form_fields[ $form_fields[ $f['field_key'] ] ] ); //unset old field id
332
					unset( $form_fields[ $f['field_key'] ] ); //unset old field key
333 View Code Duplication
				} else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
334
					$new_id = FrmField::create( $f );
335
					if ( $new_id == false ) {
336
						continue;
337
					}
338
339
		            // if no matching field id or key in this form, create the field
340
		            $imported['imported']['fields']++;
341
		        }
342 View Code Duplication
			} else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
343
				$new_id = FrmField::create( $f );
344
				if ( $new_id == false ) {
345
					continue;
346
				}
347
348
	            $imported['imported']['fields']++;
349
		    }
350
351
			unset($field, $new_id);
352
		}
353
	}
354
355
	/**
356
	* Switch the form_select on a repeating field or embedded form if it needs to be switched
357
	*
358
	* @since 2.0.16
359
	* @param array $f
360
	* @param array $imported
361
	*/
362
	private static function maybe_update_form_select( &$f, $imported ) {
363
		if ( ! isset( $imported['forms'] ) ) {
364
			return;
365
		}
366
367
		if ( $f['type'] == 'form' || ( $f['type'] == 'divider' && FrmField::is_option_true( $f['field_options'], 'repeat' ) ) ) {
368
			if ( FrmField::is_option_true( $f['field_options'], 'form_select' ) ) {
369
				$form_select = $f['field_options']['form_select'];
370
				if ( isset( $imported['forms'][ $form_select ] ) ) {
371
					$f['field_options']['form_select'] = $imported['forms'][ $form_select ];
372
				}
373
			}
374
		}
375
	}
376
377
	/**
378
	* Updates the custom style setting on import
379
	*
380
	* @since 2.0.19
381
	* @param array $form
382
	*
383
	*/
384
	private static function update_custom_style_setting_on_import( &$form ) {
385
		if ( ! isset( $form['options']['custom_style'] ) ) {
386
			return;
387
		}
388
389
		if ( is_numeric( $form['options']['custom_style'] ) ) {
390
			// Set to default
391
			$form['options']['custom_style'] = 1;
392
		} else {
393
			// Replace the style name with the style ID on import
394
			global $wpdb;
395
			$table = $wpdb->prefix . 'posts';
396
			$where = array(
397
				'post_name' => $form['options']['custom_style'],
398
				'post_type' => 'frm_styles',
399
			);
400
			$select = 'ID';
401
			$style_id = FrmDb::get_var( $table, $where, $select );
402
403
			if ( $style_id ) {
404
				$form['options']['custom_style'] = $style_id;
405
			} else {
406
				// Set to default
407
				$form['options']['custom_style'] = 1;
408
			}
409
		}
410
	}
411
412
	public static function import_xml_views( $views, $imported ) {
413
        $imported['posts'] = array();
414
        $form_action_type = FrmFormActionsController::$action_post_type;
415
416
        $post_types = array(
417
            'frm_display' => 'views',
418
            $form_action_type => 'actions',
419
            'frm_styles'    => 'styles',
420
        );
421
422
        foreach ( $views as $item ) {
423
			$post = array(
424
				'post_title'    => (string) $item->title,
425
				'post_name'     => (string) $item->post_name,
426
				'post_type'     => (string) $item->post_type,
427
				'post_password' => (string) $item->post_password,
428
				'guid'          => (string) $item->guid,
429
				'post_status'   => (string) $item->status,
430
				'post_author'   => FrmAppHelper::get_user_id_param( (string) $item->post_author ),
431
				'post_id'       => (int) $item->post_id,
432
				'post_parent'   => (int) $item->post_parent,
433
				'menu_order'    => (int) $item->menu_order,
434
				'post_content'  => FrmFieldsHelper::switch_field_ids((string) $item->content),
0 ignored issues
show
introduced by
No space before opening casting parenthesis is prohibited
Loading history...
435
				'post_excerpt'  => FrmFieldsHelper::switch_field_ids((string) $item->excerpt),
0 ignored issues
show
introduced by
No space before opening casting parenthesis is prohibited
Loading history...
436
				'is_sticky'     => (string) $item->is_sticky,
437
				'comment_status' => (string) $item->comment_status,
438
				'post_date'     => (string) $item->post_date,
439
				'post_date_gmt' => (string) $item->post_date_gmt,
440
				'ping_status'   => (string) $item->ping_status,
441
                'postmeta'      => array(),
442
                'tax_input'     => array(),
443
			);
444
445
            $old_id = $post['post_id'];
446
            self::populate_post($post, $item, $imported);
447
448
			unset($item);
449
450
			$post_id = false;
451
            if ( $post['post_type'] == $form_action_type ) {
452
                $action_control = FrmFormActionsController::get_form_actions( $post['post_excerpt'] );
453
				if ( $action_control ) {
454
					$post_id = $action_control->maybe_create_action( $post, $imported['form_status'] );
455
				}
456
                unset($action_control);
457
            } else if ( $post['post_type'] == 'frm_styles' ) {
458
                // Properly encode post content before inserting the post
459
                $post['post_content'] = FrmAppHelper::maybe_json_decode( $post['post_content'] );
460
                $post['post_content'] = FrmAppHelper::prepare_and_encode( $post['post_content'] );
461
462
                // Create/update post now
463
                $post_id = wp_insert_post( $post );
464
            } else {
465
                // Create/update post now
466
                $post_id = wp_insert_post( $post );
467
            }
468
469
            if ( ! is_numeric($post_id) ) {
470
                continue;
471
            }
472
473
            self::update_postmeta($post, $post_id);
474
475
            $this_type = 'posts';
476
			if ( isset( $post_types[ $post['post_type'] ] ) ) {
477
				$this_type = $post_types[ $post['post_type'] ];
478
            }
479
480
            if ( isset($post['ID']) && $post_id == $post['ID'] ) {
481
                $imported['updated'][ $this_type ]++;
482
            } else {
483
                $imported['imported'][ $this_type ]++;
484
            }
485
486
            unset($post);
487
488
			$imported['posts'][ (int) $old_id ] = $post_id;
489
		}
490
491
		self::maybe_update_stylesheet( $imported );
492
493
		return $imported;
494
    }
495
496
    private static function populate_post( &$post, $item, $imported ) {
497
		if ( isset($item->attachment_url) ) {
498
			$post['attachment_url'] = (string) $item->attachment_url;
499
		}
500
501
		if ( $post['post_type'] == FrmFormActionsController::$action_post_type && isset( $imported['forms'][ (int) $post['menu_order'] ] ) ) {
502
		    // update to new form id
503
		    $post['menu_order'] = $imported['forms'][ (int) $post['menu_order'] ];
504
		}
505
506
		foreach ( $item->postmeta as $meta ) {
507
		    self::populate_postmeta($post, $meta, $imported);
508
			unset($meta);
509
		}
510
511
        self::populate_taxonomies($post, $item);
512
513
        self::maybe_editing_post($post);
514
    }
515
516
    private static function populate_postmeta( &$post, $meta, $imported ) {
517
        global $frm_duplicate_ids;
518
519
	    $m = array(
520
			'key'   => (string) $meta->meta_key,
521
			'value' => (string) $meta->meta_value,
522
		);
523
524
		//switch old form and field ids to new ones
525
		if ( $m['key'] == 'frm_form_id' && isset($imported['forms'][ (int) $m['value'] ]) ) {
526
		    $m['value'] = $imported['forms'][ (int) $m['value'] ];
527
		} else {
528
		    $m['value'] = FrmAppHelper::maybe_json_decode($m['value']);
529
530
		    if ( ! empty($frm_duplicate_ids) ) {
531
532
		        if ( $m['key'] == 'frm_dyncontent' ) {
533
		            $m['value'] = FrmFieldsHelper::switch_field_ids($m['value']);
534
    		    } else if ( $m['key'] == 'frm_options' ) {
535
536
					foreach ( array( 'date_field_id', 'edate_field_id' ) as $setting_name ) {
537
						if ( isset( $m['value'][ $setting_name ] ) && is_numeric( $m['value'][ $setting_name ] ) && isset( $frm_duplicate_ids[ $m['value'][ $setting_name ] ] ) ) {
538
							$m['value'][ $setting_name ] = $frm_duplicate_ids[ $m['value'][ $setting_name ] ];
539
    		            }
540
    		        }
541
542
                    $check_dup_array = array();
543
    		        if ( isset( $m['value']['order_by'] ) && ! empty( $m['value']['order_by'] ) ) {
544
    		            if ( is_numeric( $m['value']['order_by'] ) && isset( $frm_duplicate_ids[ $m['value']['order_by'] ] ) ) {
545
    		                $m['value']['order_by'] = $frm_duplicate_ids[ $m['value']['order_by'] ];
546
    		            } else if ( is_array( $m['value']['order_by'] ) ) {
547
                            $check_dup_array[] = 'order_by';
548
    		            }
549
    		        }
550
551
    		        if ( isset( $m['value']['where'] ) && ! empty( $m['value']['where'] ) ) {
552
    		            $check_dup_array[] = 'where';
553
    		        }
554
555
                    foreach ( $check_dup_array as $check_k ) {
556
						foreach ( (array) $m['value'][ $check_k ] as $mk => $mv ) {
557
							if ( isset( $frm_duplicate_ids[ $mv ] ) ) {
558
								$m['value'][ $check_k ][ $mk ] = $frm_duplicate_ids[ $mv ];
559
		                    }
560
		                    unset($mk, $mv);
561
		                }
562
                    }
563
    		    }
564
		    }
565
		}
566
567
		if ( ! is_array($m['value']) ) {
568
		    $m['value'] = FrmAppHelper::maybe_json_decode($m['value']);
569
		}
570
571
		$post['postmeta'][ (string) $meta->meta_key ] = $m['value'];
0 ignored issues
show
introduced by
Detected usage of meta_key, possible slow query.
Loading history...
572
    }
573
574
    /**
575
     * Add terms to post
576
     * @param array $post by reference
577
     * @param object $item The XML object data
578
     */
579
    private static function populate_taxonomies( &$post, $item ) {
580
		foreach ( $item->category as $c ) {
581
			$att = $c->attributes();
582
			if ( ! isset( $att['nicename'] ) ) {
583
                continue;
584
            }
585
586
		    $taxonomy = (string) $att['domain'];
587
		    if ( is_taxonomy_hierarchical($taxonomy) ) {
588
		        $name = (string) $att['nicename'];
589
		        $h_term = get_term_by('slug', $name, $taxonomy);
590
		        if ( $h_term ) {
591
		            $name = $h_term->term_id;
592
		        }
593
		        unset($h_term);
594
		    } else {
595
		        $name = (string) $c;
596
		    }
597
598
			if ( ! isset( $post['tax_input'][ $taxonomy ] ) ) {
599
				$post['tax_input'][ $taxonomy ] = array();
600
			}
601
602
			$post['tax_input'][ $taxonomy ][] = $name;
603
		    unset($name);
604
		}
605
    }
606
607
    /**
608
     * Edit post if the key and created time match
609
     */
610
    private static function maybe_editing_post( &$post ) {
611
		$match_by = array(
612
		    'post_type'     => $post['post_type'],
613
		    'name'          => $post['post_name'],
614
		    'post_status'   => $post['post_status'],
615
		    'posts_per_page' => 1,
616
		);
617
618
		if ( in_array( $post['post_status'], array( 'trash', 'draft' ) ) ) {
619
		    $match_by['include'] = $post['post_id'];
620
		    unset($match_by['name']);
621
		}
622
623
		$editing = get_posts($match_by);
624
625
        if ( ! empty($editing) && current($editing)->post_date == $post['post_date'] ) {
626
            // set the id of the post to edit
627
            $post['ID'] = current($editing)->ID;
628
        }
629
    }
630
631
    private static function update_postmeta( &$post, $post_id ) {
632
        foreach ( $post['postmeta'] as $k => $v ) {
633
            if ( '_edit_last' == $k ) {
634
                $v = FrmAppHelper::get_user_id_param($v);
635
            } else if ( '_thumbnail_id' == $k && FrmAppHelper::pro_is_installed() ) {
636
                //change the attachment ID
637
                $v = FrmProXMLHelper::get_file_id($v);
638
            }
639
640
            update_post_meta($post_id, $k, $v);
641
642
            unset($k, $v);
643
        }
644
    }
645
646
	private static function maybe_update_stylesheet( $imported ) {
647
		if ( ( isset( $imported['imported']['styles'] ) && ! empty( $imported['imported']['styles'] ) ) || ( isset( $imported['updated']['styles'] ) && ! empty( $imported['updated']['styles'] ) ) ) {
648
			if ( is_admin() && function_exists( 'get_filesystem_method' ) ) {
649
				$frm_style = new FrmStyle();
650
				$frm_style->update( 'default' );
651
			}
652
		}
653
	}
654
655
    /**
656
     * @param string $message
657
     */
658
	public static function parse_message( $result, &$message, &$errors ) {
659
        if ( is_wp_error($result) ) {
660
            $errors[] = $result->get_error_message();
661
        } else if ( ! $result ) {
662
            return;
663
        }
664
665
        if ( ! is_array($result) ) {
666
            $message = is_string( $result ) ? $result : print_r( $result, 1 );
0 ignored issues
show
introduced by
The use of function print_r() is discouraged
Loading history...
667
            return;
668
        }
669
670
        $t_strings = array(
671
            'imported'  => __( 'Imported', 'formidable' ),
672
            'updated'   => __( 'Updated', 'formidable' ),
673
        );
674
675
        $message = '<ul>';
676
        foreach ( $result as $type => $results ) {
677
			if ( ! isset( $t_strings[ $type ] ) ) {
678
                // only print imported and updated
679
                continue;
680
            }
681
682
            $s_message = array();
683
            foreach ( $results as $k => $m ) {
684
                self::item_count_message($m, $k, $s_message);
685
                unset($k, $m);
686
            }
687
688
            if ( ! empty($s_message) ) {
689
				$message .= '<li><strong>' . $t_strings[ $type ] . ':</strong> ';
690
                $message .= implode(', ', $s_message);
691
                $message .= '</li>';
692
            }
693
        }
694
695
        if ( $message == '<ul>' ) {
696
            $message = '';
697
            $errors[] = __( 'Nothing was imported or updated', 'formidable' );
698
        } else {
699
            $message .= '</ul>';
700
        }
701
    }
702
703
	public static function item_count_message( $m, $type, &$s_message ) {
704
        if ( ! $m ) {
705
            return;
706
        }
707
708
        $strings = array(
709
            'forms'     => sprintf( _n( '%1$s Form', '%1$s Forms', $m, 'formidable' ), $m ),
710
            'fields'    => sprintf( _n( '%1$s Field', '%1$s Fields', $m, 'formidable' ), $m ),
711
            'items'     => sprintf( _n( '%1$s Entry', '%1$s Entries', $m, 'formidable' ), $m ),
712
            'views'     => sprintf( _n( '%1$s View', '%1$s Views', $m, 'formidable' ), $m ),
713
            'posts'     => sprintf( _n( '%1$s Post', '%1$s Posts', $m, 'formidable' ), $m ),
714
            'styles'     => sprintf( _n( '%1$s Style', '%1$s Styles', $m, 'formidable' ), $m ),
715
            'terms'     => sprintf( _n( '%1$s Term', '%1$s Terms', $m, 'formidable' ), $m ),
716
            'actions'   => sprintf( _n( '%1$s Form Action', '%1$s Form Actions', $m, 'formidable' ), $m ),
717
        );
718
719
		$s_message[] = isset( $strings[ $type ] ) ? $strings[ $type ] : ' ' . $m . ' ' . ucfirst( $type );
720
    }
721
722
	/**
723
	 * Prepare the form options for export
724
	 *
725
	 * @since 2.0.19
726
	 * @param string $options
727
	 * @return string
728
	 */
729
	public static function prepare_form_options_for_export( $options ) {
730
		$options = maybe_unserialize( $options );
731
		// Change custom_style to the post_name instead of ID
732
		if ( isset( $options['custom_style'] ) && 1 !== $options['custom_style'] ) {
733
			global $wpdb;
734
			$table = $wpdb->prefix . 'posts';
735
			$where = array( 'ID' => $options['custom_style'] );
736
			$select = 'post_name';
737
738
			$style_name = FrmDb::get_var( $table, $where, $select );
739
740
			if ( $style_name ) {
741
				$options['custom_style'] = $style_name;
742
			} else {
743
				$options['custom_style'] = 1;
744
			}
745
		}
746
		$options = serialize( $options );
747
		return self::cdata( $options );
748
	}
749
750
	public static function cdata( $str ) {
751
	    $str = maybe_unserialize($str);
752
	    if ( is_array($str) ) {
753
	        $str = json_encode($str);
754
		} else if ( seems_utf8( $str ) == false ) {
755
			$str = utf8_encode( $str );
756
		}
757
758
        if ( is_numeric($str) ) {
759
            return $str;
760
        }
761
762
		self::remove_invalid_characters_from_xml( $str );
763
764
		// $str = ent2ncr(esc_html($str));
765
		$str = '<![CDATA[' . str_replace( ']]>', ']]]]><![CDATA[>', $str ) . ']]>';
766
767
		return $str;
768
	}
769
770
	/**
771
	 * Remove <US> character (unit separator) from exported strings
772
	 *
773
	 * @since 2.0.22
774
	 * @param string $str
775
	 */
776
	private static function remove_invalid_characters_from_xml( &$str ) {
777
		// Remove <US> character
778
		$str = str_replace( '\x1F', '', $str );
779
	}
780
781
    public static function migrate_form_settings_to_actions( $form_options, $form_id, &$imported = array(), $switch = false ) {
782
        // Get post type
783
        $post_type = FrmFormActionsController::$action_post_type;
784
785
        // Set up imported index, if not set up yet
786
        if ( ! isset( $imported['imported']['actions'] ) ) {
787
            $imported['imported']['actions'] = 0;
788
        }
789
790
        // Migrate post settings to action
791
        self::migrate_post_settings_to_action( $form_options, $form_id, $post_type, $imported, $switch );
792
793
        // Migrate email settings to action
794
        self::migrate_email_settings_to_action( $form_options, $form_id, $post_type, $imported, $switch );
795
    }
796
797
    /**
798
    * Migrate post settings to form action
799
    *
800
    * @param string $post_type
801
    */
802
    private static function migrate_post_settings_to_action( $form_options, $form_id, $post_type, &$imported, $switch ) {
803
        if ( ! isset($form_options['create_post']) || ! $form_options['create_post'] ) {
804
            return;
805
        }
806
807
        $new_action = array(
808
            'post_type'     => $post_type,
809
            'post_excerpt'  => 'wppost',
810
			'post_title'    => __( 'Create Posts', 'formidable' ),
811
            'menu_order'    => $form_id,
812
            'post_status'   => 'publish',
813
            'post_content'  => array(),
814
            'post_name'     => $form_id .'_wppost_1',
815
        );
816
817
        $post_settings = array(
818
            'post_type', 'post_category', 'post_content',
819
            'post_excerpt', 'post_title', 'post_name', 'post_date',
820
			'post_status', 'post_custom_fields', 'post_password',
821
        );
822
823
        foreach ( $post_settings as $post_setting ) {
824
			if ( isset( $form_options[ $post_setting ] ) ) {
825
				$new_action['post_content'][ $post_setting ] = $form_options[ $post_setting ];
826
            }
827
            unset($post_setting);
828
        }
829
830
		$new_action['event'] = array( 'create', 'update' );
831
832
        if ( $switch ) {
833
			// Fields with string or int saved
834
			$basic_fields = array( 'post_title', 'post_content', 'post_excerpt', 'post_password', 'post_date', 'post_status' );
835
836
			// Fields with arrays saved
837
			$array_fields = array( 'post_category', 'post_custom_fields' );
838
839
			$new_action['post_content'] = self::switch_action_field_ids( $new_action['post_content'], $basic_fields, $array_fields );
840
        }
841
        $new_action['post_content'] = json_encode($new_action['post_content']);
842
843
        $exists = get_posts( array(
844
            'name'          => $new_action['post_name'],
845
            'post_type'     => $new_action['post_type'],
846
            'post_status'   => $new_action['post_status'],
847
            'numberposts'   => 1,
848
        ) );
849
850
        if ( ! $exists ) {
851
			// this isn't an email, but we need to use a class that will always be included
852
			FrmAppHelper::save_json_post( $new_action );
853
            $imported['imported']['actions']++;
854
        }
855
    }
856
857
	/**
858
	 * Switch old field IDs for new field IDs in emails and post
859
	 *
860
	 * @since 2.0
861
	 * @param array $post_content - check for old field IDs
862
	 * @param array $basic_fields - fields with string or int saved
863
	 * @param array $array_fields - fields with arrays saved
864
	 *
865
	 * @return string $post_content - new field IDs
866
	 */
867
	private static function switch_action_field_ids( $post_content, $basic_fields, $array_fields = array() ) {
868
        global $frm_duplicate_ids;
869
870
        // If there aren't IDs that were switched, end now
871
        if ( ! $frm_duplicate_ids ) {
872
            return;
873
        }
874
875
        // Get old IDs
876
        $old = array_keys( $frm_duplicate_ids );
877
878
        // Get new IDs
879
        $new = array_values( $frm_duplicate_ids );
880
881
        // Do a str_replace with each item to set the new IDs
882
        foreach ( $post_content as $key => $setting ) {
883
            if ( ! is_array( $setting ) && in_array( $key, $basic_fields ) ) {
884
                // Replace old IDs with new IDs
885
				$post_content[ $key ] = str_replace( $old, $new, $setting );
886
            } else if ( is_array( $setting ) && in_array( $key, $array_fields ) ) {
887
                foreach ( $setting as $k => $val ) {
888
                    // Replace old IDs with new IDs
889
					$post_content[ $key ][ $k ] = str_replace( $old, $new, $val );
890
                }
891
            }
892
            unset( $key, $setting );
893
        }
894
        return $post_content;
895
    }
896
897
    private static function migrate_email_settings_to_action( $form_options, $form_id, $post_type, &$imported, $switch ) {
898
        // No old notifications or autoresponders to carry over
899
		if ( ! isset( $form_options['auto_responder'] ) && ! isset( $form_options['notification'] ) && ! isset( $form_options['email_to'] ) ) {
900
            return;
901
        }
902
903
        // Initialize notifications array
904
        $notifications = array();
905
906
        // Migrate regular notifications
907
        self::migrate_notifications_to_action( $form_options, $form_id, $notifications );
908
909
        // Migrate autoresponders
910
        self::migrate_autoresponder_to_action( $form_options, $form_id, $notifications );
911
912
        if (  empty( $notifications ) ) {
913
            return;
914
        }
915
916
        foreach ( $notifications as $new_notification ) {
917
            $new_notification['post_type']      = $post_type;
918
            $new_notification['post_excerpt']   = 'email';
919
			$new_notification['post_title']     = __( 'Email Notification', 'formidable' );
920
            $new_notification['menu_order']     = $form_id;
921
            $new_notification['post_status']    = 'publish';
922
923
            // Switch field IDs and keys, if needed
924
            if ( $switch ) {
925
926
				// Switch field IDs in email conditional logic
927
				self::switch_email_contition_field_ids( $new_notification['post_content'] );
928
929
				// Switch all other field IDs in email
930
                $new_notification['post_content'] = FrmFieldsHelper::switch_field_ids( $new_notification['post_content'] );
931
            }
932
            $new_notification['post_content']   = FrmAppHelper::prepare_and_encode( $new_notification['post_content'] );
933
934
            $exists = get_posts( array(
935
                'name'          => $new_notification['post_name'],
936
                'post_type'     => $new_notification['post_type'],
937
                'post_status'   => $new_notification['post_status'],
938
                'numberposts'   => 1,
939
            ) );
940
941
            if ( empty($exists) ) {
942
				FrmAppHelper::save_json_post( $new_notification );
943
                $imported['imported']['actions']++;
944
            }
945
            unset($new_notification);
946
        }
947
    }
948
949
    private static function migrate_notifications_to_action( $form_options, $form_id, &$notifications ) {
950
        if ( ! isset( $form_options['notification'] ) && isset( $form_options['email_to'] ) && ! empty( $form_options['email_to'] ) ) {
951
            // add old settings into notification array
952
			$form_options['notification'] = array( 0 => $form_options );
953
        } else if ( isset( $form_options['notification']['email_to'] ) ) {
954
            // make sure it's in the correct format
955
			$form_options['notification'] = array( 0 => $form_options['notification'] );
956
        }
957
958
        if ( isset( $form_options['notification'] ) && is_array($form_options['notification']) ) {
959
            foreach ( $form_options['notification'] as $email_key => $notification ) {
960
961
                $atts = array( 'email_to' => '', 'reply_to' => '', 'reply_to_name' => '', 'event' => '', 'form_id' => $form_id, 'email_key' => $email_key );
962
963
                // Format the email data
964
                self::format_email_data( $atts, $notification );
965
966
				if ( isset( $notification['twilio'] ) && $notification['twilio'] ) {
967
					do_action( 'frm_create_twilio_action', $atts, $notification );
968
				}
969
970
                // Setup the new notification
971
                $new_notification = array();
972
                self::setup_new_notification( $new_notification, $notification, $atts );
973
974
                $notifications[] = $new_notification;
975
            }
976
        }
977
    }
978
979
    private static function format_email_data( &$atts, $notification ) {
980
        // Format email_to
981
        self::format_email_to_data( $atts, $notification );
982
983
        // Format the reply to email and name
984
        $reply_fields = array( 'reply_to' => '', 'reply_to_name' => '' );
985
        foreach ( $reply_fields as $f => $val ) {
986
			if ( isset( $notification[ $f ] ) ) {
987
				$atts[ $f ] = $notification[ $f ];
988
				if ( 'custom' == $notification[ $f ] ) {
989
					$atts[ $f ] = $notification[ 'cust_' . $f ];
990
				} else if ( is_numeric( $atts[ $f ] ) && ! empty( $atts[ $f ] ) ) {
991
					$atts[ $f ] = '[' . $atts[ $f ] . ']';
992
                }
993
            }
994
            unset( $f, $val );
995
        }
996
997
        // Format event
998
		$atts['event'] = array( 'create' );
999
        if ( isset( $notification['update_email'] ) && 1 == $notification['update_email'] ) {
1000
            $atts['event'][] = 'update';
1001
        } else if ( isset($notification['update_email']) && 2 == $notification['update_email'] ) {
1002
			$atts['event'] = array( 'update' );
1003
        }
1004
    }
1005
1006
    private static function format_email_to_data( &$atts, $notification ) {
1007
        if ( isset( $notification['email_to'] ) ) {
1008
			$atts['email_to'] = preg_split( '/ (,|;) /', $notification['email_to'] );
1009
        } else {
1010
            $atts['email_to'] = array();
1011
        }
1012
1013
        if ( isset( $notification['also_email_to'] ) ) {
1014
            $email_fields = (array) $notification['also_email_to'];
1015
            $atts['email_to'] = array_merge( $email_fields, $atts['email_to'] );
1016
            unset( $email_fields );
1017
        }
1018
1019
        foreach ( $atts['email_to'] as $key => $email_field ) {
1020
1021
            if ( is_numeric( $email_field ) ) {
1022
				$atts['email_to'][ $key ] = '[' . $email_field . ']';
1023
            }
1024
1025
            if ( strpos( $email_field, '|') ) {
1026
                $email_opt = explode( '|', $email_field );
1027
                if ( isset( $email_opt[0] ) ) {
1028
					$atts['email_to'][ $key ] = '[' . $email_opt[0] . ' show=' . $email_opt[1] . ']';
1029
                }
1030
                unset( $email_opt );
1031
            }
1032
        }
1033
        $atts['email_to'] = implode(', ', $atts['email_to']);
1034
    }
1035
1036
    private static function setup_new_notification( &$new_notification, $notification, $atts ) {
1037
        // Set up new notification
1038
        $new_notification = array(
1039
            'post_content'  => array(
1040
                'email_to'      => $atts['email_to'],
1041
                'event'         => $atts['event'],
1042
            ),
1043
            'post_name'         => $atts['form_id'] .'_email_'. $atts['email_key'],
1044
        );
1045
1046
        // Add more fields to the new notification
1047
        $add_fields = array( 'email_message', 'email_subject', 'plain_text', 'inc_user_info', 'conditions' );
1048
        foreach ( $add_fields as $add_field ) {
1049
			if ( isset( $notification[ $add_field ] ) ) {
1050
				$new_notification['post_content'][ $add_field ] = $notification[ $add_field ];
1051
            } else if ( in_array( $add_field, array( 'plain_text', 'inc_user_info' ) ) ) {
1052
				$new_notification['post_content'][ $add_field ] = 0;
1053
            } else {
1054
				$new_notification['post_content'][ $add_field ] = '';
1055
            }
1056
            unset( $add_field );
1057
        }
1058
1059
		// Set reply to
1060
		$new_notification['post_content']['reply_to'] = $atts['reply_to'];
1061
1062
        // Set from
1063
		if ( ! empty( $atts['reply_to'] ) || ! empty( $atts['reply_to_name'] ) ) {
1064
            $new_notification['post_content']['from'] = ( empty($atts['reply_to_name']) ? '[sitename]' : $atts['reply_to_name'] ) .' <'. ( empty($atts['reply_to']) ? '[admin_email]' : $atts['reply_to'] ) .'>';
1065
        }
1066
    }
1067
1068
	/**
1069
	* Switch field IDs in pre-2.0 email conditional logic
1070
	*
1071
	* @param $post_content array, pass by reference
1072
	*/
1073
	private static function switch_email_contition_field_ids( &$post_content ) {
1074
		// Switch field IDs in conditional logic
1075
		if ( isset( $post_content['conditions'] ) && is_array( $post_content['conditions'] ) ) {
1076
			foreach ( $post_content['conditions'] as $email_key => $val ) {
1077
				if ( is_numeric( $email_key ) ) {
1078
					$post_content['conditions'][ $email_key ] = self::switch_action_field_ids( $val, array( 'hide_field' ) );
1079
				}
1080
				unset( $email_key, $val);
1081
			}
1082
		}
1083
	}
1084
1085
    private static function migrate_autoresponder_to_action( $form_options, $form_id, &$notifications ) {
1086
        if ( isset($form_options['auto_responder']) && $form_options['auto_responder'] && isset($form_options['ar_email_message']) && $form_options['ar_email_message'] ) {
1087
            // migrate autoresponder
1088
1089
            $email_field = isset($form_options['ar_email_to']) ? $form_options['ar_email_to'] : 0;
1090
            if ( strpos($email_field, '|') ) {
1091
                // data from entries field
1092
                $email_field = explode('|', $email_field);
1093
                if ( isset($email_field[1]) ) {
1094
                    $email_field = $email_field[1];
1095
                }
1096
            }
1097
            if ( is_numeric($email_field) && ! empty($email_field) ) {
1098
                $email_field = '['. $email_field .']';
1099
            }
1100
1101
            $notification = $form_options;
1102
            $new_notification2 = array(
1103
                'post_content'  => array(
1104
                    'email_message' => $notification['ar_email_message'],
1105
                    'email_subject' => isset($notification['ar_email_subject']) ? $notification['ar_email_subject'] : '',
1106
                    'email_to'      => $email_field,
1107
                    'plain_text'    => isset($notification['ar_plain_text']) ? $notification['ar_plain_text'] : 0,
1108
                    'inc_user_info' => 0,
1109
                ),
1110
                'post_name'     => $form_id .'_email_'. count( $notifications ),
1111
            );
1112
1113
            $reply_to = isset($notification['ar_reply_to']) ? $notification['ar_reply_to'] : '';
1114
            $reply_to_name = isset($notification['ar_reply_to_name']) ? $notification['ar_reply_to_name'] : '';
1115
1116
			if ( ! empty( $reply_to ) ) {
1117
				$new_notification2['post_content']['reply_to'] = $reply_to;
1118
			}
1119
1120
			if ( ! empty( $reply_to ) || ! empty( $reply_to_name ) ) {
1121
                $new_notification2['post_content']['from'] = ( empty($reply_to_name) ? '[sitename]' : $reply_to_name ) .' <'. ( empty($reply_to) ? '[admin_email]' : $reply_to ) .'>';
1122
			}
1123
1124
            $notifications[] = $new_notification2;
1125
            unset( $new_notification2 );
1126
        }
1127
    }
1128
}
1129
1130