', esc_attr( $type ), esc_attr( $type ) ); switch ( $type ) { case 'field': /* * This settings block is for a field. */ // Define more data for this field. $fields_instance = $args['instance']; $field_id = absint( $field['id'] ); $field_name = "fields[{$field_id}]"; $groups_id = "wpforms-conditional-groups-fields-{$field_id}"; $action_selected = ! empty( $field['conditional_type'] ) ? $field['conditional_type'] : ''; $conditionals = ! empty( $field['conditionals'] ) ? $field['conditionals'] : array( array( array() ) ); $data_attrs = 'data-field-id="' . $field_id . '" '; $reference = $field_id; $enabled = isset( $field['conditional_logic'] ) ? $field['conditional_logic'] : false; $action_desc = ! empty( $args['action_desc'] ) ? $args['action_desc'] : esc_html__( 'this field if', 'wpforms-lite' ); if ( empty( $args['actions'] ) ) { $actions = array( 'show' => esc_attr__( 'Show', 'wpforms-lite' ), 'hide' => esc_attr__( 'Hide', 'wpforms-lite' ), ); } else { $actions = array_map( 'esc_attr', $args['actions'] ); } // Output Conditional Logic toggle checkbox field option. $fld = $fields_instance->field_element( 'checkbox', $field, array( 'slug' => 'conditional_logic', 'value' => $enabled, 'desc' => esc_html__( 'Enable conditional logic', 'wpforms-lite' ), 'tooltip' => '' . esc_html__( 'How to use Conditional Logic', 'wpforms-lite' ) . '', 'data' => array( 'name' => $field_name, 'actions' => $actions, 'action-desc' => esc_attr( $action_desc ), ), ), false ); $fields_instance->field_element( 'row', $field, array( 'slug' => 'conditional_logic', 'content' => $fld, 'class' => 'wpforms-conditionals-enable-toggle', ) ); // Prevent conditional logic from being applied to itself. if ( ! empty( $form_fields[ $field['id'] ] ) ) { unset( $form_fields[ $field['id'] ] ); } break; case 'panel': /* * This settings block is for something else - connections / notifications etc. */ $form_data = $args['form']; $action_desc = ! empty( $args['action_desc'] ) ? $args['action_desc'] : esc_html__( 'this connection if', 'wpforms-lite' ); if ( empty( $args['actions'] ) ) { $actions = array( 'go' => esc_attr__( 'Process', 'wpforms-lite' ), 'stop' => esc_attr__( 'Don\'t process', 'wpforms-lite' ), ); } else { $actions = array_map( 'esc_attr', $args['actions'] ); } // Below we do a bunch of voodoo to determine where this block // is located in the form builder - eg is it in a top level // setting or in a subsection, etc. if ( ! empty( $parent ) ) { if ( ! empty( $subsection ) ) { $field_name = sprintf( '%s[%s][%s]', $parent, $panel, $subsection ); $groups_id = sprintf( 'wpforms-conditional-groups-%s-%s-%s', $parent, $panel, $subsection ); $enabled = ! empty( $form_data[ $parent ][ $panel ][ $subsection ]['conditional_logic'] ) ? true : false; $action_selected = ! empty( $form_data[ $parent ][ $panel ][ $subsection ]['conditional_type'] ) ? $form_data[ $parent ][ $panel ][ $subsection ]['conditional_type'] : ''; $conditionals = ! empty( $form_data[ $parent ][ $panel ][ $subsection ]['conditionals'] ) ? $form_data[ $parent ][ $panel ][ $subsection ]['conditionals'] : array( array( array() ) ); } else { $field_name = sprintf( '%s[%s]', $parent, $panel ); $groups_id = sprintf( 'wpforms-conditional-groups-%s-%s', $parent, $panel ); $enabled = ! empty( $form_data[ $parent ][ $panel ]['conditional_logic'] ) ? true : false; $action_selected = ! empty( $form_data[ $parent ][ $panel ]['conditional_type'] ) ? $form_data[ $parent ][ $panel ]['conditional_type'] : ''; $conditionals = ! empty( $form_data[ $parent ][ $panel ]['conditionals'] ) ? $form_data[ $parent ][ $panel ]['conditionals'] : array( array( array() ) ); } } else { $field_name = sprintf( '%s', $panel ); $groups_id = sprintf( 'wpforms-conditional-groups-%s', $panel ); $enabled = ! empty( $form_data[ $panel ]['conditional_logic'] ) ? true : false; $action_selected = ! empty( $form_data[ $panel ]['conditional_type'] ) ? $form_data[ $panel ]['conditional_type'] : ''; $conditionals = ! empty( $form_data[ $panel ]['conditionals'] ) ? $form_data[ $panel ]['conditionals'] : array( array( array() ) ); } // Output Conditional Logic toggle checkbox panel setting. wpforms_panel_field( 'checkbox', $panel, 'conditional_logic', $args['form'], esc_html__( 'Enable conditional logic', 'wpforms-lite' ), array( 'tooltip' => '' . esc_html__( 'How to use Conditional Logic', 'wpforms-lite' ) . '', 'parent' => $parent, 'subsection' => $subsection, 'input_id' => 'wpforms-panel-field-' . implode( '-', array_filter( array( $parent, $panel, $subsection, 'conditional_logic', 'checkbox' ) ) ), 'input_class' => 'wpforms-panel-field-conditional_logic-checkbox', 'class' => 'wpforms-conditionals-enable-toggle', 'data' => array( 'name' => $field_name, 'actions' => $actions, 'action-desc' => esc_attr( $action_desc ), ), ) ); break; default: $enabled = false; $field_name = ''; $reference = ''; $action_selected = ''; $action_desc = ''; $groups_id = ''; $actions = array(); $conditionals = array(); } // Only display the block details if conditional logic is enabled. if ( $enabled ) : $data_attrs .= 'data-input-name="' . esc_attr( $field_name ) . '"'; $style = $enabled ? '' : 'display:none;'; // Groups wrap open markup. printf( '
', sanitize_html_class( $groups_id ), esc_attr( $style ) ); // This is the "[Show] this field if" type text and setting. echo '

'; echo ''; echo esc_html( $action_desc ); // Eg "this field if". echo '

'; // Go through each conditional logic group. foreach ( $conditionals as $group_id => $group ) : // Individual group open markup. echo '
'; echo ''; foreach ( $group as $rule_id => $rule ) : $selected_current = false; // Individual rule table row. echo ''; // Rule field - allows the user to select // which field the conditional logic rule is // anchored to. echo ''; // Rule operator - allows the user to // determine the comparison operator used // for processing. echo ''; // Rule value - allows the user to // determine the value we are using for // comparison. echo ''; // Rule actions. echo ''; echo ''; // Close individual rule table row. endforeach; // End foreach() for individual rules. echo '
'; printf( ''; echo ''; printf( ''; echo ''; if ( isset( $rule['field'] ) ) { // For empty/not empty fields the field value input is not needed so we disable it. if ( ! empty( $rule['operator'] ) && in_array( $rule['operator'], array( 'e', '!e' ), true ) ) { $disabled = 'disabled'; $rule['value'] = ''; } else { $disabled = ''; } if ( isset( $form_fields[ $rule['field'] ]['type'] ) && in_array( $form_fields[ $rule['field'] ]['type'], array( 'text', 'textarea', 'email', 'url', 'number', 'hidden', 'rating', 'net_promoter_score' ), true ) ) { $type = in_array( $form_fields[ $rule['field'] ]['type'], array( 'rating', 'net_promoter_score' ), true ) ? 'number' : 'text'; printf( '', $type, $field_name, $group_id, $rule_id, esc_attr( $rule['value'] ), $disabled ); } else { printf( ''; } } else { echo ''; } // End if(). echo ''; echo ''; echo ''; echo '
'; echo '
' . esc_html_x( 'or', 'Conditional Logic: new rule logic.', 'wpforms-lite' ) . '
'; echo '
'; // Close individual group markup. endforeach; // End foreach() for conditional logic groups. echo ''; echo '
'; // Close Groups wrap markup. endif; // End $enabled. echo ''; // Close block markup. $output = ob_get_clean(); if ( $echo ) { echo $output; //phpcs:ignore } else { return $output; } } /** * Alias method for backwards compatibility. * * @since 1.1.0 * @deprecated 1.3.8 Use wpforms_conditional_logic()->builder_block() instead. * * @param array $args Data needed for a block to be generated properly. * @param bool $echo Whether to return or print. Default: print. * * @return string */ public function conditionals_block( $args = array(), $echo = true ) { if ( $echo ) { echo $this->builder_block( $args, $echo ); //phpcs:ignore } else { return $this->builder_block( $args, $echo ); } } /** * Process conditional rules. * * Checks if a form passes the conditional logic rules that are provided. * * @since 1.3.8 * * @param array $fields List of fields with data and settings. * @param array $form_data Form data and settings. * @param array $conditionals List of conditionals. * * @return bool */ public function process( $fields, $form_data, $conditionals ) { if ( empty( $conditionals ) ) { return true; } $pass = false; foreach ( $conditionals as $group_id => $group ) { $pass_group = true; if ( ! empty( $group ) ) { foreach ( $group as $rule_id => $rule ) { if ( ! isset( $rule['field'] ) || '' == $rule['field'] || ! isset( $rule['operator'] ) ) { continue; } if ( ! isset( $rule['value'] ) && ! in_array( $rule['operator'], array( 'e', '!e' ), true ) ) { continue; } $rule_field = $rule['field']; $rule_operator = $rule['operator']; $rule_value = isset( $rule['value'] ) ? $rule['value'] : ''; if ( in_array( $fields[ $rule_field ]['type'], array( 'text', 'textarea', 'email', 'url', 'number', 'hidden', 'rating', 'net_promoter_score' ), true ) ) { // Text based fields. $left = trim( strtolower( $fields[ $rule_field ]['value'] ) ); $right = trim( strtolower( $rule_value ) ); switch ( $rule_operator ) { case '==': $pass_rule = ( $left == $right ); break; case '!=': $pass_rule = ( $left != $right ); break; case 'c': $pass_rule = ( strpos( $left, $right ) !== false ); break; case '!c': $pass_rule = ( strpos( $left, $right ) === false ); break; case '^': $pass_rule = ( strrpos( $left, $right, -strlen( $left ) ) !== false ); break; case '~': $pass_rule = ( ( $temp = strlen( $left ) - strlen( $right ) ) >= 0 && strpos( $left, $right, $temp ) !== false ); break; case 'e': $pass_rule = ( '' == $left ); break; case '!e': $pass_rule = ( '' != $left ); break; case '>': $left = preg_replace( '/[^0-9.]/', '', $left ); $pass_rule = ( '' !== $left ) && ( floatval( $left ) > floatval( $right ) ); break; case '<': $left = preg_replace( '/[^0-9.]/', '', $left ); $pass_rule = ( '' !== $left ) && ( floatval( $left ) < floatval( $right ) ); break; default: $pass_rule = apply_filters( 'wpforms_process_conditional_logic', false, $rule_operator, $left, $right ); break; } } else { // Selector based fields. $provided_id = false; if ( in_array( $fields[ $rule_field ]['type'], array( 'payment-multiple', 'payment-checkbox', 'payment-select' ), true ) && isset( $fields[ $rule_field ]['value_raw'] ) && '' != $fields[ $rule_field ]['value_raw'] ) { // Payment Multiple/Checkbox fields store the option key, // so we can reference that easily. $provided_id = $fields[ $rule_field ]['value_raw']; } elseif ( isset( $fields[ $rule_field ]['value'] ) && '' != $fields[ $rule_field ]['value'] ) { // Other select type fields we don't store the // option key so we have to do the logic to locate // it ourselves. $provided_id = array(); if ( 'checkbox' === $fields[ $rule_field ]['type'] ) { $values = explode( "\n", $fields[ $rule_field ]['value'] ); } else { $values = (array) $fields[ $rule_field ]['value']; } foreach ( $form_data['fields'][ $rule_field ]['choices'] as $key => $choice ) { $choice = array_map( 'sanitize_text_field', $choice ); foreach ( $values as $value ) { $value = wpforms_decode_string( $value ); if ( in_array( $value, $choice, true ) ) { $provided_id[] = $key; } } } } $left = (array) $provided_id; $right = strtolower( trim( (int) $rule_value ) ); switch ( $rule_operator ) { case '==': case 'c': // BC, no longer available. case '^': // BC, no longer available. case '~': // BC, no longer available. $pass_rule = in_array( $right, $left ); break; case '!=': case '!c': // BC, no longer available. $pass_rule = ! in_array( $right, $left ); break; case 'e': $pass_rule = ( false === $left[0] ); break; case '!e': $pass_rule = ( false !== $left[0] ); break; default: $pass_rule = apply_filters( 'wpforms_process_conditional_logic', false, $rule_operator, $left, $right ); break; } } // End if(). if ( ! $pass_rule ) { $pass_group = false; break; } } // End foreach(). } // End if(). if ( $pass_group ) { $pass = true; } } // End foreach(). return $pass; } /** * Alias function for backwards compatibility. * * @since 1.0.0 * * @param array $fields List of fields with data and settings. * @param array $form_data Form data and settings. * @param array $conditionals List of conditionals. * * @return bool */ public function conditionals_process( $fields, $form_data, $conditionals ) { return $this->process( $fields, $form_data, $conditionals ); } } /** * The function which returns the one WPForms_Conditional_Logic_Core instance. * * Use this function like you would a global variable, except without needing * to declare the global. * * @since 1.1.0 * * @return WPForms_Conditional_Logic_Core */ function wpforms_conditional_logic() { return WPForms_Conditional_Logic_Core::instance(); } wpforms_conditional_logic();