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 +70 -21 6.28 → trunk View file →
@@ -132,13 +132,15 @@
132 132 $imported = self::pre_import_data();
133 133
134 134 foreach ( array( 'term', 'form', 'view' ) as $item_type ) {
135 135 // Grab cats, tags, and terms, or forms or posts.
136 - if ( isset( $xml->{$item_type} ) ) {
137 - $function_name = 'import_xml_' . $item_type . 's';
138 - $imported = self::$function_name( $xml->{$item_type}, $imported );
139 - unset( $function_name, $xml->{$item_type} );
136 + if ( ! isset( $xml->{$item_type} ) ) {
137 + continue;
140 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} );
141 143 }
142 144
143 145 $imported = apply_filters( 'frm_importing_xml', $imported, $xml );
144 146
@@ -292,8 +294,23 @@
292 294 }//end foreach
293 295
294 296 self::maybe_update_child_form_parent_id( $imported['forms'], $child_forms );
295 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 +
296 313 return $imported;
297 314 }
298 315
299 316 /**
@@ -464,14 +481,16 @@
464 481 * @param array $child_forms
465 482 */
466 483 private static function maybe_update_child_form_parent_id( $imported_forms, $child_forms ) {
467 484 foreach ( $child_forms as $child_form_id => $old_parent_form_id ) {
468 - if ( isset( $imported_forms[ $old_parent_form_id ] ) && (int) $imported_forms[ $old_parent_form_id ] !== (int) $old_parent_form_id ) {
469 - // Update all children with this old parent_form_id
470 - $new_parent_form_id = (int) $imported_forms[ $old_parent_form_id ];
471 - FrmForm::update( $child_form_id, array( 'parent_form_id' => $new_parent_form_id ) );
472 - 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;
473 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 );
474 493 }
475 494 }
476 495
477 496 /**
@@ -600,13 +619,40 @@
600 619 'field_order' => (int) $field->field_order,
601 620 'form_id' => (int) $form_id,
602 621 'required' => (int) $field->required,
603 622 'options' => FrmAppHelper::maybe_json_decode( (string) $field->options ),
604 - 'field_options' => FrmAppHelper::maybe_json_decode( (string) $field->field_options ),
623 + 'field_options' => self::fill_field_options( $field ),
605 624 );
606 625 }
607 626
608 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 + /**
609 655 * @since 4.06
610 656 *
611 657 * @param array $f
612 658 *
@@ -1512,15 +1558,17 @@
1512 1558 * @param array $post
1513 1559 * @param int $post_id
1514 1560 */
1515 1561 private static function update_layout( &$post, $post_id ) {
1516 - if ( is_callable( 'FrmViewsLayout::maybe_create_layouts_for_view' ) ) {
1517 - $listing_layout = ! empty( $post['layout']['listing'] ) ? json_decode( $post['layout']['listing'], true ) : array();
1518 - $detail_layout = ! empty( $post['layout']['detail'] ) ? json_decode( $post['layout']['detail'], true ) : array();
1562 + if ( ! is_callable( 'FrmViewsLayout::maybe_create_layouts_for_view' ) ) {
1563 + return;
1564 + }
1519 1565
1520 - if ( $listing_layout || $detail_layout ) {
1521 - FrmViewsLayout::maybe_create_layouts_for_view( $post_id, $listing_layout, $detail_layout );
1522 - }
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 );
1523 1571 }
1524 1572 }
1525 1573
1526 1574 /**
@@ -1558,12 +1606,11 @@
1558 1606 $errors[] = $result->get_error_message();
1559 1607
1560 1608 // Remove the SimpleXML_parse_error from the WP_Error object to avoid
1561 1609 // displaying duplicate error messages from $result->get_error_message()
1562 - $error_codes = $result->get_error_codes();
1563 1610 $error_details = array();
1564 1611
1565 - foreach ( $error_codes as $error_code ) {
1612 + foreach ( $result->get_error_codes() as $error_code ) {
1566 1613 // Clone WP_Error data because WP_Error removes all error messages and data
1567 1614 // Associated with the specified error code when an item is removed.
1568 1615 // Source: https://developer.wordpress.org/reference/classes/wp_error/remove/#source
1569 1616 $error_details = $result->get_error_data( $error_code );
@@ -1831,12 +1878,14 @@
1831 1878 return;
1832 1879 }
1833 1880
1834 1881 foreach ( $options as $key => $option ) {
1835 - if ( is_array( $option ) && ! empty( $option['image'] ) ) {
1836 - $options[ $key ]['src'] = wp_get_attachment_url( $option['image'] );
1837 - $updated = true;
1882 + if ( ! is_array( $option ) || empty( $option['image'] ) ) {
1883 + continue;
1838 1884 }
1885 +
1886 + $options[ $key ]['src'] = wp_get_attachment_url( $option['image'] );
1887 + $updated = true;
1839 1888 }
1840 1889
1841 1890 if ( $updated ) {
1842 1891 $field->options = maybe_serialize( $options );