Completed
Push — master ( 252d83...3596f7 )
by Jamie
03:30
created

FrmXMLHelper::maybe_update_stylesheet()   B

Complexity

Conditions 7
Paths 3

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 8
rs 8.2222
cc 7
eloc 5
nc 3
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
		$in_section = 0;
282
283
		foreach ( $xml_fields as $field ) {
284
		    $f = array(
285
		        'id'            => (int) $field->id,
286
		        'field_key'     => (string) $field->field_key,
287
		        'name'          => (string) $field->name,
288
		        'description'   => (string) $field->description,
289
		        'type'          => (string) $field->type,
290
		        'default_value' => FrmAppHelper::maybe_json_decode( (string) $field->default_value),
291
		        'field_order'   => (int) $field->field_order,
292
		        'form_id'       => (int) $form_id,
293
		        'required'      => (int) $field->required,
294
		        'options'       => FrmAppHelper::maybe_json_decode( (string) $field->options),
295
				'field_options' => FrmAppHelper::maybe_json_decode( (string) $field->field_options ),
296
		    );
297
298
		    if ( is_array($f['default_value']) && in_array($f['type'], array(
299
		        'text', 'email', 'url', 'textarea',
300
		        'number','phone', 'date', 'time',
301
		        'hidden', 'password', 'tag', 'image',
302
		    )) ) {
303
		        if ( count($f['default_value']) === 1 ) {
304
					$f['default_value'] = '[' . reset( $f['default_value'] ) . ']';
305
		        } else {
306
		            $f['default_value'] = reset($f['default_value']);
307
		        }
308
		    }
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
				} else {
334
					// if no matching field id or key in this form, create the field
335
					self::maybe_update_in_section_variable( $in_section, $f );
336
					self::create_imported_field( $f, $imported );
337
				}
338
			} else {
339
340
				self::maybe_update_in_section_variable( $in_section, $f );
341
				self::create_imported_field( $f, $imported );
342
			}
343
		}
344
	}
345
346
	/**
347
	 * Update the current in_section value
348
	 *
349
	 * @since 2.0.25
350
	 * @param object $field
0 ignored issues
show
Bug introduced by
There is no parameter named $field. Was it maybe removed?

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

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

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

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

Loading history...
351
	 * @param int $in_section
352
	 */
353
	private static function maybe_update_in_section_variable( &$in_section, &$f ) {
354
		// If we're at the end of a section, switch $in_section is 0
355
		if ( in_array( $f['type'], array( 'end_divider', 'break' ) ) ) {
356
			$in_section = 0;
357
		}
358
359
		// Update the current field's in_section value
360
		if ( ! isset( $f['field_options']['in_section'] ) ) {
361
			$f['field_options']['in_section'] = $in_section;
362
		}
363
364
		// If we're starting a new section, switch $in_section to ID of divider
365
		if ( $f['type'] == 'divider' ) {
366
			$in_section = $f['id'];
367
		}
368
	}
369
370
	/**
371
	* Switch the form_select on a repeating field or embedded form if it needs to be switched
372
	*
373
	* @since 2.0.16
374
	* @param array $f
375
	* @param array $imported
376
	*/
377
	private static function maybe_update_form_select( &$f, $imported ) {
378
		if ( ! isset( $imported['forms'] ) ) {
379
			return;
380
		}
381
382
		if ( $f['type'] == 'form' || ( $f['type'] == 'divider' && FrmField::is_option_true( $f['field_options'], 'repeat' ) ) ) {
383
			if ( FrmField::is_option_true( $f['field_options'], 'form_select' ) ) {
384
				$form_select = $f['field_options']['form_select'];
385
				if ( isset( $imported['forms'][ $form_select ] ) ) {
386
					$f['field_options']['form_select'] = $imported['forms'][ $form_select ];
387
				}
388
			}
389
		}
390
	}
391
392
	/**
393
	 * Create an imported field
394
	 *
395
	 * @since 2.0.24
396
	 * @param array $f
397
	 * @param array $imported
398
	 */
399
	private static function create_imported_field( $f, &$imported ) {
400
		$new_id = FrmField::create( $f );
401
		if ( $new_id != false ) {
402
			$imported[ 'imported' ][ 'fields' ]++;
0 ignored issues
show
introduced by
Array keys should NOT be surrounded by spaces if they only contain a string or an integer.
Loading history...
403
		}
404
	}
405
406
	/**
407
	* Updates the custom style setting on import
408
	*
409
	* @since 2.0.19
410
	* @param array $form
411
	*
412
	*/
413
	private static function update_custom_style_setting_on_import( &$form ) {
414
		if ( ! isset( $form['options']['custom_style'] ) ) {
415
			return;
416
		}
417
418
		if ( is_numeric( $form['options']['custom_style'] ) ) {
419
			// Set to default
420
			$form['options']['custom_style'] = 1;
421
		} else {
422
			// Replace the style name with the style ID on import
423
			global $wpdb;
424
			$table = $wpdb->prefix . 'posts';
425
			$where = array(
426
				'post_name' => $form['options']['custom_style'],
427
				'post_type' => 'frm_styles',
428
			);
429
			$select = 'ID';
430
			$style_id = FrmDb::get_var( $table, $where, $select );
431
432
			if ( $style_id ) {
433
				$form['options']['custom_style'] = $style_id;
434
			} else {
435
				// Set to default
436
				$form['options']['custom_style'] = 1;
437
			}
438
		}
439
	}
440
441
	public static function import_xml_views( $views, $imported ) {
442
        $imported['posts'] = array();
443
        $form_action_type = FrmFormActionsController::$action_post_type;
444
445
        $post_types = array(
446
            'frm_display' => 'views',
447
            $form_action_type => 'actions',
448
            'frm_styles'    => 'styles',
449
        );
450
451
        foreach ( $views as $item ) {
452
			$post = array(
453
				'post_title'    => (string) $item->title,
454
				'post_name'     => (string) $item->post_name,
455
				'post_type'     => (string) $item->post_type,
456
				'post_password' => (string) $item->post_password,
457
				'guid'          => (string) $item->guid,
458
				'post_status'   => (string) $item->status,
459
				'post_author'   => FrmAppHelper::get_user_id_param( (string) $item->post_author ),
460
				'post_id'       => (int) $item->post_id,
461
				'post_parent'   => (int) $item->post_parent,
462
				'menu_order'    => (int) $item->menu_order,
463
				'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...
464
				'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...
465
				'is_sticky'     => (string) $item->is_sticky,
466
				'comment_status' => (string) $item->comment_status,
467
				'post_date'     => (string) $item->post_date,
468
				'post_date_gmt' => (string) $item->post_date_gmt,
469
				'ping_status'   => (string) $item->ping_status,
470
                'postmeta'      => array(),
471
                'tax_input'     => array(),
472
			);
473
474
            $old_id = $post['post_id'];
475
            self::populate_post($post, $item, $imported);
476
477
			unset($item);
478
479
			$post_id = false;
480
            if ( $post['post_type'] == $form_action_type ) {
481
                $action_control = FrmFormActionsController::get_form_actions( $post['post_excerpt'] );
482
				if ( $action_control ) {
483
					$post_id = $action_control->maybe_create_action( $post, $imported['form_status'] );
484
				}
485
                unset($action_control);
486
            } else if ( $post['post_type'] == 'frm_styles' ) {
487
                // Properly encode post content before inserting the post
488
                $post['post_content'] = FrmAppHelper::maybe_json_decode( $post['post_content'] );
489
                $post['post_content'] = FrmAppHelper::prepare_and_encode( $post['post_content'] );
490
491
                // Create/update post now
492
                $post_id = wp_insert_post( $post );
493
            } else {
494
                // Create/update post now
495
                $post_id = wp_insert_post( $post );
496
            }
497
498
            if ( ! is_numeric($post_id) ) {
499
                continue;
500
            }
501
502
            self::update_postmeta($post, $post_id);
503
504
            $this_type = 'posts';
505
			if ( isset( $post_types[ $post['post_type'] ] ) ) {
506
				$this_type = $post_types[ $post['post_type'] ];
507
            }
508
509
            if ( isset($post['ID']) && $post_id == $post['ID'] ) {
510
                $imported['updated'][ $this_type ]++;
511
            } else {
512
                $imported['imported'][ $this_type ]++;
513
            }
514
515
            unset($post);
516
517
			$imported['posts'][ (int) $old_id ] = $post_id;
518
		}
519
520
		self::maybe_update_stylesheet( $imported );
521
522
		return $imported;
523
    }
524
525
    private static function populate_post( &$post, $item, $imported ) {
526
		if ( isset($item->attachment_url) ) {
527
			$post['attachment_url'] = (string) $item->attachment_url;
528
		}
529
530
		if ( $post['post_type'] == FrmFormActionsController::$action_post_type && isset( $imported['forms'][ (int) $post['menu_order'] ] ) ) {
531
		    // update to new form id
532
		    $post['menu_order'] = $imported['forms'][ (int) $post['menu_order'] ];
533
		}
534
535
		foreach ( $item->postmeta as $meta ) {
536
		    self::populate_postmeta($post, $meta, $imported);
537
			unset($meta);
538
		}
539
540
        self::populate_taxonomies($post, $item);
541
542
        self::maybe_editing_post($post);
543
    }
544
545
    private static function populate_postmeta( &$post, $meta, $imported ) {
546
        global $frm_duplicate_ids;
547
548
	    $m = array(
549
			'key'   => (string) $meta->meta_key,
550
			'value' => (string) $meta->meta_value,
551
		);
552
553
		//switch old form and field ids to new ones
554
		if ( $m['key'] == 'frm_form_id' && isset($imported['forms'][ (int) $m['value'] ]) ) {
555
		    $m['value'] = $imported['forms'][ (int) $m['value'] ];
556
		} else {
557
		    $m['value'] = FrmAppHelper::maybe_json_decode($m['value']);
558
559
		    if ( ! empty($frm_duplicate_ids) ) {
560
561
		        if ( $m['key'] == 'frm_dyncontent' ) {
562
		            $m['value'] = FrmFieldsHelper::switch_field_ids($m['value']);
563
    		    } else if ( $m['key'] == 'frm_options' ) {
564
565
					foreach ( array( 'date_field_id', 'edate_field_id' ) as $setting_name ) {
566
						if ( isset( $m['value'][ $setting_name ] ) && is_numeric( $m['value'][ $setting_name ] ) && isset( $frm_duplicate_ids[ $m['value'][ $setting_name ] ] ) ) {
567
							$m['value'][ $setting_name ] = $frm_duplicate_ids[ $m['value'][ $setting_name ] ];
568
    		            }
569
    		        }
570
571
                    $check_dup_array = array();
572
    		        if ( isset( $m['value']['order_by'] ) && ! empty( $m['value']['order_by'] ) ) {
573
    		            if ( is_numeric( $m['value']['order_by'] ) && isset( $frm_duplicate_ids[ $m['value']['order_by'] ] ) ) {
574
    		                $m['value']['order_by'] = $frm_duplicate_ids[ $m['value']['order_by'] ];
575
    		            } else if ( is_array( $m['value']['order_by'] ) ) {
576
                            $check_dup_array[] = 'order_by';
577
    		            }
578
    		        }
579
580
    		        if ( isset( $m['value']['where'] ) && ! empty( $m['value']['where'] ) ) {
581
    		            $check_dup_array[] = 'where';
582
    		        }
583
584
                    foreach ( $check_dup_array as $check_k ) {
585
						foreach ( (array) $m['value'][ $check_k ] as $mk => $mv ) {
586
							if ( isset( $frm_duplicate_ids[ $mv ] ) ) {
587
								$m['value'][ $check_k ][ $mk ] = $frm_duplicate_ids[ $mv ];
588
		                    }
589
		                    unset($mk, $mv);
590
		                }
591
                    }
592
    		    }
593
		    }
594
		}
595
596
		if ( ! is_array($m['value']) ) {
597
		    $m['value'] = FrmAppHelper::maybe_json_decode($m['value']);
598
		}
599
600
		$post['postmeta'][ (string) $meta->meta_key ] = $m['value'];
0 ignored issues
show
introduced by
Detected usage of meta_key, possible slow query.
Loading history...
601
    }
602
603
    /**
604
     * Add terms to post
605
     * @param array $post by reference
606
     * @param object $item The XML object data
607
     */
608
    private static function populate_taxonomies( &$post, $item ) {
609
		foreach ( $item->category as $c ) {
610
			$att = $c->attributes();
611
			if ( ! isset( $att['nicename'] ) ) {
612
                continue;
613
            }
614
615
		    $taxonomy = (string) $att['domain'];
616
		    if ( is_taxonomy_hierarchical($taxonomy) ) {
617
		        $name = (string) $att['nicename'];
618
		        $h_term = get_term_by('slug', $name, $taxonomy);
619
		        if ( $h_term ) {
620
		            $name = $h_term->term_id;
621
		        }
622
		        unset($h_term);
623
		    } else {
624
		        $name = (string) $c;
625
		    }
626
627
			if ( ! isset( $post['tax_input'][ $taxonomy ] ) ) {
628
				$post['tax_input'][ $taxonomy ] = array();
629
			}
630
631
			$post['tax_input'][ $taxonomy ][] = $name;
632
		    unset($name);
633
		}
634
    }
635
636
    /**
637
     * Edit post if the key and created time match
638
     */
639
    private static function maybe_editing_post( &$post ) {
640
		$match_by = array(
641
		    'post_type'     => $post['post_type'],
642
		    'name'          => $post['post_name'],
643
		    'post_status'   => $post['post_status'],
644
		    'posts_per_page' => 1,
645
		);
646
647
		if ( in_array( $post['post_status'], array( 'trash', 'draft' ) ) ) {
648
		    $match_by['include'] = $post['post_id'];
649
		    unset($match_by['name']);
650
		}
651
652
		$editing = get_posts($match_by);
653
654
        if ( ! empty($editing) && current($editing)->post_date == $post['post_date'] ) {
655
            // set the id of the post to edit
656
            $post['ID'] = current($editing)->ID;
657
        }
658
    }
659
660
    private static function update_postmeta( &$post, $post_id ) {
661
        foreach ( $post['postmeta'] as $k => $v ) {
662
            if ( '_edit_last' == $k ) {
663
                $v = FrmAppHelper::get_user_id_param($v);
664
            } else if ( '_thumbnail_id' == $k && FrmAppHelper::pro_is_installed() ) {
665
                //change the attachment ID
666
                $v = FrmProXMLHelper::get_file_id($v);
667
            }
668
669
            update_post_meta($post_id, $k, $v);
670
671
            unset($k, $v);
672
        }
673
    }
674
675
	private static function maybe_update_stylesheet( $imported ) {
676
		if ( ( isset( $imported['imported']['styles'] ) && ! empty( $imported['imported']['styles'] ) ) || ( isset( $imported['updated']['styles'] ) && ! empty( $imported['updated']['styles'] ) ) ) {
677
			if ( is_admin() && function_exists( 'get_filesystem_method' ) ) {
678
				$frm_style = new FrmStyle();
679
				$frm_style->update( 'default' );
680
			}
681
		}
682
	}
683
684
    /**
685
     * @param string $message
686
     */
687
	public static function parse_message( $result, &$message, &$errors ) {
688
        if ( is_wp_error($result) ) {
689
            $errors[] = $result->get_error_message();
690
        } else if ( ! $result ) {
691
            return;
692
        }
693
694
        if ( ! is_array($result) ) {
695
            $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...
696
            return;
697
        }
698
699
        $t_strings = array(
700
            'imported'  => __( 'Imported', 'formidable' ),
701
            'updated'   => __( 'Updated', 'formidable' ),
702
        );
703
704
        $message = '<ul>';
705
        foreach ( $result as $type => $results ) {
706
			if ( ! isset( $t_strings[ $type ] ) ) {
707
                // only print imported and updated
708
                continue;
709
            }
710
711
            $s_message = array();
712
            foreach ( $results as $k => $m ) {
713
                self::item_count_message($m, $k, $s_message);
714
                unset($k, $m);
715
            }
716
717
            if ( ! empty($s_message) ) {
718
				$message .= '<li><strong>' . $t_strings[ $type ] . ':</strong> ';
719
                $message .= implode(', ', $s_message);
720
                $message .= '</li>';
721
            }
722
        }
723
724
        if ( $message == '<ul>' ) {
725
            $message = '';
726
            $errors[] = __( 'Nothing was imported or updated', 'formidable' );
727
        } else {
728
            $message .= '</ul>';
729
        }
730
    }
731
732
	public static function item_count_message( $m, $type, &$s_message ) {
733
        if ( ! $m ) {
734
            return;
735
        }
736
737
        $strings = array(
738
            'forms'     => sprintf( _n( '%1$s Form', '%1$s Forms', $m, 'formidable' ), $m ),
739
            'fields'    => sprintf( _n( '%1$s Field', '%1$s Fields', $m, 'formidable' ), $m ),
740
            'items'     => sprintf( _n( '%1$s Entry', '%1$s Entries', $m, 'formidable' ), $m ),
741
            'views'     => sprintf( _n( '%1$s View', '%1$s Views', $m, 'formidable' ), $m ),
742
            'posts'     => sprintf( _n( '%1$s Post', '%1$s Posts', $m, 'formidable' ), $m ),
743
            'styles'     => sprintf( _n( '%1$s Style', '%1$s Styles', $m, 'formidable' ), $m ),
744
            'terms'     => sprintf( _n( '%1$s Term', '%1$s Terms', $m, 'formidable' ), $m ),
745
            'actions'   => sprintf( _n( '%1$s Form Action', '%1$s Form Actions', $m, 'formidable' ), $m ),
746
        );
747
748
		$s_message[] = isset( $strings[ $type ] ) ? $strings[ $type ] : ' ' . $m . ' ' . ucfirst( $type );
749
    }
750
751
	/**
752
	 * Prepare the form options for export
753
	 *
754
	 * @since 2.0.19
755
	 * @param string $options
756
	 * @return string
757
	 */
758
	public static function prepare_form_options_for_export( $options ) {
759
		$options = maybe_unserialize( $options );
760
		// Change custom_style to the post_name instead of ID
761
		if ( isset( $options['custom_style'] ) && 1 !== $options['custom_style'] ) {
762
			global $wpdb;
763
			$table = $wpdb->prefix . 'posts';
764
			$where = array( 'ID' => $options['custom_style'] );
765
			$select = 'post_name';
766
767
			$style_name = FrmDb::get_var( $table, $where, $select );
768
769
			if ( $style_name ) {
770
				$options['custom_style'] = $style_name;
771
			} else {
772
				$options['custom_style'] = 1;
773
			}
774
		}
775
		$options = serialize( $options );
776
		return self::cdata( $options );
777
	}
778
779
	public static function cdata( $str ) {
780
	    $str = maybe_unserialize($str);
781
	    if ( is_array($str) ) {
782
	        $str = json_encode($str);
783
		} else if ( seems_utf8( $str ) == false ) {
784
			$str = utf8_encode( $str );
785
		}
786
787
        if ( is_numeric($str) ) {
788
            return $str;
789
        }
790
791
		self::remove_invalid_characters_from_xml( $str );
792
793
		// $str = ent2ncr(esc_html($str));
794
		$str = '<![CDATA[' . str_replace( ']]>', ']]]]><![CDATA[>', $str ) . ']]>';
795
796
		return $str;
797
	}
798
799
	/**
800
	 * Remove <US> character (unit separator) from exported strings
801
	 *
802
	 * @since 2.0.22
803
	 * @param string $str
804
	 */
805
	private static function remove_invalid_characters_from_xml( &$str ) {
806
		// Remove <US> character
807
		$str = str_replace( '\x1F', '', $str );
808
	}
809
810
    public static function migrate_form_settings_to_actions( $form_options, $form_id, &$imported = array(), $switch = false ) {
811
        // Get post type
812
        $post_type = FrmFormActionsController::$action_post_type;
813
814
        // Set up imported index, if not set up yet
815
        if ( ! isset( $imported['imported']['actions'] ) ) {
816
            $imported['imported']['actions'] = 0;
817
        }
818
819
        // Migrate post settings to action
820
        self::migrate_post_settings_to_action( $form_options, $form_id, $post_type, $imported, $switch );
821
822
        // Migrate email settings to action
823
        self::migrate_email_settings_to_action( $form_options, $form_id, $post_type, $imported, $switch );
824
    }
825
826
    /**
827
    * Migrate post settings to form action
828
    *
829
    * @param string $post_type
830
    */
831
    private static function migrate_post_settings_to_action( $form_options, $form_id, $post_type, &$imported, $switch ) {
832
        if ( ! isset($form_options['create_post']) || ! $form_options['create_post'] ) {
833
            return;
834
        }
835
836
        $new_action = array(
837
            'post_type'     => $post_type,
838
            'post_excerpt'  => 'wppost',
839
			'post_title'    => __( 'Create Posts', 'formidable' ),
840
            'menu_order'    => $form_id,
841
            'post_status'   => 'publish',
842
            'post_content'  => array(),
843
			'post_name'     => $form_id . '_wppost_1',
844
        );
845
846
        $post_settings = array(
847
            'post_type', 'post_category', 'post_content',
848
            'post_excerpt', 'post_title', 'post_name', 'post_date',
849
			'post_status', 'post_custom_fields', 'post_password',
850
        );
851
852
        foreach ( $post_settings as $post_setting ) {
853
			if ( isset( $form_options[ $post_setting ] ) ) {
854
				$new_action['post_content'][ $post_setting ] = $form_options[ $post_setting ];
855
            }
856
            unset($post_setting);
857
        }
858
859
		$new_action['event'] = array( 'create', 'update' );
860
861
        if ( $switch ) {
862
			// Fields with string or int saved
863
			$basic_fields = array( 'post_title', 'post_content', 'post_excerpt', 'post_password', 'post_date', 'post_status' );
864
865
			// Fields with arrays saved
866
			$array_fields = array( 'post_category', 'post_custom_fields' );
867
868
			$new_action['post_content'] = self::switch_action_field_ids( $new_action['post_content'], $basic_fields, $array_fields );
869
        }
870
        $new_action['post_content'] = json_encode($new_action['post_content']);
871
872
        $exists = get_posts( array(
873
            'name'          => $new_action['post_name'],
874
            'post_type'     => $new_action['post_type'],
875
            'post_status'   => $new_action['post_status'],
876
            'numberposts'   => 1,
877
        ) );
878
879
        if ( ! $exists ) {
880
			// this isn't an email, but we need to use a class that will always be included
881
			FrmAppHelper::save_json_post( $new_action );
882
            $imported['imported']['actions']++;
883
        }
884
    }
885
886
	/**
887
	 * Switch old field IDs for new field IDs in emails and post
888
	 *
889
	 * @since 2.0
890
	 * @param array $post_content - check for old field IDs
891
	 * @param array $basic_fields - fields with string or int saved
892
	 * @param array $array_fields - fields with arrays saved
893
	 *
894
	 * @return string $post_content - new field IDs
895
	 */
896
	private static function switch_action_field_ids( $post_content, $basic_fields, $array_fields = array() ) {
897
        global $frm_duplicate_ids;
898
899
        // If there aren't IDs that were switched, end now
900
        if ( ! $frm_duplicate_ids ) {
901
            return;
902
        }
903
904
        // Get old IDs
905
        $old = array_keys( $frm_duplicate_ids );
906
907
        // Get new IDs
908
        $new = array_values( $frm_duplicate_ids );
909
910
        // Do a str_replace with each item to set the new IDs
911
        foreach ( $post_content as $key => $setting ) {
912
            if ( ! is_array( $setting ) && in_array( $key, $basic_fields ) ) {
913
                // Replace old IDs with new IDs
914
				$post_content[ $key ] = str_replace( $old, $new, $setting );
915
            } else if ( is_array( $setting ) && in_array( $key, $array_fields ) ) {
916
                foreach ( $setting as $k => $val ) {
917
                    // Replace old IDs with new IDs
918
					$post_content[ $key ][ $k ] = str_replace( $old, $new, $val );
919
                }
920
            }
921
            unset( $key, $setting );
922
        }
923
        return $post_content;
924
    }
925
926
    private static function migrate_email_settings_to_action( $form_options, $form_id, $post_type, &$imported, $switch ) {
927
        // No old notifications or autoresponders to carry over
928
		if ( ! isset( $form_options['auto_responder'] ) && ! isset( $form_options['notification'] ) && ! isset( $form_options['email_to'] ) ) {
929
            return;
930
        }
931
932
        // Initialize notifications array
933
        $notifications = array();
934
935
        // Migrate regular notifications
936
        self::migrate_notifications_to_action( $form_options, $form_id, $notifications );
937
938
        // Migrate autoresponders
939
        self::migrate_autoresponder_to_action( $form_options, $form_id, $notifications );
940
941
        if (  empty( $notifications ) ) {
942
            return;
943
        }
944
945
        foreach ( $notifications as $new_notification ) {
946
            $new_notification['post_type']      = $post_type;
947
            $new_notification['post_excerpt']   = 'email';
948
			$new_notification['post_title']     = __( 'Email Notification', 'formidable' );
949
            $new_notification['menu_order']     = $form_id;
950
            $new_notification['post_status']    = 'publish';
951
952
            // Switch field IDs and keys, if needed
953
            if ( $switch ) {
954
955
				// Switch field IDs in email conditional logic
956
				self::switch_email_contition_field_ids( $new_notification['post_content'] );
957
958
				// Switch all other field IDs in email
959
                $new_notification['post_content'] = FrmFieldsHelper::switch_field_ids( $new_notification['post_content'] );
960
            }
961
            $new_notification['post_content']   = FrmAppHelper::prepare_and_encode( $new_notification['post_content'] );
962
963
            $exists = get_posts( array(
964
                'name'          => $new_notification['post_name'],
965
                'post_type'     => $new_notification['post_type'],
966
                'post_status'   => $new_notification['post_status'],
967
                'numberposts'   => 1,
968
            ) );
969
970
            if ( empty($exists) ) {
971
				FrmAppHelper::save_json_post( $new_notification );
972
                $imported['imported']['actions']++;
973
            }
974
            unset($new_notification);
975
        }
976
    }
977
978
    private static function migrate_notifications_to_action( $form_options, $form_id, &$notifications ) {
979
        if ( ! isset( $form_options['notification'] ) && isset( $form_options['email_to'] ) && ! empty( $form_options['email_to'] ) ) {
980
            // add old settings into notification array
981
			$form_options['notification'] = array( 0 => $form_options );
982
        } else if ( isset( $form_options['notification']['email_to'] ) ) {
983
            // make sure it's in the correct format
984
			$form_options['notification'] = array( 0 => $form_options['notification'] );
985
        }
986
987
        if ( isset( $form_options['notification'] ) && is_array($form_options['notification']) ) {
988
            foreach ( $form_options['notification'] as $email_key => $notification ) {
989
990
                $atts = array( 'email_to' => '', 'reply_to' => '', 'reply_to_name' => '', 'event' => '', 'form_id' => $form_id, 'email_key' => $email_key );
991
992
                // Format the email data
993
                self::format_email_data( $atts, $notification );
994
995
				if ( isset( $notification['twilio'] ) && $notification['twilio'] ) {
996
					do_action( 'frm_create_twilio_action', $atts, $notification );
997
				}
998
999
                // Setup the new notification
1000
                $new_notification = array();
1001
                self::setup_new_notification( $new_notification, $notification, $atts );
1002
1003
                $notifications[] = $new_notification;
1004
            }
1005
        }
1006
    }
1007
1008
    private static function format_email_data( &$atts, $notification ) {
1009
        // Format email_to
1010
        self::format_email_to_data( $atts, $notification );
1011
1012
        // Format the reply to email and name
1013
        $reply_fields = array( 'reply_to' => '', 'reply_to_name' => '' );
1014
        foreach ( $reply_fields as $f => $val ) {
1015
			if ( isset( $notification[ $f ] ) ) {
1016
				$atts[ $f ] = $notification[ $f ];
1017
				if ( 'custom' == $notification[ $f ] ) {
1018
					$atts[ $f ] = $notification[ 'cust_' . $f ];
1019
				} else if ( is_numeric( $atts[ $f ] ) && ! empty( $atts[ $f ] ) ) {
1020
					$atts[ $f ] = '[' . $atts[ $f ] . ']';
1021
                }
1022
            }
1023
            unset( $f, $val );
1024
        }
1025
1026
        // Format event
1027
		$atts['event'] = array( 'create' );
1028
        if ( isset( $notification['update_email'] ) && 1 == $notification['update_email'] ) {
1029
            $atts['event'][] = 'update';
1030
        } else if ( isset($notification['update_email']) && 2 == $notification['update_email'] ) {
1031
			$atts['event'] = array( 'update' );
1032
        }
1033
    }
1034
1035
    private static function format_email_to_data( &$atts, $notification ) {
1036
        if ( isset( $notification['email_to'] ) ) {
1037
			$atts['email_to'] = preg_split( '/ (,|;) /', $notification['email_to'] );
1038
        } else {
1039
            $atts['email_to'] = array();
1040
        }
1041
1042
        if ( isset( $notification['also_email_to'] ) ) {
1043
            $email_fields = (array) $notification['also_email_to'];
1044
            $atts['email_to'] = array_merge( $email_fields, $atts['email_to'] );
1045
            unset( $email_fields );
1046
        }
1047
1048
        foreach ( $atts['email_to'] as $key => $email_field ) {
1049
1050
            if ( is_numeric( $email_field ) ) {
1051
				$atts['email_to'][ $key ] = '[' . $email_field . ']';
1052
            }
1053
1054
            if ( strpos( $email_field, '|') ) {
1055
                $email_opt = explode( '|', $email_field );
1056
                if ( isset( $email_opt[0] ) ) {
1057
					$atts['email_to'][ $key ] = '[' . $email_opt[0] . ' show=' . $email_opt[1] . ']';
1058
                }
1059
                unset( $email_opt );
1060
            }
1061
        }
1062
        $atts['email_to'] = implode(', ', $atts['email_to']);
1063
    }
1064
1065
    private static function setup_new_notification( &$new_notification, $notification, $atts ) {
1066
        // Set up new notification
1067
        $new_notification = array(
1068
            'post_content'  => array(
1069
                'email_to'      => $atts['email_to'],
1070
                'event'         => $atts['event'],
1071
            ),
1072
			'post_name'         => $atts['form_id'] . '_email_' . $atts['email_key'],
1073
        );
1074
1075
        // Add more fields to the new notification
1076
        $add_fields = array( 'email_message', 'email_subject', 'plain_text', 'inc_user_info', 'conditions' );
1077
        foreach ( $add_fields as $add_field ) {
1078
			if ( isset( $notification[ $add_field ] ) ) {
1079
				$new_notification['post_content'][ $add_field ] = $notification[ $add_field ];
1080
            } else if ( in_array( $add_field, array( 'plain_text', 'inc_user_info' ) ) ) {
1081
				$new_notification['post_content'][ $add_field ] = 0;
1082
            } else {
1083
				$new_notification['post_content'][ $add_field ] = '';
1084
            }
1085
            unset( $add_field );
1086
        }
1087
1088
		// Set reply to
1089
		$new_notification['post_content']['reply_to'] = $atts['reply_to'];
1090
1091
        // Set from
1092
		if ( ! empty( $atts['reply_to'] ) || ! empty( $atts['reply_to_name'] ) ) {
1093
			$new_notification['post_content']['from'] = ( empty( $atts['reply_to_name'] ) ? '[sitename]' : $atts['reply_to_name'] ) . ' <' . ( empty( $atts['reply_to'] ) ? '[admin_email]' : $atts['reply_to'] ) . '>';
1094
        }
1095
    }
1096
1097
	/**
1098
	* Switch field IDs in pre-2.0 email conditional logic
1099
	*
1100
	* @param $post_content array, pass by reference
1101
	*/
1102
	private static function switch_email_contition_field_ids( &$post_content ) {
1103
		// Switch field IDs in conditional logic
1104
		if ( isset( $post_content['conditions'] ) && is_array( $post_content['conditions'] ) ) {
1105
			foreach ( $post_content['conditions'] as $email_key => $val ) {
1106
				if ( is_numeric( $email_key ) ) {
1107
					$post_content['conditions'][ $email_key ] = self::switch_action_field_ids( $val, array( 'hide_field' ) );
1108
				}
1109
				unset( $email_key, $val);
1110
			}
1111
		}
1112
	}
1113
1114
    private static function migrate_autoresponder_to_action( $form_options, $form_id, &$notifications ) {
1115
        if ( isset($form_options['auto_responder']) && $form_options['auto_responder'] && isset($form_options['ar_email_message']) && $form_options['ar_email_message'] ) {
1116
            // migrate autoresponder
1117
1118
            $email_field = isset($form_options['ar_email_to']) ? $form_options['ar_email_to'] : 0;
1119
            if ( strpos($email_field, '|') ) {
1120
                // data from entries field
1121
                $email_field = explode('|', $email_field);
1122
                if ( isset($email_field[1]) ) {
1123
                    $email_field = $email_field[1];
1124
                }
1125
            }
1126
            if ( is_numeric($email_field) && ! empty($email_field) ) {
1127
				$email_field = '[' . $email_field . ']';
1128
            }
1129
1130
            $notification = $form_options;
1131
            $new_notification2 = array(
1132
                'post_content'  => array(
1133
                    'email_message' => $notification['ar_email_message'],
1134
                    'email_subject' => isset($notification['ar_email_subject']) ? $notification['ar_email_subject'] : '',
1135
                    'email_to'      => $email_field,
1136
                    'plain_text'    => isset($notification['ar_plain_text']) ? $notification['ar_plain_text'] : 0,
1137
                    'inc_user_info' => 0,
1138
                ),
1139
				'post_name'     => $form_id . '_email_' . count( $notifications ),
1140
            );
1141
1142
            $reply_to = isset($notification['ar_reply_to']) ? $notification['ar_reply_to'] : '';
1143
            $reply_to_name = isset($notification['ar_reply_to_name']) ? $notification['ar_reply_to_name'] : '';
1144
1145
			if ( ! empty( $reply_to ) ) {
1146
				$new_notification2['post_content']['reply_to'] = $reply_to;
1147
			}
1148
1149
			if ( ! empty( $reply_to ) || ! empty( $reply_to_name ) ) {
1150
				$new_notification2['post_content']['from'] = ( empty( $reply_to_name ) ? '[sitename]' : $reply_to_name ) . ' <' . ( empty( $reply_to ) ? '[admin_email]' : $reply_to ) . '>';
1151
			}
1152
1153
            $notifications[] = $new_notification2;
1154
            unset( $new_notification2 );
1155
        }
1156
    }
1157
}
1158
1159