548 lines
17 KiB
PHP
548 lines
17 KiB
PHP
<?php
|
|
/**
|
|
* Form Builder Component Class.
|
|
*
|
|
* @package fusion-builder
|
|
* @since 3.1
|
|
*/
|
|
|
|
// Do not allow directly accessing this file.
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit( 'Direct script access denied.' );
|
|
}
|
|
|
|
|
|
/**
|
|
* Form Builder Component Class.
|
|
*
|
|
* @since 3.1
|
|
*/
|
|
abstract class Fusion_Form_Component extends Fusion_Element {
|
|
|
|
/**
|
|
* Global form options.
|
|
*
|
|
* @access public
|
|
* @since 3.1
|
|
* @var array
|
|
*/
|
|
public $params = [];
|
|
|
|
/**
|
|
* Shortcode handle.
|
|
*
|
|
* @access public
|
|
* @since 3.1
|
|
* @var string
|
|
*/
|
|
public $shortcode_handle = '';
|
|
|
|
/**
|
|
* The number of elements.
|
|
*
|
|
* @var int
|
|
*/
|
|
public $counter = 0;
|
|
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @since 3.1
|
|
* @param string $shortcode_handle Shortcode Handle.
|
|
*/
|
|
public function __construct( $shortcode_handle ) {
|
|
parent::__construct();
|
|
$this->shortcode_handle = $shortcode_handle;
|
|
add_shortcode( $this->shortcode_handle, [ $this, 'render' ] );
|
|
}
|
|
|
|
/**
|
|
* Get the element default arguments.
|
|
*
|
|
* @return array
|
|
*/
|
|
abstract public static function get_element_defaults();
|
|
|
|
/**
|
|
* Render the shortcode
|
|
*
|
|
* @access public
|
|
* @since 2.2
|
|
* @param array $args Shortcode parameters.
|
|
* @param string $content Content between shortcode.
|
|
* @return string HTML output.
|
|
*/
|
|
public function render( $args, $content = '' ) {
|
|
$this->counter++;
|
|
|
|
$defaults = FusionBuilder::set_shortcode_defaults( $this->get_element_defaults(), $args, $this->shortcode_handle );
|
|
$content = apply_filters( 'fusion_shortcode_content', $content, $this->shortcode_handle, $args );
|
|
|
|
$this->args = $defaults;
|
|
|
|
$html = $this->get_form_field( $content );
|
|
|
|
$this->on_render();
|
|
|
|
return apply_filters( 'fusion_form_component_' . $this->shortcode_handle . '_content', $html, $args );
|
|
}
|
|
|
|
/**
|
|
* Creates all meta data for the form elements.
|
|
*
|
|
* @since 3.1
|
|
* @access public
|
|
* @param array $args All needed values for the form field.
|
|
* @return string The meta data of a form element.
|
|
*/
|
|
public function create_element_data( $args ) {
|
|
$data = [
|
|
'checked' => '',
|
|
'disabled' => '',
|
|
'required' => '',
|
|
'invalid_notice' => '',
|
|
'empty_notice' => '',
|
|
'required_label' => '',
|
|
'required_placeholder' => '',
|
|
'placeholder' => '',
|
|
'label' => '',
|
|
'label_class' => '',
|
|
'style' => '',
|
|
'holds_private_data' => 'no',
|
|
'upload_size' => '',
|
|
'pattern' => '',
|
|
];
|
|
|
|
$is_hidden = isset( $args['hidden'] ) && $args['hidden'];
|
|
|
|
if ( ! $args ) {
|
|
return $data;
|
|
}
|
|
|
|
// TODO: move input specific code to own file.
|
|
if ( 'fusion_form_checkbox' === $this->shortcode_handle && isset( $args['checked'] ) && $args['checked'] ) {
|
|
$data['checked'] = ' checked="checked"';
|
|
}
|
|
|
|
if ( 'fusion_form_upload' === $this->shortcode_handle && isset( $args['upload_size'] ) && $args['upload_size'] ) {
|
|
$data['upload_size'] = ' data-size="' . esc_attr( $args['upload_size'] ) . '"';
|
|
}
|
|
|
|
if ( isset( $args['required'] ) && ( 'yes' === $args['required'] || 'selection' === $args['required'] ) ) {
|
|
if ( 'selection' !== $args['required'] ) {
|
|
$data['required'] = ' required="true" aria-required="true"';
|
|
}
|
|
$data['required_label_text'] = __( 'required', 'fusion-builder' );
|
|
if ( ! empty( $args['required_label_text'] ) ) {
|
|
$data['required_label_text'] = $args['required_label_text'];
|
|
}
|
|
|
|
$data['required_label'] = ' <abbr class="fusion-form-element-required" title="' . esc_attr( $data['required_label_text'] ) . '">*</abbr>';
|
|
$data['required_placeholder'] = '*';
|
|
|
|
if ( isset( $args['empty_notice'] ) && '' !== $args['empty_notice'] ) {
|
|
$data['empty_notice'] = $args['empty_notice'];
|
|
}
|
|
}
|
|
|
|
if ( isset( $args['disabled'] ) && 'yes' === $args['disabled'] ) {
|
|
$data['disabled'] = ' disabled';
|
|
|
|
if ( isset( $args['placeholder'] ) && '' !== $args['placeholder'] ) {
|
|
$data['value'] = $args['placeholder'];
|
|
}
|
|
}
|
|
|
|
$data['class'] = ' class="fusion-form-input"';
|
|
|
|
if ( isset( $args['placeholder'] ) && '' !== $args['placeholder'] ) {
|
|
if ( 'fusion_form_select' === $this->shortcode_handle ) {
|
|
$data['placeholder'] = [ $args['placeholder'] . ' ' . $data['required_placeholder'] ];
|
|
} else {
|
|
$data['placeholder'] = ' placeholder="' . esc_attr( $args['placeholder'] . ' ' . $data['required_placeholder'] ) . '"';
|
|
}
|
|
}
|
|
|
|
if ( isset( $args['label'] ) && '' !== $args['label'] && ! $is_hidden ) {
|
|
$non_label_elements = [ 'fusion_form_radio', 'fusion_form_checkbox', 'fusion_form_image_select', 'fusion_form_rating' ];
|
|
|
|
if ( 'fusion_form_checkbox' === $this->shortcode_handle ) {
|
|
$data['label_class'] = ' class="fusion-form-checkbox-label"';
|
|
}
|
|
|
|
$tag_open = '<label for="' . esc_attr( $args['name'] ) . '"' . esc_attr( $data['label_class'] ) . '>';
|
|
$tag_close = '</label>';
|
|
|
|
if ( in_array( $this->shortcode_handle, $non_label_elements, true ) ) {
|
|
$tag_open = '<span class="label">';
|
|
$tag_close = '</span>';
|
|
}
|
|
|
|
$data['label'] = $tag_open . esc_html( $args['label'] ) . $data['required_label'] . $tag_close;
|
|
}
|
|
|
|
$data['holds_private_data'] = ' data-holds-private-data="false"';
|
|
if ( isset( $args['holds_private_data'] ) && $args['holds_private_data'] ) {
|
|
$data['holds_private_data'] = ' data-holds-private-data="true"';
|
|
}
|
|
|
|
$data['input_attributes'] = '';
|
|
|
|
// Number field min and max.
|
|
if ( isset( $args['min'] ) && is_numeric( $args['min'] ) ) {
|
|
$data['input_attributes'] .= ' min="' . $args['min'] . '"';
|
|
}
|
|
|
|
if ( isset( $args['max'] ) && is_numeric( $args['max'] ) ) {
|
|
$data['input_attributes'] .= ' max="' . $args['max'] . '"';
|
|
}
|
|
|
|
if ( isset( $args['must_match'] ) && '' !== $args['must_match'] ) {
|
|
$data['input_attributes'] = ' data-must-match="' . $args['must_match'] . '"';
|
|
}
|
|
|
|
// Text field minlength and maxlength.
|
|
if ( isset( $args['minlength'] ) && is_numeric( $args['minlength'] ) ) {
|
|
$data['input_attributes'] .= ' minlength="' . $args['minlength'] . '"';
|
|
}
|
|
if ( isset( $args['maxlength'] ) && ! empty( $args['maxlength'] ) ) {
|
|
$data['input_attributes'] .= ' maxlength="' . $args['maxlength'] . '"';
|
|
}
|
|
|
|
if ( isset( $args['invalid_notice'] ) && '' !== $args['invalid_notice'] ) {
|
|
$data['invalid_notice'] = $args['invalid_notice'];
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Generate and returns tooltip html for the input field.
|
|
*
|
|
* @since 3.1
|
|
* @access public
|
|
* @param array $args All needed values for the form field.
|
|
* @return string $html HTML for tooltip.
|
|
*/
|
|
public function get_field_tooltip( $args ) {
|
|
global $fusion_form;
|
|
$html = '';
|
|
|
|
if ( '' !== $args['tooltip'] ) {
|
|
$html .= '<div class="fusion-form-tooltip">';
|
|
$html .= '<i class="awb-icon-question-circle"></i>';
|
|
$html .= '<span class="fusion-form-tooltip-content">' . $args['tooltip'] . '</span>';
|
|
$html .= '</div>';
|
|
}
|
|
|
|
return $html;
|
|
}
|
|
|
|
/**
|
|
* Renders normal text inputs.
|
|
*
|
|
* @since 3.1
|
|
* @access private
|
|
* @param array $args All needed values for the form field.
|
|
* @param string $type The type of the input, e.g. text, number, email.
|
|
* @return string The text input element.
|
|
*/
|
|
public function generate_input_field( $args, $type = 'text' ) {
|
|
global $fusion_form;
|
|
|
|
$html = '';
|
|
$element_data = $this->create_element_data( $args );
|
|
|
|
if ( '' !== $args['tooltip'] ) {
|
|
$element_data['label'] .= $this->get_field_tooltip( $args );
|
|
}
|
|
|
|
$args['value'] = isset( $args['value'] ) ? $args['value'] : ( isset( $element_data['value'] ) ? $element_data['value'] : '' );
|
|
|
|
$element_html = '<input type="' . $type . '" ';
|
|
|
|
$autocomplete = 'custom' === $args['autocomplete'] ? $args['autocomplete_custom'] : $args['autocomplete'];
|
|
$element_html .= 'autocomplete="' . esc_attr( $autocomplete ) . '" ';
|
|
|
|
if ( 'hidden' !== $type && '' !== $this->args['tab_index'] ) {
|
|
$element_html .= 'tabindex="' . $this->args['tab_index'] . '" ';
|
|
}
|
|
|
|
$args['name'] = esc_attr( $args['name'] );
|
|
$args['value'] = esc_attr( $args['value'] );
|
|
|
|
$element_html .= 'text' === $type && isset( $args['pattern'] ) && '' !== $args['pattern'] ? $this->add_pattern( $args ) : '';
|
|
$element_html .= in_array( $type, [ 'email', 'password', 'tel' ], true ) && isset( $args['pattern'] ) && '' !== $args['pattern'] ? ' pattern="' . fusion_decode_if_needed( $args['pattern'] ) . '" ' : '';
|
|
$element_html .= '' !== $element_data['invalid_notice'] ? ' data-invalid-notice="' . $element_data['invalid_notice'] . '" ' : '';
|
|
$element_html .= '' !== $element_data['empty_notice'] ? ' data-empty-notice="' . $element_data['empty_notice'] . '" ' : '';
|
|
$element_html .= 'name="' . $args['name'] . '" id="' . $args['name'] . '" value="' . $args['value'] . '" ' . $element_data['class'] . $element_data['required'] . $element_data['disabled'] . $element_data['placeholder'] . $element_data['style'] . $element_data['holds_private_data'] . $element_data['input_attributes'] . $element_data['pattern'] . '/>';
|
|
|
|
$icon_wrapper_open = '';
|
|
if ( isset( $args['input_field_icon'] ) && '' !== $args['input_field_icon'] ) {
|
|
$icon_wrapper_open = '<div class="fusion-form-input-with-icon">';
|
|
$icon_html = '<i class="awb-form-icon ' . fusion_font_awesome_name_handler( $args['input_field_icon'] ) . '"></i>';
|
|
$element_html = $icon_html . $element_html;
|
|
}
|
|
|
|
if ( 'password' === $type && 'yes' === $this->args['reveal_password'] ) {
|
|
if ( '' === $icon_wrapper_open ) {
|
|
$icon_wrapper_open = '<div class="fusion-form-input-with-icon awb-form-pw-reveal">';
|
|
} else {
|
|
$icon_wrapper_open = str_replace( 'fusion-form-input-with-icon', 'fusion-form-input-with-icon awb-form-pw-reveal awb-form-both-icons', $icon_wrapper_open );
|
|
}
|
|
$element_html .= '<i class="awb-form-pw-reveal-icon awb-icon-eye-slash" id="' . $args['name'] . '_' . $this->counter . '"></i>';
|
|
}
|
|
|
|
$element_html = $icon_wrapper_open . $element_html;
|
|
$element_html .= '' === $icon_wrapper_open ? '' : '</div>';
|
|
|
|
if ( '' !== $element_data['label'] ) {
|
|
$element_data['label'] = '<div class="fusion-form-label-wrapper">' . $element_data['label'] . '</div>';
|
|
}
|
|
|
|
if ( 'above' === $fusion_form['form_meta']['label_position'] ) {
|
|
$html .= $element_data['label'] . $element_html;
|
|
} else {
|
|
$html .= $element_html . $element_data['label'];
|
|
}
|
|
|
|
return $html;
|
|
}
|
|
|
|
/**
|
|
* Adds pattern attribute to text field.
|
|
*
|
|
* @since 3.8
|
|
* @access public
|
|
* @param array $args All needed values for the form field.
|
|
* @return string The updated HTML.
|
|
*/
|
|
public function add_pattern( $args ) {
|
|
$patterns = [
|
|
'letters' => '[a-zA-Z]+',
|
|
'alpha_numeric' => '[a-zA-Z0-9]+',
|
|
'number' => '[0-9]+',
|
|
'credit_card_number' => '[0-9]{13,16}',
|
|
'phone' => '[0-9()#&+*-=.]+',
|
|
'url' => '(http(s)?:\/\/.)?(www\.)?[\-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([\-a-zA-Z0-9@:%_\+.~#?&\/\/=]*)',
|
|
];
|
|
|
|
return isset( $patterns[ $args['pattern'] ] ) ? ' pattern="' . $patterns[ $args['pattern'] ] . '" ' : ' pattern="' . fusion_decode_if_needed( $args['custom_pattern'] ) . '" ';
|
|
}
|
|
|
|
/**
|
|
* Renders checkbox inputs.
|
|
*
|
|
* @since 3.1
|
|
* @access private
|
|
* @param array $args All needed values for the form field.
|
|
* @param string $type The type of the input, e.g. radio, checkbox.
|
|
* @return string The checkbox input element.
|
|
*/
|
|
public function checkbox( $args, $type = 'checkbox' ) {
|
|
global $fusion_form;
|
|
|
|
$options = '';
|
|
$html = '';
|
|
|
|
if ( empty( $args['options'] ) ) {
|
|
return $html;
|
|
} else {
|
|
$args['options'] = json_decode( fusion_decode_if_needed( $args['options'] ), true );
|
|
}
|
|
|
|
$element_data = $this->create_element_data( $args );
|
|
|
|
foreach ( $args['options'] as $key => $option ) {
|
|
$checked = $option[0] ? ' checked ' : '';
|
|
$label = trim( $option[1] );
|
|
$value = isset( $option[2] ) && '' !== $option[2] ? trim( $option[2] ) : $label;
|
|
|
|
$name = empty( $args['name'] ) ? $args['label'] : $args['name'];
|
|
$element_name = ( 'checkbox' === $type ) ? $name . '[]' : $name;
|
|
|
|
$checkbox_class = ( 'floated' === $args['form_field_layout'] ) ? 'fusion-form-' . $type . ' option-inline' : 'fusion-form-' . $type;
|
|
$label_id = $type . '-' . str_replace( ' ', '-', strtolower( $name ) ) . '-' . $this->counter . '-' . $key;
|
|
$options .= '<div class="' . $checkbox_class . '">';
|
|
$options .= '<input ';
|
|
$options .= '' !== $element_data['empty_notice'] ? 'data-empty-notice="' . $element_data['empty_notice'] . '" ' : '';
|
|
$options .= 'tabindex="' . $args['tab_index'] . '" id="' . $label_id . '" type="' . $type . '" value="' . $value . '" name="' . $element_name . '"' . $element_data['class'] . $element_data['required'] . $checked . $element_data['holds_private_data'] . '/>';
|
|
$options .= '<label for="' . $label_id . '">';
|
|
$options .= $label . '</label>';
|
|
$options .= '</div>';
|
|
}
|
|
|
|
$fieldset_attr_string = '';
|
|
if ( isset( $args['fieldset_attr_string'] ) && $args['fieldset_attr_string'] ) {
|
|
$fieldset_attr_string = ' ' . $args['fieldset_attr_string'];
|
|
}
|
|
$element_html = '<fieldset' . $fieldset_attr_string . '>';
|
|
$element_html .= $options;
|
|
$element_html .= '</fieldset>';
|
|
|
|
if ( '' !== $args['tooltip'] ) {
|
|
$element_data['label'] .= $this->get_field_tooltip( $args );
|
|
}
|
|
|
|
if ( '' !== $element_data['label'] ) {
|
|
$element_data['label'] = '<div class="fusion-form-label-wrapper">' . $element_data['label'] . '</div>';
|
|
}
|
|
|
|
if ( 'above' === $fusion_form['form_meta']['label_position'] ) {
|
|
$html .= $element_data['label'] . $element_html;
|
|
} else {
|
|
$html .= $element_html . $element_data['label'];
|
|
}
|
|
|
|
return $html;
|
|
}
|
|
|
|
/**
|
|
* Adds field data to the form.
|
|
*
|
|
* @access public
|
|
* @since 3.1
|
|
* @return void
|
|
*/
|
|
public function add_field_data_to_form() {
|
|
global $fusion_form;
|
|
|
|
if ( ! isset( $fusion_form['form_fields'] ) ) {
|
|
$fusion_form['form_fields'] = [];
|
|
}
|
|
|
|
$fusion_form['form_fields'][] = $this->shortcode_handle;
|
|
|
|
if ( isset( $this->args['label'] ) ) {
|
|
$fusion_form['field_labels'][ $this->args['name'] ] = $this->args['label'];
|
|
}
|
|
|
|
$field_name = str_replace( 'fusion_form_', '', $this->shortcode_handle );
|
|
$name = isset( $this->args['name'] ) ? $this->args['name'] : $field_name . '_' . $this->counter;
|
|
|
|
if ( isset( $this->args['logics'] ) ) {
|
|
$fusion_form['field_logics'][ $name ] = base64_decode( $this->args['logics'] );
|
|
}
|
|
$fusion_form['field_types'][ $name ] = $field_name;
|
|
}
|
|
|
|
/**
|
|
* Adds field wrapper html.
|
|
*
|
|
* @access public
|
|
* @since 3.1
|
|
* @return string
|
|
*/
|
|
public function add_field_wrapper_html() {
|
|
$label_position = 'above';
|
|
|
|
if ( $this->params['form_meta']['label_position'] ) {
|
|
$label_position = $this->params['form_meta']['label_position'];
|
|
}
|
|
|
|
$html = '<div ';
|
|
|
|
// Add custom ID if it's there.
|
|
if ( isset( $this->args['id'] ) && '' !== $this->args['id'] ) {
|
|
$html .= 'id="' . esc_attr( $this->args['id'] ) . '" ';
|
|
}
|
|
|
|
// Start building class.
|
|
$html .= 'class="fusion-form-field ' . str_replace( '_', '-', $this->shortcode_handle ) . '-field fusion-form-label-' . $label_position;
|
|
|
|
// Add custom class if it's there.
|
|
if ( isset( $this->args['class'] ) && '' !== $this->args['class'] ) {
|
|
$html .= ' ' . esc_attr( $this->args['class'] );
|
|
}
|
|
|
|
// Hide field if it has got logics.
|
|
if ( isset( $this->args['logics'] ) && '' !== $this->args['logics'] && '[]' !== base64_decode( $this->args['logics'] ) ) {
|
|
$html .= ' fusion-form-field-hidden';
|
|
}
|
|
|
|
// Close class quotes.
|
|
$html .= '"';
|
|
|
|
$html .= ' style="' . $this->get_style_variables() . '"';
|
|
|
|
$html .= ' data-form-id="' . $this->params['form_number'] . '">';
|
|
|
|
return $html;
|
|
}
|
|
|
|
/**
|
|
* Get the style variables.
|
|
*
|
|
* @access protected
|
|
* @since 3.9
|
|
* @return string
|
|
*/
|
|
public function get_style_variables() {
|
|
return '';
|
|
}
|
|
|
|
/**
|
|
* Get the global $fusion_form value.
|
|
*
|
|
* @access public
|
|
* @since 3.1
|
|
* @return array
|
|
*/
|
|
public function get_form_data() {
|
|
global $fusion_form;
|
|
|
|
if ( ! isset( $fusion_form['id'] ) ) {
|
|
if ( fusion_doing_ajax() && isset( $_POST['post_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
|
$fusion_form = Fusion_Builder_Form_Helper::fusion_form_set_form_data( (int) sanitize_text_field( wp_unslash( $_POST['post_id'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification
|
|
} elseif ( ! fusion_doing_ajax() && isset( $_POST['post_ID'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
|
$fusion_form = Fusion_Builder_Form_Helper::fusion_form_set_form_data( (int) sanitize_text_field( wp_unslash( $_POST['post_ID'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification
|
|
} elseif ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
|
|
|
|
// We need default form params, otherwise REST request triggers PHP notices when content is rendered.
|
|
$fusion_form = Fusion_Builder_Form_Helper::fusion_form_set_form_data( 0 );
|
|
}
|
|
}
|
|
|
|
return $fusion_form;
|
|
}
|
|
|
|
/**
|
|
* Render form field html.
|
|
*
|
|
* @access public
|
|
* @since 3.1
|
|
* @param string $content The content.
|
|
* @return string
|
|
*/
|
|
public function get_form_field( $content ) {
|
|
global $fusion_form;
|
|
|
|
// Add form data to form element.
|
|
if ( empty( $this->params ) || $this->params['id'] !== $fusion_form['id'] ) {
|
|
$this->params = $this->get_form_data();
|
|
}
|
|
|
|
// Add form element data to a form.
|
|
$this->add_field_data_to_form();
|
|
|
|
// Get form input html.
|
|
$html = $this->add_field_wrapper_html();
|
|
$html .= $this->render_input_field( $content );
|
|
$html .= '</div>';
|
|
|
|
return $html;
|
|
}
|
|
|
|
/**
|
|
* Render form input field html.
|
|
*
|
|
* @access public
|
|
* @since 3.1
|
|
* @param string $content The content.
|
|
* @return false
|
|
*/
|
|
public function render_input_field( $content ) {
|
|
return false;
|
|
}
|
|
}
|