<?php if ( ! defined( 'ABSPATH' ) ) { die( 'You are not allowed to call this page directly.' ); } class FrmProNestedFormsController { /** * Display an embedded form on the current page * * @since 2.02.06 * * @param array $field * @param string $field_name * @param array $errors */ public static function display_front_end_embedded_form( $field, $field_name, $errors ) { $args = array( 'errors' => $errors, 'repeat' => 0, ); self::display_front_end_nested_form( $field_name, $field, $args ); } /** * Display a repeating section on the current page * * @since 2.02.06 * * @param array $field * @param string $field_name * @param array $errors */ public static function display_front_end_repeating_section( $field, $field_name, $errors ) { $args = array( 'errors' => $errors, 'repeat' => 5, ); self::display_front_end_nested_form( $field_name, $field, $args ); } /** * Display an embedded form/repeating section on the current page * * @param string $field_name * @param array $field * @param array $args */ public static function display_front_end_nested_form( $field_name, $field, $args = array() ) { if ( ! is_numeric( $field['form_select'] ) ) { return; } $defaults = array( 'repeat' => 0, 'errors' => array(), ); $args = wp_parse_args( $args, $defaults ); $subform = FrmForm::getOne( $field['form_select'] ); if ( empty( $subform ) ) { return; } $subfields = FrmField::get_all_for_form( $field['form_select'] ); self::insert_basic_hidden_field( $field_name . '[form]', $field['form_select'], '', compact( 'field' ) ); if ( empty( $subfields ) ) { return; } $repeat_atts = array( 'form' => $subform, 'fields' => $subfields, 'errors' => $args['errors'], 'parent_field' => $field, 'repeat' => $args['repeat'], 'field_name' => $field_name, 'is_repeat_limit_reached' => self::is_repeat_limit_reached_for_field( $field ), ); if ( empty( $field['value'] ) ) { // Row count must be zero if field value is empty $start_rows = apply_filters( 'frm_repeat_start_rows', 1, $field ); for ( $i = 0, $j = $start_rows; $i < $j; $i ++ ) { // add an empty sub entry $repeat_atts['row_count'] = $i; $repeat_atts['i'] = $i; self::display_single_iteration_of_nested_form( $field_name, $repeat_atts ); } return; } $row_count = 0; $processed_item_ids = array(); foreach ( (array) $field['value'] as $k => $checked ) { $repeat_atts['i'] = $k; $repeat_atts['value'] = ''; if ( ! isset( $field['value']['form'] ) ) { // this is not a posted value from moving between pages $checked = apply_filters( 'frm_hidden_value', $checked, $field ); if ( empty( $checked ) || ! is_numeric( $checked ) ) { continue; } $repeat_atts['i'] = 'i' . $checked; $repeat_atts['entry_id'] = $checked; $repeat_atts['value'] = $checked; } elseif ( $k === 'form' || $k === 'row_ids' ) { continue; } elseif ( strpos( $k, 'i' ) === 0 ) { // include the entry id when values are posted $repeat_atts['entry_id'] = absint( str_replace( 'i', '', $k ) ); } elseif ( self::new_entries_have_been_submitted() ) { $entry_id = self::get_new_inserted_repeater_item_id( $checked, $processed_item_ids ); if ( $entry_id ) { $repeat_atts['i'] = 'i' . $entry_id; $repeat_atts['entry_id'] = $entry_id; $repeat_atts['value'] = $entry_id; } } if ( ! empty( $repeat_atts['entry_id'] ) ) { $processed_item_ids[] = (int) $repeat_atts['entry_id']; } // Keep track of row count $repeat_atts['row_count'] = $row_count; $row_count ++; // show each existing sub entry self::display_single_iteration_of_nested_form( $field_name, $repeat_atts ); unset( $k, $checked ); } unset( $subform, $subfields ); } private static function new_entries_have_been_submitted() { global $frm_vars; return ! empty( $frm_vars['saved_entries'] ); } /** * Get the entry id for a repeater field that was just processed * If data has just been posted, the new entry ids for repeaters are not passed, so we need to get them from the database * * @param array $values * @param array $processed_item_ids * @return int $entry_id 0 if no entry matches or if the entry has already been processed */ private static function get_new_inserted_repeater_item_id( $values, &$processed_item_ids ) { global $frm_vars; if ( empty( $frm_vars['saved_entries'] ) ) { return 0; } $values = array_filter( $values, function( $value ) { return '' !== $value; } ); if ( 0 === count( $values ) ) { return 0; } // Name or Address field value is array and needs to be converted to string. self::convert_array_values_to_string( $values ); $child_field_ids = array_keys( $values ); $value = array_values( $values ); $where = array( 'item_id' => $frm_vars['saved_entries'], 'field_id' => $child_field_ids, 'meta_value' => $value, ); $entry_id = (int) FrmDb::get_var( 'frm_item_metas', $where, 'item_id' ); if ( ! $entry_id || in_array( $entry_id, $processed_item_ids, true ) ) { return 0; } $processed_item_ids[] = $entry_id; return $entry_id; } /** * Converts array values to string. * * @since 5.0.07 * * @param array $arr The array. */ private static function convert_array_values_to_string( &$arr ) { foreach ( $arr as &$value ) { if ( is_array( $value ) ) { $value = serialize( $value ); } } } /** * Check if repeat limit is reached for a section field * * @since 2.05 * * @param array $field * * @return bool */ private static function is_repeat_limit_reached_for_field( $field ) { if ( ! isset( $field['repeat_limit'] ) || $field['repeat_limit'] !== '' ) { return false; } if ( empty( $field['value'] ) ) { $row_count = 1; } else if ( isset( $field['value']['row_ids'] ) ) { if ( is_array( $field['value']['row_ids'] ) ) { $row_count = count( $field['value']['row_ids'] ); } else { $row_count = 1; } } else { // When editing an entry, the value will be an array of child IDs on initial load $row_count = count( $field['value'] ); } return self::is_repeat_limit_reached( $field['repeat_limit'], $row_count ); } /** * Add a repeating section row with ajax */ public static function ajax_add_repeat_row() { $field_id = FrmAppHelper::get_post_param( 'field_id', '', 'absint' ); if ( ! $field_id ) { wp_die(); } $row_count = FrmAppHelper::get_post_param( 'numberOfSections', 0, 'absint' ); $field = FrmField::getOne( $field_id ); $repeat_limit = absint( FrmField::get_option_in_object( $field, 'repeat_limit' ) ); $args = array( 'i' => FrmAppHelper::get_post_param( 'i', 0, 'absint' ), 'parent_field' => $field->id, 'form' => ( isset( $field->field_options['form_select'] ) ? $field->field_options['form_select'] : 0 ), 'repeat' => 1, ); $field_name = 'item_meta[' . $args['parent_field'] . ']'; if ( self::is_repeat_limit_reached( $repeat_limit, $row_count ) ) { echo json_encode( array() ); wp_die(); } $response = array( 'is_repeat_limit_reached' => self::is_repeat_limit_reached( $repeat_limit, $row_count + 1 ), ); if ( is_callable( 'FrmFormsController::add_js_validate_form_to_global_vars' ) ) { $form = FrmForm::getOne( $field->form_id ); if ( ! empty( $form->options['js_validate'] ) ) { FrmFormsController::add_js_validate_form_to_global_vars( $form ); } } FrmProEntriesController::maybe_include_exclude_fields( $form->id ); ob_start(); self::display_single_iteration_of_nested_form( $field_name, $args ); $response['html'] = ob_get_contents(); ob_end_clean(); echo json_encode( $response ); wp_die(); } /** * Check if the repeat limit is reached * * @since 2.05 * * @param int $repeat_limit * @param int $row_count * * @return bool */ private static function is_repeat_limit_reached( $repeat_limit, $row_count ) { return $repeat_limit && $row_count >= $repeat_limit; } /** * Load JavaScript for hidden subfields * Applies to repeating sections and embed form fields * TODO: clean this up, maybe don't remove child fields from field array when they're on a different page * * @since 2.01.0 * * @param array $field */ public static function load_hidden_sub_field_javascript( $field ) { if ( self::is_hidden_nested_form_field( $field ) ) { $child_fields = FrmField::get_all_for_form( $field['form_select'] ); foreach ( $child_fields as $child_field_obj ) { $child_field = FrmProFieldsHelper::convert_field_object_to_flat_array( $child_field_obj ); $child_field['original_type'] = $child_field['type']; $child_field['type'] = 'hidden'; $child_field['parent_form_id'] = $field['form_id']; if ( ! isset( $child_field['value'] ) ) { $child_field['value'] = ''; } if ( $field['original_type'] == 'form' ) { // This is needed when field script is loaded through hidden sub fields. $child_field['in_embed_form'] = $field['id']; } FrmProFieldsHelper::add_field_javascript( $child_field ); } } } /** * Format the saved value in nested form fields when value is not posted * This will only be used on initial form load when editing an entry * * @since 2.0 * * @param array $field */ public static function format_saved_values_for_hidden_nested_forms( &$field ) { $is_hidden_nested_form_field_with_saved_value = ( self::is_hidden_nested_form_field( $field ) && ! isset( $field['value']['form'] ) && ! empty( $field['value'] ) ); if ( ! $is_hidden_nested_form_field_with_saved_value || ! is_numeric( $field['form_select'] ) ) { return; } // Begin formatting field value $field['value'] = array( 'form' => $field['form_select'], 'row_ids' => self::format_entry_ids_for_row_ids( $field['value'] ), ); // Get child fields $child_fields = FrmField::get_all_for_form( $field['form_select'] ); // Loop through children and entries to get values foreach ( $field['value']['row_ids'] as $row_id ) { $entry_id = str_replace( 'i', '', $row_id ); $field['value'][ $row_id ] = array( 0 => '' ); $entry = FrmEntry::getOne( $entry_id, true ); foreach ( $child_fields as $child ) { $field['value'][ $row_id ][ $child->id ] = isset( $entry->metas[ $child->id ] ) ? $entry->metas[ $child->id ] : ''; if ( $child->type == 'date' ) { $current_value = $field['value'][ $row_id ][ $child->id ]; $field['value'][ $row_id ][ $child->id ] = FrmProAppHelper::maybe_convert_from_db_date( $current_value ); } } } } /** * Check if a field is a hidden repeating section/embedded form * * @since 2.02.06 * * @param $field * * @return bool */ public static function is_hidden_nested_form_field( $field ) { $is_hidden_nested_form_field = false; if ( isset( $field['original_type'] ) && $field['type'] == 'hidden' ) { if ( $field['original_type'] == 'form' ) { $is_hidden_nested_form_field = true; } else if ( $field['original_type'] == 'divider' && $field['repeat'] ) { $is_hidden_nested_form_field = true; } } return $is_hidden_nested_form_field; } /** * Insert the fields and JavaScript for a hidden nested form * * @since 2.02.06 * * @param array $field * @param string $field_name * @param array|string $field_value */ public static function insert_hidden_nested_form( $field, $field_name, $field_value ) { self::load_hidden_sub_field_javascript( $field ); self::insert_hidden_nested_form_fields( $field, $field_name, $field_value ); } /** * Insert the fields in a hidden nested form * * @since 2.02.06 * * @param array $field * @param string $field_name * @param array|string $value_array */ private static function insert_hidden_nested_form_fields( $field, $field_name, $value_array ) { if ( ! is_array( $value_array ) ) { self::insert_basic_hidden_field( $field_name, '', $field['html_id'], compact( 'field' ) ); return; } foreach ( $value_array as $key => $value ) { if ( $key === 'form' ) { self::insert_basic_hidden_field( $field_name . '[' . $key . ']', $value, '', compact( 'field' ) ); } else if ( $key === 'row_ids' ) { self::insert_hidden_row_id_inputs( $field, $value ); } else { self::insert_hidden_sub_field_inputs( $field, $field_name . '[' . $key . ']', $value, $key ); } } } /** * Insert the row_ids input for a nested form * * @since 2.02.06 * * @param array $field * @param array|string $value */ private static function insert_hidden_row_id_inputs( $field, $value ) { if ( ! is_array( $value ) ) { $value = array( 0 ); } $name = 'item_meta[' . $field['id'] . '][row_ids][]'; foreach ( $value as $row_id ) { self::insert_basic_hidden_field( $name, $row_id, '', compact( 'field' ) ); } } /** * Insert the sub fields in a hidden nested form * * @since 2.02.06 * * @param array $field * @param string $field_name * @param array|string $value * @param string $value_key */ private static function insert_hidden_sub_field_inputs( $field, $field_name, $value, $value_key ) { if ( is_array( $value ) ) { foreach ( $value as $k => $checked2 ) { $checked2 = apply_filters( 'frm_hidden_value', $checked2, $field ); self::insert_hidden_sub_field_inputs( $field, $field_name . '[' . $k . ']', $checked2, $k ); } unset( $k, $checked2 ); } else { $html_id = self::get_html_id_for_hidden_sub_fields( $field_name, $value_key, $field['html_id'] ); self::insert_basic_hidden_field( $field_name, $value, $html_id, compact( 'field' ) ); } } /** * Insert a basic hidden field * * @since 2.02.06 * * @param string $name * @param string $value * @param string $id */ private static function insert_basic_hidden_field( $name, $value, $id, $args = array() ) { if ( strpos( $name, '[form]' ) !== false ) { $class = 'frm_dnc'; } else { $class = ''; } if ( $id ) { $html = ''; $subfield_id = self::get_sub_field_id( $name ); if ( isset( $args['field'] ) && $args['field']['id'] == $subfield_id ) { $field = $args['field']; } else { $field = $subfield_id ? FrmField::getOne( $subfield_id ) : null; } if ( $field ) { $field = (array) $field; $field['original_type'] = isset( $field['original_type'] ) ? $field['original_type'] : $field['type']; $field['type'] = 'hidden'; $field['value'] = $value; FrmProFieldsController::add_currency_field_attributes( $field, $html, $args['field'] ); if ( isset( $args['field'] ) && isset( $args['field']['parent_form_id'] ) ) { // Pass the parent ID on as needed. $field['form_id'] = $args['field']['parent_form_id']; } } ?><input type="hidden" name="<?php echo esc_attr( $name ); ?>" id="<?php echo esc_attr( $id ); ?>" value="<?php echo esc_attr( $value ); ?>" <?php echo $html; ?>/> <?php if ( isset( $field ) && isset( $field['original_type'] ) && ( $field['original_type'] === 'product' || $field['original_type'] === 'total' ) ) { FrmProCurrencyHelper::add_currency_to_global( $field['form_id'] ); } } else { ?><input type="hidden" name="<?php echo esc_attr( $name ); ?>" value="<?php echo esc_attr( $value ); ?>" class="<?php echo esc_attr( $class ); ?>" /> <?php } } private static function get_sub_field_id( $field_name ) { $matches = array(); // .+ is safer than d+ because field keys might be used at times. preg_match( '/item_meta(\[.+?\]){3}/i', $field_name, $matches, PREG_OFFSET_CAPTURE ); if ( ! count( $matches ) ) { return 0; } $name = $matches[0][0]; $parts = explode( '][', $name . '[' ); return $parts[ count( $parts ) - 2 ]; } /** * Make sure fields in a hidden repeating section get the correct HTML ids * Their HTML ID should be the same when hidden or visible to work with calculations and logic * * @since 2.02.06 * * @param string $field_name * @param string $opt_key * @param string $html_id * * @return string */ private static function get_html_id_for_hidden_sub_fields( $field_name, $opt_key, $html_id ) { $parts = explode( '][', $field_name . '[' ); if ( count( $parts ) > 2 ) { if ( $parts[2] === 'other' ) { $html_id = self::get_html_id_for_hidden_other_fields( $parts, $opt_key, $html_id ); } else { $field_id = absint( $parts[2] ); if ( $field_id === 0 ) { $html_id = ''; } else { $field_key = FrmField::get_key_by_id( $field_id ); if ( $field_key ) { $html_id = 'field_' . $field_key . '-' . $parts[1]; // allow for a multi-dimensional array for the ids if ( isset( $parts[3] ) && $parts[3] != '' ) { $html_id .= '-' . $parts[3]; } } } } } return $html_id; } /** * Get the HTML ID for hidden other fields inside of repeating sections when value is posted * * @since 2.0.8 * * @param array $parts (array of the field name) * @param string|boolean $opt_key * @param string $html_id * * @return string */ private static function get_html_id_for_hidden_other_fields( $parts, $opt_key, $html_id ) { $field_id = absint( $parts[3] ); $field_key = FrmField::get_key_by_id( $field_id ); if ( $field_key ) { $html_id = 'field_' . $field_key . '-' . $parts[1]; // If checkbox field or multi-select dropdown if ( $opt_key && FrmFieldsHelper::is_other_opt( $opt_key ) ) { $html_id .= '-' . $opt_key . '-otext'; } else { $html_id .= '-otext'; } } return $html_id; } /** * Convert entry IDs to row IDs * * @since 2.02.06 * * @param array|string $entry_ids * * @return array */ private static function format_entry_ids_for_row_ids( $entry_ids ) { $row_ids = array(); foreach ( (array) $entry_ids as $entry_id ) { if ( $entry_id ) { $row_ids[] = 'i' . $entry_id; } } return $row_ids; } /** * Display a single iteration of a nested form * * @since 2.02.06 * * @param string $field_name * @param array $args */ private static function display_single_iteration_of_nested_form( $field_name, $args = array() ) { $defaults = array( 'i' => 0, 'entry_id' => false, 'form' => false, 'fields' => array(), 'errors' => array(), 'parent_field' => 0, 'repeat' => 0, 'row_count' => false, 'value' => '', 'field_name' => '', 'is_repeat_limit_reached' => false, ); $args = wp_parse_args( $args, $defaults ); if ( empty( $args['parent_field'] ) ) { return; } if ( is_numeric( $args['parent_field'] ) ) { $args['parent_field'] = (array) FrmField::getOne( $args['parent_field'] ); $args['parent_field']['format'] = isset( $args['parent_field']['field_options']['format'] ) ? $args['parent_field']['field_options']['format'] : ''; } FrmForm::maybe_get_form( $args['form'] ); if ( empty( $args['fields'] ) ) { $args['fields'] = FrmField::get_all_for_form( $args['form']->id ); } $values = array(); if ( $args['fields'] ) { $pass_args = array( 'parent_form_id' => $args['parent_field']['form_id'], 'parent_field_id' => $args['parent_field']['id'], 'key_pointer' => $args['i'], 'repeating' => true, 'fields' => $args['fields'], 'in_embed_form' => $args['parent_field']['type'] == 'form' ? $args['parent_field']['id'] : '0', ); // Find the connection between here and where logic is packaged if ( empty( $args['entry_id'] ) ) { $just_created_entry = FrmFormsController::just_created_entry( $args['parent_field']['form_id'] ); $values = FrmEntriesHelper::setup_new_vars( $args['fields'], $args['form'], $just_created_entry, $pass_args ); } else { $entry = FrmEntry::getOne( $args['entry_id'], true ); if ( $entry && $entry->form_id == $args['form']->id ) { $values = FrmProEntriesController::setup_entry_values_for_editing( $entry, $pass_args ); } else { return; } } } $format = isset( $args['parent_field']['format'] ) ? $args['parent_field']['format'] : ''; $end = false; $count = 0; foreach ( $values['fields'] as $subfield ) { if ( 'end_divider' == $subfield['type'] ) { $end = $subfield; } else if ( ! in_array( $subfield['type'], array( 'hidden', 'user_id' ) ) ) { if ( isset( $subfield['conf_field'] ) && $subfield['conf_field'] ) { $count = $count + 2; } else { $count ++; } } unset( $subfield ); } if ( $args['repeat'] ) { $count ++; } $field_class = self::grid_field_class( $count, $format ); $section_classes = self::repeat_container_classes( $format, $args ); echo '<div id="frm_section_' . esc_attr( $args['parent_field']['id'] . '-' . $args['i'] ) . '" class="' . esc_attr( $section_classes ) . '">' . "\n"; self::add_hidden_repeat_row_id( $args ); self::add_default_item_meta_field( $args ); /** * Allows changing subfields in the repeater field. * * @since 5.0 * * @param array $subfields Subfields. * @param array $args Custom arguments. */ $values['fields'] = apply_filters( 'frm_subfields_in_repeater', $values['fields'], $args ); $label_pos = 'top'; $field_num = 1; foreach ( $values['fields'] as $subfield ) { $subfield_name = $field_name . '[' . $args['i'] . '][' . $subfield['id'] . ']'; $subfield_plus_id = '-' . $args['i']; $subfield_id = $subfield['id'] . '-' . $args['parent_field']['id'] . $subfield_plus_id; if ( $args['parent_field'] && ! empty( $args['parent_field']['value'] ) && isset( $args['parent_field']['value']['form'] ) && isset( $args['parent_field']['value'][ $args['i'] ] ) && isset( $args['parent_field']['value'][ $args['i'] ][ $subfield['id'] ] ) ) { // this is a posted value from moving between pages, so set the POSTed value $subfield['value'] = $args['parent_field']['value'][ $args['i'] ][ $subfield['id'] ]; } if ( ! empty( $field_class ) ) { if ( 1 == $field_num ) { $subfield['classes'] .= ' frm_first'; } self::add_class_to_field( $field_class, 'field', $subfield['classes'] ); } $field_num ++; if ( 'top' == $label_pos && in_array( $subfield['label'], array( 'top', 'hidden', '', 'inside' ) ) ) { // add placeholder label if repeating $label_pos = 'hidden'; } // Track whether field is in an embedded form if ( 'form' == $args['parent_field']['type'] ) { // TODO: Check if this is needed $subfield['in_embed_form'] = $args['parent_field']['id']; } $field_args = array( 'field_name' => $subfield_name, 'field_id' => $subfield_id, 'field_plus_id' => $subfield_plus_id, 'section_id' => $args['parent_field']['id'], 'errors' => $args['errors'], 'form' => $args['form'], 'parent_form_id' => $args['parent_field']['form_id'], ); $field_obj = FrmFieldFactory::get_field_type( $subfield['type'], $subfield ); $field_obj->show_field( $field_args ); unset( $subfield_name, $subfield_id ); } if ( ! $args['repeat'] ) { // Close frm_repeat div echo '</div>' . "\n"; return; } $args['format'] = $format; $args['label_pos'] = $label_pos; $args['field_class'] = $field_class; echo self::get_repeat_buttons( $args, $end ); // Close frm_repeat div echo '</div>' . "\n"; } /** * @since 3.0 * * @return string|array */ private static function grid_field_class( $count, $format ) { if ( empty( $format ) ) { return ''; } if ( 2 == $count ) { $class = array( 10, 2 ); } elseif ( $count < 13 ) { $field_width = floor( 12 / ( $count ) ); $submit_width = 12 - ( $field_width * ( $count - 1 ) ); $class = array( $field_width, $submit_width ); } else { $class = ''; } return $class; } private static function add_class_to_field( $add_class, $type, &$classes ) { if ( is_array( $add_class ) ) { $position = 'button' === $type ? 1 : 0; $classes .= ' frm' . $add_class[ $position ]; } elseif ( $add_class ) { $classes .= ' frm' . $add_class; } } /** * @since 3.0 * * @return string */ private static function repeat_container_classes( $format, $args ) { $section_classes = array( 'frm_repeat_' . ( empty( $format ) ? 'sec' : $format ), 'frm_repeat_' . $args['parent_field']['id'] . ( $args['row_count'] === 0 ? ' frm_first_repeat' : '' ), 'frm_grid_container', ); return implode( ' ', $section_classes ); } /** * Adds the row_ids to a nested form on the current page * * @since 2.02.06 * * @param $args */ private static function add_hidden_repeat_row_id( $args ) { echo '<input type="hidden" name="item_meta[' . esc_attr( $args['parent_field']['id'] ) . '][row_ids][]" value="' . esc_attr( $args['i'] ) . '" />'; } /** * Add item meta to each row in repeating section or embedded form so the entry is always validated * * @since 2.0.08 * * @param array $args */ private static function add_default_item_meta_field( $args ) { echo '<input type="hidden" name="item_meta[' . esc_attr( $args['parent_field']['id'] ) . '][' . esc_attr( $args['i'] ) . '][0]" value="" />'; } /** * Get the HTML for repeat buttons * * @param array $args * @param bool $end * * @return mixed|void */ private static function get_repeat_buttons( $args, $end = false ) { $args['end_format'] = 'icon'; if ( ! $end ) { $end = self::get_end_repeat_field( $args ); } if ( $end ) { $args['add_label'] = $end['add_label']; $args['remove_label'] = $end['remove_label']; if ( ! empty( $end['format'] ) ) { $args['end_format'] = $end['format']; } } $triggers = self::repeat_button_html( $args, $end ); return apply_filters( 'frm_repeat_triggers', $triggers, $end, $args['parent_field'], $args['field_class'] ); } /** * Get the end divider field for a repeating section * * @param array $args * * @return mixed|void */ private static function get_end_repeat_field( $args ) { $query = array( 'fi.form_id' => $args['parent_field']['form_id'], 'type' => 'end_divider', 'field_order >' => $args['parent_field']['field_order'] + 1, ); $end_field = FrmField::getAll( $query, 'field_order', 1 ); $field_array = FrmProFieldsHelper::initialize_array_field( $end_field ); foreach ( array( 'format', 'add_label', 'remove_label', 'classes' ) as $o ) { if ( isset( $end_field->field_options[ $o ] ) ) { $field_array[ $o ] = $end_field->field_options[ $o ]; } } FrmFieldsHelper::prepare_new_front_field( $field_array, $end_field ); return $field_array; } /** * Get the HTML for the repeat buttons * * @param array $args * @param array $end * * @return string */ private static function repeat_button_html( $args, $end ) { $defaults = array( 'add_icon' => '', 'remove_icon' => '', 'add_label' => __( 'Add', 'formidable' ), 'remove_label' => __( 'Remove', 'formidable' ), 'add_classes' => ' frm_button', 'remove_classes' => ' frm_button', 'is_repeat_limit_reached' => false, ); $args = wp_parse_args( $args, $defaults ); if ( ! isset( $args['end_format'] ) && isset( $args['format'] ) ) { $args['end_format'] = $args['format']; } if ( 'both' == $args['end_format'] ) { $args['remove_icon'] = '<i class="frm_icon_font frm_minus_icon"> </i> '; $args['add_icon'] = '<i class="frm_icon_font frm_plus_icon"> </i> '; } else if ( 'text' != $args['end_format'] ) { $args['add_label'] = ''; $args['remove_label'] = ''; $args['add_classes'] = ' frm_icon_font frm_plus_icon'; $args['remove_classes'] = ' frm_icon_font frm_minus_icon'; } if ( $args['is_repeat_limit_reached'] ) { $args['add_classes'] .= ' frm_hide_add_button'; } $classes = 'frm_form_field frm_' . $args['label_pos'] . '_container frm_repeat_buttons'; self::add_class_to_field( $args['field_class'], 'button', $classes ); // Get classes for end divider $classes .= ( $end && isset( $end['classes'] ) ) ? ' ' . $end['classes'] : ''; $triggers = '<div class="' . esc_attr( $classes ) . '">'; if ( 'hidden' == $args['label_pos'] && ! empty( $args['format'] ) ) { $triggers .= '<label class="frm_primary_label">&nbsp;</label>'; } $triggers .= '<a href="#" class="frm_add_form_row' . esc_attr( $args['add_classes'] ) . '" data-parent="' . esc_attr( $args['parent_field']['id'] ) . '" aria-label="' . esc_attr( $defaults['add_label'] ) . '">' . $args['add_icon'] . $args['add_label'] . '</a>' . "\n"; $triggers .= '<a href="#" class="frm_remove_form_row' . esc_attr( $args['remove_classes'] ) . '" data-key="' . esc_attr( $args['i'] ) . '" data-parent="' . esc_attr( $args['parent_field']['id'] ) . '" aria-label="' . esc_attr( $defaults['remove_label'] ) . '">' . $args['remove_icon'] . $args['remove_label'] . '</a> '; $triggers .= '</div>'; return $triggers; } }