PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / trunk
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More vtrunk
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
← All changes | classes/helpers/FrmXMLHelper.php +824 -347 6.5.2 → trunk View file →
@@ -5,12 +5,18 @@
5 5
6 6 class FrmXMLHelper {
7 7
8 8 /**
9 - * @var bool $installing_template true if importing an XML from API, false if importing an XML file manually.
9 + * @var bool true if importing an XML from API, false if importing an XML file manually.
10 10 */
11 11 private static $installing_template = false;
12 12
13 + /**
14 + * @param array|string $opt
15 + * @param string $padding
16 + *
17 + * @return void
18 + */
13 19 public static function get_xml_values( $opt, $padding ) {
14 20 if ( is_array( $opt ) ) {
15 21 foreach ( $opt as $ok => $ov ) {
16 22 echo "\n" . esc_html( $padding );
@@ -16,8 +22,9 @@
16 22 echo "\n" . esc_html( $padding );
17 23 $tag = ( is_numeric( $ok ) ? 'key:' : '' ) . $ok;
18 24 echo '<' . esc_html( $tag ) . '>';
19 25 self::get_xml_values( $ov, $padding . ' ' );
26 +
20 27 if ( is_array( $ov ) ) {
21 28 echo "\n" . esc_html( $padding );
22 29 }
23 30 echo '</' . esc_html( $tag ) . '>';
@@ -26,8 +33,13 @@
26 33 echo self::cdata( $opt ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
27 34 }
28 35 }
29 36
37 + /**
38 + * @param string $file
39 + *
40 + * @return array|WP_Error The items imported
41 + */
30 42 public static function import_xml( $file ) {
31 43 if ( ! defined( 'WP_IMPORTING' ) ) {
32 44 define( 'WP_IMPORTING', true );
33 45 }
@@ -34,10 +46,10 @@
34 46
35 47 if ( ! class_exists( 'DOMDocument' ) ) {
36 48 $error_message = sprintf(
37 49 /* translators: 1: Documentation link */
38 - __( 'In order to install XML, your server must have DOMDocument installed. Follow our documentation on %1$s to ensure DOMDocument is properly set up and XML support is enabled.', 'formidable' ),
39 - '<a href="https://formidableforms.com/knowledgebase/import-forms-entries-and-views/#kb-your-server-does-not-have-xml-enabled" target="_blank">Importing Forms, Entries, and Views</a>'
50 + __( 'In order to install XML, your server must have DOMDocument installed. Follow our documentation on %1$s to ensure DOMDocument is properly set up and XML support is enabled.', 'formidable' ), // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
51 + '<a href="https://formidableforms.com/knowledgebase/import-forms-entries-and-views/#kb-your-server-does-not-have-xml-enabled" target="_blank">Importing Forms, Entries, and Views</a>' // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
40 52 );
41 53
42 54 return new WP_Error( 'SimpleXML_parse_error', $error_message, libxml_get_errors() );
43 55 }
@@ -49,8 +61,9 @@
49 61
50 62 // LIBXML_COMPACT activates small nodes allocation optimization.
51 63 // Use LIBXML_PARSEHUGE to avoid "parser error : internal error: Huge input lookup" for large (300MB) files.
52 64 $success = $dom->loadXML( $xml_string, LIBXML_COMPACT | LIBXML_PARSEHUGE );
65 +
53 66 if ( ! $success ) {
54 67 return new WP_Error( 'SimpleXML_parse_error', __( 'There was an error when reading this XML file', 'formidable' ), libxml_get_errors() );
55 68 }
56 69
@@ -60,9 +73,9 @@
60 73
61 74 $xml = simplexml_import_dom( $dom );
62 75 unset( $dom );
63 76
64 - // halt if loading produces an error
77 + // Halt if loading produces an error
65 78 if ( ! $xml ) {
66 79 return new WP_Error( 'SimpleXML_parse_error', __( 'There was an error when reading this XML file', 'formidable' ), libxml_get_errors() );
67 80 }
68 81
@@ -72,12 +85,13 @@
72 85 /**
73 86 * @since 6.2.3
74 87 *
75 88 * @param string $xml_string
89 + *
76 90 * @return void
77 91 */
78 92 private static function maybe_fix_xml( &$xml_string ) {
79 - if ( '<?xml' !== substr( $xml_string, 0, 5 ) ) {
93 + if ( ! str_starts_with( $xml_string, '<?xml' ) ) {
80 94 // Some XML files have may have unexpected characters at the start.
81 95 $xml_string = substr( $xml_string, strpos( $xml_string, '<?xml' ) );
82 96 }
83 97
@@ -84,17 +98,20 @@
84 98 // The Equity theme adds a <meta name="generator" content="Equity 1.7.13" /> tag using the "the_generator" filter.
85 99 // Strip that out as it breaks the XML import.
86 100 $channel_start_position = strpos( $xml_string, '<channel>' );
87 101 $content_before_channel_tag = substr( $xml_string, 0, $channel_start_position );
88 - if ( 0 !== strpos( $content_before_channel_tag, '<meta name="generator" ' ) ) {
89 - $content_before_channel_tag = preg_replace(
90 - '/<meta\s+[^>]*name="generator"[^>]*\/>/i',
91 - '',
92 - $content_before_channel_tag,
93 - 1
94 - );
95 - $xml_string = $content_before_channel_tag . substr( $xml_string, $channel_start_position );
102 +
103 + if ( str_starts_with( $content_before_channel_tag, '<meta name="generator" ' ) ) {
104 + return;
96 105 }
106 +
107 + $content_before_channel_tag = preg_replace(
108 + '/<meta\s+[^>]*name="generator"[^>]*\/>/i',
109 + '',
110 + $content_before_channel_tag,
111 + 1
112 + );
113 + $xml_string = $content_before_channel_tag . substr( $xml_string, $channel_start_position );
97 114 }
98 115
99 116 /**
100 117 * Add terms, forms (form and field ids), posts (post ids), and entries to db, in that order
@@ -102,8 +119,9 @@
102 119 * @since 3.06
103 120 *
104 121 * @param object $xml
105 122 * @param bool $installing_template
123 + *
106 124 * @return array The number of items imported
107 125 */
108 126 public static function import_xml_now( $xml, $installing_template = false ) {
109 127 if ( ! defined( 'WP_IMPORTING' ) ) {
@@ -114,18 +132,20 @@
114 132 $imported = self::pre_import_data();
115 133
116 134 foreach ( array( 'term', 'form', 'view' ) as $item_type ) {
117 135 // Grab cats, tags, and terms, or forms or posts.
118 - if ( isset( $xml->{$item_type} ) ) {
119 - $function_name = 'import_xml_' . $item_type . 's';
120 - $imported = self::$function_name( $xml->{$item_type}, $imported );
121 - unset( $function_name, $xml->{$item_type} );
136 + if ( ! isset( $xml->{$item_type} ) ) {
137 + continue;
122 138 }
139 +
140 + $function_name = 'import_xml_' . $item_type . 's';
141 + $imported = self::$function_name( $xml->{$item_type}, $imported );
142 + unset( $function_name, $xml->{$item_type} );
123 143 }
124 144
125 145 $imported = apply_filters( 'frm_importing_xml', $imported, $xml );
126 146
127 - if ( ! isset( $imported['form_status'] ) || empty( $imported['form_status'] ) ) {
147 + if ( empty( $imported['form_status'] ) ) {
128 148 // Check for an error message in the XML.
129 149 if ( isset( $xml->Code ) && isset( $xml->Message ) ) { // phpcs:ignore WordPress.NamingConventions
130 150 $imported['error'] = (string) $xml->Message; // phpcs:ignore WordPress.NamingConventions
131 151 }
@@ -135,8 +155,9 @@
135 155 }
136 156
137 157 /**
138 158 * @since 3.06
159 + *
139 160 * @return array
140 161 */
141 162 private static function pre_import_data() {
142 163 $defaults = array(
@@ -156,8 +177,14 @@
156 177 'terms' => array(),
157 178 );
158 179 }
159 180
181 + /**
182 + * @param SimpleXMLElement $terms
183 + * @param array $imported
184 + *
185 + * @return array
186 + */
160 187 public static function import_xml_terms( $terms, $imported ) {
161 188 foreach ( $terms as $t ) {
162 189 if ( term_exists( (string) $t->term_slug, (string) $t->term_taxonomy ) ) {
163 190 continue;
@@ -170,19 +197,19 @@
170 197 (string) $t->term_taxonomy,
171 198 array(
172 199 'slug' => (string) $t->term_slug,
173 200 'description' => (string) $t->term_description,
174 - 'parent' => empty( $parent ) ? 0 : $parent,
201 + 'parent' => $parent ? $parent : 0,
175 202 )
176 203 );
177 204
178 205 if ( $term && is_array( $term ) ) {
179 - $imported['imported']['terms'] ++;
206 + ++$imported['imported']['terms'];
180 207 $imported['terms'][ (int) $t->term_id ] = $term['term_id'];
181 208 }
182 209
183 210 unset( $term, $t );
184 - }
211 + }//end foreach
185 212
186 213 return $imported;
187 214 }
188 215
@@ -187,23 +214,30 @@
187 214 }
188 215
189 216 /**
190 217 * @since 2.0.8
218 + *
219 + * @param object $t
220 + *
221 + * @return int|string
191 222 */
192 223 private static function get_term_parent_id( $t ) {
193 224 $parent = (string) $t->term_parent;
194 - if ( ! empty( $parent ) ) {
225 +
226 + if ( $parent ) {
195 227 $parent = term_exists( (string) $t->term_parent, (string) $t->term_taxonomy );
196 - if ( $parent ) {
197 - $parent = $parent['term_id'];
198 - } else {
199 - $parent = 0;
200 - }
228 + $parent = $parent ? $parent['term_id'] : 0;
201 229 }
202 230
203 231 return $parent;
204 232 }
205 233
234 + /**
235 + * @param SimpleXMLElement $forms
236 + * @param array $imported
237 + *
238 + * @return array
239 + */
206 240 public static function import_xml_forms( $forms, $imported ) {
207 241 $child_forms = array();
208 242
209 243 // Import child forms first
@@ -213,13 +247,13 @@
213 247 $form = self::fill_form( $item );
214 248
215 249 self::update_custom_style_setting_on_import( $form );
216 250
217 - $this_form = self::maybe_get_form( $form );
218 -
251 + $this_form = self::maybe_get_form( $form );
219 252 $old_id = false;
220 253 $form_fields = false;
221 - if ( ! empty( $this_form ) ) {
254 +
255 + if ( $this_form ) {
222 256 $form_id = $this_form->id;
223 257 $old_id = $this_form->id;
224 258 self::update_form( $this_form, $form, $imported );
225 259
@@ -225,12 +259,13 @@
225 259
226 260 $form_fields = self::get_form_fields( $form_id );
227 261 } else {
228 262 $form_id = FrmForm::create( $form );
263 +
229 264 if ( $form_id ) {
230 265 if ( empty( $form['parent_form_id'] ) ) {
231 266 // Don't include the repeater form in the imported count.
232 - $imported['imported']['forms'] ++;
267 + ++$imported['imported']['forms'];
233 268 }
234 269
235 270 // Keep track of whether this specific form was updated or not.
236 271 $imported['form_status'][ $form_id ] = 'imported';
@@ -255,15 +290,35 @@
255 290
256 291 do_action( 'frm_after_import_form', $form_id, $form );
257 292
258 293 unset( $form, $item );
259 - }
294 + }//end foreach
260 295
261 296 self::maybe_update_child_form_parent_id( $imported['forms'], $child_forms );
262 297
298 + /**
299 + * Fires after all forms in the XML have been imported.
300 + *
301 + * Child forms are imported before their parent form, so per-form fix-ups
302 + * cannot resolve conditional logic that references fields in a form
303 + * imported later. Use this action for cross-form fix-ups that require
304 + * the fully populated `$frm_duplicate_ids` map.
305 + *
306 + * @since 6.31
307 + *
308 + * @param array $imported Summary of imported items, including
309 + * 'forms' => array( old_form_id => new_form_id ).
310 + */
311 + do_action( 'frm_after_import_forms', $imported );
312 +
263 313 return $imported;
264 314 }
265 315
316 + /**
317 + * @param object $item
318 + *
319 + * @return array
320 + */
266 321 private static function fill_form( $item ) {
267 322 $form = array(
268 323 'id' => (int) $item->id,
269 324 'form_key' => (string) $item->form_key,
@@ -291,21 +346,27 @@
291 346
292 347 return $form;
293 348 }
294 349
350 + /**
351 + * @param array $form
352 + *
353 + * @return false|object
354 + */
295 355 private static function maybe_get_form( $form ) {
296 - // if template, allow to edit if form keys match, otherwise, creation date must also match
356 + // If template, allow to edit if form keys match, otherwise, creation date must also match
297 357 $edit_query = array(
298 358 'form_key' => $form['form_key'],
299 359 'is_template' => $form['is_template'],
300 360 );
361 +
301 362 if ( ! $form['is_template'] ) {
302 363 $edit_query['created_at'] = $form['created_at'];
303 364 }
304 365
305 366 $edit_query = apply_filters( 'frm_match_xml_form', $edit_query, $form );
367 + $form = FrmForm::getAll( $edit_query, '', 1 );
306 368
307 - $form = FrmForm::getAll( $edit_query, '', 1 );
308 369 if ( is_object( $form ) && $form->status === 'trash' ) {
309 370 FrmForm::destroy( $form->id );
310 371 return false;
311 372 }
@@ -312,14 +373,22 @@
312 373
313 374 return $form;
314 375 }
315 376
377 + /**
378 + * @param object $this_form
379 + * @param array $form
380 + * @param array $imported
381 + *
382 + * @return void
383 + */
316 384 private static function update_form( $this_form, $form, &$imported ) {
317 385 $form_id = $this_form->id;
318 386 FrmForm::update( $form_id, $form );
387 +
319 388 if ( empty( $form['parent_form_id'] ) ) {
320 389 // Don't include the repeater form in the updated count.
321 - $imported['updated']['forms'] ++;
390 + ++$imported['updated']['forms'];
322 391 }
323 392
324 393 // Keep track of whether this specific form was updated or not
325 394 $imported['form_status'][ $form_id ] = 'updated';
@@ -324,32 +393,43 @@
324 393 // Keep track of whether this specific form was updated or not
325 394 $imported['form_status'][ $form_id ] = 'updated';
326 395 }
327 396
397 + /**
398 + * @param int|string $form_id
399 + *
400 + * @return array
401 + */
328 402 private static function get_form_fields( $form_id ) {
329 403 $form_fields = FrmField::get_all_for_form( $form_id, '', 'exclude', 'exclude' );
330 404 $old_fields = array();
405 +
331 406 foreach ( $form_fields as $f ) {
332 407 $old_fields[ $f->id ] = $f;
333 408 $old_fields[ $f->field_key ] = $f->id;
334 409 unset( $f );
335 410 }
336 - $form_fields = $old_fields;
337 411
338 - return $form_fields;
412 + return $old_fields;
339 413 }
340 414
341 415 /**
342 416 * Delete any fields attached to this form that were not included in the template
417 + *
418 + * @param array $form_fields
419 + *
420 + * @return void
343 421 */
344 422 private static function delete_removed_fields( $form_fields ) {
345 - if ( ! empty( $form_fields ) ) {
346 - foreach ( $form_fields as $field ) {
347 - if ( is_object( $field ) ) {
348 - FrmField::destroy( $field->id );
349 - }
350 - unset( $field );
423 + if ( ! $form_fields ) {
424 + return;
425 + }
426 +
427 + foreach ( $form_fields as $field ) {
428 + if ( is_object( $field ) ) {
429 + FrmField::destroy( $field->id );
351 430 }
431 + unset( $field );
352 432 }
353 433 }
354 434
355 435 /**
@@ -380,10 +460,10 @@
380 460 * Keep track of all imported child forms
381 461 *
382 462 * @since 2.0.16
383 463 *
384 - * @param int $form_id
385 - * @param int $parent_form_id
464 + * @param int $form_id
465 + * @param int $parent_form_id
386 466 * @param array $child_forms
387 467 */
388 468 private static function track_imported_child_forms( $form_id, $parent_form_id, &$child_forms ) {
389 469 if ( $parent_form_id ) {
@@ -401,14 +481,16 @@
401 481 * @param array $child_forms
402 482 */
403 483 private static function maybe_update_child_form_parent_id( $imported_forms, $child_forms ) {
404 484 foreach ( $child_forms as $child_form_id => $old_parent_form_id ) {
405 - if ( isset( $imported_forms[ $old_parent_form_id ] ) && (int) $imported_forms[ $old_parent_form_id ] !== (int) $old_parent_form_id ) {
406 - // Update all children with this old parent_form_id
407 - $new_parent_form_id = (int) $imported_forms[ $old_parent_form_id ];
408 - FrmForm::update( $child_form_id, array( 'parent_form_id' => $new_parent_form_id ) );
409 - do_action( 'frm_update_child_form_parent_id', $child_form_id, $new_parent_form_id );
485 + if ( ! isset( $imported_forms[ $old_parent_form_id ] ) || (int) $imported_forms[ $old_parent_form_id ] === (int) $old_parent_form_id ) {
486 + continue;
410 487 }
488 +
489 + // Update all children with this old parent_form_id
490 + $new_parent_form_id = (int) $imported_forms[ $old_parent_form_id ];
491 + FrmForm::update( $child_form_id, array( 'parent_form_id' => $new_parent_form_id ) );
492 + do_action( 'frm_update_child_form_parent_id', $child_form_id, $new_parent_form_id );
411 493 }
412 494 }
413 495
414 496 /**
@@ -416,8 +498,14 @@
416 498 *
417 499 * @since 2.0.13
418 500 *
419 501 * TODO: Cut down on params
502 + *
503 + * @param SimpleXMLElement $xml_fields
504 + * @param int|string $form_id
505 + * @param object $this_form
506 + * @param array $form_fields
507 + * @param array $imported
420 508 */
421 509 private static function import_xml_fields( $xml_fields, $form_id, $this_form, &$form_fields, &$imported ) {
422 510 $in_section = 0;
423 511 $keys_by_original_field_id = array();
@@ -431,40 +519,45 @@
431 519 self::maybe_update_form_select( $f, $imported );
432 520 self::maybe_update_get_values_form_setting( $imported, $f );
433 521 self::migrate_placeholders( $f );
434 522
435 - if ( ! empty( $this_form ) ) {
436 - // check for field to edit by field id
523 + if ( $this_form ) {
524 + // Check for field to edit by field id
437 525 if ( isset( $form_fields[ $f['id'] ] ) ) {
438 526 FrmField::update( $f['id'], $f );
439 - $imported['updated']['fields'] ++;
527 + ++$imported['updated']['fields'];
440 528
441 529 unset( $form_fields[ $f['id'] ] );
442 530
443 - //unset old field key
531 + // Unset old field key.
444 532 if ( isset( $form_fields[ $f['field_key'] ] ) ) {
445 533 unset( $form_fields[ $f['field_key'] ] );
446 534 }
447 535 } elseif ( isset( $form_fields[ $f['field_key'] ] ) ) {
448 536 $keys_by_original_field_id[ $f['id'] ] = $f['field_key'];
537 + $old_field_id = $f['id'];
449 538
450 - // check for field to edit by field key
539 + // Check for field to edit by field key
451 540 unset( $f['id'] );
452 541
453 542 FrmField::update( $form_fields[ $f['field_key'] ], $f );
454 - $imported['updated']['fields'] ++;
543 + ++$imported['updated']['fields'];
455 544
456 - unset( $form_fields[ $form_fields[ $f['field_key'] ] ] ); //unset old field id
457 - unset( $form_fields[ $f['field_key'] ] ); //unset old field key
545 + self::do_after_field_imported_action( $f, $form_fields, $old_field_id );
546 +
547 + // Unset old field id.
548 + unset( $form_fields[ $form_fields[ $f['field_key'] ] ] );
549 +
550 + // Unset old field key.
551 + unset( $form_fields[ $f['field_key'] ] );
458 552 } else {
459 - // if no matching field id or key in this form, create the field
553 + // If no matching field id or key in this form, create the field.
460 554 self::create_imported_field( $f, $imported );
461 - }
555 + }//end if
462 556 } else {
463 -
464 557 self::create_imported_field( $f, $imported );
465 - }
466 - }
558 + }//end if
559 + }//end foreach
467 560
468 561 if ( $keys_by_original_field_id ) {
469 562 self::maybe_update_field_ids( $form_id, $keys_by_original_field_id );
470 563 }
@@ -469,8 +562,53 @@
469 562 self::maybe_update_field_ids( $form_id, $keys_by_original_field_id );
470 563 }
471 564 }
472 565
566 + /**
567 + * @since 6.8.4
568 + *
569 + * @param array $field_array
570 + *
571 + * @return array
572 + */
573 + private static function update_field_options_with_defaults( $field_array ) {
574 + $defaults = self::default_field_options( $field_array['type'] );
575 + $field_array['field_options'] = array_merge( $defaults, $field_array['field_options'] );
576 +
577 + return $field_array;
578 + }
579 +
580 + /**
581 + * @since 6.8.4
582 + *
583 + * @param array $field_array
584 + * @param array $form_fields
585 + * @param int $old_field_id
586 + *
587 + * @return void
588 + */
589 + private static function do_after_field_imported_action( $field_array, $form_fields, $old_field_id ) {
590 + // Assign field array the update field's ID.
591 + $field_array['id'] = $form_fields[ $field_array['field_key'] ];
592 +
593 + /**
594 + * Fires when an existing field is imported.
595 + *
596 + * @since 6.8.4
597 + *
598 + * @param array $field_array
599 + * @param int $field_id
600 + * @param int $old_field_id
601 + */
602 + do_action( 'frm_after_existing_field_is_imported', $field_array, $form_fields[ $field_array['field_key'] ], $old_field_id );
603 + }
604 +
605 + /**
606 + * @param object $field
607 + * @param int|string $form_id
608 + *
609 + * @return array
610 + */
473 611 private static function fill_field( $field, $form_id ) {
474 612 return array(
475 613 'id' => (int) $field->id,
476 614 'field_key' => (string) $field->field_key,
@@ -481,14 +619,45 @@
481 619 'field_order' => (int) $field->field_order,
482 620 'form_id' => (int) $form_id,
483 621 'required' => (int) $field->required,
484 622 'options' => FrmAppHelper::maybe_json_decode( (string) $field->options ),
485 - 'field_options' => FrmAppHelper::maybe_json_decode( (string) $field->field_options ),
623 + 'field_options' => self::fill_field_options( $field ),
486 624 );
487 625 }
488 626
489 627 /**
628 + * Reads a field's options out of the file as an array.
629 + *
630 + * Field options are a settings map, and every step of the import reads them
631 + * as one. A file whose value there cannot be read, because it is empty or
632 + * was written by something other than an export, used to end the whole
633 + * import with a fatal error on the first field it reached. An empty set of
634 + * options is recoverable, since the defaults for the field type fill the
635 + * gaps, so prefer that over stopping.
636 + *
637 + * Unserialize is tried as well as JSON so options written by an older
638 + * version are still read rather than thrown away.
639 + *
640 + * @since 6.35
641 + *
642 + * @param object $field Field element from the file.
643 + *
644 + * @return array
645 + */
646 + private static function fill_field_options( $field ) {
647 + $options = (string) $field->field_options;
648 +
649 + FrmAppHelper::unserialize_or_decode( $options );
650 +
651 + return is_array( $options ) ? $options : array();
652 + }
653 +
654 + /**
490 655 * @since 4.06
656 + *
657 + * @param array $f
658 + *
659 + * @return void
491 660 */
492 661 private static function set_default_value( &$f ) {
493 662 $has_default = array(
494 663 'text',
@@ -502,15 +671,17 @@
502 671 'password',
503 672 'tag',
504 673 );
505 674
506 - if ( is_array( $f['default_value'] ) && in_array( $f['type'], $has_default, true ) ) {
507 - if ( count( $f['default_value'] ) === 1 ) {
508 - $f['default_value'] = '[' . reset( $f['default_value'] ) . ']';
509 - } else {
510 - $f['default_value'] = reset( $f['default_value'] );
511 - }
675 + if ( ! is_array( $f['default_value'] ) || ! in_array( $f['type'], $has_default, true ) ) {
676 + return;
512 677 }
678 +
679 + if ( count( $f['default_value'] ) === 1 ) {
680 + $f['default_value'] = '[' . reset( $f['default_value'] ) . ']';
681 + } else {
682 + $f['default_value'] = reset( $f['default_value'] );
683 + }
513 684 }
514 685
515 686 /**
516 687 * Make sure the required indicator is set.
@@ -515,8 +686,12 @@
515 686 /**
516 687 * Make sure the required indicator is set.
517 688 *
518 689 * @since 4.05
690 + *
691 + * @param array $f
692 + *
693 + * @return void
519 694 */
520 695 private static function maybe_add_required( &$f ) {
521 696 if ( $f['required'] && ! isset( $f['field_options']['required_indicator'] ) ) {
522 697 $f['field_options']['required_indicator'] = '*';
@@ -526,14 +701,17 @@
526 701 /**
527 702 * Update the current in_section value at the beginning of the field loop
528 703 *
529 704 * @since 2.0.25
530 - * @param int $in_section
705 + *
706 + * @param int $in_section
531 707 * @param array $f
708 + *
709 + * @return void
532 710 */
533 711 private static function maybe_update_in_section_variable( &$in_section, &$f ) {
534 712 // If we're at the end of a section, switch $in_section is 0
535 - if ( in_array( $f['type'], array( 'end_divider', 'break', 'form' ) ) ) {
713 + if ( in_array( $f['type'], array( 'end_divider', 'break', 'form' ), true ) ) {
536 714 $in_section = 0;
537 715 }
538 716
539 717 // Update the current field's in_section value
@@ -541,9 +719,9 @@
541 719 $f['field_options']['in_section'] = $in_section;
542 720 }
543 721
544 722 // If we're starting a new section, switch $in_section to ID of divider
545 - if ( $f['type'] == 'divider' ) {
723 + if ( $f['type'] === 'divider' ) {
546 724 $in_section = $f['id'];
547 725 }
548 726 }
549 727
@@ -559,16 +737,21 @@
559 737 if ( ! isset( $imported['forms'] ) ) {
560 738 return;
561 739 }
562 740
563 - if ( $f['type'] == 'form' || ( $f['type'] == 'divider' && FrmField::is_option_true( $f['field_options'], 'repeat' ) ) ) {
564 - if ( FrmField::is_option_true( $f['field_options'], 'form_select' ) ) {
565 - $form_select = (int) $f['field_options']['form_select'];
566 - if ( isset( $imported['forms'][ $form_select ] ) ) {
567 - $f['field_options']['form_select'] = $imported['forms'][ $form_select ];
568 - }
569 - }
741 + if ( $f['type'] !== 'form' && ( $f['type'] !== 'divider' || ! FrmField::is_option_true( $f['field_options'], 'repeat' ) ) ) {
742 + return;
570 743 }
744 +
745 + if ( ! FrmField::is_option_true( $f['field_options'], 'form_select' ) ) {
746 + return;
747 + }
748 +
749 + $form_select = (int) $f['field_options']['form_select'];
750 +
751 + if ( isset( $imported['forms'][ $form_select ] ) ) {
752 + $f['field_options']['form_select'] = $imported['forms'][ $form_select ];
753 + }
571 754 }
572 755
573 756 /**
574 757 * Update the get_values_form setting if the form was imported
@@ -576,8 +759,10 @@
576 759 * @since 2.01.0
577 760 *
578 761 * @param array $imported
579 762 * @param array $f
763 + *
764 + * @return void
580 765 */
581 766 private static function maybe_update_get_values_form_setting( $imported, &$f ) {
582 767 if ( ! isset( $imported['forms'] ) ) {
583 768 return;
@@ -582,36 +767,35 @@
582 767 if ( ! isset( $imported['forms'] ) ) {
583 768 return;
584 769 }
585 770
586 - if ( FrmField::is_option_true_in_array( $f['field_options'], 'get_values_form' ) ) {
587 - $old_form = $f['field_options']['get_values_form'];
588 - if ( isset( $imported['forms'][ $old_form ] ) ) {
589 - $f['field_options']['get_values_form'] = $imported['forms'][ $old_form ];
590 - }
771 + if ( ! FrmField::is_option_true_in_array( $f['field_options'], 'get_values_form' ) ) {
772 + return;
591 773 }
592 - }
593 774
594 - /**
595 - * If field settings have been migrated, update the values during import.
596 - *
597 - * @since 4.0
598 - */
599 - private static function run_field_migrations( &$f ) {
600 - self::migrate_placeholders( $f );
601 - $f = apply_filters( 'frm_import_xml_field', $f );
775 + $old_form = $f['field_options']['get_values_form'];
776 +
777 + if ( isset( $imported['forms'][ $old_form ] ) ) {
778 + $f['field_options']['get_values_form'] = $imported['forms'][ $old_form ];
779 + }
602 780 }
603 781
604 782 /**
605 783 * @since 4.0
784 + *
785 + * @param array $f
786 + *
787 + * @return void
606 788 */
607 789 private static function migrate_placeholders( &$f ) {
608 790 $update_values = self::migrate_field_placeholder( $f, 'clear_on_focus' );
791 +
609 792 foreach ( $update_values as $k => $v ) {
610 793 $f[ $k ] = $v;
611 794 }
612 795
613 796 $update_values = self::migrate_field_placeholder( $f, 'default_blank' );
797 +
614 798 foreach ( $update_values as $k => $v ) {
615 799 $f[ $k ] = $v;
616 800 }
617 801 }
@@ -620,13 +804,18 @@
620 804 * Move clear_on_focus or default_blank to placeholder.
621 805 * Also called during database migration in FrmMigrate.
622 806 *
623 807 * @since 4.0
808 + *
809 + * @param array|object $field
810 + * @param string $type
811 + *
624 812 * @return array
625 813 */
626 814 public static function migrate_field_placeholder( $field, $type ) {
627 - $field = (array) $field;
815 + $field = (array) $field;
628 816 $field_options = $field['field_options'];
817 +
629 818 if ( empty( $field_options[ $type ] ) || empty( $field['default_value'] ) ) {
630 819 return array();
631 820 }
632 821
@@ -639,27 +828,34 @@
639 828 );
640 829
641 830 // If a dropdown placeholder was used, remove the option so it won't be included twice.
642 831 $options = $field['options'];
643 - if ( $type === 'default_blank' && is_array( $options ) ) {
644 - $default_value = $field['default_value'];
645 - if ( is_array( $default_value ) ) {
646 - $default_value = reset( $default_value );
832 +
833 + if ( $type !== 'default_blank' || ! is_array( $options ) ) {
834 + return $changes;
835 + }
836 +
837 + $default_value = $field['default_value'];
838 +
839 + if ( is_array( $default_value ) ) {
840 + $default_value = reset( $default_value );
841 + }
842 +
843 + foreach ( $options as $opt_key => $opt ) {
844 + if ( is_array( $opt ) ) {
845 + $opt = $opt['value'] ?? $opt['label'] ?? reset( $opt );
647 846 }
648 847
649 - foreach ( $options as $opt_key => $opt ) {
650 - if ( is_array( $opt ) ) {
651 - $opt = isset( $opt['value'] ) ? $opt['value'] : ( isset( $opt['label'] ) ? $opt['label'] : reset( $opt ) );
652 - }
653 -
654 - if ( $opt == $default_value ) {
655 - unset( $options[ $opt_key ] );
656 - break;
657 - }
848 + // phpcs:ignore Universal.Operators.StrictComparisons
849 + if ( $opt == $default_value ) {
850 + unset( $options[ $opt_key ] );
851 + break;
658 852 }
659 - $changes['options'] = $options;
660 853 }
661 854
855 + $changes['options'] = $options;
856 + // end if
857 +
662 858 return $changes;
663 859 }
664 860
665 861 /**
@@ -668,12 +864,13 @@
668 864 * @since 2.0.25
669 865 *
670 866 * @param array $f
671 867 * @param array $imported
868 + *
869 + * @return void
672 870 */
673 871 private static function create_imported_field( $f, &$imported ) {
674 - $defaults = self::default_field_options( $f['type'] );
675 - $f['field_options'] = array_merge( $defaults, $f['field_options'] );
872 + $f = self::update_field_options_with_defaults( $f );
676 873
677 874 if ( is_callable( 'FrmProFileImport::import_attachment' ) ) {
678 875 $f = self::maybe_import_images_for_options( $f );
679 876 }
@@ -678,12 +875,15 @@
678 875 $f = self::maybe_import_images_for_options( $f );
679 876 }
680 877
681 878 $new_id = FrmField::create( $f );
682 - if ( $new_id != false ) {
683 - $imported['imported']['fields'] ++;
684 - do_action( 'frm_after_field_is_imported', $f, $new_id );
879 +
880 + if ( ! $new_id ) {
881 + return;
685 882 }
883 +
884 + ++$imported['imported']['fields'];
885 + do_action( 'frm_after_field_is_imported', $f, $new_id );
686 886 }
687 887
688 888 /**
689 889 * Import images for radio buttons and checkboxes from image src if available.
@@ -690,8 +890,9 @@
690 890 *
691 891 * @since 5.5.1
692 892 *
693 893 * @param array $field
894 + *
694 895 * @return array
695 896 */
696 897 private static function maybe_import_images_for_options( $field ) {
697 898 if ( empty( $field['options'] ) || ! is_array( $field['options'] ) ) {
@@ -702,13 +903,15 @@
702 903 if ( ! is_array( $option ) || empty( $option['src'] ) ) {
703 904 continue;
704 905 }
705 906
706 - $field_object = (object) $field;
707 - $field_object->type = 'file'; // Fake the file type as FrmProImport::import_attachment checks for file type.
907 + $field_object = (object) $field;
908 + // Fake the file type as FrmProImport::import_attachment checks for file type.
909 + $field_object->type = 'file';
708 910
709 911 $image_id = FrmProFileImport::import_attachment( $option['src'], $field_object );
710 - unset( $field['options'][ $key ]['src'] ); // Remove the src from options as it isn't required after import.
912 + // Remove the src from options as it isn't required after import.
913 + unset( $field['options'][ $key ]['src'] );
711 914
712 915 if ( is_numeric( $image_id ) ) {
713 916 $field['options'][ $key ]['image'] = $image_id;
714 917 }
@@ -720,10 +923,13 @@
720 923 /**
721 924 * Fix field ids for fields that already exist prior to import.
722 925 *
723 926 * @since 4.07
724 - * @param int $form_id
927 + *
928 + * @param int $form_id
725 929 * @param array $keys_by_original_field_id
930 + *
931 + * @return void
726 932 */
727 933 protected static function maybe_update_field_ids( $form_id, $keys_by_original_field_id ) {
728 934 global $frm_duplicate_ids;
729 935
@@ -743,15 +949,17 @@
743 949 $field = (array) $field;
744 950 $frm_duplicate_ids = $keys_by_original_field_id;
745 951 $after = FrmFieldsHelper::switch_field_ids( $field );
746 952
953 + if ( $before['field_options'] === $after['field_options'] ) {
954 + continue;
955 + }
956 +
957 + $frm_duplicate_ids = $field_id_by_key;
958 + $after = FrmFieldsHelper::switch_field_ids( $after );
959 +
747 960 if ( $before['field_options'] !== $after['field_options'] ) {
748 - $frm_duplicate_ids = $field_id_by_key;
749 - $after = FrmFieldsHelper::switch_field_ids( $after );
750 -
751 - if ( $before['field_options'] !== $after['field_options'] ) {
752 - FrmField::update( $field['id'], array( 'field_options' => $after['field_options'] ) );
753 - }
961 + FrmField::update( $field['id'], array( 'field_options' => $after['field_options'] ) );
754 962 }
755 963 }
756 964
757 965 $frm_duplicate_ids = $former_duplicate_ids;
@@ -763,8 +971,10 @@
763 971 *
764 972 * @since 2.0.19
765 973 *
766 974 * @param array $form
975 + *
976 + * @return void
767 977 */
768 978 private static function update_custom_style_setting_on_import( &$form ) {
769 979 if ( ! isset( $form['options']['custom_style'] ) ) {
770 980 return;
@@ -772,29 +982,32 @@
772 982
773 983 if ( is_numeric( $form['options']['custom_style'] ) && 1 === intval( $form['options']['custom_style'] ) ) {
774 984 // Set to default
775 985 $form['options']['custom_style'] = 1;
776 - } else {
777 - // Replace the style name with the style ID on import
778 - global $wpdb;
779 - $table = $wpdb->prefix . 'posts';
780 - $where = array(
781 - 'post_name' => $form['options']['custom_style'],
782 - 'post_type' => 'frm_styles',
783 - );
784 - $select = 'ID';
785 - $style_id = FrmDb::get_var( $table, $where, $select );
786 986
787 - if ( $style_id ) {
788 - $form['options']['custom_style'] = $style_id;
789 - } else {
790 - // save the old style to maybe update after styles import
791 - $form['options']['old_style'] = $form['options']['custom_style'];
987 + return;
988 + }
792 989
793 - // Set to default
794 - $form['options']['custom_style'] = 1;
795 - }
990 + // Replace the style name with the style ID on import
991 + global $wpdb;
992 + $table = $wpdb->prefix . 'posts';
993 + $where = array(
994 + 'post_name' => $form['options']['custom_style'],
995 + 'post_type' => 'frm_styles',
996 + );
997 + $select = 'ID';
998 + $style_id = FrmDb::get_var( $table, $where, $select );
999 +
1000 + if ( $style_id ) {
1001 + $form['options']['custom_style'] = $style_id;
1002 + return;
796 1003 }
1004 +
1005 + // Save the old style to maybe update after styles import
1006 + $form['options']['old_style'] = $form['options']['custom_style'];
1007 +
1008 + // Set to default
1009 + $form['options']['custom_style'] = 1;
797 1010 }
798 1011
799 1012 /**
800 1013 * After styles are imported, check for any forms that were linked
@@ -800,25 +1013,40 @@
800 1013 * After styles are imported, check for any forms that were linked
801 1014 * and link them back up.
802 1015 *
803 1016 * @since 2.2.7
1017 + *
1018 + * @param int|string $form_id
1019 + *
1020 + * @return void
804 1021 */
805 1022 private static function update_custom_style_setting_after_import( $form_id ) {
806 1023 $form = FrmForm::getOne( $form_id );
807 1024
808 - if ( $form && isset( $form->options['old_style'] ) ) {
809 - $form = (array) $form;
810 - $saved_style = $form['options']['custom_style'];
811 - $form['options']['custom_style'] = $form['options']['old_style'];
812 - self::update_custom_style_setting_on_import( $form );
813 - $has_changed = ( $form['options']['custom_style'] != $saved_style && $form['options']['custom_style'] != $form['options']['old_style'] );
814 - if ( $has_changed ) {
815 - FrmForm::update( $form['id'], $form );
816 - }
1025 + if ( ! $form || ! isset( $form->options['old_style'] ) ) {
1026 + return;
817 1027 }
1028 +
1029 + $form = (array) $form;
1030 + $saved_style = $form['options']['custom_style'];
1031 + $form['options']['custom_style'] = $form['options']['old_style'];
1032 + self::update_custom_style_setting_on_import( $form );
1033 + $has_changed = $form['options']['custom_style'] != $saved_style && $form['options']['custom_style'] != $form['options']['old_style']; // phpcs:ignore Universal.Operators.StrictComparisons, SlevomatCodingStandard.Files.LineLength.LineTooLong
1034 +
1035 + if ( $has_changed ) {
1036 + FrmForm::update( $form['id'], $form );
1037 + }
818 1038 }
819 1039
820 - public static function import_xml_views( $views, $imported ) {
1040 + /**
1041 + * Handle import for all posts. This includes views, styles, pages, and form actions.
1042 + *
1043 + * @param SimpleXMLElement $views
1044 + * @param array $imported
1045 + *
1046 + * @return array
1047 + */
1048 + public static function import_xml_views( $views, $imported ) { // phpcs:ignore SlevomatCodingStandard.Complexity.Cognitive.ComplexityTooHigh
821 1049 $imported['posts'] = array();
822 1050 $form_action_type = FrmFormActionsController::$action_post_type;
823 1051
824 1052 $post_types = array(
@@ -855,8 +1083,13 @@
855 1083 );
856 1084
857 1085 $post['post_content'] = self::switch_form_ids( $post['post_content'], $imported['forms'] );
858 1086
1087 + // Fix issue with line breaks appearing in descriptions as "rn".
1088 + if ( $post['post_type'] === $form_action_type ) {
1089 + $post['post_content'] = str_replace( '\\\\r\\\\n', '\\r\\n', $post['post_content'] );
1090 + }
1091 +
859 1092 $old_id = $post['post_id'];
860 1093 self::populate_post( $post, $item, $imported );
861 1094
862 1095 unset( $item );
@@ -861,11 +1094,13 @@
861 1094
862 1095 unset( $item );
863 1096
864 1097 $post_id = false;
1098 +
865 1099 if ( $post['post_type'] === $form_action_type ) {
866 1100 $action_control = FrmFormActionsController::get_form_actions( $post['post_excerpt'] );
867 - if ( $action_control && is_object( $action_control ) ) {
1101 +
1102 + if ( $action_control && is_object( $action_control ) && isset( $imported['form_status'] ) ) {
868 1103 $post_id = $action_control->maybe_create_action( $post, $imported['form_status'] );
869 1104 }
870 1105 unset( $action_control );
871 1106 } elseif ( $post['post_type'] === 'frm_styles' ) {
@@ -871,8 +1106,10 @@
871 1106 } elseif ( $post['post_type'] === 'frm_styles' ) {
872 1107 // Properly encode post content before inserting the post
873 1108 $post['post_content'] = FrmAppHelper::maybe_json_decode( $post['post_content'] );
874 1109 $post['post_content'] = FrmAppHelper::prepare_and_encode( $post['post_content'] );
1110 + // Store template data additionally to a postmeta that can be used to revert the style to default template style.
1111 + $post['postmeta']['frm_style_default'] = $post['post_content'];
875 1112
876 1113 // Create/update post now
877 1114 $post_id = wp_insert_post( $post );
878 1115 } else {
@@ -882,15 +1119,15 @@
882 1119 $post['post_parent'] = $imported['posts'][ $post['post_parent'] ];
883 1120 }
884 1121 // Create/update post now
885 1122 $post_id = wp_insert_post( $post );
886 - }
1123 + }//end if
887 1124
888 1125 if ( ! is_numeric( $post_id ) ) {
889 1126 continue;
890 1127 }
891 1128
892 - if ( false !== strpos( $post['post_content'], '[display-frm-data' ) || false !== strpos( $post['post_content'], '[formidable' ) ) {
1129 + if ( str_contains( $post['post_content'], '[display-frm-data' ) || str_contains( $post['post_content'], '[formidable' ) ) {
893 1130 $posts_with_shortcodes[ $post_id ] = $post;
894 1131 }
895 1132
896 1133 self::update_postmeta( $post, $post_id );
@@ -896,28 +1133,29 @@
896 1133 self::update_postmeta( $post, $post_id );
897 1134 self::update_layout( $post, $post_id );
898 1135
899 1136 $this_type = 'posts';
1137 +
900 1138 if ( isset( $post_types[ $post['post_type'] ] ) ) {
901 1139 $this_type = $post_types[ $post['post_type'] ];
902 1140 }
903 1141
904 - if ( isset( $post['ID'] ) && $post_id == $post['ID'] ) {
905 - $imported['updated'][ $this_type ] ++;
1142 + if ( isset( $post['ID'] ) && (int) $post_id === (int) $post['ID'] ) {
1143 + ++$imported['updated'][ $this_type ];
906 1144 } else {
907 - $imported['imported'][ $this_type ] ++;
1145 + ++$imported['imported'][ $this_type ];
908 1146 }
909 1147
910 - $imported['posts'][ (int) $old_id ] = $post_id;
1148 + $imported['posts'][ $old_id ] = $post_id;
911 1149
912 1150 if ( $post['post_type'] === 'frm_display' ) {
913 - $view_ids[ (int) $old_id ] = $post_id;
1151 + $view_ids[ $old_id ] = $post_id;
914 1152 }
915 1153
916 1154 do_action( 'frm_after_import_view', $post_id, $post );
917 1155
918 1156 unset( $post );
919 - }
1157 + }//end foreach
920 1158
921 1159 if ( $posts_with_shortcodes && $view_ids ) {
922 1160 self::maybe_switch_view_ids_after_importing_posts( $posts_with_shortcodes, $view_ids );
923 1161 }
@@ -923,9 +1161,9 @@
923 1161 }
924 1162 unset( $posts_with_shortcodes, $view_ids );
925 1163
926 1164 if ( ! empty( $imported['forms'] ) ) {
927 - // clear imported forms style cache to make sure the new styles are applied to the forms
1165 + // Clear imported forms style cache to make sure the new styles are applied to the forms
928 1166 self::clear_forms_style_caches( $imported['forms'] );
929 1167 }
930 1168
931 1169 self::maybe_update_stylesheet( $imported );
@@ -938,12 +1176,14 @@
938 1176 /**
939 1177 * Clears styles from cache for imported forms
940 1178 *
941 1179 * @param array $imported_forms
1180 + *
1181 + * @return void
942 1182 */
943 1183 private static function clear_forms_style_caches( $imported_forms ) {
944 1184 $where = array(
945 - 'id' => $imported_forms,
1185 + 'id' => $imported_forms,
946 1186 'options LIKE' => '"old_style"',
947 1187 );
948 1188 $forms = FrmDb::get_results( 'frm_forms', $where );
949 1189
@@ -948,18 +1188,19 @@
948 1188 $forms = FrmDb::get_results( 'frm_forms', $where );
949 1189
950 1190 foreach ( $forms as $form ) {
951 1191 FrmAppHelper::unserialize_or_decode( $form->options );
1192 +
952 1193 if ( ! $form->options ) {
953 1194 continue;
954 1195 }
1196 +
955 1197 $where = array(
956 1198 'post_name' => $form->options['old_style'],
957 1199 'post_type' => FrmStylesController::$post_type,
958 1200 );
959 1201
960 - $select = 'ID';
961 -
1202 + $select = 'ID';
962 1203 $cache_key = FrmDb::generate_cache_key( $where, array( 'limit' => 1 ), $select, 'var' );
963 1204 FrmDb::delete_cache_and_transient( $cache_key, 'post' );
964 1205 }
965 1206 }
@@ -968,12 +1209,13 @@
968 1209 * Replace old form ids with new ones in a string.
969 1210 *
970 1211 * @param string $string
971 1212 * @param array<int> $form_ids new form ids indexed by old form id.
1213 + *
972 1214 * @return string
973 1215 */
974 1216 private static function switch_form_ids( $string, $form_ids ) {
975 - if ( false === strpos( $string, '[formidable' ) ) {
1217 + if ( ! str_contains( $string, '[formidable' ) ) {
976 1218 // Skip string replacing if there are no form shortcodes in string.
977 1219 return $string;
978 1220 }
979 1221
@@ -1000,13 +1242,15 @@
1000 1242
1001 1243 /**
1002 1244 * @param array<array> $posts_with_shortcodes indexed by current post id.
1003 1245 * @param array<int> $view_ids new view ids indexed by old view id.
1246 + *
1004 1247 * @return void
1005 1248 */
1006 1249 private static function maybe_switch_view_ids_after_importing_posts( $posts_with_shortcodes, $view_ids ) {
1007 1250 foreach ( $posts_with_shortcodes as $imported_post_id => $post ) {
1008 1251 $post_content = self::switch_view_ids( $post['post_content'], $view_ids );
1252 +
1009 1253 if ( $post_content === $post['post_content'] ) {
1010 1254 continue;
1011 1255 }
1012 1256
@@ -1023,12 +1267,13 @@
1023 1267 * Replace old view ids with new ones in a string.
1024 1268 *
1025 1269 * @param string $string
1026 1270 * @param array<int> $view_ids new view ids indexed by old view id.
1271 + *
1027 1272 * @return string
1028 1273 */
1029 1274 private static function switch_view_ids( $string, $view_ids ) {
1030 - if ( false === strpos( $string, '[display-frm-data' ) ) {
1275 + if ( ! str_contains( $string, '[display-frm-data' ) ) {
1031 1276 // Skip string replacing if there are no view shortcodes in string.
1032 1277 return $string;
1033 1278 }
1034 1279
@@ -1055,30 +1300,40 @@
1055 1300 }
1056 1301
1057 1302 /**
1058 1303 * @param string $content
1304 + *
1059 1305 * @return string
1060 1306 */
1061 1307 private static function maybe_prepare_json_view_content( $content ) {
1062 1308 $maybe_decoded = FrmAppHelper::maybe_json_decode( $content );
1309 +
1063 1310 if ( is_array( $maybe_decoded ) && isset( $maybe_decoded[0] ) && isset( $maybe_decoded[0]['box'] ) ) {
1064 1311 return FrmAppHelper::prepare_and_encode( $maybe_decoded );
1065 1312 }
1313 +
1066 1314 return $content;
1067 1315 }
1068 1316
1317 + /**
1318 + * @param array $post
1319 + * @param object $item
1320 + * @param array $imported
1321 + *
1322 + * @return void
1323 + */
1069 1324 private static function populate_post( &$post, $item, $imported ) {
1070 1325 if ( isset( $item->attachment_url ) ) {
1071 1326 $post['attachment_url'] = (string) $item->attachment_url;
1072 1327 }
1073 1328
1074 - if ( $post['post_type'] == FrmFormActionsController::$action_post_type && isset( $imported['forms'][ (int) $post['menu_order'] ] ) ) {
1075 - // update to new form id
1329 + if ( $post['post_type'] === FrmFormActionsController::$action_post_type && isset( $imported['forms'][ (int) $post['menu_order'] ] ) ) {
1330 + // Update to new form id
1076 1331 $post['menu_order'] = $imported['forms'][ (int) $post['menu_order'] ];
1077 1332 }
1078 1333
1079 1334 // Don't allow default styles to take over a site's default style
1080 - if ( 'frm_styles' == $post['post_type'] ) {
1335 + if ( 'frm_styles' === $post['post_type'] ) {
1081 1336 $post['menu_order'] = 0;
1082 1337 }
1083 1338
1084 1339 foreach ( $item->postmeta as $meta ) {
@@ -1100,9 +1355,9 @@
1100 1355 * @param array $post
1101 1356 * @param stdClass $meta
1102 1357 * @param array $imported
1103 1358 */
1104 - private static function populate_postmeta( &$post, $meta, $imported ) {
1359 + private static function populate_postmeta( &$post, $meta, $imported ) { // phpcs:ignore SlevomatCodingStandard.Complexity.Cognitive.ComplexityTooHigh, Generic.Metrics.CyclomaticComplexity.MaxExceeded, SlevomatCodingStandard.Files.LineLength.LineTooLong
1105 1360 global $frm_duplicate_ids;
1106 1361
1107 1362 $m = array(
1108 1363 'key' => (string) $meta->meta_key,
@@ -1108,20 +1363,19 @@
1108 1363 'key' => (string) $meta->meta_key,
1109 1364 'value' => (string) $meta->meta_value,
1110 1365 );
1111 1366
1112 - //switch old form and field ids to new ones
1367 + // Switch old form and field ids to new ones.
1113 1368 if ( 'frm_form_id' === $m['key'] && isset( $imported['forms'][ (int) $m['value'] ] ) ) {
1114 1369 $m['value'] = $imported['forms'][ (int) $m['value'] ];
1115 1370 } else {
1116 1371 $m['value'] = FrmAppHelper::maybe_json_decode( $m['value'] );
1117 1372
1118 - if ( ! empty( $frm_duplicate_ids ) ) {
1373 + if ( $frm_duplicate_ids ) {
1119 1374 if ( 'frm_dyncontent' === $m['key'] ) {
1120 1375 $m['value'] = self::maybe_prepare_json_view_content( $m['value'] );
1121 1376 $m['value'] = FrmFieldsHelper::switch_field_ids( $m['value'] );
1122 1377 } elseif ( 'frm_options' === $m['key'] ) {
1123 -
1124 1378 foreach ( array( 'date_field_id', 'edate_field_id' ) as $setting_name ) {
1125 1379 if ( isset( $m['value'][ $setting_name ] ) && is_numeric( $m['value'][ $setting_name ] ) && isset( $frm_duplicate_ids[ $m['value'][ $setting_name ] ] ) ) {
1126 1380 $m['value'][ $setting_name ] = $frm_duplicate_ids[ $m['value'][ $setting_name ] ];
1127 1381 }
@@ -1126,10 +1380,38 @@
1126 1380 $m['value'][ $setting_name ] = $frm_duplicate_ids[ $m['value'][ $setting_name ] ];
1127 1381 }
1128 1382 }
1129 1383
1384 + if ( ! empty( $m['value']['map_address_fields'] ) ) {
1385 + foreach ( $m['value']['map_address_fields'] as $address_field_key => $address_field_id ) {
1386 + if ( isset( $frm_duplicate_ids[ $address_field_id ] ) ) {
1387 + $m['value']['map_address_fields'][ $address_field_key ] = $frm_duplicate_ids[ $address_field_id ];
1388 + }
1389 + }
1390 + }
1391 +
1392 + if ( ! empty( $m['value']['calendar_options'] ) ) {
1393 + foreach ( $m['value']['calendar_options'] as $calendar_option_group_key => $calendar_option ) {
1394 + if ( isset( $frm_duplicate_ids[ $calendar_option['value'] ] ) ) {
1395 + $m['value']['calendar_options'][ $calendar_option_group_key ]['value'] = $frm_duplicate_ids[ $calendar_option['value'] ];
1396 + }
1397 + }
1398 + }
1399 +
1400 + if ( ! empty( $m['value']['timeline_options'] ) ) {
1401 + foreach ( $m['value']['timeline_options'] as $timeline_option_group_key => $timeline_group_option ) {
1402 + foreach ( $timeline_group_option as $timeline_option_key => $timeline_option ) {
1403 + // @mago-expect lint:excessive-nesting
1404 + if ( isset( $frm_duplicate_ids[ $timeline_option ] ) ) {
1405 + $m['value']['timeline_options'][ $timeline_option_group_key ][ $timeline_option_key ] = $frm_duplicate_ids[ $timeline_option ];
1406 + }
1407 + }
1408 + }
1409 + }
1410 +
1130 1411 $check_dup_array = array();
1131 - if ( isset( $m['value']['order_by'] ) && ! empty( $m['value']['order_by'] ) ) {
1412 +
1413 + if ( ! empty( $m['value']['order_by'] ) ) {
1132 1414 if ( is_numeric( $m['value']['order_by'] ) && isset( $frm_duplicate_ids[ $m['value']['order_by'] ] ) ) {
1133 1415 $m['value']['order_by'] = $frm_duplicate_ids[ $m['value']['order_by'] ];
1134 1416 } elseif ( is_array( $m['value']['order_by'] ) ) {
1135 1417 $check_dup_array[] = 'order_by';
@@ -1135,9 +1417,9 @@
1135 1417 $check_dup_array[] = 'order_by';
1136 1418 }
1137 1419 }
1138 1420
1139 - if ( isset( $m['value']['where'] ) && ! empty( $m['value']['where'] ) ) {
1421 + if ( ! empty( $m['value']['where'] ) ) {
1140 1422 $check_dup_array[] = 'where';
1141 1423 }
1142 1424
1143 1425 foreach ( $check_dup_array as $check_k ) {
@@ -1147,11 +1429,11 @@
1147 1429 }
1148 1430 unset( $mk, $mv );
1149 1431 }
1150 1432 }
1151 - }
1152 - }
1153 - }
1433 + }//end if
1434 + }//end if
1435 + }//end if
1154 1436
1155 1437 if ( ! is_array( $m['value'] ) ) {
1156 1438 $m['value'] = FrmAppHelper::maybe_json_decode( $m['value'] );
1157 1439 }
@@ -1158,8 +1440,14 @@
1158 1440
1159 1441 $post['postmeta'][ (string) $meta->meta_key ] = $m['value'];
1160 1442 }
1161 1443
1444 + /**
1445 + * @param array $post
1446 + * @param object $layout
1447 + *
1448 + * @return void
1449 + */
1162 1450 private static function populate_layout( &$post, $layout ) {
1163 1451 $post['layout'][ (string) $layout->type ] = (string) $layout->data;
1164 1452 }
1165 1453
@@ -1165,22 +1453,25 @@
1165 1453
1166 1454 /**
1167 1455 * Add terms to post
1168 1456 *
1169 - * @param array $post by reference
1170 - * @param object $item The XML object data
1457 + * @param array $post By reference.
1458 + * @param object $item The XML object data.
1171 1459 */
1172 1460 private static function populate_taxonomies( &$post, $item ) {
1173 1461 foreach ( $item->category as $c ) {
1174 1462 $att = $c->attributes();
1463 +
1175 1464 if ( ! isset( $att['nicename'] ) ) {
1176 1465 continue;
1177 1466 }
1178 1467
1179 1468 $taxonomy = (string) $att['domain'];
1469 +
1180 1470 if ( is_taxonomy_hierarchical( $taxonomy ) ) {
1181 1471 $name = (string) $att['nicename'];
1182 1472 $h_term = get_term_by( 'slug', $name, $taxonomy );
1473 +
1183 1474 if ( $h_term ) {
1184 1475 $name = $h_term->term_id;
1185 1476 }
1186 1477 unset( $h_term );
@@ -1193,13 +1484,17 @@
1193 1484 }
1194 1485
1195 1486 $post['tax_input'][ $taxonomy ][] = $name;
1196 1487 unset( $name );
1197 - }
1488 + }//end foreach
1198 1489 }
1199 1490
1200 1491 /**
1201 - * Edit post if the key and created time match
1492 + * Edit post if the key and created time match.
1493 + *
1494 + * @param array $post By reference.
1495 + *
1496 + * @return void
1202 1497 */
1203 1498 private static function maybe_editing_post( &$post ) {
1204 1499 $match_by = array(
1205 1500 'post_type' => $post['post_type'],
@@ -1207,9 +1502,9 @@
1207 1502 'post_status' => $post['post_status'],
1208 1503 'posts_per_page' => 1,
1209 1504 );
1210 1505
1211 - if ( in_array( $post['post_status'], array( 'trash', 'draft' ) ) ) {
1506 + if ( in_array( $post['post_status'], array( 'trash', 'draft' ), true ) ) {
1212 1507 $match_by['include'] = $post['post_id'];
1213 1508 unset( $match_by['name'] );
1214 1509 }
1215 1510
@@ -1214,10 +1509,11 @@
1214 1509 }
1215 1510
1216 1511 $editing = get_posts( $match_by );
1217 1512
1218 - if ( ! empty( $editing ) && current( $editing )->post_date == $post['post_date'] ) {
1219 - // set the id of the post to edit
1513 + // phpcs:ignore Universal.Operators.StrictComparisons
1514 + if ( $editing && current( $editing )->post_date == $post['post_date'] ) {
1515 + // Set the id of the post to edit
1220 1516 $post['ID'] = current( $editing )->ID;
1221 1517 }
1222 1518 }
1223 1519
@@ -1223,8 +1519,9 @@
1223 1519
1224 1520 /**
1225 1521 * @param array $post
1226 1522 * @param int $post_id
1523 + *
1227 1524 * @return void
1228 1525 */
1229 1526 private static function update_postmeta( &$post, $post_id ) {
1230 1527 foreach ( $post['postmeta'] as $k => $v ) {
@@ -1249,13 +1546,13 @@
1249 1546
1250 1547 case 'frm_param':
1251 1548 add_rewrite_endpoint( $v, EP_PERMALINK | EP_PAGES );
1252 1549 break;
1253 - }
1550 + }//end switch
1254 1551
1255 1552 update_post_meta( $post_id, $k, $v );
1256 1553 unset( $k, $v );
1257 - }
1554 + }//end foreach
1258 1555 }
1259 1556
1260 1557 /**
1261 1558 * @param array $post
@@ -1261,33 +1558,49 @@
1261 1558 * @param array $post
1262 1559 * @param int $post_id
1263 1560 */
1264 1561 private static function update_layout( &$post, $post_id ) {
1265 - if ( is_callable( 'FrmViewsLayout::maybe_create_layouts_for_view' ) ) {
1266 - $listing_layout = ! empty( $post['layout']['listing'] ) ? json_decode( $post['layout']['listing'], true ) : array();
1267 - $detail_layout = ! empty( $post['layout']['detail'] ) ? json_decode( $post['layout']['detail'], true ) : array();
1268 - if ( $listing_layout || $detail_layout ) {
1269 - FrmViewsLayout::maybe_create_layouts_for_view( $post_id, $listing_layout, $detail_layout );
1270 - }
1562 + if ( ! is_callable( 'FrmViewsLayout::maybe_create_layouts_for_view' ) ) {
1563 + return;
1271 1564 }
1565 +
1566 + $listing_layout = ! empty( $post['layout']['listing'] ) ? json_decode( $post['layout']['listing'], true ) : array();
1567 + $detail_layout = ! empty( $post['layout']['detail'] ) ? json_decode( $post['layout']['detail'], true ) : array();
1568 +
1569 + if ( $listing_layout || $detail_layout ) {
1570 + FrmViewsLayout::maybe_create_layouts_for_view( $post_id, $listing_layout, $detail_layout );
1571 + }
1272 1572 }
1273 1573
1574 + /**
1575 + * @param array $imported
1576 + *
1577 + * @return void
1578 + */
1274 1579 private static function maybe_update_stylesheet( $imported ) {
1275 - $new_styles = isset( $imported['imported']['styles'] ) && ! empty( $imported['imported']['styles'] );
1276 - $updated_styles = isset( $imported['updated']['styles'] ) && ! empty( $imported['updated']['styles'] );
1277 - if ( $new_styles || $updated_styles ) {
1278 - if ( is_admin() && function_exists( 'get_filesystem_method' ) ) {
1279 - $frm_style = new FrmStyle();
1280 - $frm_style->update( 'default' );
1281 - }
1282 - foreach ( $imported['forms'] as $form_id ) {
1283 - self::update_custom_style_setting_after_import( $form_id );
1284 - }
1580 + $new_styles = ! empty( $imported['imported']['styles'] );
1581 + $updated_styles = ! empty( $imported['updated']['styles'] );
1582 +
1583 + if ( ! $new_styles && ! $updated_styles ) {
1584 + return;
1285 1585 }
1586 +
1587 + if ( is_admin() && function_exists( 'get_filesystem_method' ) ) {
1588 + $frm_style = new FrmStyle();
1589 + $frm_style->update( 'default' );
1590 + }
1591 +
1592 + foreach ( $imported['forms'] as $form_id ) {
1593 + self::update_custom_style_setting_after_import( $form_id );
1594 + }
1286 1595 }
1287 1596
1288 1597 /**
1598 + * @param mixed $result
1289 1599 * @param string $message
1600 + * @param array $errors
1601 + *
1602 + * @return void
1290 1603 */
1291 1604 public static function parse_message( $result, &$message, &$errors ) {
1292 1605 if ( is_wp_error( $result ) ) {
1293 1606 $errors[] = $result->get_error_message();
@@ -1293,15 +1606,16 @@
1293 1606 $errors[] = $result->get_error_message();
1294 1607
1295 1608 // Remove the SimpleXML_parse_error from the WP_Error object to avoid
1296 1609 // displaying duplicate error messages from $result->get_error_message()
1297 - $error_codes = $result->get_error_codes();
1298 1610 $error_details = array();
1299 - foreach ( $error_codes as $error_code ) {
1611 +
1612 + foreach ( $result->get_error_codes() as $error_code ) {
1300 1613 // Clone WP_Error data because WP_Error removes all error messages and data
1301 - // associated with the specified error code when an item is removed.
1614 + // Associated with the specified error code when an item is removed.
1302 1615 // Source: https://developer.wordpress.org/reference/classes/wp_error/remove/#source
1303 1616 $error_details = $result->get_error_data( $error_code );
1617 +
1304 1618 if ( $error_code === 'SimpleXML_parse_error' ) {
1305 1619 $result->remove( $error_code );
1306 1620 break;
1307 1621 }
@@ -1306,20 +1620,21 @@
1306 1620 break;
1307 1621 }
1308 1622 }
1309 1623
1310 - if ( ! empty( $error_details ) ) {
1624 + if ( $error_details ) {
1311 1625 $errors[] = '<br />' . esc_html_x( 'Error details:', 'import xml message', 'formidable' ) . '<br />' . esc_html( print_r( $error_details, 1 ) );
1312 1626 }
1313 1627
1314 1628 return;
1315 - } elseif ( ! $result ) {
1629 + }//end if
1630 +
1631 + if ( ! $result ) {
1316 1632 return;
1317 1633 }
1318 1634
1319 1635 if ( ! is_array( $result ) ) {
1320 1636 $message = is_string( $result ) ? $result : htmlentities( print_r( $result, 1 ) );
1321 -
1322 1637 return;
1323 1638 }
1324 1639
1325 1640 $t_strings = array(
@@ -1327,42 +1642,48 @@
1327 1642 'updated' => __( 'Updated', 'formidable' ),
1328 1643 );
1329 1644
1330 1645 $message = '<ul>';
1646 +
1331 1647 foreach ( $result as $type => $results ) {
1332 1648 if ( ! isset( $t_strings[ $type ] ) ) {
1333 - // only print imported and updated
1649 + // Only print imported and updated
1334 1650 continue;
1335 1651 }
1336 1652
1337 1653 $s_message = array();
1654 +
1338 1655 foreach ( $results as $k => $m ) {
1339 1656 self::item_count_message( $m, $k, $s_message );
1340 1657 unset( $k, $m );
1341 1658 }
1342 1659
1343 - if ( ! empty( $s_message ) ) {
1344 - $message .= '<li><strong>' . $t_strings[ $type ] . ':</strong> ';
1345 - $message .= implode( ', ', $s_message );
1346 - $message .= '</li>';
1660 + if ( ! $s_message ) {
1661 + continue;
1347 1662 }
1348 - }
1349 1663
1350 - if ( $message == '<ul>' ) {
1664 + $message .= '<li><strong>' . $t_strings[ $type ] . ':</strong> ';
1665 + $message .= implode( ', ', $s_message );
1666 + $message .= '</li>';
1667 + }//end foreach
1668 +
1669 + if ( $message === '<ul>' ) {
1351 1670 $message = '';
1352 1671 $errors[] = __( 'Nothing was imported or updated', 'formidable' );
1353 - } else {
1354 - self::add_form_link_to_message( $result, $message );
1355 1672
1356 - /**
1357 - * @since 5.3
1358 - *
1359 - * @param string $message
1360 - * @param array $result
1361 - */
1362 - $message = apply_filters( 'frm_xml_parsed_message', $message, $result );
1363 - $message .= '</ul>';
1673 + return;
1364 1674 }
1675 +
1676 + self::add_form_link_to_message( $result, $message );
1677 +
1678 + /**
1679 + * @since 5.3
1680 + *
1681 + * @param string $message
1682 + * @param array $result
1683 + */
1684 + $message = apply_filters( 'frm_xml_parsed_message', $message, $result );
1685 + $message .= '</ul>';
1365 1686 }
1366 1687
1367 1688 /**
1368 1689 * @param int $m
@@ -1367,8 +1688,10 @@
1367 1688 /**
1368 1689 * @param int $m
1369 1690 * @param string $type
1370 1691 * @param array<string> $s_message
1692 + *
1693 + * @return void
1371 1694 */
1372 1695 public static function item_count_message( $m, $type, &$s_message ) {
1373 1696 if ( ! $m ) {
1374 1697 return;
@@ -1394,21 +1717,22 @@
1394 1717 );
1395 1718
1396 1719 if ( isset( $strings[ $type ] ) ) {
1397 1720 $s_message[] = $strings[ $type ];
1398 - } else {
1399 - $string = ' ' . $m . ' ' . ucfirst( $type );
1721 + return;
1722 + }
1400 1723
1401 - /**
1402 - * @since 5.3
1403 - *
1404 - * @param string $string Message string for imported item.
1405 - * @param int $m Number of item that was imported.
1406 - * }
1407 - */
1408 - $string = apply_filters( 'frm_xml_' . $type . '_count_message', $string, $m );
1409 - $s_message[] = $string;
1410 - }
1724 + $string = ' ' . $m . ' ' . ucfirst( $type );
1725 +
1726 + /**
1727 + * @since 5.3
1728 + *
1729 + * @param string $string Message string for imported item.
1730 + * @param int $m Number of item that was imported.
1731 + * }
1732 + */
1733 + $string = apply_filters( 'frm_xml_' . $type . '_count_message', $string, $m );
1734 + $s_message[] = $string;
1411 1735 }
1412 1736
1413 1737 /**
1414 1738 * If a single form was imported, include a link in the success message.
@@ -1413,24 +1737,28 @@
1413 1737 /**
1414 1738 * If a single form was imported, include a link in the success message.
1415 1739 *
1416 1740 * @since 4.0
1741 + *
1417 1742 * @param array $result The response from the XML import.
1418 1743 * @param string $message The response shown on the page after import.
1419 1744 */
1420 1745 private static function add_form_link_to_message( $result, &$message ) {
1421 1746 $total_forms = $result['imported']['forms'] + $result['updated']['forms'];
1747 +
1422 1748 if ( $total_forms > 1 ) {
1423 1749 return;
1424 1750 }
1425 1751
1426 1752 $primary_form = reset( $result['forms'] );
1427 - if ( ! empty( $primary_form ) ) {
1428 - $primary_form = FrmForm::getOne( $primary_form );
1429 - $form_id = empty( $primary_form->parent_form_id ) ? $primary_form->id : $primary_form->parent_form_id;
1430 1753
1431 - $message .= '<li><a href="' . esc_url( FrmForm::get_edit_link( $form_id ) ) . '">' . esc_html__( 'Go to imported form', 'formidable' ) . '</a></li>';
1754 + if ( ! $primary_form ) {
1755 + return;
1432 1756 }
1757 +
1758 + $primary_form = FrmForm::getOne( $primary_form );
1759 + $form_id = ! empty( $primary_form->parent_form_id ) ? $primary_form->parent_form_id : $primary_form->id;
1760 + $message .= '<li><a href="' . esc_url( FrmForm::get_edit_link( $form_id ) ) . '">' . esc_html__( 'Go to imported form', 'formidable' ) . '</a></li>';
1433 1761 }
1434 1762
1435 1763 /**
1436 1764 * Prepare the form options for export
@@ -1443,22 +1771,17 @@
1443 1771 */
1444 1772 public static function prepare_form_options_for_export( $options ) {
1445 1773 FrmAppHelper::unserialize_or_decode( $options );
1446 1774 // Change custom_style to the post_name instead of ID (1 may be a string)
1447 - $not_default = isset( $options['custom_style'] ) && 1 != $options['custom_style'];
1775 + $not_default = isset( $options['custom_style'] ) && 1 != $options['custom_style']; // phpcs:ignore Universal.Operators.StrictComparisons
1776 +
1448 1777 if ( $not_default ) {
1449 1778 global $wpdb;
1450 - $table = $wpdb->prefix . 'posts';
1451 - $where = array( 'ID' => $options['custom_style'] );
1452 - $select = 'post_name';
1453 -
1454 - $style_name = FrmDb::get_var( $table, $where, $select );
1455 -
1456 - if ( $style_name ) {
1457 - $options['custom_style'] = $style_name;
1458 - } else {
1459 - $options['custom_style'] = 1;
1460 - }
1779 + $table = $wpdb->prefix . 'posts';
1780 + $where = array( 'ID' => $options['custom_style'] );
1781 + $select = 'post_name';
1782 + $style_name = FrmDb::get_var( $table, $where, $select );
1783 + $options['custom_style'] = $style_name ? $style_name : 1;
1461 1784 }
1462 1785 self::remove_default_form_options( $options );
1463 1786 $options = serialize( $options );
1464 1787
@@ -1469,11 +1792,16 @@
1469 1792 * If the saved value is the same as the default, remove it from the export
1470 1793 * This keeps file size down and prevents overriding global settings after import
1471 1794 *
1472 1795 * @since 3.06
1796 + *
1797 + * @param array $options By reference.
1798 + *
1799 + * @return void
1473 1800 */
1474 1801 private static function remove_default_form_options( &$options ) {
1475 1802 $defaults = FrmFormsHelper::get_default_opts();
1803 +
1476 1804 if ( is_callable( 'FrmProFormsHelper::get_default_opts' ) ) {
1477 1805 $defaults += FrmProFormsHelper::get_default_opts();
1478 1806 }
1479 1807 self::remove_defaults( $defaults, $options );
@@ -1482,8 +1810,12 @@
1482 1810 /**
1483 1811 * Remove extra settings from field to keep file size down
1484 1812 *
1485 1813 * @since 3.06
1814 + *
1815 + * @param object $field
1816 + *
1817 + * @return void
1486 1818 */
1487 1819 public static function prepare_field_for_export( &$field ) {
1488 1820 self::remove_default_field_options( $field );
1489 1821 self::add_image_src_to_image_options( $field );
@@ -1492,11 +1824,16 @@
1492 1824 /**
1493 1825 * Remove defaults from field options too
1494 1826 *
1495 1827 * @since 3.06
1828 + *
1829 + * @param object $field
1830 + *
1831 + * @return void
1496 1832 */
1497 1833 private static function remove_default_field_options( &$field ) {
1498 1834 $defaults = self::default_field_options( $field->type );
1835 +
1499 1836 if ( empty( $defaults['blank'] ) ) {
1500 1837 $global_settings = new FrmSettings();
1501 1838 $global_defaults = $global_settings->default_options();
1502 1839 $defaults['blank'] = $global_defaults['blank_msg'];
@@ -1524,12 +1861,13 @@
1524 1861 *
1525 1862 * @since 5.5.1
1526 1863 *
1527 1864 * @param stdClass $field
1865 + *
1528 1866 * @return void
1529 1867 */
1530 1868 private static function add_image_src_to_image_options( $field ) {
1531 - if ( empty( $field->options ) || false === strpos( $field->options, 'image' ) ) {
1869 + if ( empty( $field->options ) || ! str_contains( $field->options, 'image' ) ) {
1532 1870 return;
1533 1871 }
1534 1872
1535 1873 $updated = false;
@@ -1540,12 +1878,14 @@
1540 1878 return;
1541 1879 }
1542 1880
1543 1881 foreach ( $options as $key => $option ) {
1544 - if ( is_array( $option ) && ! empty( $option['image'] ) ) {
1545 - $options[ $key ]['src'] = wp_get_attachment_url( $option['image'] );
1546 - $updated = true;
1882 + if ( ! is_array( $option ) || empty( $option['image'] ) ) {
1883 + continue;
1547 1884 }
1885 +
1886 + $options[ $key ]['src'] = wp_get_attachment_url( $option['image'] );
1887 + $updated = true;
1548 1888 }
1549 1889
1550 1890 if ( $updated ) {
1551 1891 $field->options = maybe_serialize( $options );
@@ -1553,14 +1893,20 @@
1553 1893 }
1554 1894
1555 1895 /**
1556 1896 * @since 3.06.03
1897 + *
1898 + * @param string $type
1899 + *
1900 + * @return array
1557 1901 */
1558 1902 private static function default_field_options( $type ) {
1559 1903 $defaults = FrmFieldsHelper::get_default_field_options( $type );
1904 +
1560 1905 if ( empty( $defaults['custom_html'] ) ) {
1561 1906 $defaults['custom_html'] = FrmFieldsHelper::get_default_html( $type );
1562 1907 }
1908 +
1563 1909 return $defaults;
1564 1910 }
1565 1911
1566 1912 /**
@@ -1567,8 +1913,13 @@
1567 1913 * Compare the default array to the saved values and
1568 1914 * remove if they are the same
1569 1915 *
1570 1916 * @since 3.06
1917 + *
1918 + * @param array $defaults
1919 + * @param array $saved
1920 + *
1921 + * @return void
1571 1922 */
1572 1923 private static function remove_defaults( $defaults, &$saved ) {
1573 1924 foreach ( $saved as $key => $value ) {
1574 1925 if ( isset( $defaults[ $key ] ) && $defaults[ $key ] === $value ) {
@@ -1580,8 +1931,14 @@
1580 1931 /**
1581 1932 * The line endings may prevent html from being equal when it should
1582 1933 *
1583 1934 * @since 3.06
1935 + *
1936 + * @param string $html_name
1937 + * @param array $defaults
1938 + * @param array $options
1939 + *
1940 + * @return void
1584 1941 */
1585 1942 private static function remove_default_html( $html_name, $defaults, &$options ) {
1586 1943 if ( ! isset( $options[ $html_name ] ) || ! isset( $defaults[ $html_name ] ) ) {
1587 1944 return;
@@ -1588,26 +1945,34 @@
1588 1945 }
1589 1946
1590 1947 $old_html = str_replace( "\r\n", "\n", $options[ $html_name ] );
1591 1948 $default_html = $defaults[ $html_name ];
1949 +
1950 + // phpcs:ignore Universal.Operators.StrictComparisons
1592 1951 if ( $old_html == $default_html ) {
1593 1952 unset( $options[ $html_name ] );
1594 -
1595 1953 return;
1596 1954 }
1597 1955
1598 1956 // Account for some of the older field default HTML.
1599 1957 $default_html = str_replace( ' id="frm_desc_field_[key]"', '', $default_html );
1600 - if ( $old_html == $default_html ) {
1958 +
1959 + if ( $old_html === $default_html ) {
1601 1960 unset( $options[ $html_name ] );
1602 1961 }
1603 1962 }
1604 1963
1964 + /**
1965 + * @param string $str
1966 + *
1967 + * @return string
1968 + */
1605 1969 public static function cdata( $str ) {
1606 1970 FrmAppHelper::unserialize_or_decode( $str );
1971 +
1607 1972 if ( is_array( $str ) ) {
1608 1973 $str = json_encode( $str );
1609 - } elseif ( seems_utf8( $str ) === false ) {
1974 + } elseif ( FrmAppHelper::is_valid_utf8( $str ) === false ) {
1610 1975 $str = FrmAppHelper::maybe_utf8_encode( $str );
1611 1976 }
1612 1977
1613 1978 if ( is_numeric( $str ) ) {
@@ -1616,11 +1981,9 @@
1616 1981
1617 1982 self::remove_invalid_characters_from_xml( $str );
1618 1983
1619 1984 // $str = ent2ncr(esc_html( $str));
1620 - $str = '<![CDATA[' . str_replace( ']]>', ']]]]><![CDATA[>', $str ) . ']]>';
1621 -
1622 - return $str;
1985 + return '<![CDATA[' . str_replace( ']]>', ']]]]><![CDATA[>', $str ) . ']]>';
1623 1986 }
1624 1987
1625 1988 /**
1626 1989 * Remove <US> character (unit separator) from exported strings
@@ -1627,8 +1990,10 @@
1627 1990 *
1628 1991 * @since 2.0.22
1629 1992 *
1630 1993 * @param string $str
1994 + *
1995 + * @return void
1631 1996 */
1632 1997 private static function remove_invalid_characters_from_xml( &$str ) {
1633 1998 // Remove <US> character
1634 1999 $str = str_replace( '\x1F', '', $str );
@@ -1633,8 +1998,18 @@
1633 1998 // Remove <US> character
1634 1999 $str = str_replace( '\x1F', '', $str );
1635 2000 }
1636 2001
2002 + /**
2003 + * Migrate form settings to actions
2004 + *
2005 + * @param array $form_options
2006 + * @param int $form_id
2007 + * @param array $imported
2008 + * @param bool $switch
2009 + *
2010 + * @return void
2011 + */
1637 2012 public static function migrate_form_settings_to_actions( $form_options, $form_id, &$imported = array(), $switch = false ) {
1638 2013 // Get post type
1639 2014 $post_type = FrmFormActionsController::$action_post_type;
1640 2015
@@ -1652,12 +2027,16 @@
1652 2027
1653 2028 /**
1654 2029 * Migrate post settings to form action
1655 2030 *
2031 + * @param array $form_options
2032 + * @param int $form_id
1656 2033 * @param string $post_type
2034 + * @param array $imported
2035 + * @param bool $switch
1657 2036 */
1658 2037 private static function migrate_post_settings_to_action( $form_options, $form_id, $post_type, &$imported, $switch ) {
1659 - if ( ! isset( $form_options['create_post'] ) || ! $form_options['create_post'] ) {
2038 + if ( empty( $form_options['create_post'] ) ) {
1660 2039 return;
1661 2040 }
1662 2041
1663 2042 $new_action = array(
@@ -1709,8 +2088,9 @@
1709 2088 $array_fields = array( 'post_category', 'post_custom_fields' );
1710 2089
1711 2090 $new_action['post_content'] = self::switch_action_field_ids( $new_action['post_content'], $basic_fields, $array_fields );
1712 2091 }
2092 +
1713 2093 $new_action['post_content'] = json_encode( $new_action['post_content'] );
1714 2094
1715 2095 $exists = get_posts(
1716 2096 array(
@@ -1720,13 +2100,15 @@
1720 2100 'numberposts' => 1,
1721 2101 )
1722 2102 );
1723 2103
1724 - if ( ! $exists ) {
1725 - // this isn't an email, but we need to use a class that will always be included
1726 - FrmDb::save_json_post( $new_action );
1727 - $imported['imported']['actions'] ++;
2104 + if ( $exists ) {
2105 + return;
1728 2106 }
2107 +
2108 + // This isn't an email, but we need to use a class that will always be included
2109 + FrmDb::save_json_post( $new_action );
2110 + ++$imported['imported']['actions'];
1729 2111 }
1730 2112
1731 2113 /**
1732 2114 * Switch old field IDs for new field IDs in emails and post
@@ -1732,11 +2114,11 @@
1732 2114 * Switch old field IDs for new field IDs in emails and post
1733 2115 *
1734 2116 * @since 2.0
1735 2117 *
1736 - * @param array $post_content - check for old field IDs
1737 - * @param array $basic_fields - fields with string or int saved
1738 - * @param array $array_fields - fields with arrays saved
2118 + * @param array $post_content Check for old field IDs.
2119 + * @param array $basic_fields Fields with string or int saved.
2120 + * @param array $array_fields Fields with arrays saved.
1739 2121 *
1740 2122 * @return string $post_content - new field IDs
1741 2123 */
1742 2124 private static function switch_action_field_ids( $post_content, $basic_fields, $array_fields = array() ) {
@@ -1743,9 +2125,9 @@
1743 2125 global $frm_duplicate_ids;
1744 2126
1745 2127 // If there aren't IDs that were switched, end now
1746 2128 if ( ! $frm_duplicate_ids ) {
1747 - return;
2129 + return null;
1748 2130 }
1749 2131
1750 2132 // Get old IDs
1751 2133 $old = array_keys( $frm_duplicate_ids );
@@ -1754,11 +2136,13 @@
1754 2136 $new = array_values( $frm_duplicate_ids );
1755 2137
1756 2138 // Do a str_replace with each item to set the new IDs
1757 2139 foreach ( $post_content as $key => $setting ) {
2140 + // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
1758 2141 if ( ! is_array( $setting ) && in_array( $key, $basic_fields ) ) {
1759 2142 // Replace old IDs with new IDs
1760 2143 $post_content[ $key ] = str_replace( $old, $new, $setting );
2144 + // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
1761 2145 } elseif ( is_array( $setting ) && in_array( $key, $array_fields ) ) {
1762 2146 foreach ( $setting as $k => $val ) {
1763 2147 // Replace old IDs with new IDs
1764 2148 $post_content[ $key ][ $k ] = str_replace( $old, $new, $val );
@@ -1769,8 +2153,19 @@
1769 2153
1770 2154 return $post_content;
1771 2155 }
1772 2156
2157 + /**
2158 + * Migrate email settings to action
2159 + *
2160 + * @param array $form_options
2161 + * @param int $form_id
2162 + * @param string $post_type
2163 + * @param array $imported
2164 + * @param bool $switch
2165 + *
2166 + * @return void
2167 + */
1773 2168 private static function migrate_email_settings_to_action( $form_options, $form_id, $post_type, &$imported, $switch ) {
1774 2169 // No old notifications or autoresponders to carry over
1775 2170 if ( ! isset( $form_options['auto_responder'] ) && ! isset( $form_options['notification'] ) && ! isset( $form_options['email_to'] ) ) {
1776 2171 return;
@@ -1784,9 +2179,9 @@
1784 2179
1785 2180 // Migrate autoresponders
1786 2181 self::migrate_autoresponder_to_action( $form_options, $form_id, $notifications );
1787 2182
1788 - if ( empty( $notifications ) ) {
2183 + if ( ! $notifications ) {
1789 2184 return;
1790 2185 }
1791 2186
1792 2187 foreach ( $notifications as $new_notification ) {
@@ -1797,9 +2192,8 @@
1797 2192 $new_notification['post_status'] = 'publish';
1798 2193
1799 2194 // Switch field IDs and keys, if needed
1800 2195 if ( $switch ) {
1801 -
1802 2196 // Switch field IDs in email conditional logic
1803 2197 self::switch_email_condition_field_ids( $new_notification['post_content'] );
1804 2198
1805 2199 // Switch all other field IDs in email
@@ -1804,8 +2198,9 @@
1804 2198
1805 2199 // Switch all other field IDs in email
1806 2200 $new_notification['post_content'] = FrmFieldsHelper::switch_field_ids( $new_notification['post_content'] );
1807 2201 }
2202 +
1808 2203 $new_notification['post_content'] = FrmAppHelper::prepare_and_encode( $new_notification['post_content'] );
1809 2204
1810 2205 $exists = get_posts(
1811 2206 array(
@@ -1815,14 +2210,14 @@
1815 2210 'numberposts' => 1,
1816 2211 )
1817 2212 );
1818 2213
1819 - if ( empty( $exists ) ) {
2214 + if ( ! $exists ) {
1820 2215 FrmDb::save_json_post( $new_notification );
1821 - $imported['imported']['actions'] ++;
2216 + ++$imported['imported']['actions'];
1822 2217 }
1823 2218 unset( $new_notification );
1824 - }
2219 + }//end foreach
1825 2220
1826 2221 self::remove_deprecated_notification_settings( $form_id, $form_options );
1827 2222 }
1828 2223
@@ -1831,32 +2226,44 @@
1831 2226 *
1832 2227 * @since 2.05
1833 2228 *
1834 2229 * @param int|string $form_id
1835 - * @param array $form_options
2230 + * @param array $form_options
2231 + *
2232 + * @return void
1836 2233 */
1837 2234 private static function remove_deprecated_notification_settings( $form_id, $form_options ) {
1838 2235 $delete_settings = array( 'notification', 'autoresponder', 'email_to' );
2236 +
1839 2237 foreach ( $delete_settings as $index ) {
1840 2238 if ( isset( $form_options[ $index ] ) ) {
1841 2239 unset( $form_options[ $index ] );
1842 2240 }
1843 2241 }
2242 +
1844 2243 FrmForm::update( $form_id, array( 'options' => $form_options ) );
1845 2244 }
1846 2245
2246 + /**
2247 + * Migrate notifications to action
2248 + *
2249 + * @param array $form_options
2250 + * @param int $form_id
2251 + * @param array $notifications
2252 + *
2253 + * @return void
2254 + */
1847 2255 private static function migrate_notifications_to_action( $form_options, $form_id, &$notifications ) {
1848 - if ( ! isset( $form_options['notification'] ) && isset( $form_options['email_to'] ) && ! empty( $form_options['email_to'] ) ) {
1849 - // add old settings into notification array
2256 + if ( ! isset( $form_options['notification'] ) && ! empty( $form_options['email_to'] ) ) {
2257 + // Add old settings into notification array
1850 2258 $form_options['notification'] = array( 0 => $form_options );
1851 2259 } elseif ( isset( $form_options['notification']['email_to'] ) ) {
1852 - // make sure it's in the correct format
2260 + // Make sure it's in the correct format
1853 2261 $form_options['notification'] = array( 0 => $form_options['notification'] );
1854 2262 }
1855 2263
1856 2264 if ( isset( $form_options['notification'] ) && is_array( $form_options['notification'] ) ) {
1857 2265 foreach ( $form_options['notification'] as $email_key => $notification ) {
1858 -
1859 2266 $atts = array(
1860 2267 'email_to' => '',
1861 2268 'reply_to' => '',
1862 2269 'reply_to_name' => '',
@@ -1867,9 +2274,9 @@
1867 2274
1868 2275 // Format the email data
1869 2276 self::format_email_data( $atts, $notification );
1870 2277
1871 - if ( isset( $notification['twilio'] ) && $notification['twilio'] ) {
2278 + if ( ! empty( $notification['twilio'] ) ) {
1872 2279 do_action( 'frm_create_twilio_action', $atts, $notification );
1873 2280 }
1874 2281
1875 2282 // Setup the new notification
@@ -1876,12 +2283,20 @@
1876 2283 $new_notification = array();
1877 2284 self::setup_new_notification( $new_notification, $notification, $atts );
1878 2285
1879 2286 $notifications[] = $new_notification;
1880 - }
1881 - }
2287 + }//end foreach
2288 + }//end if
1882 2289 }
1883 2290
2291 + /**
2292 + * Format email data
2293 + *
2294 + * @param array $atts
2295 + * @param array $notification
2296 + *
2297 + * @return void
2298 + */
1884 2299 private static function format_email_data( &$atts, $notification ) {
1885 2300 // Format email_to
1886 2301 self::format_email_to_data( $atts, $notification );
1887 2302
@@ -1889,14 +2304,16 @@
1889 2304 $reply_fields = array(
1890 2305 'reply_to' => '',
1891 2306 'reply_to_name' => '',
1892 2307 );
2308 +
1893 2309 foreach ( $reply_fields as $f => $val ) {
1894 2310 if ( isset( $notification[ $f ] ) ) {
1895 2311 $atts[ $f ] = $notification[ $f ];
1896 - if ( 'custom' == $notification[ $f ] ) {
2312 +
2313 + if ( 'custom' === $notification[ $f ] ) {
1897 2314 $atts[ $f ] = $notification[ 'cust_' . $f ];
1898 - } elseif ( is_numeric( $atts[ $f ] ) && ! empty( $atts[ $f ] ) ) {
2315 + } elseif ( is_numeric( $atts[ $f ] ) && $atts[ $f ] ) {
1899 2316 $atts[ $f ] = '[' . $atts[ $f ] . ']';
1900 2317 }
1901 2318 }
1902 2319 unset( $f, $val );
@@ -1903,21 +2320,27 @@
1903 2320 }
1904 2321
1905 2322 // Format event
1906 2323 $atts['event'] = array( 'create' );
2324 +
2325 + // phpcs:ignore Universal.Operators.StrictComparisons
1907 2326 if ( isset( $notification['update_email'] ) && 1 == $notification['update_email'] ) {
1908 2327 $atts['event'][] = 'update';
1909 - } elseif ( isset( $notification['update_email'] ) && 2 == $notification['update_email'] ) {
2328 + } elseif ( isset( $notification['update_email'] ) && 2 == $notification['update_email'] ) { // phpcs:ignore Universal.Operators.StrictComparisons
1910 2329 $atts['event'] = array( 'update' );
1911 2330 }
1912 2331 }
1913 2332
2333 + /**
2334 + * Format email_to data
2335 + *
2336 + * @param array $atts
2337 + * @param array $notification
2338 + *
2339 + * @return void
2340 + */
1914 2341 private static function format_email_to_data( &$atts, $notification ) {
1915 - if ( isset( $notification['email_to'] ) ) {
1916 - $atts['email_to'] = preg_split( '/ (,|;) /', $notification['email_to'] );
1917 - } else {
1918 - $atts['email_to'] = array();
1919 - }
2342 + $atts['email_to'] = isset( $notification['email_to'] ) ? preg_split( '/ (,|;) /', $notification['email_to'] ) : array();
1920 2343
1921 2344 if ( isset( $notification['also_email_to'] ) ) {
1922 2345 $email_fields = (array) $notification['also_email_to'];
1923 2346 $atts['email_to'] = array_merge( $email_fields, $atts['email_to'] );
@@ -1924,24 +2347,36 @@
1924 2347 unset( $email_fields );
1925 2348 }
1926 2349
1927 2350 foreach ( $atts['email_to'] as $key => $email_field ) {
1928 -
1929 2351 if ( is_numeric( $email_field ) ) {
1930 2352 $atts['email_to'][ $key ] = '[' . $email_field . ']';
1931 2353 }
1932 2354
1933 - if ( strpos( $email_field, '|' ) ) {
1934 - $email_opt = explode( '|', $email_field );
1935 - if ( isset( $email_opt[0] ) ) {
1936 - $atts['email_to'][ $key ] = '[' . $email_opt[0] . ' show=' . $email_opt[1] . ']';
1937 - }
1938 - unset( $email_opt );
2355 + if ( ! str_contains( $email_field, '|' ) ) {
2356 + continue;
1939 2357 }
2358 +
2359 + $email_opt = explode( '|', $email_field );
2360 +
2361 + if ( isset( $email_opt[0] ) ) {
2362 + $atts['email_to'][ $key ] = '[' . $email_opt[0] . ' show=' . $email_opt[1] . ']';
2363 + }
2364 + unset( $email_opt );
1940 2365 }
2366 +
1941 2367 $atts['email_to'] = implode( ', ', $atts['email_to'] );
1942 2368 }
1943 2369
2370 + /**
2371 + * Setup new notification
2372 + *
2373 + * @param array $new_notification
2374 + * @param array $notification
2375 + * @param array $atts
2376 + *
2377 + * @return void
2378 + */
1944 2379 private static function setup_new_notification( &$new_notification, $notification, $atts ) {
1945 2380 // Set up new notification
1946 2381 $new_notification = array(
1947 2382 'post_content' => array(
@@ -1952,12 +2387,13 @@
1952 2387 );
1953 2388
1954 2389 // Add more fields to the new notification
1955 2390 $add_fields = array( 'email_message', 'email_subject', 'plain_text', 'inc_user_info', 'conditions' );
2391 +
1956 2392 foreach ( $add_fields as $add_field ) {
1957 2393 if ( isset( $notification[ $add_field ] ) ) {
1958 2394 $new_notification['post_content'][ $add_field ] = $notification[ $add_field ];
1959 - } elseif ( in_array( $add_field, array( 'plain_text', 'inc_user_info' ) ) ) {
2395 + } elseif ( in_array( $add_field, array( 'plain_text', 'inc_user_info' ), true ) ) {
1960 2396 $new_notification['post_content'][ $add_field ] = 0;
1961 2397 } else {
1962 2398 $new_notification['post_content'][ $add_field ] = '';
1963 2399 }
@@ -1968,9 +2404,9 @@
1968 2404 $new_notification['post_content']['reply_to'] = $atts['reply_to'];
1969 2405
1970 2406 // Set from
1971 2407 if ( ! empty( $atts['reply_to'] ) || ! empty( $atts['reply_to_name'] ) ) {
1972 - $new_notification['post_content']['from'] = ( empty( $atts['reply_to_name'] ) ? '[sitename]' : $atts['reply_to_name'] ) . ' <' . ( empty( $atts['reply_to'] ) ? '[admin_email]' : $atts['reply_to'] ) . '>';
2408 + $new_notification['post_content']['from'] = ( ! empty( $atts['reply_to_name'] ) ? $atts['reply_to_name'] : '[sitename]' ) . ' <' . ( ! empty( $atts['reply_to'] ) ? $atts['reply_to'] : '[admin_email]' ) . '>'; // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
1973 2409 }
1974 2410 }
1975 2411
1976 2412 /**
@@ -1975,72 +2411,90 @@
1975 2411
1976 2412 /**
1977 2413 * Switch field IDs in pre-2.0 email conditional logic
1978 2414 *
1979 - * @param $post_content array, pass by reference
2415 + * @param array $post_content Pass by reference.
2416 + *
2417 + * @return void
1980 2418 */
1981 2419 private static function switch_email_condition_field_ids( &$post_content ) {
1982 2420 // Switch field IDs in conditional logic
1983 - if ( isset( $post_content['conditions'] ) && is_array( $post_content['conditions'] ) ) {
1984 - foreach ( $post_content['conditions'] as $email_key => $val ) {
1985 - if ( is_numeric( $email_key ) ) {
1986 - $post_content['conditions'][ $email_key ] = self::switch_action_field_ids( $val, array( 'hide_field' ) );
1987 - }
1988 - unset( $email_key, $val );
2421 + if ( ! isset( $post_content['conditions'] ) || ! is_array( $post_content['conditions'] ) ) {
2422 + return;
2423 + }
2424 +
2425 + foreach ( $post_content['conditions'] as $email_key => $val ) {
2426 + if ( is_numeric( $email_key ) ) {
2427 + $post_content['conditions'][ $email_key ] = self::switch_action_field_ids( $val, array( 'hide_field' ) );
1989 2428 }
2429 + unset( $email_key, $val );
1990 2430 }
1991 2431 }
1992 2432
2433 + /**
2434 + * Migrate autoresponder to action
2435 + *
2436 + * @param array $form_options
2437 + * @param int $form_id
2438 + * @param array $notifications
2439 + *
2440 + * @return void
2441 + */
1993 2442 private static function migrate_autoresponder_to_action( $form_options, $form_id, &$notifications ) {
1994 - if ( isset( $form_options['auto_responder'] ) && $form_options['auto_responder'] && isset( $form_options['ar_email_message'] ) && $form_options['ar_email_message'] ) {
1995 - // migrate autoresponder
2443 + if ( empty( $form_options['auto_responder'] ) || empty( $form_options['ar_email_message'] ) ) {
2444 + return;
2445 + }
1996 2446
1997 - $email_field = isset( $form_options['ar_email_to'] ) ? $form_options['ar_email_to'] : 0;
1998 - if ( strpos( $email_field, '|' ) ) {
1999 - // data from entries field
2000 - $email_field = explode( '|', $email_field );
2001 - if ( isset( $email_field[1] ) ) {
2002 - $email_field = $email_field[1];
2003 - }
2447 + // Migrate autoresponder
2448 +
2449 + $email_field = $form_options['ar_email_to'] ?? 0;
2450 +
2451 + if ( str_contains( $email_field, '|' ) ) {
2452 + // Data from entries field
2453 + $email_field = explode( '|', $email_field );
2454 +
2455 + if ( isset( $email_field[1] ) ) {
2456 + $email_field = $email_field[1];
2004 2457 }
2005 - if ( is_numeric( $email_field ) && ! empty( $email_field ) ) {
2006 - $email_field = '[' . $email_field . ']';
2007 - }
2458 + }
2008 2459
2009 - $notification = $form_options;
2010 - $new_notification2 = array(
2011 - 'post_content' => array(
2012 - 'email_message' => $notification['ar_email_message'],
2013 - 'email_subject' => isset( $notification['ar_email_subject'] ) ? $notification['ar_email_subject'] : '',
2014 - 'email_to' => $email_field,
2015 - 'plain_text' => isset( $notification['ar_plain_text'] ) ? $notification['ar_plain_text'] : 0,
2016 - 'inc_user_info' => 0,
2017 - ),
2018 - 'post_name' => $form_id . '_email_' . count( $notifications ),
2019 - );
2460 + if ( is_numeric( $email_field ) && $email_field ) {
2461 + $email_field = '[' . $email_field . ']';
2462 + }
2020 2463
2021 - $reply_to = isset( $notification['ar_reply_to'] ) ? $notification['ar_reply_to'] : '';
2022 - $reply_to_name = isset( $notification['ar_reply_to_name'] ) ? $notification['ar_reply_to_name'] : '';
2464 + $notification = $form_options;
2465 + $new_notification2 = array(
2466 + 'post_content' => array(
2467 + 'email_message' => $notification['ar_email_message'],
2468 + 'email_subject' => $notification['ar_email_subject'] ?? '',
2469 + 'email_to' => $email_field,
2470 + 'plain_text' => $notification['ar_plain_text'] ?? 0,
2471 + 'inc_user_info' => 0,
2472 + ),
2473 + 'post_name' => $form_id . '_email_' . count( $notifications ),
2474 + );
2023 2475
2024 - if ( ! empty( $reply_to ) ) {
2025 - $new_notification2['post_content']['reply_to'] = $reply_to;
2026 - }
2476 + $reply_to = $notification['ar_reply_to'] ?? '';
2477 + $reply_to_name = $notification['ar_reply_to_name'] ?? '';
2027 2478
2028 - if ( ! empty( $reply_to ) || ! empty( $reply_to_name ) ) {
2029 - $new_notification2['post_content']['from'] = ( empty( $reply_to_name ) ? '[sitename]' : $reply_to_name ) . ' <' . ( empty( $reply_to ) ? '[admin_email]' : $reply_to ) . '>';
2030 - }
2479 + if ( $reply_to ) {
2480 + $new_notification2['post_content']['reply_to'] = $reply_to;
2481 + }
2031 2482
2032 - $notifications[] = $new_notification2;
2033 - unset( $new_notification2 );
2483 + if ( $reply_to || $reply_to_name ) {
2484 + $new_notification2['post_content']['from'] = ( $reply_to_name ? $reply_to_name : '[sitename]' ) . ' <' . ( $reply_to ? $reply_to : '[admin_email]' ) . '>'; // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
2034 2485 }
2486 +
2487 + $notifications[] = $new_notification2;
2488 + unset( $new_notification2 );
2035 2489 }
2036 2490
2037 2491 /**
2038 2492 * PHP 8 backward compatibility for the libxml_disable_entity_loader function
2039 2493 *
2040 - * @param boolean $disable
2494 + * @param bool $loader
2041 2495 *
2042 - * @return boolean
2496 + * @return bool
2043 2497 */
2044 2498 public static function maybe_libxml_disable_entity_loader( $loader ) {
2045 2499 if ( version_compare( phpversion(), '8.0', '<' ) && function_exists( 'libxml_disable_entity_loader' ) ) {
2046 2500 $loader = libxml_disable_entity_loader( $loader ); // phpcs:disable Generic.PHP.DeprecatedFunctions.Deprecated
@@ -2048,9 +2502,32 @@
2048 2502
2049 2503 return $loader;
2050 2504 }
2051 2505
2506 + /**
2507 + * PHP 8 backward compatibility for the libxml_disable_entity_loader function
2508 + *
2509 + * @return bool
2510 + */
2052 2511 public static function check_if_libxml_disable_entity_loader_exists() {
2053 2512 return version_compare( phpversion(), '8.0', '<' ) && ! function_exists( 'libxml_disable_entity_loader' );
2054 2513 }
2514 +
2515 + /**
2516 + * Get the file types allowed for importing.
2517 + * This is used in the "accept" attribute for the file upload input on the XML import page.
2518 + *
2519 + * @since 6.8.3
2520 + *
2521 + * @return array
2522 + */
2523 + public static function get_supported_upload_file_types() {
2524 + $file_types = array( '.xml' );
2525 +
2526 + if ( FrmAppHelper::pro_is_installed() ) {
2527 + // CSV Importing is only available in Pro.
2528 + $file_types[] = '.csv';
2529 + }
2530 +
2531 + return $file_types;
2532 + }
2055 2533 }
2056 -