Completed
Pull Request — master (#107)
by Stephanie
03:20
created

FrmXMLHelper   F

Complexity

Total Complexity 272

Size/Duplication

Total Lines 1408
Duplicated Lines 0.85 %

Coupling/Cohesion

Components 2
Dependencies 10

Importance

Changes 0
Metric Value
dl 12
loc 1408
rs 0.8
c 0
b 0
f 0
wmc 272
lcom 2
cbo 10

52 Methods

Rating   Name   Duplication   Size   Complexity  
A get_xml_values() 0 16 5
B import_xml() 0 29 6
A import_xml_now() 0 14 3
A pre_import_data() 0 18 1
B import_xml_terms() 0 28 6
A get_term_parent_id() 0 12 3
A import_xml_forms() 0 52 4
A fill_form() 0 18 2
A maybe_get_form() 0 14 2
A update_form() 0 7 1
A get_form_fields() 0 11 2
A delete_removed_fields() 0 10 4
A put_child_forms_first() 0 16 4
A track_imported_child_forms() 0 5 2
A maybe_update_child_form_parent_id() 0 11 4
B import_xml_fields() 0 50 9
A fill_field() 0 15 1
A maybe_update_in_section_variable() 0 16 4
B maybe_update_form_select() 6 14 7
A maybe_update_get_values_form_setting() 6 12 4
A create_imported_field() 0 7 2
A update_custom_style_setting_on_import() 0 30 4
A update_custom_style_setting_after_import() 0 14 5
C import_xml_views() 0 87 11
B populate_post() 0 24 6
D populate_postmeta() 0 57 21
B populate_taxonomies() 0 27 6
A maybe_editing_post() 0 20 4
A update_postmeta() 0 15 5
A maybe_update_custom_css() 0 10 2
B maybe_update_stylesheet() 0 13 8
B parse_message() 0 44 10
A item_count_message() 0 18 3
A prepare_form_options_for_export() 0 22 4
A remove_default_form_options() 0 7 2
A prepare_field_for_export() 0 3 1
A remove_default_field_options() 0 25 4
A remove_defaults() 0 11 3
A remove_default_html() 0 18 5
A cdata() 0 19 4
A remove_invalid_characters_from_xml() 0 4 1
A migrate_form_settings_to_actions() 0 15 2
B migrate_post_settings_to_action() 0 52 7
B switch_action_field_ids() 0 29 8
B migrate_email_settings_to_action() 0 55 8
A remove_deprecated_notification_settings() 0 9 3
B migrate_notifications_to_action() 0 36 10
B format_email_data() 0 29 10
B format_email_to_data() 0 29 7
B setup_new_notification() 0 31 8
A switch_email_contition_field_ids() 0 11 5
F migrate_autoresponder_to_action() 0 43 19

How to fix   Duplicated Code    Complexity   

Duplicated Code

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

Common duplication problems, and corresponding solutions are:

Complex Class

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

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

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

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

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" . esc_html( $padding );
12
				$tag = ( is_numeric( $ok ) ? 'key:' : '' ) . $ok;
13
				echo '<' . esc_html( $tag ) . '>';
14
				self::get_xml_values( $ov, $padding . '    ' );
15
				if ( is_array( $ov ) ) {
16
					echo "\n" . esc_html( $padding );
17
				}
18
				echo '</' . esc_html( $tag ) . '>';
19
			}
20
		} else {
21
			echo self::cdata( $opt ); // WPCS: XSS ok.
22
		}
23
	}
24
25
	public static function import_xml( $file ) {
26
		if ( ! defined( 'WP_IMPORTING' ) ) {
27
			define( 'WP_IMPORTING', true );
28
        }
29
30
		if ( ! class_exists( 'DOMDocument' ) ) {
31
            return new WP_Error( 'SimpleXML_parse_error', __( 'Your server does not have XML enabled', 'formidable' ), libxml_get_errors() );
32
        }
33
34
		$dom = new DOMDocument();
35
		$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...
36
		if ( ! $success ) {
37
			return new WP_Error( 'SimpleXML_parse_error', __( 'There was an error when reading this XML file', 'formidable' ), libxml_get_errors() );
38
		}
39
40
		if ( ! function_exists( 'simplexml_import_dom' ) ) {
41
			return new WP_Error( 'SimpleXML_parse_error', __( 'Your server is missing the simplexml_import_dom function', 'formidable' ), libxml_get_errors() );
42
		}
43
44
		$xml = simplexml_import_dom( $dom );
45
		unset( $dom );
46
47
		// halt if loading produces an error
48
		if ( ! $xml ) {
49
			return new WP_Error( 'SimpleXML_parse_error', __( 'There was an error when reading this XML file', 'formidable' ), libxml_get_errors() );
50
		}
51
52
		return self::import_xml_now( $xml );
53
	}
54
55
	/**
56
	 * Add terms, forms (form and field ids), posts (post ids), and entries to db, in that order
57
	 *
58
	 * @since 3.06
59
	 * @return array The number of items imported
60
	 */
61
	public static function import_xml_now( $xml ) {
62
		$imported = self::pre_import_data();
63
64
		foreach ( array( 'term', 'form', 'view' ) as $item_type ) {
65
            // grab cats, tags, and terms, or forms or posts
66
			if ( isset( $xml->{$item_type} ) ) {
67
				$function_name = 'import_xml_' . $item_type . 's';
68
				$imported = self::$function_name( $xml->{$item_type}, $imported );
69
				unset( $function_name, $xml->{$item_type} );
70
            }
71
        }
72
73
		return apply_filters( 'frm_importing_xml', $imported, $xml );
74
	}
75
76
	/**
77
	 * @since 3.06
78
	 * @return array
79
	 */
80
	private static function pre_import_data() {
81
		$defaults = array(
82
			'forms'   => 0,
83
			'fields'  => 0,
84
			'terms'   => 0,
85
			'posts'   => 0,
86
			'views'   => 0,
87
			'actions' => 0,
88
			'styles'  => 0,
89
		);
90
91
        return array(
92
            'imported' => $defaults,
93
			'updated'  => $defaults,
94
			'forms'    => array(),
95
			'terms'    => array(),
96
        );
97
	}
98
99
	public static function import_xml_terms( $terms, $imported ) {
100
        foreach ( $terms as $t ) {
101
			if ( term_exists( (string) $t->term_slug, (string) $t->term_taxonomy ) ) {
102
			    continue;
103
			}
104
105
			$parent = self::get_term_parent_id( $t );
106
107
			$term = wp_insert_term(
108
				(string) $t->term_name,
109
				(string) $t->term_taxonomy,
110
				array(
111
					'slug'          => (string) $t->term_slug,
112
					'description'   => (string) $t->term_description,
113
					'parent'        => empty( $parent ) ? 0 : $parent,
114
				)
115
			);
116
117
			if ( $term && is_array( $term ) ) {
118
                $imported['imported']['terms']++;
119
				$imported['terms'][ (int) $t->term_id ] = $term['term_id'];
120
            }
121
122
			unset( $term, $t );
123
		}
124
125
		return $imported;
126
    }
127
128
	/**
129
	 * @since 2.0.8
130
	 */
131
	private static function get_term_parent_id( $t ) {
132
		$parent = (string) $t->term_parent;
133
		if ( ! empty( $parent ) ) {
134
			$parent = term_exists( (string) $t->term_parent, (string) $t->term_taxonomy );
135
			if ( $parent ) {
136
				$parent = $parent['term_id'];
137
			} else {
138
				$parent = 0;
139
			}
140
		}
141
		return $parent;
142
	}
143
144
	public static function import_xml_forms( $forms, $imported ) {
145
		$child_forms = array();
146
147
		// Import child forms first
148
		self::put_child_forms_first( $forms );
149
150
		foreach ( $forms as $item ) {
151
            $form = self::fill_form( $item );
152
153
			self::update_custom_style_setting_on_import( $form );
154
155
	        $this_form = self::maybe_get_form( $form );
156
157
			$old_id = false;
158
			$form_fields = false;
159
			if ( ! empty( $this_form ) ) {
160
				$form_id = $this_form->id;
161
				$old_id = $this_form->id;
162
				self::update_form( $this_form, $form, $imported );
163
164
				$form_fields = self::get_form_fields( $form_id );
165
			} else {
166
				$form_id = FrmForm::create( $form );
167
		        if ( $form_id ) {
168
		            $imported['imported']['forms']++;
169
		            // Keep track of whether this specific form was updated or not
170
					$imported['form_status'][ $form_id ] = 'imported';
171
					self::track_imported_child_forms( (int) $form_id, $form['parent_form_id'], $child_forms );
172
		        }
173
			}
174
175
			self::import_xml_fields( $item->field, $form_id, $this_form, $form_fields, $imported );
176
177
			self::delete_removed_fields( $form_fields );
178
179
		    // Update field ids/keys to new ones
180
			do_action( 'frm_after_duplicate_form', $form_id, $form, array( 'old_id' => $old_id ) );
181
182
			$imported['forms'][ (int) $item->id ] = $form_id;
183
184
            // Send pre 2.0 form options through function that creates actions
185
            self::migrate_form_settings_to_actions( $form['options'], $form_id, $imported, true );
186
187
			do_action( 'frm_after_import_form', $form_id, $form );
188
189
			unset( $form, $item );
190
		}
191
192
		self::maybe_update_child_form_parent_id( $imported['forms'], $child_forms );
193
194
		return $imported;
195
    }
196
197
	private static function fill_form( $item ) {
198
		$form = array(
199
			'id'            => (int) $item->id,
200
			'form_key'      => (string) $item->form_key,
201
			'name'          => (string) $item->name,
202
			'description'   => (string) $item->description,
203
			'options'       => (string) $item->options,
204
			'logged_in'     => (int) $item->logged_in,
205
			'is_template'   => (int) $item->is_template,
206
			'default_template' => (int) $item->default_template,
207
			'editable'      => (int) $item->editable,
208
			'status'        => (string) $item->status,
209
			'parent_form_id' => isset( $item->parent_form_id ) ? (int) $item->parent_form_id : 0,
210
			'created_at'    => date( 'Y-m-d H:i:s', strtotime( (string) $item->created_at ) ),
211
		);
212
		$form['options'] = FrmAppHelper::maybe_json_decode( $form['options'] );
213
		return $form;
214
	}
215
216
	private static function maybe_get_form( $form ) {
217
		// if template, allow to edit if form keys match, otherwise, creation date must also match
218
		$edit_query = array(
219
			'form_key'    => $form['form_key'],
220
			'is_template' => $form['is_template'],
221
		);
222
		if ( ! $form['is_template'] ) {
223
			$edit_query['created_at'] = $form['created_at'];
224
		}
225
226
		$edit_query = apply_filters( 'frm_match_xml_form', $edit_query, $form );
227
228
		return FrmForm::getAll( $edit_query, '', 1 );
229
	}
230
231
	private static function update_form( $this_form, $form, &$imported ) {
232
		$form_id = $this_form->id;
233
		FrmForm::update( $form_id, $form );
234
		$imported['updated']['forms']++;
235
		// Keep track of whether this specific form was updated or not
236
		$imported['form_status'][ $form_id ] = 'updated';
237
	}
238
239
	private static function get_form_fields( $form_id ) {
240
		$form_fields = FrmField::get_all_for_form( $form_id, '', 'exclude', 'exclude' );
241
		$old_fields = array();
242
		foreach ( $form_fields as $f ) {
243
			$old_fields[ $f->id ] = $f;
244
			$old_fields[ $f->field_key ] = $f->id;
245
			unset( $f );
246
		}
247
		$form_fields = $old_fields;
248
		return $form_fields;
249
	}
250
251
	/**
252
	 * Delete any fields attached to this form that were not included in the template
253
	 */
254
	private static function delete_removed_fields( $form_fields ) {
255
		if ( ! empty( $form_fields ) ) {
256
			foreach ( $form_fields as $field ) {
257
				if ( is_object( $field ) ) {
258
					FrmField::destroy( $field->id );
259
				}
260
				unset( $field );
261
			}
262
		}
263
	}
264
265
	/**
266
	* Put child forms first so they will be imported before parents
267
	*
268
	* @since 2.0.16
269
	* @param array $forms
270
	*/
271
	private static function put_child_forms_first( &$forms ) {
272
		$child_forms = array();
273
		$regular_forms = array();
274
275
		foreach ( $forms as $form ) {
276
			$parent_form_id = isset( $form->parent_form_id ) ? (int) $form->parent_form_id : 0;
277
278
			if ( $parent_form_id ) {
279
				$child_forms[] = $form;
280
			} else {
281
				$regular_forms[] = $form;
282
			}
283
		}
284
285
		$forms = array_merge( $child_forms, $regular_forms );
286
	}
287
288
	/**
289
	* Keep track of all imported child forms
290
	*
291
	* @since 2.0.16
292
	* @param int $form_id
293
	* @param int $parent_form_id
294
	* @param array $child_forms
295
	*/
296
	private static function track_imported_child_forms( $form_id, $parent_form_id, &$child_forms ) {
297
		if ( $parent_form_id ) {
298
			$child_forms[ $form_id ] = $parent_form_id;
299
		}
300
	}
301
302
	/**
303
	* Update the parent_form_id on imported child forms
304
	* Child forms are imported first so their parent_form_id will need to be updated after the parent is imported
305
	*
306
	* @since 2.0.6
307
	* @param array $imported_forms
308
	* @param array $child_forms
309
	*/
310
	private static function maybe_update_child_form_parent_id( $imported_forms, $child_forms ) {
311
		foreach ( $child_forms as $child_form_id => $old_parent_form_id ) {
312
313
			if ( isset( $imported_forms[ $old_parent_form_id ] ) && $imported_forms[ $old_parent_form_id ] != $old_parent_form_id ) {
314
				// Update all children with this old parent_form_id
315
				$new_parent_form_id = (int) $imported_forms[ $old_parent_form_id ];
316
317
				FrmForm::update( $child_form_id, array( 'parent_form_id' => $new_parent_form_id ) );
318
			}
319
		}
320
	}
321
322
	/**
323
	* Import all fields for a form
324
	 *
325
	* @since 2.0.13
326
	*
327
	* TODO: Cut down on params
328
	*/
329
	private static function import_xml_fields( $xml_fields, $form_id, $this_form, &$form_fields, &$imported ) {
330
		$in_section = 0;
331
332
		foreach ( $xml_fields as $field ) {
333
			$f = self::fill_field( $field, $form_id );
334
335
			$has_default = array( 'text', 'email', 'url', 'textarea', 'number', 'phone', 'date', 'hidden', 'password', 'tag' );
336
			if ( is_array( $f['default_value'] ) && in_array( $f['type'], $has_default, true ) ) {
337
				if ( count( $f['default_value'] ) === 1 ) {
338
					$f['default_value'] = '[' . reset( $f['default_value'] ) . ']';
339
				} else {
340
					$f['default_value'] = reset( $f['default_value'] );
341
				}
342
			}
343
344
			self::maybe_update_in_section_variable( $in_section, $f );
345
			self::maybe_update_form_select( $f, $imported );
346
			self::maybe_update_get_values_form_setting( $imported, $f );
347
348
			if ( ! empty( $this_form ) ) {
349
				// check for field to edit by field id
350
				if ( isset( $form_fields[ $f['id'] ] ) ) {
351
					FrmField::update( $f['id'], $f );
352
					$imported['updated']['fields']++;
353
354
					unset( $form_fields[ $f['id'] ] );
355
356
					//unset old field key
357
					if ( isset( $form_fields[ $f['field_key'] ] ) ) {
358
						unset( $form_fields[ $f['field_key'] ] );
359
					}
360
				} else if ( isset( $form_fields[ $f['field_key'] ] ) ) {
361
					// check for field to edit by field key
362
					unset( $f['id'] );
363
364
					FrmField::update( $form_fields[ $f['field_key'] ], $f );
365
					$imported['updated']['fields']++;
366
367
					unset( $form_fields[ $form_fields[ $f['field_key'] ] ] ); //unset old field id
368
					unset( $form_fields[ $f['field_key'] ] ); //unset old field key
369
				} else {
370
					// if no matching field id or key in this form, create the field
371
					self::create_imported_field( $f, $imported );
372
				}
373
			} else {
374
375
				self::create_imported_field( $f, $imported );
376
			}
377
		}
378
	}
379
380
	private static function fill_field( $field, $form_id ) {
381
		return array(
382
			'id'            => (int) $field->id,
383
			'field_key'     => (string) $field->field_key,
384
			'name'          => (string) $field->name,
385
			'description'   => (string) $field->description,
386
			'type'          => (string) $field->type,
387
			'default_value' => FrmAppHelper::maybe_json_decode( (string) $field->default_value ),
388
			'field_order'   => (int) $field->field_order,
389
			'form_id'       => (int) $form_id,
390
			'required'      => (int) $field->required,
391
			'options'       => FrmAppHelper::maybe_json_decode( (string) $field->options ),
392
			'field_options' => FrmAppHelper::maybe_json_decode( (string) $field->field_options ),
393
		);
394
	}
395
396
	/**
397
	 * Update the current in_section value
398
	 *
399
	 * @since 2.0.25
400
	 * @param int $in_section
401
	 * @param array $f
402
	 */
403
	private static function maybe_update_in_section_variable( &$in_section, &$f ) {
404
		// If we're at the end of a section, switch $in_section is 0
405
		if ( in_array( $f['type'], array( 'end_divider', 'break', 'form' ) ) ) {
406
			$in_section = 0;
407
		}
408
409
		// Update the current field's in_section value
410
		if ( ! isset( $f['field_options']['in_section'] ) ) {
411
			$f['field_options']['in_section'] = $in_section;
412
		}
413
414
		// If we're starting a new section, switch $in_section to ID of divider
415
		if ( $f['type'] == 'divider' ) {
416
			$in_section = $f['id'];
417
		}
418
	}
419
420
	/**
421
	* Switch the form_select on a repeating field or embedded form if it needs to be switched
422
	*
423
	* @since 2.0.16
424
	* @param array $f
425
	* @param array $imported
426
	*/
427
	private static function maybe_update_form_select( &$f, $imported ) {
428
		if ( ! isset( $imported['forms'] ) ) {
429
			return;
430
		}
431
432
		if ( $f['type'] == 'form' || ( $f['type'] == 'divider' && FrmField::is_option_true( $f['field_options'], 'repeat' ) ) ) {
433 View Code Duplication
			if ( FrmField::is_option_true( $f['field_options'], 'form_select' ) ) {
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...
434
				$form_select = (int) $f['field_options']['form_select'];
435
				if ( isset( $imported['forms'][ $form_select ] ) ) {
436
					$f['field_options']['form_select'] = $imported['forms'][ $form_select ];
437
				}
438
			}
439
		}
440
	}
441
442
	/**
443
	 * Update the get_values_form setting if the form was imported
444
	 *
445
	 * @since 2.01.0
446
	 * @param array $imported
447
	 * @param array $f
448
	 */
449
	private static function maybe_update_get_values_form_setting( $imported, &$f ) {
450
		if ( ! isset( $imported['forms'] ) ) {
451
			return;
452
		}
453
454 View Code Duplication
		if ( FrmField::is_option_true_in_array( $f['field_options'], 'get_values_form' ) ) {
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...
455
			$old_form = $f['field_options']['get_values_form'];
456
			if ( isset( $imported['forms'][ $old_form ] ) ) {
457
				$f['field_options']['get_values_form'] = $imported['forms'][ $old_form ];
458
			}
459
		}
460
	}
461
462
	/**
463
	 * Create an imported field
464
	 *
465
	 * @since 2.0.25
466
	 * @param array $f
467
	 * @param array $imported
468
	 */
469
	private static function create_imported_field( $f, &$imported ) {
470
		$new_id = FrmField::create( $f );
471
		if ( $new_id != false ) {
472
			$imported['imported']['fields']++;
473
			do_action( 'frm_after_field_is_imported', $f, $new_id );
474
		}
475
	}
476
477
	/**
478
	* Updates the custom style setting on import
479
	* Convert the post slug to an ID
480
	*
481
	* @since 2.0.19
482
	* @param array $form
483
	*/
484
	private static function update_custom_style_setting_on_import( &$form ) {
485
		if ( ! isset( $form['options']['custom_style'] ) ) {
486
			return;
487
		}
488
489
		if ( is_numeric( $form['options']['custom_style'] ) ) {
490
			// Set to default
491
			$form['options']['custom_style'] = 1;
492
		} else {
493
			// Replace the style name with the style ID on import
494
			global $wpdb;
495
			$table = $wpdb->prefix . 'posts';
496
			$where = array(
497
				'post_name' => $form['options']['custom_style'],
498
				'post_type' => 'frm_styles',
499
			);
500
			$select = 'ID';
501
			$style_id = FrmDb::get_var( $table, $where, $select );
502
503
			if ( $style_id ) {
504
				$form['options']['custom_style'] = $style_id;
505
			} else {
506
				// save the old style to maybe update after styles import
507
				$form['options']['old_style'] = $form['options']['custom_style'];
508
509
				// Set to default
510
				$form['options']['custom_style'] = 1;
511
			}
512
		}
513
	}
514
515
	/**
516
	 * After styles are imported, check for any forms that were linked
517
	 * and link them back up.
518
	 *
519
	 * @since 2.2.7
520
	 */
521
	private static function update_custom_style_setting_after_import( $form_id ) {
522
		$form = FrmForm::getOne( $form_id );
523
524
		if ( $form && isset( $form->options['old_style'] ) ) {
525
			$form = (array) $form;
526
			$saved_style = $form['options']['custom_style'];
527
			$form['options']['custom_style'] = $form['options']['old_style'];
528
			self::update_custom_style_setting_on_import( $form );
529
			$has_changed = ( $form['options']['custom_style'] != $saved_style && $form['options']['custom_style'] != $form['options']['old_style'] );
530
			if ( $has_changed ) {
531
				FrmForm::update( $form['id'], $form );
532
			}
533
		}
534
	}
535
536
	public static function import_xml_views( $views, $imported ) {
537
        $imported['posts'] = array();
538
        $form_action_type = FrmFormActionsController::$action_post_type;
539
540
        $post_types = array(
541
            'frm_display' => 'views',
542
            $form_action_type => 'actions',
543
            'frm_styles'    => 'styles',
544
        );
545
546
        foreach ( $views as $item ) {
547
			$post = array(
548
				'post_title'    => (string) $item->title,
549
				'post_name'     => (string) $item->post_name,
550
				'post_type'     => (string) $item->post_type,
551
				'post_password' => (string) $item->post_password,
552
				'guid'          => (string) $item->guid,
553
				'post_status'   => (string) $item->status,
554
				'post_author'   => FrmAppHelper::get_user_id_param( (string) $item->post_author ),
555
				'post_id'       => (int) $item->post_id,
556
				'post_parent'   => (int) $item->post_parent,
557
				'menu_order'    => (int) $item->menu_order,
558
				'post_content'  => FrmFieldsHelper::switch_field_ids( (string) $item->content ),
559
				'post_excerpt'  => FrmFieldsHelper::switch_field_ids( (string) $item->excerpt ),
560
				'is_sticky'     => (string) $item->is_sticky,
561
				'comment_status' => (string) $item->comment_status,
562
				'post_date'     => (string) $item->post_date,
563
				'post_date_gmt' => (string) $item->post_date_gmt,
564
				'ping_status'   => (string) $item->ping_status,
565
                'postmeta'      => array(),
566
                'tax_input'     => array(),
567
			);
568
569
            $old_id = $post['post_id'];
570
			self::populate_post( $post, $item, $imported );
571
572
			unset( $item );
573
574
			$post_id = false;
575
            if ( $post['post_type'] == $form_action_type ) {
576
                $action_control = FrmFormActionsController::get_form_actions( $post['post_excerpt'] );
577
				if ( $action_control && is_object( $action_control ) ) {
578
					$post_id = $action_control->maybe_create_action( $post, $imported['form_status'] );
579
				}
580
				unset( $action_control );
581
            } else if ( $post['post_type'] == 'frm_styles' ) {
582
                // Properly encode post content before inserting the post
583
                $post['post_content'] = FrmAppHelper::maybe_json_decode( $post['post_content'] );
584
				$custom_css = isset( $post['post_content']['custom_css'] ) ? $post['post_content']['custom_css'] : '';
585
                $post['post_content'] = FrmAppHelper::prepare_and_encode( $post['post_content'] );
586
587
                // Create/update post now
588
                $post_id = wp_insert_post( $post );
589
				self::maybe_update_custom_css( $custom_css );
590
            } else {
591
                // Create/update post now
592
                $post_id = wp_insert_post( $post );
593
            }
594
595
			if ( ! is_numeric( $post_id ) ) {
596
                continue;
597
            }
598
599
			self::update_postmeta( $post, $post_id );
600
601
            $this_type = 'posts';
602
			if ( isset( $post_types[ $post['post_type'] ] ) ) {
603
				$this_type = $post_types[ $post['post_type'] ];
604
            }
605
606
			if ( isset( $post['ID'] ) && $post_id == $post['ID'] ) {
607
                $imported['updated'][ $this_type ]++;
608
            } else {
609
                $imported['imported'][ $this_type ]++;
610
            }
611
612
			$imported['posts'][ (int) $old_id ] = $post_id;
613
614
			do_action( 'frm_after_import_view', $post_id, $post );
615
616
			unset( $post );
617
		}
618
619
		self::maybe_update_stylesheet( $imported );
620
621
		return $imported;
622
    }
623
624
    private static function populate_post( &$post, $item, $imported ) {
625
		if ( isset( $item->attachment_url ) ) {
626
			$post['attachment_url'] = (string) $item->attachment_url;
627
		}
628
629
		if ( $post['post_type'] == FrmFormActionsController::$action_post_type && isset( $imported['forms'][ (int) $post['menu_order'] ] ) ) {
630
		    // update to new form id
631
		    $post['menu_order'] = $imported['forms'][ (int) $post['menu_order'] ];
632
		}
633
634
		// Don't allow default styles to take over a site's default style
635
		if ( 'frm_styles' == $post['post_type'] ) {
636
			$post['menu_order'] = 0;
637
		}
638
639
		foreach ( $item->postmeta as $meta ) {
640
			self::populate_postmeta( $post, $meta, $imported );
641
			unset( $meta );
642
		}
643
644
		self::populate_taxonomies( $post, $item );
645
646
		self::maybe_editing_post( $post );
647
    }
648
649
    private static function populate_postmeta( &$post, $meta, $imported ) {
650
        global $frm_duplicate_ids;
651
652
	    $m = array(
653
			'key'   => (string) $meta->meta_key,
654
			'value' => (string) $meta->meta_value,
655
		);
656
657
		//switch old form and field ids to new ones
658
		if ( $m['key'] == 'frm_form_id' && isset( $imported['forms'][ (int) $m['value'] ] ) ) {
659
		    $m['value'] = $imported['forms'][ (int) $m['value'] ];
660
		} else {
661
		    $m['value'] = FrmAppHelper::maybe_json_decode( $m['value'] );
662
663
			if ( ! empty( $frm_duplicate_ids ) ) {
664
665
		        if ( $m['key'] == 'frm_dyncontent' ) {
666
					$m['value'] = FrmFieldsHelper::switch_field_ids( $m['value'] );
667
    		    } else if ( $m['key'] == 'frm_options' ) {
668
669
					foreach ( array( 'date_field_id', 'edate_field_id' ) as $setting_name ) {
670
						if ( isset( $m['value'][ $setting_name ] ) && is_numeric( $m['value'][ $setting_name ] ) && isset( $frm_duplicate_ids[ $m['value'][ $setting_name ] ] ) ) {
671
							$m['value'][ $setting_name ] = $frm_duplicate_ids[ $m['value'][ $setting_name ] ];
672
    		            }
673
    		        }
674
675
                    $check_dup_array = array();
676
    		        if ( isset( $m['value']['order_by'] ) && ! empty( $m['value']['order_by'] ) ) {
677
    		            if ( is_numeric( $m['value']['order_by'] ) && isset( $frm_duplicate_ids[ $m['value']['order_by'] ] ) ) {
678
    		                $m['value']['order_by'] = $frm_duplicate_ids[ $m['value']['order_by'] ];
679
    		            } else if ( is_array( $m['value']['order_by'] ) ) {
680
                            $check_dup_array[] = 'order_by';
681
    		            }
682
    		        }
683
684
    		        if ( isset( $m['value']['where'] ) && ! empty( $m['value']['where'] ) ) {
685
    		            $check_dup_array[] = 'where';
686
    		        }
687
688
                    foreach ( $check_dup_array as $check_k ) {
689
						foreach ( (array) $m['value'][ $check_k ] as $mk => $mv ) {
690
							if ( isset( $frm_duplicate_ids[ $mv ] ) ) {
691
								$m['value'][ $check_k ][ $mk ] = $frm_duplicate_ids[ $mv ];
692
		                    }
693
							unset( $mk, $mv );
694
		                }
695
                    }
696
    		    }
697
		    }
698
		}
699
700
		if ( ! is_array( $m['value'] ) ) {
701
			$m['value'] = FrmAppHelper::maybe_json_decode( $m['value'] );
702
		}
703
704
		$post['postmeta'][ (string) $meta->meta_key ] = $m['value'];
0 ignored issues
show
introduced by
Detected usage of meta_key, possible slow query.
Loading history...
705
    }
706
707
    /**
708
     * Add terms to post
709
	 *
710
     * @param array $post by reference
711
     * @param object $item The XML object data
712
     */
713
    private static function populate_taxonomies( &$post, $item ) {
714
		foreach ( $item->category as $c ) {
715
			$att = $c->attributes();
716
			if ( ! isset( $att['nicename'] ) ) {
717
                continue;
718
            }
719
720
		    $taxonomy = (string) $att['domain'];
721
			if ( is_taxonomy_hierarchical( $taxonomy ) ) {
722
		        $name = (string) $att['nicename'];
723
				$h_term = get_term_by( 'slug', $name, $taxonomy );
724
		        if ( $h_term ) {
725
		            $name = $h_term->term_id;
726
		        }
727
				unset( $h_term );
728
		    } else {
729
		        $name = (string) $c;
730
		    }
731
732
			if ( ! isset( $post['tax_input'][ $taxonomy ] ) ) {
733
				$post['tax_input'][ $taxonomy ] = array();
734
			}
735
736
			$post['tax_input'][ $taxonomy ][] = $name;
737
			unset( $name );
738
		}
739
    }
740
741
    /**
742
     * Edit post if the key and created time match
743
     */
744
    private static function maybe_editing_post( &$post ) {
745
		$match_by = array(
746
		    'post_type'     => $post['post_type'],
747
		    'name'          => $post['post_name'],
748
		    'post_status'   => $post['post_status'],
749
		    'posts_per_page' => 1,
750
		);
751
752
		if ( in_array( $post['post_status'], array( 'trash', 'draft' ) ) ) {
753
		    $match_by['include'] = $post['post_id'];
754
			unset( $match_by['name'] );
755
		}
756
757
		$editing = get_posts( $match_by );
758
759
		if ( ! empty( $editing ) && current( $editing )->post_date == $post['post_date'] ) {
760
			// set the id of the post to edit
761
			$post['ID'] = current( $editing )->ID;
762
		}
763
    }
764
765
    private static function update_postmeta( &$post, $post_id ) {
766
        foreach ( $post['postmeta'] as $k => $v ) {
767
            if ( '_edit_last' == $k ) {
768
				$v = FrmAppHelper::get_user_id_param( $v );
769
            } else if ( '_thumbnail_id' == $k && FrmAppHelper::pro_is_installed() ) {
770
                //change the attachment ID
771
				$field_obj = FrmFieldFactory::get_field_type( 'file' );
772
				$v = $field_obj->get_file_id( $v );
773
            }
774
775
			update_post_meta( $post_id, $k, $v );
776
777
			unset( $k, $v );
778
        }
779
    }
780
781
	/**
782
	 * If a template includes custom css, let's include it.
783
	 * The custom css is included on the default style.
784
	 *
785
	 * @since 2.03
786
	 */
787
	private static function maybe_update_custom_css( $custom_css ) {
788
		if ( empty( $custom_css ) ) {
789
			return;
790
		}
791
792
		$frm_style = new FrmStyle();
793
		$default_style = $frm_style->get_default_style();
794
		$default_style->post_content['custom_css'] .= "\r\n\r\n" . $custom_css;
795
		$frm_style->save( $default_style );
796
	}
797
798
	private static function maybe_update_stylesheet( $imported ) {
799
		$new_styles = isset( $imported['imported']['styles'] ) && ! empty( $imported['imported']['styles'] );
800
		$updated_styles = isset( $imported['updated']['styles'] ) && ! empty( $imported['updated']['styles'] );
801
		if ( $new_styles || $updated_styles ) {
802
			if ( is_admin() && function_exists( 'get_filesystem_method' ) ) {
803
				$frm_style = new FrmStyle();
804
				$frm_style->update( 'default' );
805
			}
806
			foreach ( $imported['forms'] as $form_id ) {
807
				self::update_custom_style_setting_after_import( $form_id );
808
			}
809
		}
810
	}
811
812
    /**
813
     * @param string $message
814
     */
815
	public static function parse_message( $result, &$message, &$errors ) {
816
		if ( is_wp_error( $result ) ) {
817
            $errors[] = $result->get_error_message();
818
        } else if ( ! $result ) {
819
            return;
820
        }
821
822
		if ( ! is_array( $result ) ) {
823
            $message = is_string( $result ) ? $result : htmlentities( print_r( $result, 1 ) );
0 ignored issues
show
introduced by
The use of function print_r() is discouraged
Loading history...
824
            return;
825
        }
826
827
        $t_strings = array(
828
            'imported'  => __( 'Imported', 'formidable' ),
829
            'updated'   => __( 'Updated', 'formidable' ),
830
        );
831
832
        $message = '<ul>';
833
        foreach ( $result as $type => $results ) {
834
			if ( ! isset( $t_strings[ $type ] ) ) {
835
                // only print imported and updated
836
                continue;
837
            }
838
839
			$s_message = array();
840
			foreach ( $results as $k => $m ) {
841
				self::item_count_message( $m, $k, $s_message );
842
				unset( $k, $m );
843
			}
844
845
			if ( ! empty( $s_message ) ) {
846
				$message .= '<li><strong>' . $t_strings[ $type ] . ':</strong> ';
847
				$message .= implode( ', ', $s_message );
848
				$message .= '</li>';
849
			}
850
        }
851
852
        if ( $message == '<ul>' ) {
853
            $message = '';
854
            $errors[] = __( 'Nothing was imported or updated', 'formidable' );
855
        } else {
856
            $message .= '</ul>';
857
        }
858
    }
859
860
	public static function item_count_message( $m, $type, &$s_message ) {
861
        if ( ! $m ) {
862
            return;
863
        }
864
865
        $strings = array(
866
            'forms'     => sprintf( _n( '%1$s Form', '%1$s Forms', $m, 'formidable' ), $m ),
867
            'fields'    => sprintf( _n( '%1$s Field', '%1$s Fields', $m, 'formidable' ), $m ),
868
            'items'     => sprintf( _n( '%1$s Entry', '%1$s Entries', $m, 'formidable' ), $m ),
869
            'views'     => sprintf( _n( '%1$s View', '%1$s Views', $m, 'formidable' ), $m ),
870
            'posts'     => sprintf( _n( '%1$s Post', '%1$s Posts', $m, 'formidable' ), $m ),
871
            'styles'     => sprintf( _n( '%1$s Style', '%1$s Styles', $m, 'formidable' ), $m ),
872
            'terms'     => sprintf( _n( '%1$s Term', '%1$s Terms', $m, 'formidable' ), $m ),
873
            'actions'   => sprintf( _n( '%1$s Form Action', '%1$s Form Actions', $m, 'formidable' ), $m ),
874
        );
875
876
		$s_message[] = isset( $strings[ $type ] ) ? $strings[ $type ] : ' ' . $m . ' ' . ucfirst( $type );
877
    }
878
879
	/**
880
	 * Prepare the form options for export
881
	 *
882
	 * @since 2.0.19
883
	 * @param string $options
884
	 * @return string
885
	 */
886
	public static function prepare_form_options_for_export( $options ) {
887
		$options = maybe_unserialize( $options );
888
		// Change custom_style to the post_name instead of ID (1 may be a string)
889
		$not_default = isset( $options['custom_style'] ) && 1 != $options['custom_style'];
890
		if ( $not_default ) {
891
			global $wpdb;
892
			$table = $wpdb->prefix . 'posts';
893
			$where = array( 'ID' => $options['custom_style'] );
894
			$select = 'post_name';
895
896
			$style_name = FrmDb::get_var( $table, $where, $select );
897
898
			if ( $style_name ) {
899
				$options['custom_style'] = $style_name;
900
			} else {
901
				$options['custom_style'] = 1;
902
			}
903
		}
904
		self::remove_default_form_options( $options );
905
		$options = serialize( $options );
906
		return self::cdata( $options );
907
	}
908
909
	/**
910
	 * If the saved value is the same as the default, remove it from the export
911
	 * This keeps file size down and prevents overriding global settings after import
912
	 *
913
	 * @since 3.05.01
914
	 */
915
	private static function remove_default_form_options( &$options ) {
916
		$defaults = FrmFormsHelper::get_default_opts();
917
		if ( is_callable( 'FrmProFormsHelper::get_default_opts' ) ) {
918
			$defaults += FrmProFormsHelper::get_default_opts();
919
		}
920
 		self::remove_defaults( $defaults, $options );
921
	}
922
923
	/**
924
	 * Remove extra settings from field to keep file size down
925
	 *
926
	 * @since 3.05.01
927
	 */
928
	public static function prepare_field_for_export( &$field ) {
929
		self::remove_default_field_options( $field );
930
	}
931
932
	/**
933
	 * Remove defaults from field options too
934
	 *
935
	 * @since 3.05.01
936
	 */
937
	private static function remove_default_field_options( &$field ) {
938
		$defaults = FrmFieldsHelper::get_default_field_options( $field->type );
939
		if ( empty( $defaults['blank'] ) ) {
940
			$global_settings = new FrmSettings();
941
			$global_defaults = $global_settings->default_options();
942
			$defaults['blank'] = $global_defaults['blank_msg'];
943
		}
944
945
		if ( empty( $defaults['custom_html'] ) ) {
946
			$defaults['custom_html'] = FrmFieldsHelper::get_default_html( $field->type );
947
		}
948
		$options = maybe_unserialize( $field->field_options );
949
 		self::remove_defaults( $defaults, $options );
950
		self::remove_default_html( 'custom_html', $defaults, $options );
951
952
		// Get variations on the defaults.
953
		if ( isset( $options['invalid'] ) ) {
954
			$defaults = array(
955
				'invalid' => sprintf( __( '%s is invalid', 'formidable' ), $field->name ),
956
			);
957
			self::remove_defaults( $defaults, $options );
958
		}
959
960
		$field->field_options = serialize( $options );
961
	}
962
963
 	/**
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
964
	 * Compare the default array to the saved values and
965
	 * remove if they are the same
966
	 *
967
	 * @since 3.05.01
968
	 */
969
	private static function remove_defaults( $defaults, &$saved ) {
970
		$array_defaults = array_filter( $defaults, 'is_array' );
971
		foreach ( $array_defaults as $d => $default ) {
972
			// compare array defaults
973
			if ( $default == $saved[ $d ] ) {
974
				unset( $saved[ $d ] );
975
			}
976
			unset( $defaults[ $d ] );
977
		}
978
 		$saved = array_diff_assoc( (array) $saved, $defaults );
979
	}
980
981
 	/**
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
982
	 * The line endings may prevent html from being equal when it should
983
	 *
984
	 * @since 3.05.01
985
	 */
986
	private static function remove_default_html( $html_name, $defaults, &$options ) {
987
		if ( ! isset( $options[ $html_name ] ) || ! isset( $defaults[ $html_name ] ) ) {
988
			return;
989
		}
990
991
		$old_html = str_replace( "\r\n", "\n", $options[ $html_name ] );
992
		$default_html = $defaults[ $html_name ];
993
		if ( $old_html == $default_html ) {
994
			unset( $options[ $html_name ] );
995
			return;
996
		}
997
998
		// Account for some of the older field default HTML.
999
		$default_html = str_replace( ' id="frm_desc_field_[key]"', '', $default_html );
1000
		if ( $old_html == $default_html ) {
1001
			unset( $options[ $html_name ] );
1002
		}
1003
	}
1004
1005
	public static function cdata( $str ) {
1006
		$str = maybe_unserialize( $str );
1007
		if ( is_array( $str ) ) {
1008
			$str = json_encode( $str );
1009
		} else if ( seems_utf8( $str ) == false ) {
1010
			$str = utf8_encode( $str );
1011
		}
1012
1013
		if ( is_numeric( $str ) ) {
1014
            return $str;
1015
        }
1016
1017
		self::remove_invalid_characters_from_xml( $str );
1018
1019
		// $str = ent2ncr(esc_html( $str));
1020
		$str = '<![CDATA[' . str_replace( ']]>', ']]]]><![CDATA[>', $str ) . ']]>';
1021
1022
		return $str;
1023
	}
1024
1025
	/**
1026
	 * Remove <US> character (unit separator) from exported strings
1027
	 *
1028
	 * @since 2.0.22
1029
	 * @param string $str
1030
	 */
1031
	private static function remove_invalid_characters_from_xml( &$str ) {
1032
		// Remove <US> character
1033
		$str = str_replace( '\x1F', '', $str );
1034
	}
1035
1036
    public static function migrate_form_settings_to_actions( $form_options, $form_id, &$imported = array(), $switch = false ) {
1037
        // Get post type
1038
        $post_type = FrmFormActionsController::$action_post_type;
1039
1040
        // Set up imported index, if not set up yet
1041
        if ( ! isset( $imported['imported']['actions'] ) ) {
1042
            $imported['imported']['actions'] = 0;
1043
        }
1044
1045
        // Migrate post settings to action
1046
        self::migrate_post_settings_to_action( $form_options, $form_id, $post_type, $imported, $switch );
1047
1048
        // Migrate email settings to action
1049
        self::migrate_email_settings_to_action( $form_options, $form_id, $post_type, $imported, $switch );
1050
    }
1051
1052
    /**
1053
    * Migrate post settings to form action
1054
    *
1055
    * @param string $post_type
1056
    */
1057
    private static function migrate_post_settings_to_action( $form_options, $form_id, $post_type, &$imported, $switch ) {
1058
		if ( ! isset( $form_options['create_post'] ) || ! $form_options['create_post'] ) {
1059
            return;
1060
        }
1061
1062
        $new_action = array(
1063
            'post_type'     => $post_type,
1064
            'post_excerpt'  => 'wppost',
1065
			'post_title'    => __( 'Create Posts', 'formidable' ),
1066
            'menu_order'    => $form_id,
1067
            'post_status'   => 'publish',
1068
            'post_content'  => array(),
1069
			'post_name'     => $form_id . '_wppost_1',
1070
        );
1071
1072
		$post_settings = array( 'post_type', 'post_category', 'post_content', 'post_excerpt', 'post_title', 'post_name', 'post_date', 'post_status', 'post_custom_fields', 'post_password' );
1073
1074
        foreach ( $post_settings as $post_setting ) {
1075
			if ( isset( $form_options[ $post_setting ] ) ) {
1076
				$new_action['post_content'][ $post_setting ] = $form_options[ $post_setting ];
1077
            }
1078
			unset( $post_setting );
1079
        }
1080
1081
		$new_action['event'] = array( 'create', 'update' );
1082
1083
        if ( $switch ) {
1084
			// Fields with string or int saved
1085
			$basic_fields = array( 'post_title', 'post_content', 'post_excerpt', 'post_password', 'post_date', 'post_status' );
1086
1087
			// Fields with arrays saved
1088
			$array_fields = array( 'post_category', 'post_custom_fields' );
1089
1090
			$new_action['post_content'] = self::switch_action_field_ids( $new_action['post_content'], $basic_fields, $array_fields );
1091
        }
1092
		$new_action['post_content'] = json_encode( $new_action['post_content'] );
1093
1094
		$exists = get_posts(
1095
			array(
1096
				'name'          => $new_action['post_name'],
1097
				'post_type'     => $new_action['post_type'],
1098
				'post_status'   => $new_action['post_status'],
1099
				'numberposts'   => 1,
1100
			)
1101
		);
1102
1103
        if ( ! $exists ) {
1104
			// this isn't an email, but we need to use a class that will always be included
1105
			FrmDb::save_json_post( $new_action );
1106
            $imported['imported']['actions']++;
1107
        }
1108
    }
1109
1110
	/**
1111
	 * Switch old field IDs for new field IDs in emails and post
1112
	 *
1113
	 * @since 2.0
1114
	 * @param array $post_content - check for old field IDs
1115
	 * @param array $basic_fields - fields with string or int saved
1116
	 * @param array $array_fields - fields with arrays saved
1117
	 *
1118
	 * @return string $post_content - new field IDs
1119
	 */
1120
	private static function switch_action_field_ids( $post_content, $basic_fields, $array_fields = array() ) {
1121
        global $frm_duplicate_ids;
1122
1123
        // If there aren't IDs that were switched, end now
1124
        if ( ! $frm_duplicate_ids ) {
1125
            return;
1126
        }
1127
1128
        // Get old IDs
1129
        $old = array_keys( $frm_duplicate_ids );
1130
1131
        // Get new IDs
1132
        $new = array_values( $frm_duplicate_ids );
1133
1134
        // Do a str_replace with each item to set the new IDs
1135
        foreach ( $post_content as $key => $setting ) {
1136
            if ( ! is_array( $setting ) && in_array( $key, $basic_fields ) ) {
1137
                // Replace old IDs with new IDs
1138
				$post_content[ $key ] = str_replace( $old, $new, $setting );
1139
            } else if ( is_array( $setting ) && in_array( $key, $array_fields ) ) {
1140
                foreach ( $setting as $k => $val ) {
1141
                    // Replace old IDs with new IDs
1142
					$post_content[ $key ][ $k ] = str_replace( $old, $new, $val );
1143
                }
1144
            }
1145
            unset( $key, $setting );
1146
        }
1147
        return $post_content;
1148
    }
1149
1150
    private static function migrate_email_settings_to_action( $form_options, $form_id, $post_type, &$imported, $switch ) {
1151
        // No old notifications or autoresponders to carry over
1152
		if ( ! isset( $form_options['auto_responder'] ) && ! isset( $form_options['notification'] ) && ! isset( $form_options['email_to'] ) ) {
1153
            return;
1154
        }
1155
1156
        // Initialize notifications array
1157
        $notifications = array();
1158
1159
        // Migrate regular notifications
1160
        self::migrate_notifications_to_action( $form_options, $form_id, $notifications );
1161
1162
        // Migrate autoresponders
1163
        self::migrate_autoresponder_to_action( $form_options, $form_id, $notifications );
1164
1165
        if ( empty( $notifications ) ) {
1166
            return;
1167
        }
1168
1169
        foreach ( $notifications as $new_notification ) {
1170
            $new_notification['post_type']      = $post_type;
1171
            $new_notification['post_excerpt']   = 'email';
1172
			$new_notification['post_title']     = __( 'Email Notification', 'formidable' );
1173
            $new_notification['menu_order']     = $form_id;
1174
            $new_notification['post_status']    = 'publish';
1175
1176
            // Switch field IDs and keys, if needed
1177
            if ( $switch ) {
1178
1179
				// Switch field IDs in email conditional logic
1180
				self::switch_email_contition_field_ids( $new_notification['post_content'] );
1181
1182
				// Switch all other field IDs in email
1183
                $new_notification['post_content'] = FrmFieldsHelper::switch_field_ids( $new_notification['post_content'] );
1184
            }
1185
            $new_notification['post_content']   = FrmAppHelper::prepare_and_encode( $new_notification['post_content'] );
1186
1187
			$exists = get_posts(
1188
				array(
1189
					'name'          => $new_notification['post_name'],
1190
					'post_type'     => $new_notification['post_type'],
1191
					'post_status'   => $new_notification['post_status'],
1192
					'numberposts'   => 1,
1193
				)
1194
			);
1195
1196
			if ( empty( $exists ) ) {
1197
				FrmDb::save_json_post( $new_notification );
1198
                $imported['imported']['actions']++;
1199
            }
1200
			unset( $new_notification );
1201
        }
1202
1203
		self::remove_deprecated_notification_settings( $form_id, $form_options );
1204
    }
1205
1206
	/**
1207
	 * Remove deprecated notification settings after migration
1208
	 *
1209
	 * @since 2.05
1210
	 *
1211
	 * @param int|string $form_id
1212
	 * @param array $form_options
1213
	 */
1214
	private static function remove_deprecated_notification_settings( $form_id, $form_options ) {
1215
		$delete_settings = array( 'notification', 'autoresponder', 'email_to' );
1216
		foreach ( $delete_settings as $index ) {
1217
			if ( isset( $form_options[ $index ] ) ) {
1218
				unset( $form_options[ $index ] );
1219
			}
1220
		}
1221
		FrmForm::update( $form_id, array( 'options' => $form_options ) );
1222
	}
1223
1224
    private static function migrate_notifications_to_action( $form_options, $form_id, &$notifications ) {
1225
        if ( ! isset( $form_options['notification'] ) && isset( $form_options['email_to'] ) && ! empty( $form_options['email_to'] ) ) {
1226
            // add old settings into notification array
1227
			$form_options['notification'] = array( 0 => $form_options );
1228
        } else if ( isset( $form_options['notification']['email_to'] ) ) {
1229
            // make sure it's in the correct format
1230
			$form_options['notification'] = array( 0 => $form_options['notification'] );
1231
        }
1232
1233
		if ( isset( $form_options['notification'] ) && is_array( $form_options['notification'] ) ) {
1234
            foreach ( $form_options['notification'] as $email_key => $notification ) {
1235
1236
				$atts = array(
1237
					'email_to'  => '',
1238
					'reply_to'  => '',
1239
					'reply_to_name' => '',
1240
					'event'     => '',
1241
					'form_id'   => $form_id,
1242
					'email_key' => $email_key,
1243
				);
1244
1245
                // Format the email data
1246
                self::format_email_data( $atts, $notification );
1247
1248
				if ( isset( $notification['twilio'] ) && $notification['twilio'] ) {
1249
					do_action( 'frm_create_twilio_action', $atts, $notification );
1250
				}
1251
1252
                // Setup the new notification
1253
                $new_notification = array();
1254
                self::setup_new_notification( $new_notification, $notification, $atts );
1255
1256
                $notifications[] = $new_notification;
1257
            }
1258
        }
1259
    }
1260
1261
    private static function format_email_data( &$atts, $notification ) {
1262
        // Format email_to
1263
        self::format_email_to_data( $atts, $notification );
1264
1265
        // Format the reply to email and name
1266
		$reply_fields = array(
1267
			'reply_to'      => '',
1268
			'reply_to_name' => '',
1269
		);
1270
        foreach ( $reply_fields as $f => $val ) {
1271
			if ( isset( $notification[ $f ] ) ) {
1272
				$atts[ $f ] = $notification[ $f ];
1273
				if ( 'custom' == $notification[ $f ] ) {
1274
					$atts[ $f ] = $notification[ 'cust_' . $f ];
1275
				} else if ( is_numeric( $atts[ $f ] ) && ! empty( $atts[ $f ] ) ) {
1276
					$atts[ $f ] = '[' . $atts[ $f ] . ']';
1277
                }
1278
            }
1279
            unset( $f, $val );
1280
        }
1281
1282
        // Format event
1283
		$atts['event'] = array( 'create' );
1284
        if ( isset( $notification['update_email'] ) && 1 == $notification['update_email'] ) {
1285
            $atts['event'][] = 'update';
1286
		} elseif ( isset( $notification['update_email'] ) && 2 == $notification['update_email'] ) {
1287
			$atts['event'] = array( 'update' );
1288
        }
1289
    }
1290
1291
    private static function format_email_to_data( &$atts, $notification ) {
1292
        if ( isset( $notification['email_to'] ) ) {
1293
			$atts['email_to'] = preg_split( '/ (,|;) /', $notification['email_to'] );
1294
        } else {
1295
            $atts['email_to'] = array();
1296
        }
1297
1298
        if ( isset( $notification['also_email_to'] ) ) {
1299
            $email_fields = (array) $notification['also_email_to'];
1300
            $atts['email_to'] = array_merge( $email_fields, $atts['email_to'] );
1301
            unset( $email_fields );
1302
        }
1303
1304
        foreach ( $atts['email_to'] as $key => $email_field ) {
1305
1306
            if ( is_numeric( $email_field ) ) {
1307
				$atts['email_to'][ $key ] = '[' . $email_field . ']';
1308
            }
1309
1310
			if ( strpos( $email_field, '|' ) ) {
1311
                $email_opt = explode( '|', $email_field );
1312
                if ( isset( $email_opt[0] ) ) {
1313
					$atts['email_to'][ $key ] = '[' . $email_opt[0] . ' show=' . $email_opt[1] . ']';
1314
                }
1315
                unset( $email_opt );
1316
            }
1317
        }
1318
		$atts['email_to'] = implode( ', ', $atts['email_to'] );
1319
    }
1320
1321
    private static function setup_new_notification( &$new_notification, $notification, $atts ) {
1322
        // Set up new notification
1323
        $new_notification = array(
1324
            'post_content'  => array(
1325
                'email_to'      => $atts['email_to'],
1326
                'event'         => $atts['event'],
1327
            ),
1328
			'post_name'         => $atts['form_id'] . '_email_' . $atts['email_key'],
1329
        );
1330
1331
        // Add more fields to the new notification
1332
        $add_fields = array( 'email_message', 'email_subject', 'plain_text', 'inc_user_info', 'conditions' );
1333
        foreach ( $add_fields as $add_field ) {
1334
			if ( isset( $notification[ $add_field ] ) ) {
1335
				$new_notification['post_content'][ $add_field ] = $notification[ $add_field ];
1336
            } else if ( in_array( $add_field, array( 'plain_text', 'inc_user_info' ) ) ) {
1337
				$new_notification['post_content'][ $add_field ] = 0;
1338
            } else {
1339
				$new_notification['post_content'][ $add_field ] = '';
1340
            }
1341
            unset( $add_field );
1342
        }
1343
1344
		// Set reply to
1345
		$new_notification['post_content']['reply_to'] = $atts['reply_to'];
1346
1347
        // Set from
1348
		if ( ! empty( $atts['reply_to'] ) || ! empty( $atts['reply_to_name'] ) ) {
1349
			$new_notification['post_content']['from'] = ( empty( $atts['reply_to_name'] ) ? '[sitename]' : $atts['reply_to_name'] ) . ' <' . ( empty( $atts['reply_to'] ) ? '[admin_email]' : $atts['reply_to'] ) . '>';
1350
        }
1351
    }
1352
1353
	/**
1354
	* Switch field IDs in pre-2.0 email conditional logic
1355
	*
1356
	* @param $post_content array, pass by reference
1357
	*/
1358
	private static function switch_email_contition_field_ids( &$post_content ) {
1359
		// Switch field IDs in conditional logic
1360
		if ( isset( $post_content['conditions'] ) && is_array( $post_content['conditions'] ) ) {
1361
			foreach ( $post_content['conditions'] as $email_key => $val ) {
1362
				if ( is_numeric( $email_key ) ) {
1363
					$post_content['conditions'][ $email_key ] = self::switch_action_field_ids( $val, array( 'hide_field' ) );
1364
				}
1365
				unset( $email_key, $val );
1366
			}
1367
		}
1368
	}
1369
1370
    private static function migrate_autoresponder_to_action( $form_options, $form_id, &$notifications ) {
1371
		if ( isset( $form_options['auto_responder'] ) && $form_options['auto_responder'] && isset( $form_options['ar_email_message'] ) && $form_options['ar_email_message'] ) {
1372
			// migrate autoresponder
1373
1374
			$email_field = isset( $form_options['ar_email_to'] ) ? $form_options['ar_email_to'] : 0;
1375
			if ( strpos( $email_field, '|' ) ) {
1376
				// data from entries field
1377
				$email_field = explode( '|', $email_field );
1378
				if ( isset( $email_field[1] ) ) {
1379
					$email_field = $email_field[1];
1380
				}
1381
			}
1382
			if ( is_numeric( $email_field ) && ! empty( $email_field ) ) {
1383
				$email_field = '[' . $email_field . ']';
1384
			}
1385
1386
            $notification = $form_options;
1387
            $new_notification2 = array(
1388
				'post_content'  => array(
1389
					'email_message' => $notification['ar_email_message'],
1390
					'email_subject' => isset( $notification['ar_email_subject'] ) ? $notification['ar_email_subject'] : '',
1391
					'email_to'      => $email_field,
1392
					'plain_text'    => isset( $notification['ar_plain_text'] ) ? $notification['ar_plain_text'] : 0,
1393
					'inc_user_info' => 0,
1394
				),
1395
				'post_name'     => $form_id . '_email_' . count( $notifications ),
1396
            );
1397
1398
			$reply_to = isset( $notification['ar_reply_to'] ) ? $notification['ar_reply_to'] : '';
1399
			$reply_to_name = isset( $notification['ar_reply_to_name'] ) ? $notification['ar_reply_to_name'] : '';
1400
1401
			if ( ! empty( $reply_to ) ) {
1402
				$new_notification2['post_content']['reply_to'] = $reply_to;
1403
			}
1404
1405
			if ( ! empty( $reply_to ) || ! empty( $reply_to_name ) ) {
1406
				$new_notification2['post_content']['from'] = ( empty( $reply_to_name ) ? '[sitename]' : $reply_to_name ) . ' <' . ( empty( $reply_to ) ? '[admin_email]' : $reply_to ) . '>';
1407
			}
1408
1409
            $notifications[] = $new_notification2;
1410
            unset( $new_notification2 );
1411
        }
1412
    }
1413
}
1414
1415