Commit realizado el 12:13:52 08-04-2024
This commit is contained in:
3186
wp-content/plugins/wpforms-lite/includes/fields/class-base.php
Normal file
3186
wp-content/plugins/wpforms-lite/includes/fields/class-base.php
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,780 @@
|
||||
<?php
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checkbox field.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class WPForms_Field_Checkbox extends WPForms_Field {
|
||||
|
||||
/**
|
||||
* Primary class constructor.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
// Define field type information.
|
||||
$this->name = esc_html__( 'Checkboxes', 'wpforms-lite' );
|
||||
$this->keywords = esc_html__( 'choice', 'wpforms-lite' );
|
||||
$this->type = 'checkbox';
|
||||
$this->icon = 'fa-check-square-o';
|
||||
$this->order = 110;
|
||||
$this->defaults = [
|
||||
1 => [
|
||||
'label' => esc_html__( 'First Choice', 'wpforms-lite' ),
|
||||
'value' => '',
|
||||
'image' => '',
|
||||
'icon' => '',
|
||||
'icon_style' => '',
|
||||
'default' => '',
|
||||
],
|
||||
2 => [
|
||||
'label' => esc_html__( 'Second Choice', 'wpforms-lite' ),
|
||||
'value' => '',
|
||||
'image' => '',
|
||||
'icon' => '',
|
||||
'icon_style' => '',
|
||||
'default' => '',
|
||||
],
|
||||
3 => [
|
||||
'label' => esc_html__( 'Third Choice', 'wpforms-lite' ),
|
||||
'value' => '',
|
||||
'image' => '',
|
||||
'icon' => '',
|
||||
'icon_style' => '',
|
||||
'default' => '',
|
||||
],
|
||||
];
|
||||
|
||||
$this->hooks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Hooks.
|
||||
*
|
||||
* @since 1.8.1
|
||||
*/
|
||||
private function hooks() {
|
||||
|
||||
// Customize HTML field values.
|
||||
add_filter( 'wpforms_html_field_value', [ $this, 'field_html_value' ], 10, 4 );
|
||||
|
||||
// Define additional field properties.
|
||||
add_filter( 'wpforms_field_properties_checkbox', [ $this, 'field_properties' ], 5, 3 );
|
||||
|
||||
// This field requires fieldset+legend instead of the field label.
|
||||
add_filter( "wpforms_frontend_modern_is_field_requires_fieldset_{$this->type}", '__return_true', PHP_INT_MAX, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Define additional field properties.
|
||||
*
|
||||
* @since 1.4.5
|
||||
*
|
||||
* @param array $properties Field properties.
|
||||
* @param array $field Field settings.
|
||||
* @param array $form_data Form data and settings.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function field_properties( $properties, $field, $form_data ) {
|
||||
|
||||
// Define data.
|
||||
$form_id = absint( $form_data['id'] );
|
||||
$field_id = absint( $field['id'] );
|
||||
$choices = $field['choices'];
|
||||
$dynamic = wpforms_get_field_dynamic_choices( $field, $form_id, $form_data );
|
||||
|
||||
if ( $dynamic !== false ) {
|
||||
$choices = $dynamic;
|
||||
$field['show_values'] = true;
|
||||
}
|
||||
|
||||
// Remove primary input.
|
||||
unset( $properties['inputs']['primary'] );
|
||||
|
||||
// Set input container (ul) properties.
|
||||
$properties['input_container'] = [
|
||||
'class' => [ ! empty( $field['random'] ) ? 'wpforms-randomize' : '' ],
|
||||
'data' => [],
|
||||
'attr' => [],
|
||||
'id' => "wpforms-{$form_id}-field_{$field_id}",
|
||||
];
|
||||
|
||||
$field['choice_limit'] = empty( $field['choice_limit'] ) ? 0 : (int) $field['choice_limit'];
|
||||
if ( $field['choice_limit'] > 0 ) {
|
||||
$properties['input_container']['data']['choice-limit'] = $field['choice_limit'];
|
||||
}
|
||||
|
||||
// Set input properties.
|
||||
foreach ( $choices as $key => $choice ) {
|
||||
|
||||
// Used for dynamic choices.
|
||||
$depth = isset( $choice['depth'] ) ? absint( $choice['depth'] ) : 1;
|
||||
$label = isset( $choice['label'] ) ? $choice['label'] : '';
|
||||
|
||||
// Choice labels should not be left blank, but if they are we
|
||||
// provide a basic value.
|
||||
$value = isset( $field['show_values'] ) ? $choice['value'] : $label;
|
||||
|
||||
if ( '' === $value ) {
|
||||
if ( 1 === count( $choices ) ) {
|
||||
$value = esc_html__( 'Checked', 'wpforms-lite' );
|
||||
} else {
|
||||
/* translators: %s - choice number. */
|
||||
$value = sprintf( esc_html__( 'Choice %s', 'wpforms-lite' ), $key );
|
||||
}
|
||||
}
|
||||
|
||||
$properties['inputs'][ $key ] = [
|
||||
'container' => [
|
||||
'attr' => [],
|
||||
'class' => [ "choice-{$key}", "depth-{$depth}" ],
|
||||
'data' => [],
|
||||
'id' => '',
|
||||
],
|
||||
'label' => [
|
||||
'attr' => [
|
||||
'for' => "wpforms-{$form_id}-field_{$field_id}_{$key}",
|
||||
],
|
||||
'class' => [ 'wpforms-field-label-inline' ],
|
||||
'data' => [],
|
||||
'id' => '',
|
||||
'text' => $label,
|
||||
],
|
||||
'attr' => [
|
||||
'name' => "wpforms[fields][{$field_id}][]",
|
||||
'value' => $value,
|
||||
],
|
||||
'class' => [],
|
||||
'data' => [],
|
||||
'id' => "wpforms-{$form_id}-field_{$field_id}_{$key}",
|
||||
'icon' => isset( $choice['icon'] ) ? $choice['icon'] : '',
|
||||
'icon_style' => isset( $choice['icon_style'] ) ? $choice['icon_style'] : '',
|
||||
'image' => isset( $choice['image'] ) ? $choice['image'] : '',
|
||||
'required' => ! empty( $field['required'] ) ? 'required' : '',
|
||||
'default' => isset( $choice['default'] ),
|
||||
];
|
||||
|
||||
// Rule for validator only if needed.
|
||||
if ( $field['choice_limit'] > 0 ) {
|
||||
$properties['inputs'][ $key ]['data']['rule-check-limit'] = 'true';
|
||||
}
|
||||
}
|
||||
|
||||
// Required class for pagebreak validation.
|
||||
if ( ! empty( $field['required'] ) ) {
|
||||
$properties['input_container']['class'][] = 'wpforms-field-required';
|
||||
}
|
||||
|
||||
// Custom properties if image choices is enabled.
|
||||
if ( ! $dynamic && ! empty( $field['choices_images'] ) ) {
|
||||
|
||||
$properties['input_container']['class'][] = 'wpforms-image-choices';
|
||||
$properties['input_container']['class'][] = 'wpforms-image-choices-' . sanitize_html_class( $field['choices_images_style'] );
|
||||
|
||||
foreach ( $properties['inputs'] as $key => $inputs ) {
|
||||
$properties['inputs'][ $key ]['container']['class'][] = 'wpforms-image-choices-item';
|
||||
|
||||
if ( in_array( $field['choices_images_style'], [ 'modern', 'classic' ], true ) ) {
|
||||
$properties['inputs'][ $key ]['class'][] = 'wpforms-screen-reader-element';
|
||||
}
|
||||
}
|
||||
} elseif ( ! $dynamic && ! empty( $field['choices_icons'] ) ) {
|
||||
$properties = wpforms()->get( 'icon_choices' )->field_properties( $properties, $field );
|
||||
}
|
||||
|
||||
// Custom properties for disclaimer format display.
|
||||
if ( ! empty( $field['disclaimer_format'] ) ) {
|
||||
|
||||
$properties['description']['class'][] = 'wpforms-disclaimer-description';
|
||||
$properties['description']['value'] = nl2br( $properties['description']['value'] );
|
||||
}
|
||||
|
||||
// Add selected class for choices with defaults.
|
||||
foreach ( $properties['inputs'] as $key => $inputs ) {
|
||||
if ( ! empty( $inputs['default'] ) ) {
|
||||
$properties['inputs'][ $key ]['container']['class'][] = 'wpforms-selected';
|
||||
}
|
||||
}
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Field options panel inside the builder.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param array $field Field settings.
|
||||
*/
|
||||
public function field_options( $field ) {
|
||||
/*
|
||||
* Basic field options.
|
||||
*/
|
||||
|
||||
// Options open markup.
|
||||
$this->field_option(
|
||||
'basic-options',
|
||||
$field,
|
||||
[
|
||||
'markup' => 'open',
|
||||
]
|
||||
);
|
||||
|
||||
// Label.
|
||||
$this->field_option( 'label', $field );
|
||||
|
||||
// Choices.
|
||||
$this->field_option( 'choices', $field );
|
||||
|
||||
// Choices Images.
|
||||
$this->field_option( 'choices_images', $field );
|
||||
|
||||
// Choices Images Style (theme).
|
||||
$this->field_option( 'choices_images_style', $field );
|
||||
|
||||
// Choices Icons.
|
||||
$this->field_option( 'choices_icons', $field );
|
||||
|
||||
// Choices Icons Color.
|
||||
$this->field_option( 'choices_icons_color', $field );
|
||||
|
||||
// Choices Icons Size.
|
||||
$this->field_option( 'choices_icons_size', $field );
|
||||
|
||||
// Choices Icons Style.
|
||||
$this->field_option( 'choices_icons_style', $field );
|
||||
|
||||
// Description.
|
||||
$this->field_option( 'description', $field );
|
||||
|
||||
// Required toggle.
|
||||
$this->field_option( 'required', $field );
|
||||
|
||||
// Options close markup.
|
||||
$this->field_option(
|
||||
'basic-options',
|
||||
$field,
|
||||
[
|
||||
'markup' => 'close',
|
||||
]
|
||||
);
|
||||
|
||||
/*
|
||||
* Advanced field options
|
||||
*/
|
||||
|
||||
// Options open markup.
|
||||
$this->field_option(
|
||||
'advanced-options',
|
||||
$field,
|
||||
[
|
||||
'markup' => 'open',
|
||||
]
|
||||
);
|
||||
|
||||
// Randomize order of choices.
|
||||
$this->field_element(
|
||||
'row',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'random',
|
||||
'content' => $this->field_element(
|
||||
'toggle',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'random',
|
||||
'value' => isset( $field['random'] ) ? '1' : '0',
|
||||
'desc' => esc_html__( 'Randomize Choices', 'wpforms-lite' ),
|
||||
'tooltip' => esc_html__( 'Check this option to randomize the order of the choices.', 'wpforms-lite' ),
|
||||
],
|
||||
false
|
||||
),
|
||||
]
|
||||
);
|
||||
|
||||
// Show Values toggle option. This option will only show if already used
|
||||
// or if manually enabled by a filter.
|
||||
if ( ! empty( $field['show_values'] ) || wpforms_show_fields_options_setting() ) {
|
||||
$this->field_element(
|
||||
'row',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'show_values',
|
||||
'content' => $this->field_element(
|
||||
'toggle',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'show_values',
|
||||
'value' => isset( $field['show_values'] ) ? $field['show_values'] : '0',
|
||||
'desc' => esc_html__( 'Show Values', 'wpforms-lite' ),
|
||||
'tooltip' => esc_html__( 'Check this option to manually set form field values.', 'wpforms-lite' ),
|
||||
],
|
||||
false
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Display format.
|
||||
$this->field_option( 'input_columns', $field );
|
||||
|
||||
// Choice Limit.
|
||||
$field['choice_limit'] = empty( $field['choice_limit'] ) ? 0 : (int) $field['choice_limit'];
|
||||
$this->field_element(
|
||||
'row',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'choice_limit',
|
||||
'content' =>
|
||||
$this->field_element(
|
||||
'label',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'choice_limit',
|
||||
'value' => esc_html__( 'Choice Limit', 'wpforms-lite' ),
|
||||
'tooltip' => esc_html__( 'Limit the number of checkboxes a user can select. Leave empty for unlimited.', 'wpforms-lite' ),
|
||||
],
|
||||
false
|
||||
) . $this->field_element(
|
||||
'text',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'choice_limit',
|
||||
'value' => $field['choice_limit'] > 0 ? $field['choice_limit'] : '',
|
||||
'type' => 'number',
|
||||
],
|
||||
false
|
||||
),
|
||||
]
|
||||
);
|
||||
|
||||
// Dynamic choice auto-populating toggle.
|
||||
$this->field_option( 'dynamic_choices', $field );
|
||||
|
||||
// Dynamic choice source.
|
||||
$this->field_option( 'dynamic_choices_source', $field );
|
||||
|
||||
// Custom CSS classes.
|
||||
$this->field_option( 'css', $field );
|
||||
|
||||
// Hide label.
|
||||
$this->field_option( 'label_hide', $field );
|
||||
|
||||
// Enable Disclaimer formatting.
|
||||
$this->field_element(
|
||||
'row',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'disclaimer_format',
|
||||
'content' => $this->field_element(
|
||||
'toggle',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'disclaimer_format',
|
||||
'value' => isset( $field['disclaimer_format'] ) ? '1' : '0',
|
||||
'desc' => esc_html__( 'Enable Disclaimer / Terms of Service Display', 'wpforms-lite' ),
|
||||
'tooltip' => esc_html__( 'Check this option to adjust the field styling to support Disclaimers and Terms of Service type agreements.', 'wpforms-lite' ),
|
||||
],
|
||||
false
|
||||
),
|
||||
]
|
||||
);
|
||||
|
||||
// Options close markup.
|
||||
$this->field_option(
|
||||
'advanced-options',
|
||||
$field,
|
||||
[
|
||||
'markup' => 'close',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Field preview inside the builder.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param array $field Field settings.
|
||||
*/
|
||||
public function field_preview( $field ) {
|
||||
|
||||
// Label.
|
||||
$this->field_preview_option( 'label', $field );
|
||||
|
||||
// Choices.
|
||||
$this->field_preview_option( 'choices', $field );
|
||||
|
||||
// Description.
|
||||
$this->field_preview_option(
|
||||
'description',
|
||||
$field,
|
||||
[
|
||||
'class' => ! empty( $field['disclaimer_format'] ) ? 'disclaimer nl2br' : false,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Field display on the form front-end and admin entry edit page.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param array $field Field settings.
|
||||
* @param array $deprecated Deprecated array.
|
||||
* @param array $form_data Form data and settings.
|
||||
*/
|
||||
public function field_display( $field, $deprecated, $form_data ) {
|
||||
|
||||
$using_image_choices = empty( $field['dynamic_choices'] ) && ! empty( $field['choices_images'] );
|
||||
$using_icon_choices = empty( $field['dynamic_choices'] ) && empty( $field['choices_images'] ) && ! empty( $field['choices_icons'] );
|
||||
|
||||
// Define data.
|
||||
$container = $field['properties']['input_container'];
|
||||
$choices = $field['properties']['inputs'];
|
||||
|
||||
// Do not display the field with empty choices on the frontend.
|
||||
if ( ! $choices && ! is_admin() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Display a warning message on Entry Edit page.
|
||||
if ( ! $choices && is_admin() ) {
|
||||
$this->display_empty_dynamic_choices_message( $field );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$amp_state_id = '';
|
||||
|
||||
if ( wpforms_is_amp() && ( $using_image_choices || $using_icon_choices ) ) {
|
||||
$amp_state_id = str_replace( '-', '_', sanitize_key( $container['id'] ) ) . '_state';
|
||||
$state = [];
|
||||
|
||||
foreach ( $choices as $key => $choice ) {
|
||||
$state[ $choice['id'] ] = ! empty( $choice['default'] );
|
||||
}
|
||||
printf(
|
||||
'<amp-state id="%s"><script type="application/json">%s</script></amp-state>',
|
||||
esc_attr( $amp_state_id ),
|
||||
wp_json_encode( $state )
|
||||
);
|
||||
}
|
||||
|
||||
printf(
|
||||
'<ul %s>',
|
||||
wpforms_html_attributes( $container['id'], $container['class'], $container['data'], $container['attr'] )
|
||||
);
|
||||
|
||||
foreach ( $choices as $key => $choice ) {
|
||||
|
||||
if ( wpforms_is_amp() && ( $using_image_choices || $using_icon_choices ) ) {
|
||||
$choice['container']['attr']['[class]'] = sprintf(
|
||||
'%s + ( %s[%s] ? " wpforms-selected" : "")',
|
||||
wp_json_encode( implode( ' ', $choice['container']['class'] ) ),
|
||||
$amp_state_id,
|
||||
wp_json_encode( $choice['id'] )
|
||||
);
|
||||
}
|
||||
|
||||
// If the field is required, has the label hidden, and has
|
||||
// disclaimer mode enabled, so the required status in choice
|
||||
// label.
|
||||
$required = '';
|
||||
|
||||
if ( ! empty( $field['disclaimer_format'] ) && ! empty( $choice['required'] ) && ! empty( $field['label_hide'] ) ) {
|
||||
$required = wpforms_get_field_required_label();
|
||||
}
|
||||
|
||||
printf(
|
||||
'<li %s>',
|
||||
wpforms_html_attributes( $choice['container']['id'], $choice['container']['class'], $choice['container']['data'], $choice['container']['attr'] )
|
||||
);
|
||||
|
||||
// The required constraint in HTML5 form validation does not work with checkbox groups, so omit in AMP.
|
||||
$required_attr = wpforms_is_amp() && count( $choices ) > 1 ? '' : $choice['required'];
|
||||
|
||||
if ( $using_image_choices ) {
|
||||
|
||||
// Make sure the image choices are keyboard-accessible.
|
||||
$choice['label']['attr']['tabindex'] = 0;
|
||||
|
||||
if ( wpforms_is_amp() ) {
|
||||
$choice['label']['attr']['on'] = sprintf(
|
||||
'tap:AMP.setState({ %s: { %s: ! %s[%s] } })',
|
||||
wp_json_encode( $amp_state_id ),
|
||||
wp_json_encode( $choice['id'] ),
|
||||
$amp_state_id,
|
||||
wp_json_encode( $choice['id'] )
|
||||
);
|
||||
$choice['label']['attr']['role'] = 'button';
|
||||
}
|
||||
|
||||
// Image choices.
|
||||
printf(
|
||||
'<label %s>',
|
||||
wpforms_html_attributes( $choice['label']['id'], $choice['label']['class'], $choice['label']['data'], $choice['label']['attr'] )
|
||||
);
|
||||
|
||||
echo '<span class="wpforms-image-choices-image">';
|
||||
|
||||
if ( ! empty( $choice['image'] ) ) {
|
||||
printf(
|
||||
'<img src="%s" alt="%s"%s>',
|
||||
esc_url( $choice['image'] ),
|
||||
esc_attr( $choice['label']['text'] ),
|
||||
! empty( $choice['label']['text'] ) ? ' title="' . esc_attr( $choice['label']['text'] ) . '"' : ''
|
||||
);
|
||||
}
|
||||
|
||||
echo '</span>';
|
||||
|
||||
if ( $field['choices_images_style'] === 'none' ) {
|
||||
echo '<br>';
|
||||
}
|
||||
|
||||
$choice['attr']['tabindex'] = '-1';
|
||||
|
||||
if ( wpforms_is_amp() ) {
|
||||
$choice['attr']['[checked]'] = sprintf(
|
||||
'%s[%s]',
|
||||
$amp_state_id,
|
||||
wp_json_encode( $choice['id'] )
|
||||
);
|
||||
}
|
||||
|
||||
printf(
|
||||
'<input type="checkbox" %s %s %s>',
|
||||
wpforms_html_attributes( $choice['id'], $choice['class'], $choice['data'], $choice['attr'] ),
|
||||
esc_attr( $required_attr ),
|
||||
checked( '1', $choice['default'], false )
|
||||
);
|
||||
|
||||
echo '<span class="wpforms-image-choices-label">' . wp_kses_post( $choice['label']['text'] ) . '</span>';
|
||||
|
||||
echo '</label>';
|
||||
|
||||
} elseif ( $using_icon_choices ) {
|
||||
|
||||
if ( wpforms_is_amp() ) {
|
||||
$choice['label']['attr']['on'] = sprintf(
|
||||
'tap:AMP.setState({ %s: { %s: ! %s[%s] } })',
|
||||
wp_json_encode( $amp_state_id ),
|
||||
wp_json_encode( $choice['id'] ),
|
||||
$amp_state_id,
|
||||
wp_json_encode( $choice['id'] )
|
||||
);
|
||||
$choice['label']['attr']['role'] = 'button';
|
||||
}
|
||||
|
||||
// Icon Choices.
|
||||
wpforms()->get( 'icon_choices' )->field_display( $field, $choice, 'checkbox' );
|
||||
|
||||
} else {
|
||||
|
||||
// Normal display.
|
||||
printf(
|
||||
'<input type="checkbox" %s %s %s>',
|
||||
wpforms_html_attributes( $choice['id'], $choice['class'], $choice['data'], $choice['attr'] ),
|
||||
esc_attr( $required_attr ),
|
||||
checked( '1', $choice['default'], false )
|
||||
);
|
||||
|
||||
printf(
|
||||
'<label %s>%s%s</label>',
|
||||
wpforms_html_attributes( $choice['label']['id'], $choice['label']['class'], $choice['label']['data'], $choice['label']['attr'] ),
|
||||
wp_kses_post( $choice['label']['text'] ),
|
||||
wp_kses(
|
||||
$required,
|
||||
[
|
||||
'span' => [
|
||||
'class' => true,
|
||||
],
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
echo '</li>';
|
||||
}
|
||||
|
||||
echo '</ul>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate field on form submit.
|
||||
*
|
||||
* @since 1.5.2
|
||||
*
|
||||
* @param int $field_id Field ID.
|
||||
* @param array $field_submit Submitted field value (selected option).
|
||||
* @param array $form_data Form data.
|
||||
*/
|
||||
public function validate( $field_id, $field_submit, $form_data ) {
|
||||
|
||||
$field = $form_data['fields'][ $field_id ];
|
||||
|
||||
// Skip validation if field is dynamic and choices are empty.
|
||||
if ( $this->is_dynamic_choices_empty( $field, $form_data ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$field_submit = (array) $field_submit;
|
||||
$choice_limit = empty( $form_data['fields'][ $field_id ]['choice_limit'] ) ? 0 : (int) $form_data['fields'][ $field_id ]['choice_limit'];
|
||||
$count_choices = count( $field_submit );
|
||||
|
||||
if ( $choice_limit > 0 && $count_choices > $choice_limit ) {
|
||||
// Generating the error.
|
||||
$error = wpforms_setting( 'validation-check-limit', esc_html__( 'You have exceeded the number of allowed selections: {#}.', 'wpforms-lite' ) );
|
||||
$error = str_replace( '{#}', $choice_limit, $error );
|
||||
}
|
||||
|
||||
// Basic required check - If field is marked as required, check for entry data.
|
||||
if (
|
||||
! empty( $form_data['fields'][ $field_id ]['required'] ) &&
|
||||
(
|
||||
empty( $field_submit ) ||
|
||||
(
|
||||
count( $field_submit ) === 1 &&
|
||||
( ! isset( $field_submit[0] ) || (string) $field_submit[0] === '' )
|
||||
)
|
||||
)
|
||||
) {
|
||||
$error = wpforms_get_required_label();
|
||||
}
|
||||
|
||||
if ( ! empty( $error ) ) {
|
||||
wpforms()->process->errors[ $form_data['id'] ][ $field_id ] = $error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format and sanitize field.
|
||||
*
|
||||
* @since 1.0.2
|
||||
*
|
||||
* @param int $field_id Field ID.
|
||||
* @param array $field_submit Submitted form data.
|
||||
* @param array $form_data Form data and settings.
|
||||
*/
|
||||
public function format( $field_id, $field_submit, $form_data ) {
|
||||
|
||||
$field_submit = (array) $field_submit;
|
||||
$field = $form_data['fields'][ $field_id ];
|
||||
$dynamic = ! empty( $field['dynamic_choices'] ) ? $field['dynamic_choices'] : false;
|
||||
$name = sanitize_text_field( $field['label'] );
|
||||
$value_raw = wpforms_sanitize_array_combine( $field_submit );
|
||||
|
||||
$data = [
|
||||
'name' => $name,
|
||||
'value' => '',
|
||||
'value_raw' => $value_raw,
|
||||
'id' => absint( $field_id ),
|
||||
'type' => $this->type,
|
||||
];
|
||||
|
||||
if ( 'post_type' === $dynamic && ! empty( $field['dynamic_post_type'] ) ) {
|
||||
|
||||
// Dynamic population is enabled using post type.
|
||||
$value_raw = implode( ',', array_map( 'absint', $field_submit ) );
|
||||
$data['value_raw'] = $value_raw;
|
||||
$data['dynamic'] = 'post_type';
|
||||
$data['dynamic_items'] = $value_raw;
|
||||
$data['dynamic_post_type'] = $field['dynamic_post_type'];
|
||||
$posts = [];
|
||||
|
||||
foreach ( $field_submit as $id ) {
|
||||
$post = get_post( $id );
|
||||
|
||||
if ( ! is_wp_error( $post ) && ! empty( $post ) && $data['dynamic_post_type'] === $post->post_type ) {
|
||||
$posts[] = esc_html( wpforms_get_post_title( $post ) );
|
||||
}
|
||||
}
|
||||
|
||||
$data['value'] = ! empty( $posts ) ? wpforms_sanitize_array_combine( $posts ) : '';
|
||||
|
||||
}
|
||||
elseif ( 'taxonomy' === $dynamic && ! empty( $field['dynamic_taxonomy'] ) ) {
|
||||
|
||||
// Dynamic population is enabled using taxonomy.
|
||||
$value_raw = implode( ',', array_map( 'absint', $field_submit ) );
|
||||
$data['value_raw'] = $value_raw;
|
||||
$data['dynamic'] = 'taxonomy';
|
||||
$data['dynamic_items'] = $value_raw;
|
||||
$data['dynamic_taxonomy'] = $field['dynamic_taxonomy'];
|
||||
$terms = [];
|
||||
|
||||
foreach ( $field_submit as $id ) {
|
||||
$term = get_term( $id, $field['dynamic_taxonomy'] );
|
||||
|
||||
if ( ! is_wp_error( $term ) && ! empty( $term ) ) {
|
||||
$terms[] = esc_html( wpforms_get_term_name( $term ) );
|
||||
}
|
||||
}
|
||||
|
||||
$data['value'] = ! empty( $terms ) ? wpforms_sanitize_array_combine( $terms ) : '';
|
||||
|
||||
} else {
|
||||
|
||||
// Normal processing, dynamic population is off.
|
||||
$choice_keys = [];
|
||||
|
||||
// If show_values is true, that means values posted are the raw values
|
||||
// and not the labels. So we need to set label values. Also store
|
||||
// the choice keys.
|
||||
if ( ! empty( $field['show_values'] ) && (int) $field['show_values'] === 1 ) {
|
||||
|
||||
foreach ( $field_submit as $item ) {
|
||||
foreach ( $field['choices'] as $key => $choice ) {
|
||||
if ( $item === $choice['value'] || ( empty( $choice['value'] ) && (int) str_replace( 'Choice ', '', $item ) === $key ) ) {
|
||||
$value[] = $choice['label'];
|
||||
$choice_keys[] = $key;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$data['value'] = ! empty( $value ) ? wpforms_sanitize_array_combine( $value ) : '';
|
||||
|
||||
} else {
|
||||
|
||||
$data['value'] = $value_raw;
|
||||
|
||||
// Determine choices keys, this is needed for image choices.
|
||||
foreach ( $field_submit as $item ) {
|
||||
foreach ( $field['choices'] as $key => $choice ) {
|
||||
/* translators: %s - choice number. */
|
||||
if ( $item === $choice['label'] || $item === sprintf( esc_html__( 'Choice %s', 'wpforms-lite' ), $key ) ) {
|
||||
$choice_keys[] = $key;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Images choices are enabled, lookup and store image URLs.
|
||||
if ( ! empty( $choice_keys ) && ! empty( $field['choices_images'] ) ) {
|
||||
|
||||
$data['images'] = [];
|
||||
|
||||
foreach ( $choice_keys as $key ) {
|
||||
$data['images'][] = ! empty( $field['choices'][ $key ]['image'] ) ? esc_url_raw( $field['choices'][ $key ]['image'] ) : '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Push field details to be saved.
|
||||
wpforms()->process->fields[ $field_id ] = $data;
|
||||
}
|
||||
}
|
||||
|
||||
new WPForms_Field_Checkbox();
|
1326
wp-content/plugins/wpforms-lite/includes/fields/class-email.php
Normal file
1326
wp-content/plugins/wpforms-lite/includes/fields/class-email.php
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,315 @@
|
||||
<?php
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* GDPR Checkbox field.
|
||||
*
|
||||
* @since 1.4.6
|
||||
*/
|
||||
class WPForms_Field_GDPR_Checkbox extends WPForms_Field {
|
||||
|
||||
/**
|
||||
* Primary class constructor.
|
||||
*
|
||||
* @since 1.4.6
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
// Define field type information.
|
||||
$this->name = esc_html__( 'GDPR Agreement', 'wpforms-lite' );
|
||||
$this->type = 'gdpr-checkbox';
|
||||
$this->icon = 'fa-check-square-o';
|
||||
$this->order = 500;
|
||||
$this->defaults = [
|
||||
1 => [
|
||||
'label' => esc_html__( 'I consent to having this website store my submitted information so they can respond to my inquiry.', 'wpforms-lite' ),
|
||||
'value' => '',
|
||||
'image' => '',
|
||||
'default' => '',
|
||||
],
|
||||
];
|
||||
|
||||
// Set field to default to required.
|
||||
add_filter( 'wpforms_field_new_required', [ $this, 'field_default_required' ], 10, 2 );
|
||||
|
||||
// Define additional field properties.
|
||||
add_filter( 'wpforms_field_properties_gdpr-checkbox', [ $this, 'field_properties' ], 5, 3 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Field should default to being required.
|
||||
*
|
||||
* @since 1.4.6
|
||||
*
|
||||
* @param bool $required Required status, true is required.
|
||||
* @param array $field Field settings.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function field_default_required( $required, $field ) {
|
||||
|
||||
if ( $this->type === $field['type'] ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $required;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define additional field properties.
|
||||
*
|
||||
* @since 1.4.6
|
||||
*
|
||||
* @param array $properties Field properties.
|
||||
* @param array $field Field settings.
|
||||
* @param array $form_data Form data and settings.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function field_properties( $properties, $field, $form_data ) {
|
||||
|
||||
// Define data.
|
||||
$form_id = absint( $form_data['id'] );
|
||||
$field_id = absint( $field['id'] );
|
||||
$choices = ! empty( $field['choices'] ) ? $field['choices'] : [];
|
||||
|
||||
// Remove primary input.
|
||||
unset( $properties['inputs']['primary'] );
|
||||
|
||||
// Set input container (ul) properties.
|
||||
$properties['input_container'] = [
|
||||
'class' => [],
|
||||
'data' => [],
|
||||
'attr' => [],
|
||||
'id' => "wpforms-{$form_id}-field_{$field_id}",
|
||||
];
|
||||
|
||||
// Set input properties.
|
||||
foreach ( $choices as $key => $choice ) {
|
||||
|
||||
$properties['inputs'][ $key ] = [
|
||||
'container' => [
|
||||
'attr' => [],
|
||||
'class' => [ "choice-{$key}" ],
|
||||
'data' => [],
|
||||
'id' => '',
|
||||
],
|
||||
'label' => [
|
||||
'attr' => [
|
||||
'for' => "wpforms-{$form_id}-field_{$field_id}_{$key}",
|
||||
],
|
||||
'class' => [ 'wpforms-field-label-inline' ],
|
||||
'data' => [],
|
||||
'id' => '',
|
||||
'text' => $choice['label'],
|
||||
],
|
||||
'attr' => [
|
||||
'name' => "wpforms[fields][{$field_id}][]",
|
||||
'value' => $choice['label'],
|
||||
],
|
||||
'class' => [],
|
||||
'data' => [],
|
||||
'id' => "wpforms-{$form_id}-field_{$field_id}_{$key}",
|
||||
'image' => '',
|
||||
'required' => ! empty( $field['required'] ) ? 'required' : '',
|
||||
'default' => '',
|
||||
];
|
||||
}
|
||||
|
||||
// Required class for pagebreak validation.
|
||||
if ( ! empty( $field['required'] ) ) {
|
||||
$properties['input_container']['class'][] = 'wpforms-field-required';
|
||||
}
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function is_dynamic_population_allowed( $properties, $field ) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Field options panel inside the builder.
|
||||
*
|
||||
* @since 1.4.6
|
||||
*
|
||||
* @param array $field Field settings.
|
||||
*/
|
||||
public function field_options( $field ) {
|
||||
|
||||
// Field is always required.
|
||||
$this->field_element(
|
||||
'text',
|
||||
$field,
|
||||
[
|
||||
'type' => 'hidden',
|
||||
'slug' => 'required',
|
||||
'value' => '1',
|
||||
]
|
||||
);
|
||||
|
||||
// -------------------------------------------------------------------//
|
||||
// Basic field options
|
||||
// -------------------------------------------------------------------//
|
||||
|
||||
// Options open markup.
|
||||
$this->field_option(
|
||||
'basic-options',
|
||||
$field,
|
||||
[
|
||||
'markup' => 'open',
|
||||
]
|
||||
);
|
||||
|
||||
// Label.
|
||||
$this->field_option( 'label', $field );
|
||||
|
||||
// Choices.
|
||||
$this->field_option(
|
||||
'choices',
|
||||
$field,
|
||||
[
|
||||
'label' => esc_html__( 'Agreement', 'wpforms-lite' ),
|
||||
]
|
||||
);
|
||||
|
||||
// Description.
|
||||
$this->field_option( 'description', $field );
|
||||
|
||||
// Options close markup.
|
||||
$this->field_option(
|
||||
'basic-options',
|
||||
$field,
|
||||
[
|
||||
'markup' => 'close',
|
||||
]
|
||||
);
|
||||
|
||||
// -------------------------------------------------------------------//
|
||||
// Advanced field options
|
||||
// -------------------------------------------------------------------//
|
||||
|
||||
// Options open markup.
|
||||
$this->field_option(
|
||||
'advanced-options',
|
||||
$field,
|
||||
[
|
||||
'markup' => 'open',
|
||||
]
|
||||
);
|
||||
|
||||
// Custom CSS classes.
|
||||
$this->field_option( 'css', $field );
|
||||
|
||||
// Hide label.
|
||||
$this->field_option( 'label_hide', $field );
|
||||
|
||||
// Options close markup.
|
||||
$this->field_option(
|
||||
'advanced-options',
|
||||
$field,
|
||||
[
|
||||
'markup' => 'close',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Field preview inside the builder.
|
||||
*
|
||||
* @since 1.4.6
|
||||
*
|
||||
* @param array $field Field settings.
|
||||
*/
|
||||
public function field_preview( $field ) {
|
||||
|
||||
// Label.
|
||||
$this->field_preview_option( 'label', $field );
|
||||
|
||||
// Choices.
|
||||
$this->field_preview_option( 'choices', $field );
|
||||
|
||||
// Description.
|
||||
$this->field_preview_option( 'description', $field );
|
||||
}
|
||||
|
||||
/**
|
||||
* Field display on the form front-end.
|
||||
*
|
||||
* @since 1.4.6
|
||||
*
|
||||
* @param array $field Field settings.
|
||||
* @param array $deprecated Deprecated array.
|
||||
* @param array $form_data Form data and settings.
|
||||
*/
|
||||
public function field_display( $field, $deprecated, $form_data ) {
|
||||
|
||||
// Define data.
|
||||
$container = $field['properties']['input_container'];
|
||||
$choices = $field['properties']['inputs'];
|
||||
|
||||
printf(
|
||||
'<ul %s>',
|
||||
wpforms_html_attributes( $container['id'], $container['class'], $container['data'], $container['attr'] )
|
||||
);
|
||||
|
||||
foreach ( $choices as $key => $choice ) {
|
||||
|
||||
$required = '';
|
||||
if ( ! empty( $choice['required'] ) && ! empty( $field['label_hide'] ) ) {
|
||||
$required = wpforms_get_field_required_label();
|
||||
}
|
||||
|
||||
printf(
|
||||
'<li %s>',
|
||||
wpforms_html_attributes( $choice['container']['id'], $choice['container']['class'], $choice['container']['data'], $choice['container']['attr'] )
|
||||
);
|
||||
// Normal display.
|
||||
printf(
|
||||
'<input type="checkbox" %s %s %s>',
|
||||
wpforms_html_attributes( $choice['id'], $choice['class'], $choice['data'], $choice['attr'] ),
|
||||
esc_attr( $choice['required'] ),
|
||||
checked( '1', $choice['default'], false )
|
||||
);
|
||||
|
||||
printf(
|
||||
'<label %s>%s%s</label>',
|
||||
wpforms_html_attributes( $choice['label']['id'], $choice['label']['class'], $choice['label']['data'], $choice['label']['attr'] ),
|
||||
wp_kses_post( $choice['label']['text'] ),
|
||||
$required
|
||||
); // WPCS: XSS ok.
|
||||
|
||||
echo '</li>';
|
||||
}
|
||||
|
||||
echo '</ul>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Format and sanitize field.
|
||||
*
|
||||
* @since 1.4.6
|
||||
*
|
||||
* @param int $field_id Field ID.
|
||||
* @param array $field_submit Submitted form data.
|
||||
* @param array $form_data Form data and settings.
|
||||
*/
|
||||
public function format( $field_id, $field_submit, $form_data ) {
|
||||
|
||||
wpforms()->process->fields[ $field_id ] = [
|
||||
'name' => ! empty( $form_data['fields'][ $field_id ]['label'] ) ? sanitize_text_field( $form_data['fields'][ $field_id ]['label'] ) : '',
|
||||
'value' => $form_data['fields'][ $field_id ]['choices'][1]['label'],
|
||||
'id' => absint( $field_id ),
|
||||
'type' => $this->type,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
new WPForms_Field_GDPR_Checkbox();
|
@@ -0,0 +1,857 @@
|
||||
<?php
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal information field class.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*/
|
||||
class WPForms_Field_Internal_Information extends WPForms_Field {
|
||||
|
||||
/**
|
||||
* The key used to save form checkboxes in post meta table.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const CHECKBOX_META_KEY = 'wpforms_iif_checkboxes';
|
||||
|
||||
/**
|
||||
* Class initialization method.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
$this->name = $this->is_editable() ? esc_html__( 'Internal Information', 'wpforms-lite' ) : esc_html__( 'This field is not editable', 'wpforms-lite' );
|
||||
$this->type = 'internal-information';
|
||||
$this->icon = 'fa fa-sticky-note-o';
|
||||
$this->order = 550;
|
||||
|
||||
$this->hooks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register hooks.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @noinspection PhpUnnecessaryCurlyVarSyntaxInspection
|
||||
*/
|
||||
private function hooks() {
|
||||
|
||||
add_filter( 'wpforms_entries_table_fields_disallow', [ $this, 'hide_column_in_entries_table' ], 10, 2 );
|
||||
add_filter( 'wpforms_field_preview_class', [ $this, 'add_css_class_for_field_wrapper' ], 10, 2 );
|
||||
add_filter( 'wpforms_field_new_class', [ $this, 'add_css_class_for_field_wrapper' ], 10, 2 );
|
||||
add_filter( "wpforms_pro_admin_entries_edit_is_field_displayable_{$this->type}", '__return_false' );
|
||||
add_filter( 'wpforms_builder_strings', [ $this, 'builder_strings' ], 10, 2 );
|
||||
add_filter( 'wpforms_frontend_form_data', [ $this, 'remove_internal_fields_on_front_end' ], 10, 1 );
|
||||
add_filter( 'wpforms_process_before_form_data', [ $this, 'process_before_form_data' ], 10, 2 );
|
||||
add_filter( 'wpforms_field_preview_display_duplicate_button', [ $this, 'display_duplicate_button' ], 10, 3 );
|
||||
add_action( 'wpforms_builder_enqueues', [ $this, 'builder_enqueues' ] );
|
||||
add_action( 'wp_ajax_wpforms_builder_save_internal_information_checkbox', [ $this, 'save_internal_information_checkbox' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether current field can be populated dynamically.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @param array $properties Field properties.
|
||||
* @param array $field Current field specific data.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_dynamic_population_allowed( $properties, $field ) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether current field can be populated using a fallback.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @param array $properties Field properties.
|
||||
* @param array $field Current field specific data.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_fallback_population_allowed( $properties, $field ) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define field options to display in left panel.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @param array $field Field data and settings.
|
||||
*/
|
||||
public function field_options( $field ) {
|
||||
|
||||
$this->field_option(
|
||||
'basic-options',
|
||||
$field,
|
||||
[
|
||||
'markup' => 'open',
|
||||
]
|
||||
);
|
||||
|
||||
$this->heading_option( $field );
|
||||
$this->field_option( 'description', $field );
|
||||
$this->expanded_description_option( $field );
|
||||
$this->cta_label_option( $field );
|
||||
$this->cta_link_option( $field );
|
||||
|
||||
$this->field_option(
|
||||
'basic-options',
|
||||
$field,
|
||||
[
|
||||
'markup' => 'close',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define field preview on the right side on builder.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @param array $field Field data and settings.
|
||||
*/
|
||||
public function field_preview( $field ) {
|
||||
|
||||
echo '<div class="internal-information-wrap wpforms-clear">';
|
||||
|
||||
// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
echo wpforms_render( 'fields/internal-information/icon-lightbulb' );
|
||||
|
||||
echo '<div class="internal-information-content">';
|
||||
|
||||
$this->render_preview( 'heading', $field );
|
||||
$this->render_preview( 'description', $field );
|
||||
$this->render_preview( 'expanded-description', $field );
|
||||
|
||||
if ( $this->is_button_displayable( $field ) ) {
|
||||
echo '<div class="wpforms-field-internal-information-row wpforms-field-internal-information-row-cta-button">';
|
||||
echo $this->render_custom_preview( 'cta-button', $field, [] );
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
echo '</div>';
|
||||
// phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if button is displayable.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @param array $field Field data.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_button_displayable( $field ) {
|
||||
|
||||
return ! empty( $field['expanded-description'] ) ||
|
||||
( ! empty( $field['cta-label'] ) && ! empty( $field['cta-link'] ) ) ||
|
||||
$this->is_editable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stub to make the field not visible in the front-end.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @param array $field Field data and settings.
|
||||
* @param array $field_atts Field attributes.
|
||||
* @param array $form_data Form data.
|
||||
*/
|
||||
public function field_display( $field, $field_atts, $form_data ) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Heading option.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @param array $field Field data and settings.
|
||||
*/
|
||||
private function heading_option( $field ) {
|
||||
|
||||
$output = $this->field_element(
|
||||
'label',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'heading',
|
||||
'value' => esc_html__( 'Heading', 'wpforms-lite' ),
|
||||
'tooltip' => esc_attr__( 'Enter text for the form field heading.', 'wpforms-lite' ),
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$output .= $this->field_element(
|
||||
'text',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'label',
|
||||
'value' => ! empty( $field['label'] ) ? esc_attr( $field['label'] ) : '',
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$this->field_element(
|
||||
'row',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'heading',
|
||||
'content' => $output,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expanded description option.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @param array $field Field data and settings.
|
||||
*/
|
||||
private function expanded_description_option( $field ) {
|
||||
|
||||
$output = $this->field_element(
|
||||
'label',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'expanded-description',
|
||||
'value' => esc_html__( 'Expanded Content', 'wpforms-lite' ),
|
||||
'tooltip' => esc_attr__( 'Enter text for the form field expanded description.', 'wpforms-lite' ),
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$output .= $this->field_element(
|
||||
'textarea',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'expanded-description',
|
||||
'value' => ! empty( $field['expanded-description'] ) ? esc_html( $field['expanded-description'] ) : '',
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$output .= sprintf(
|
||||
'<p class="note">%s</p>',
|
||||
esc_html__( 'Adds an expandable content area below the description.', 'wpforms-lite' )
|
||||
);
|
||||
|
||||
$this->field_element(
|
||||
'row',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'expanded-description',
|
||||
'content' => $output,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* CTA label option.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @param array $field Field data and settings.
|
||||
*/
|
||||
private function cta_label_option( $field ) {
|
||||
|
||||
$output = $this->field_element(
|
||||
'label',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'cta-label',
|
||||
'value' => esc_html__( 'CTA Label', 'wpforms-lite' ),
|
||||
'tooltip' => esc_attr__( 'Enter label for the form field call to action button. The label will be ignored if the field has extended description content: in that case button will be used to expand the description content.', 'wpforms-lite' ),
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$output .= $this->field_element(
|
||||
'text',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'cta-label',
|
||||
'value' => ! empty( $field['cta-label'] ) ? esc_attr( $field['cta-label'] ) : esc_attr__( 'Learn More', 'wpforms-lite' ),
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$this->field_element(
|
||||
'row',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'cta-label',
|
||||
'content' => $output,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* CTA link option.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @param array $field Field data and settings.
|
||||
*/
|
||||
private function cta_link_option( $field ) {
|
||||
|
||||
$output = $this->field_element(
|
||||
'label',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'cta-link',
|
||||
'value' => esc_html__( 'CTA Link', 'wpforms-lite' ),
|
||||
'tooltip' => esc_attr__( 'Enter the URL for the form field call to action button. URL will be ignored if the field has extended description content: in that case button will be used to expand the description content.', 'wpforms-lite' ),
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$output .= $this->field_element(
|
||||
'text',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'cta-link',
|
||||
'value' => ! empty( $field['cta-link'] ) ? esc_url( $field['cta-link'] ) : '',
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$output .= sprintf(
|
||||
'<p class="note">%s</p>',
|
||||
esc_html__( 'CTA is hidden if Expanded Content is used.', 'wpforms-lite' )
|
||||
);
|
||||
|
||||
$this->field_element(
|
||||
'row',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'cta-link',
|
||||
'content' => $output,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add CSS class to hide field settings when field is not editable.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @param string $option Field option to render.
|
||||
* @param array $field Field data and settings.
|
||||
* @param array $args Field preview arguments.
|
||||
* @param bool $echo Print or return the value. Print by default.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function field_element( $option, $field, $args = [], $echo = true ) {
|
||||
|
||||
if ( ! isset( $args['class'] ) ) {
|
||||
$args['class'] = '';
|
||||
}
|
||||
|
||||
if ( ! $this->is_editable() ) {
|
||||
$args['class'] .= ' wpforms-hidden ';
|
||||
}
|
||||
|
||||
return parent::field_element( $option, $field, $args, $echo );
|
||||
}
|
||||
|
||||
/**
|
||||
* Render custom option preview on the right side of builder.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @param string $option Field option to render.
|
||||
* @param array $field Field data and settings.
|
||||
* @param array $args Field arguments.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function render_custom_preview( $option, $field, $args = [] ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded, Generic.Metrics.CyclomaticComplexity.TooHigh
|
||||
|
||||
$class = ! empty( $args['class'] ) ? wpforms_sanitize_classes( $args['class'] ) : '';
|
||||
$allowed_tags = $this->get_allowed_tags();
|
||||
|
||||
switch ( $option ) {
|
||||
case 'heading':
|
||||
$label = isset( $field['label'] ) && ! wpforms_is_empty_string( $field['label'] ) ? esc_html( $field['label'] ) : '';
|
||||
|
||||
if ( ! $label ) {
|
||||
$class .= ' hidden ';
|
||||
}
|
||||
|
||||
return sprintf(
|
||||
'<label class="label-title heading %s"><span class="text">%s</span><span class="required">*</span></label>',
|
||||
esc_attr( $class ),
|
||||
esc_html( $label )
|
||||
);
|
||||
|
||||
case 'description': // phpcs:ignore WPForms.Formatting.Switch.AddEmptyLineBefore
|
||||
$description = isset( $field['description'] ) && ! empty( $field['description'] ) ? wp_kses( $field['description'], $allowed_tags ) : '';
|
||||
$description = wpautop( $this->replace_checkboxes( $description, $field ) );
|
||||
$description = $this->add_link_attributes( $description );
|
||||
|
||||
return sprintf( '<div class="description %s">%s</div>', $class, $description );
|
||||
|
||||
case 'expanded-description': // phpcs:ignore WPForms.Formatting.Switch.AddEmptyLineBefore
|
||||
$description = isset( $field['expanded-description'] ) && ! wpforms_is_empty_string( $field['expanded-description'] ) ? wp_kses( $field['expanded-description'], $allowed_tags ) : '';
|
||||
$description = wpautop( $this->replace_checkboxes( $description, $field ) );
|
||||
$description = $this->add_link_attributes( $description );
|
||||
|
||||
return sprintf( '<div class="expanded-description %s">%s</div>', esc_attr( $class ), wp_kses( $description, $allowed_tags ) );
|
||||
|
||||
case 'cta-button': // phpcs:ignore WPForms.Formatting.Switch.AddEmptyLineBefore
|
||||
$label = isset( $field['cta-label'] ) && ! empty( $field['cta-label'] ) && empty( $field['expanded-description'] ) ? esc_attr( $field['cta-label'] ) : esc_attr__( 'Learn More', 'wpforms-lite' );
|
||||
|
||||
if ( isset( $field['expanded-description'] ) && ! empty( $field['expanded-description'] ) ) {
|
||||
return sprintf(
|
||||
'<div class="cta-button cta-expand-description not-expanded %s"><a href="#" target="_blank" rel="noopener noreferrer"><span class="button-label">%s</span> %s %s</a></div>',
|
||||
esc_attr( $class ),
|
||||
esc_html( $label ),
|
||||
wpforms_render( 'fields/internal-information/icon-not-expanded' ),
|
||||
wpforms_render( 'fields/internal-information/icon-expanded' )
|
||||
);
|
||||
}
|
||||
|
||||
if ( isset( $field['cta-link'] ) && ! empty( $field['cta-link'] ) ) {
|
||||
return sprintf( '<div class="cta-button cta-link-external %s"><a href="%s" target="_blank" rel="noopener noreferrer">%s</a></div>', esc_attr( $class ), esc_url( $this->add_url_utm( $field ) ), esc_html( $label ) );
|
||||
}
|
||||
|
||||
return sprintf( '<div class="cta-button cta-link-external %s"><a href="" target="_blank" rel="noopener noreferrer" class="hidden"><span class="button-label"></span></a></div>', esc_attr( $class ) );
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Display field button in left panel only if the field is editable.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @param array $fields All fields to display in the left panel.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function field_button( $fields ) {
|
||||
|
||||
if ( $this->is_editable() ) {
|
||||
return parent::field_button( $fields );
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* When the form is going to be displayed on front-end, remove internal information fields.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @param array $form_data Form data.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function remove_internal_fields_on_front_end( $form_data ) {
|
||||
|
||||
if ( empty( $form_data['fields'] ) ) {
|
||||
return $form_data;
|
||||
}
|
||||
|
||||
foreach ( $form_data['fields'] as $id => $field ) {
|
||||
if ( $field['type'] === $this->type ) {
|
||||
unset( $form_data['fields'][ $id ] );
|
||||
}
|
||||
}
|
||||
|
||||
return $form_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove field from form data before processing the form submit.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @param array $form_data Form data.
|
||||
* @param array $entry Form submission raw data ($_POST).
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function process_before_form_data( $form_data, $entry ) {
|
||||
|
||||
return $this->remove_internal_fields_on_front_end( $form_data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not display the duplicate button.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @param bool $is_visible If true, the duplicate button will be displayed.
|
||||
* @param array $field Field data and settings.
|
||||
* @param array $form_data Form data and settings.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function display_duplicate_button( $is_visible, $field, $form_data ) {
|
||||
|
||||
if ( $this->is_internal_information_field( $field ) && ! $this->is_editable() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $is_visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide column from the entries list table.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @param array $disallowed Table columns.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function hide_column_in_entries_table( $disallowed ) {
|
||||
|
||||
$disallowed[] = $this->type;
|
||||
|
||||
return $disallowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add CSS class for the field parent div informing about mode (editable or not).
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @param string $css CSS classes.
|
||||
* @param array $field Field data and settings.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function add_css_class_for_field_wrapper( $css, $field ) {
|
||||
|
||||
if ( ! $this->is_internal_information_field( $field ) ) {
|
||||
return $css;
|
||||
}
|
||||
|
||||
if ( $this->is_editable() ) {
|
||||
$css .= ' internal-information-editable ';
|
||||
|
||||
return $css;
|
||||
}
|
||||
|
||||
$css .= ' ui-sortable-disabled internal-information-not-editable internal-information-not-draggable ';
|
||||
|
||||
return str_replace( 'ui-sortable-handle', '', $css );
|
||||
}
|
||||
|
||||
/**
|
||||
* Save checkbox state to the post meta table.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*/
|
||||
public function save_internal_information_checkbox() {
|
||||
|
||||
// Run several checks: required items, security, permissions.
|
||||
if (
|
||||
! isset( $_POST['formId'], $_POST['name'], $_POST['checked'] ) ||
|
||||
! check_ajax_referer( 'wpforms-builder', 'nonce', false ) ||
|
||||
! wpforms_current_user_can( 'edit_forms' )
|
||||
) {
|
||||
wp_send_json_error();
|
||||
}
|
||||
|
||||
$form_id = (int) $_POST['formId'];
|
||||
$checked = (int) $_POST['checked'];
|
||||
$name = sanitize_text_field( wp_unslash( $_POST['name'] ) );
|
||||
$post_meta = get_post_meta( $form_id, self::CHECKBOX_META_KEY, true );
|
||||
$post_meta = ! empty( $post_meta ) ? (array) $post_meta : [];
|
||||
|
||||
if ( $checked ) {
|
||||
$post_meta[ $name ] = $checked;
|
||||
} else {
|
||||
unset( $post_meta[ $name ] );
|
||||
}
|
||||
|
||||
update_post_meta( $form_id, self::CHECKBOX_META_KEY, $post_meta );
|
||||
|
||||
wp_send_json_success();
|
||||
}
|
||||
|
||||
/**
|
||||
* Localized strings for wpforms-internal-information-field JS script.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @param array $strings Localized strings.
|
||||
* @param array $form The form element.
|
||||
*
|
||||
* @return array
|
||||
* @noinspection PhpUnusedParameterInspection
|
||||
*/
|
||||
public function builder_strings( $strings, $form ) {
|
||||
|
||||
$strings['iif_redirect_url_field_error'] = esc_html__( 'You should enter a valid absolute address to the CTA Link field or leave it empty.', 'wpforms-lite' );
|
||||
$strings['iif_dismiss'] = esc_html__( 'Dismiss', 'wpforms-lite' );
|
||||
$strings['iif_more'] = esc_html__( 'Learn More', 'wpforms-lite' );
|
||||
|
||||
return $strings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue wpforms-internal-information-field script.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @param string $view Current view.
|
||||
*
|
||||
* @noinspection PhpUnusedParameterInspection, PhpUnnecessaryCurlyVarSyntaxInspection
|
||||
*/
|
||||
public function builder_enqueues( $view ) {
|
||||
|
||||
$min = wpforms_get_min_suffix();
|
||||
|
||||
wp_enqueue_script(
|
||||
'wpforms-md5-hash',
|
||||
WPFORMS_PLUGIN_URL . 'assets/lib/md5.min.js',
|
||||
[ 'wpforms-builder' ],
|
||||
'2.19.0'
|
||||
);
|
||||
|
||||
wp_enqueue_script(
|
||||
'wpforms-internal-information-field',
|
||||
WPFORMS_PLUGIN_URL . "assets/js/components/admin/fields/internal-information-field{$min}.js",
|
||||
[ 'wpforms-builder', 'wpforms-md5-hash', 'wpforms-builder-drag-fields' ],
|
||||
WPFORMS_VERSION
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user is allowed to edit the field's content.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_editable() {
|
||||
|
||||
/**
|
||||
* Allow changing a mode.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @param bool $is_editable True if editable mode is allowed. Default: false.
|
||||
*/
|
||||
return (bool) apply_filters( 'wpforms_field_internal_information_is_editable', false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the field has type internal-information.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @param array $field Field data.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_internal_information_field( $field ) {
|
||||
|
||||
return isset( $field['type'] ) && $field['type'] === $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render result of field_preview_option into custom div.
|
||||
*
|
||||
* If field has no value, do not echo anything.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @param string $label Field label.
|
||||
* @param array $field Field settings and data.
|
||||
* @param array $args Field arguments.
|
||||
*/
|
||||
private function render_preview( $label, $field, $args = [] ) {
|
||||
|
||||
$key = $label === 'heading' ? 'label' : $label;
|
||||
|
||||
if ( empty( $field[ $key ] ) && ! $this->is_editable() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$allowed_tags = $this->get_allowed_tags();
|
||||
|
||||
printf(
|
||||
'<div class="wpforms-field-internal-information-row wpforms-field-internal-information-row-%s">%s</div>',
|
||||
esc_attr( $label ),
|
||||
wp_kses( $this->render_custom_preview( $label, $field, $args ), $allowed_tags )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace `[] some text` with checkboxes.
|
||||
*
|
||||
* Additionally, generates input name by hashing the line of text where the checkbox is.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @param string $description Expanded description.
|
||||
* @param array $field Field data and settings.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function replace_checkboxes( $description, array $field ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
|
||||
|
||||
if ( ! $this->form_id ) {
|
||||
return $description;
|
||||
}
|
||||
|
||||
$lines = explode( PHP_EOL, $description );
|
||||
$replaced = [];
|
||||
$post_meta = get_post_meta( $this->form_id, self::CHECKBOX_META_KEY, true );
|
||||
$post_meta = ! empty( $post_meta ) ? (array) $post_meta : [];
|
||||
$field_id = isset( $field['id'] ) ? $field['id'] : 0;
|
||||
$needle = '[] ';
|
||||
|
||||
foreach ( $lines as $line_number => $line ) {
|
||||
$line = trim( $line );
|
||||
|
||||
if ( strpos( $line, $needle ) !== 0 ) {
|
||||
$replaced[] = $line . PHP_EOL;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$field_name = sprintf( 'iif-%d-%s-%d', $field_id, md5( $line ), $line_number );
|
||||
$checked = (int) isset( $post_meta[ $field_name ] );
|
||||
$attributes = [
|
||||
'name' => esc_attr( $field_name ),
|
||||
'value' => 1,
|
||||
];
|
||||
|
||||
if ( $this->is_editable() ) {
|
||||
$attributes['disabled'] = 'disabled';
|
||||
$attributes['title'] = esc_html__( 'This field is disabled in the editor mode.', 'wpforms-lite' );
|
||||
}
|
||||
|
||||
$html = sprintf(
|
||||
'<div class="wpforms-field-internal-information-checkbox-input"><input type="checkbox" %s %s /></div><div class="wpforms-field-internal-information-checkbox-label">',
|
||||
wpforms_html_attributes(
|
||||
'',
|
||||
[ 'wpforms-field-internal-information-checkbox' ],
|
||||
[],
|
||||
$attributes
|
||||
),
|
||||
! $this->is_editable() ? checked( $checked, 1, false ) : ''
|
||||
);
|
||||
|
||||
$line = substr_replace( $line, $html, 0, strlen( $needle ) );
|
||||
|
||||
$replaced[] = '<div class="wpforms-field-internal-information-checkbox-wrap">' . $line . '</div></div>';
|
||||
}
|
||||
|
||||
return implode( '', $replaced );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return allowed tags specific to internal information field content.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_allowed_tags() {
|
||||
|
||||
$allowed_tags = wpforms_builder_preview_get_allowed_tags();
|
||||
|
||||
$allowed_tags['input'] = [
|
||||
'type' => [],
|
||||
'name' => [],
|
||||
'value' => [],
|
||||
'class' => [],
|
||||
'checked' => [],
|
||||
'disabled' => [],
|
||||
'title' => [],
|
||||
];
|
||||
|
||||
return $allowed_tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds link parameters to all links in the provided content.
|
||||
*
|
||||
* @since 1.8.3
|
||||
*
|
||||
* @param string $content The content to modify.
|
||||
*
|
||||
* @return string The modified content with UTM parameters added to links.
|
||||
*/
|
||||
private function add_link_attributes( $content ) {
|
||||
|
||||
if ( empty( $content ) || ! class_exists( 'DOMDocument' ) ) {
|
||||
return $content;
|
||||
}
|
||||
|
||||
$dom = new DOMDocument();
|
||||
$form_data = wpforms()->get( 'form' )->get( $this->form_id, [ 'content_only' => true ] );
|
||||
$template_data = ! empty( $form_data['meta'] ) ? wpforms()->get( 'builder_templates' )->get_template( $form_data['meta']['template'] ) : [];
|
||||
$template_name = ! empty( $template_data ) ? $template_data['name'] : '';
|
||||
|
||||
$dom->loadHTML( htmlspecialchars_decode( htmlentities( $content ) ) );
|
||||
|
||||
$links = $dom->getElementsByTagName( 'a' );
|
||||
|
||||
foreach ( $links as $link ) {
|
||||
$href = $link->getAttribute( 'href' );
|
||||
$text = $link->textContent; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
|
||||
$modified_href = wpforms_utm_link( $href, 'Form Template Information Note', $template_name, $text );
|
||||
|
||||
$link->setAttribute( 'href', $modified_href );
|
||||
$link->setAttribute( 'target', '_blank' );
|
||||
$link->setAttribute( 'rel', 'noopener noreferrer' );
|
||||
}
|
||||
|
||||
// Remove the wrapper elements.
|
||||
$body = $dom->getElementsByTagName( 'body' )->item( 0 );
|
||||
$inner_html = '';
|
||||
|
||||
foreach ( $body->childNodes as $node ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
|
||||
$inner_html .= $dom->saveHTML( $node );
|
||||
}
|
||||
|
||||
return $inner_html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add UTM parameters to the CTA button link.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @param array $field Field data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function add_url_utm( $field ) {
|
||||
|
||||
if ( strpos( $field['cta-link'], 'https://wpforms.com' ) === 0 ) {
|
||||
return wpforms_utm_link( $field['cta-link'], 'Template Documentation' );
|
||||
}
|
||||
|
||||
return $field['cta-link'];
|
||||
}
|
||||
}
|
||||
|
||||
new WPForms_Field_Internal_Information();
|
622
wp-content/plugins/wpforms-lite/includes/fields/class-name.php
Normal file
622
wp-content/plugins/wpforms-lite/includes/fields/class-name.php
Normal file
@@ -0,0 +1,622 @@
|
||||
<?php
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Name text field.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class WPForms_Field_Name extends WPForms_Field {
|
||||
|
||||
/**
|
||||
* Primary class constructor.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
// Define field type information.
|
||||
$this->name = esc_html__( 'Name', 'wpforms-lite' );
|
||||
$this->keywords = esc_html__( 'user, first, last', 'wpforms-lite' );
|
||||
$this->type = 'name';
|
||||
$this->icon = 'fa-user';
|
||||
$this->order = 150;
|
||||
|
||||
$this->hooks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Hooks.
|
||||
*
|
||||
* @since 1.8.1
|
||||
*/
|
||||
private function hooks() {
|
||||
|
||||
// Define additional field properties.
|
||||
add_filter( 'wpforms_field_properties_name', [ $this, 'field_properties' ], 5, 3 );
|
||||
|
||||
// Set field to default to required.
|
||||
add_filter( 'wpforms_field_new_required', [ $this, 'default_required' ], 10, 2 );
|
||||
|
||||
// This field requires fieldset+legend instead of the field label.
|
||||
add_filter( "wpforms_frontend_modern_is_field_requires_fieldset_{$this->type}", [ $this, 'is_field_requires_fieldset' ], PHP_INT_MAX, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Define additional field properties.
|
||||
*
|
||||
* @since 1.3.7
|
||||
*
|
||||
* @param array $properties Field properties.
|
||||
* @param array $field Field data and settings.
|
||||
* @param array $form_data Form data and settings.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function field_properties( $properties, $field, $form_data ) {
|
||||
|
||||
$format = ! empty( $field['format'] ) ? esc_attr( $field['format'] ) : 'first-last';
|
||||
|
||||
// Simple format.
|
||||
if ( 'simple' === $format ) {
|
||||
$properties['inputs']['primary']['attr']['placeholder'] = ! empty( $field['simple_placeholder'] ) ? $field['simple_placeholder'] : '';
|
||||
$properties['inputs']['primary']['attr']['value'] = ! empty( $field['simple_default'] ) ? wpforms_process_smart_tags( $field['simple_default'], $form_data ) : '';
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
// Expanded formats.
|
||||
// Remove primary for expanded formats since we have first, middle, last.
|
||||
unset( $properties['inputs']['primary'] );
|
||||
|
||||
$form_id = absint( $form_data['id'] );
|
||||
$field_id = absint( $field['id'] );
|
||||
|
||||
$props = [
|
||||
'inputs' => [
|
||||
'first' => [
|
||||
'attr' => [
|
||||
'name' => "wpforms[fields][{$field_id}][first]",
|
||||
'value' => ! empty( $field['first_default'] ) ? wpforms_process_smart_tags( $field['first_default'], $form_data ) : '',
|
||||
'placeholder' => ! empty( $field['first_placeholder'] ) ? $field['first_placeholder'] : '',
|
||||
],
|
||||
'block' => [
|
||||
'wpforms-field-row-block',
|
||||
'wpforms-first',
|
||||
],
|
||||
'class' => [
|
||||
'wpforms-field-name-first',
|
||||
],
|
||||
'data' => [],
|
||||
'id' => "wpforms-{$form_id}-field_{$field_id}",
|
||||
'required' => ! empty( $field['required'] ) ? 'required' : '',
|
||||
'sublabel' => [
|
||||
'hidden' => ! empty( $field['sublabel_hide'] ),
|
||||
'value' => esc_html__( 'First', 'wpforms-lite' ),
|
||||
],
|
||||
],
|
||||
'middle' => [
|
||||
'attr' => [
|
||||
'name' => "wpforms[fields][{$field_id}][middle]",
|
||||
'value' => ! empty( $field['middle_default'] ) ? wpforms_process_smart_tags( $field['middle_default'], $form_data ) : '',
|
||||
'placeholder' => ! empty( $field['middle_placeholder'] ) ? $field['middle_placeholder'] : '',
|
||||
],
|
||||
'block' => [
|
||||
'wpforms-field-row-block',
|
||||
'wpforms-one-fifth',
|
||||
],
|
||||
'class' => [
|
||||
'wpforms-field-name-middle',
|
||||
],
|
||||
'data' => [],
|
||||
'id' => "wpforms-{$form_id}-field_{$field_id}-middle",
|
||||
'required' => '',
|
||||
'sublabel' => [
|
||||
'hidden' => ! empty( $field['sublabel_hide'] ),
|
||||
'value' => esc_html__( 'Middle', 'wpforms-lite' ),
|
||||
],
|
||||
],
|
||||
'last' => [
|
||||
'attr' => [
|
||||
'name' => "wpforms[fields][{$field_id}][last]",
|
||||
'value' => ! empty( $field['last_default'] ) ? wpforms_process_smart_tags( $field['last_default'], $form_data ) : '',
|
||||
'placeholder' => ! empty( $field['last_placeholder'] ) ? $field['last_placeholder'] : '',
|
||||
],
|
||||
'block' => [
|
||||
'wpforms-field-row-block',
|
||||
|
||||
],
|
||||
'class' => [
|
||||
'wpforms-field-name-last',
|
||||
],
|
||||
'data' => [],
|
||||
'id' => "wpforms-{$form_id}-field_{$field_id}-last",
|
||||
'required' => ! empty( $field['required'] ) ? 'required' : '',
|
||||
'sublabel' => [
|
||||
'hidden' => ! empty( $field['sublabel_hide'] ),
|
||||
'value' => esc_html__( 'Last', 'wpforms-lite' ),
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$properties = array_merge_recursive( $properties, $props );
|
||||
|
||||
$has_common_error = ! empty( $properties['error']['value'] ) && is_string( $properties['error']['value'] );
|
||||
|
||||
// Input First: add error class if needed.
|
||||
if ( ! empty( $properties['error']['value']['first'] ) || $has_common_error ) {
|
||||
$properties['inputs']['first']['class'][] = 'wpforms-error';
|
||||
}
|
||||
|
||||
// Input First: add required class if needed.
|
||||
if ( ! empty( $field['required'] ) ) {
|
||||
$properties['inputs']['first']['class'][] = 'wpforms-field-required';
|
||||
}
|
||||
|
||||
// Input First: add column class.
|
||||
$properties['inputs']['first']['block'][] = 'first-last' === $format ? 'wpforms-one-half' : 'wpforms-two-fifths';
|
||||
|
||||
// Input Middle: add error class if needed.
|
||||
if ( $has_common_error ) {
|
||||
$properties['inputs']['middle']['class'][] = 'wpforms-error';
|
||||
}
|
||||
|
||||
// Input Last: add error class if needed.
|
||||
if ( ! empty( $properties['error']['value']['last'] ) || $has_common_error ) {
|
||||
$properties['inputs']['last']['class'][] = 'wpforms-error';
|
||||
}
|
||||
|
||||
// Input Last: add required class if needed.
|
||||
if ( ! empty( $field['required'] ) ) {
|
||||
$properties['inputs']['last']['class'][] = 'wpforms-field-required';
|
||||
}
|
||||
|
||||
// Input Last: add column class.
|
||||
$properties['inputs']['last']['block'][] = 'first-last' === $format ? 'wpforms-one-half' : 'wpforms-two-fifths';
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Name fields should default to being required.
|
||||
*
|
||||
* @since 1.0.8
|
||||
*
|
||||
* @param bool $required
|
||||
* @param array $field
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function default_required( $required, $field ) {
|
||||
|
||||
if ( 'name' === $field['type'] ) {
|
||||
return true;
|
||||
}
|
||||
return $required;
|
||||
}
|
||||
|
||||
/**
|
||||
* Field options panel inside the builder.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param array $field
|
||||
*/
|
||||
public function field_options( $field ) {
|
||||
|
||||
// Define data.
|
||||
$format = ! empty( $field['format'] ) ? esc_attr( $field['format'] ) : 'first-last';
|
||||
|
||||
/*
|
||||
* Basic field options.
|
||||
*/
|
||||
|
||||
// Options open markup.
|
||||
$args = [
|
||||
'markup' => 'open',
|
||||
];
|
||||
|
||||
$this->field_option( 'basic-options', $field, $args );
|
||||
|
||||
// Label.
|
||||
$this->field_option( 'label', $field );
|
||||
|
||||
// Format.
|
||||
$lbl = $this->field_element(
|
||||
'label',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'format',
|
||||
'value' => esc_html__( 'Format', 'wpforms-lite' ),
|
||||
'tooltip' => esc_html__( 'Select format to use for the name form field', 'wpforms-lite' ),
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$fld = $this->field_element(
|
||||
'select',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'format',
|
||||
'value' => $format,
|
||||
'options' => [
|
||||
'simple' => esc_html__( 'Simple', 'wpforms-lite' ),
|
||||
'first-last' => esc_html__( 'First Last', 'wpforms-lite' ),
|
||||
'first-middle-last' => esc_html__( 'First Middle Last', 'wpforms-lite' ),
|
||||
],
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$args = [
|
||||
'slug' => 'format',
|
||||
'content' => $lbl . $fld,
|
||||
];
|
||||
|
||||
$this->field_element( 'row', $field, $args );
|
||||
|
||||
// Description.
|
||||
$this->field_option( 'description', $field );
|
||||
|
||||
// Required toggle.
|
||||
$this->field_option( 'required', $field );
|
||||
|
||||
// Options close markup.
|
||||
$args = [
|
||||
'markup' => 'close',
|
||||
];
|
||||
|
||||
$this->field_option( 'basic-options', $field, $args );
|
||||
|
||||
/*
|
||||
* Advanced field options.
|
||||
*/
|
||||
|
||||
// Options open markup.
|
||||
$args = [
|
||||
'markup' => 'open',
|
||||
];
|
||||
|
||||
$this->field_option( 'advanced-options', $field, $args );
|
||||
|
||||
// Size.
|
||||
$this->field_option( 'size', $field );
|
||||
|
||||
echo '<div class="format-selected-' . $format . ' format-selected">';
|
||||
|
||||
// Simple.
|
||||
$simple_placeholder = ! empty( $field['simple_placeholder'] ) ? esc_attr( $field['simple_placeholder'] ) : '';
|
||||
$simple_default = ! empty( $field['simple_default'] ) ? esc_attr( $field['simple_default'] ) : '';
|
||||
printf( '<div class="wpforms-clear wpforms-field-option-row wpforms-field-option-row-simple" id="wpforms-field-option-row-%d-simple" data-subfield="simple" data-field-id="%d">', $field['id'], $field['id'] );
|
||||
$this->field_element( 'label', $field, [ 'slug' => 'simple_placeholder', 'value' => esc_html__( 'Name', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Name field advanced options.', 'wpforms-lite' ) ] );
|
||||
echo '<div class="wpforms-field-options-columns-2 wpforms-field-options-columns">';
|
||||
echo '<div class="placeholder wpforms-field-options-column">';
|
||||
printf( '<input type="text" class="placeholder" id="wpforms-field-option-%d-simple_placeholder" name="fields[%d][simple_placeholder]" value="%s">', (int) $field['id'], (int) $field['id'], esc_attr( $simple_placeholder ) );
|
||||
printf( '<label for="wpforms-field-option-%d-simple_placeholder" class="sub-label">%s</label>', (int) $field['id'], esc_html__( 'Placeholder', 'wpforms-lite' ) );
|
||||
echo '</div>';
|
||||
echo '<div class="default wpforms-field-options-column">';
|
||||
printf( '<input type="text" class="default" id="wpforms-field-option-%d-simple_default" name="fields[%d][simple_default]" value="%s">', (int) $field['id'], (int) $field['id'], esc_attr( $simple_default ) );
|
||||
printf( '<label for="wpforms-field-option-%d-simple_default" class="sub-label">%s</label>', (int) $field['id'], esc_html__( 'Default Value', 'wpforms-lite' ) );
|
||||
echo '</div>';
|
||||
echo '</div>';
|
||||
echo '</div>';
|
||||
|
||||
// First.
|
||||
$first_placeholder = ! empty( $field['first_placeholder'] ) ? esc_attr( $field['first_placeholder'] ) : '';
|
||||
$first_default = ! empty( $field['first_default'] ) ? esc_attr( $field['first_default'] ) : '';
|
||||
printf( '<div class="wpforms-clear wpforms-field-option-row wpforms-field-option-row-first" id="wpforms-field-option-row-%d-first" data-subfield="first-name" data-field-id="%d">', $field['id'], $field['id'] );
|
||||
$this->field_element( 'label', $field, [ 'slug' => 'first_placeholder', 'value' => esc_html__( 'First Name', 'wpforms-lite' ), 'tooltip' => esc_html__( 'First name field advanced options.', 'wpforms-lite' ) ] );
|
||||
echo '<div class="wpforms-field-options-columns-2 wpforms-field-options-columns">';
|
||||
echo '<div class="placeholder wpforms-field-options-column">';
|
||||
printf( '<input type="text" class="placeholder" id="wpforms-field-option-%1$d-first_placeholder" name="fields[%1$d][first_placeholder]" value="%2$s">', (int) $field['id'], esc_attr( $first_placeholder ) );
|
||||
printf( '<label for="wpforms-field-option-%d-first_placeholder" class="sub-label">%s</label>', (int) $field['id'], esc_html__( 'Placeholder', 'wpforms-lite' ) );
|
||||
echo '</div>';
|
||||
echo '<div class="default wpforms-field-options-column">';
|
||||
printf( '<input type="text" class="default" id="wpforms-field-option-%1$d-first_default" name="fields[%1$d][first_default]" value="%2$s">', (int) $field['id'], esc_attr( $first_default ) );
|
||||
printf( '<label for="wpforms-field-option-%d-first_default" class="sub-label">%s</label>', (int) $field['id'], esc_html__( 'Default Value', 'wpforms-lite' ) );
|
||||
echo '</div>';
|
||||
echo '</div>';
|
||||
echo '</div>';
|
||||
|
||||
// Middle.
|
||||
$middle_placeholder = ! empty( $field['middle_placeholder'] ) ? esc_attr( $field['middle_placeholder'] ) : '';
|
||||
$middle_default = ! empty( $field['middle_default'] ) ? esc_attr( $field['middle_default'] ) : '';
|
||||
printf( '<div class="wpforms-clear wpforms-field-option-row wpforms-field-option-row-middle" id="wpforms-field-option-row-%d-middle" data-subfield="middle-name" data-field-id="%d">', $field['id'], $field['id'] );
|
||||
$this->field_element( 'label', $field, [ 'slug' => 'middle_placeholder', 'value' => esc_html__( 'Middle Name', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Middle name field advanced options.', 'wpforms-lite' ) ] );
|
||||
echo '<div class="wpforms-field-options-columns-2 wpforms-field-options-columns">';
|
||||
echo '<div class="placeholder wpforms-field-options-column">';
|
||||
printf( '<input type="text" class="placeholder" id="wpforms-field-option-%1$d-middle_placeholder" name="fields[%1$d][middle_placeholder]" value="%2$s">', (int) $field['id'], esc_attr( $middle_placeholder ) );
|
||||
printf( '<label for="wpforms-field-option-%d-middle_placeholder" class="sub-label">%s</label>', (int) $field['id'], esc_html__( 'Placeholder', 'wpforms-lite' ) );
|
||||
echo '</div>';
|
||||
echo '<div class="default wpforms-field-options-column">';
|
||||
printf( '<input type="text" class="default" id="wpforms-field-option-%1$d-middle_default" name="fields[%1$d][middle_default]" value="%2$s">', (int) $field['id'], esc_attr( $middle_default ) );
|
||||
printf( '<label for="wpforms-field-option-%d-middle_default" class="sub-label">%s</label>', (int) $field['id'], esc_html__( 'Default Value', 'wpforms-lite' ) );
|
||||
echo '</div>';
|
||||
echo '</div>';
|
||||
echo '</div>';
|
||||
|
||||
// Last.
|
||||
$last_placeholder = ! empty( $field['last_placeholder'] ) ? esc_attr( $field['last_placeholder'] ) : '';
|
||||
$last_default = ! empty( $field['last_default'] ) ? esc_attr( $field['last_default'] ) : '';
|
||||
printf( '<div class="wpforms-clear wpforms-field-option-row wpforms-field-option-row-last" id="wpforms-field-option-row-%d-last" data-subfield="last-name" data-field-id="%d">', $field['id'], $field['id'] );
|
||||
$this->field_element( 'label', $field, [ 'slug' => 'last_placeholder', 'value' => esc_html__( 'Last Name', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Last name field advanced options.', 'wpforms-lite' ) ] );
|
||||
echo '<div class="wpforms-field-options-columns-2 wpforms-field-options-columns">';
|
||||
echo '<div class="placeholder wpforms-field-options-column">';
|
||||
printf( '<input type="text" class="placeholder" id="wpforms-field-option-%1$d-last_placeholder" name="fields[%1$d][last_placeholder]" value="%2$s">', (int) $field['id'], esc_attr( $last_placeholder ) );
|
||||
printf( '<label for="wpforms-field-option-%d-last_placeholder" class="sub-label">%s</label>', (int) $field['id'], esc_html__( 'Placeholder', 'wpforms-lite' ) );
|
||||
echo '</div>';
|
||||
echo '<div class="default wpforms-field-options-column">';
|
||||
printf( '<input type="text" class="default" id="wpforms-field-option-%1$d-last_default" name="fields[%1$d][last_default]" value="%2$s">', (int) $field['id'], esc_attr( $last_default ) );
|
||||
printf( '<label for="wpforms-field-option-%d-last_default" class="sub-label">%s</label>', (int) $field['id'], esc_html__( 'Default Value', 'wpforms-lite' ) );
|
||||
echo '</div>';
|
||||
echo '</div>';
|
||||
echo '</div>';
|
||||
|
||||
echo '</div>';
|
||||
|
||||
// Custom CSS classes.
|
||||
$this->field_option( 'css', $field );
|
||||
|
||||
// Hide Label.
|
||||
$this->field_option( 'label_hide', $field );
|
||||
|
||||
// Hide sublabels.
|
||||
$sublabel_class = isset( $field['format'] ) && ! in_array( $field['format'], [ 'first-last', 'first-middle-last' ], true ) ? 'wpforms-hidden' : '';
|
||||
|
||||
$this->field_option( 'sublabel_hide', $field, [ 'class' => $sublabel_class ] );
|
||||
|
||||
// Options close markup.
|
||||
$args = [
|
||||
'markup' => 'close',
|
||||
];
|
||||
|
||||
$this->field_option( 'advanced-options', $field, $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Field preview inside the builder.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param array $field Field information.
|
||||
*/
|
||||
public function field_preview( $field ) {
|
||||
|
||||
// Define data.
|
||||
$simple_placeholder = ! empty( $field['simple_placeholder'] ) ? $field['simple_placeholder'] : '';
|
||||
$first_placeholder = ! empty( $field['first_placeholder'] ) ? $field['first_placeholder'] : '';
|
||||
$middle_placeholder = ! empty( $field['middle_placeholder'] ) ? $field['middle_placeholder'] : '';
|
||||
$last_placeholder = ! empty( $field['last_placeholder'] ) ? $field['last_placeholder'] : '';
|
||||
$simple_default = ! empty( $field['simple_default'] ) ? $field['simple_default'] : '';
|
||||
$first_default = ! empty( $field['first_default'] ) ? $field['first_default'] : '';
|
||||
$middle_default = ! empty( $field['middle_default'] ) ? $field['middle_default'] : '';
|
||||
$last_default = ! empty( $field['last_default'] ) ? $field['last_default'] : '';
|
||||
$format = ! empty( $field['format'] ) ? $field['format'] : 'first-last';
|
||||
|
||||
// Label.
|
||||
$this->field_preview_option( 'label', $field );
|
||||
?>
|
||||
|
||||
<div class="format-selected-<?php echo sanitize_html_class( $format ); ?> format-selected wpforms-clear">
|
||||
|
||||
<div class="wpforms-simple">
|
||||
<input type="text" placeholder="<?php echo esc_attr( $simple_placeholder ); ?>" value="<?php echo esc_attr( $simple_default ); ?>" class="primary-input" readonly>
|
||||
</div>
|
||||
|
||||
<div class="wpforms-first-name">
|
||||
<input type="text" placeholder="<?php echo esc_attr( $first_placeholder ); ?>" value="<?php echo esc_attr( $first_default ); ?>" class="primary-input" readonly>
|
||||
<label class="wpforms-sub-label"><?php esc_html_e( 'First', 'wpforms-lite' ); ?></label>
|
||||
</div>
|
||||
|
||||
<div class="wpforms-middle-name">
|
||||
<input type="text" placeholder="<?php echo esc_attr( $middle_placeholder ); ?>" value="<?php echo esc_attr( $middle_default ); ?>" class="primary-input" readonly>
|
||||
<label class="wpforms-sub-label"><?php esc_html_e( 'Middle', 'wpforms-lite' ); ?></label>
|
||||
</div>
|
||||
|
||||
<div class="wpforms-last-name">
|
||||
<input type="text" placeholder="<?php echo esc_attr( $last_placeholder ); ?>" value="<?php echo esc_attr( $last_default ); ?>" class="primary-input" readonly>
|
||||
<label class="wpforms-sub-label"><?php esc_html_e( 'Last', 'wpforms-lite' ); ?></label>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<?php
|
||||
// Description.
|
||||
$this->field_preview_option( 'description', $field );
|
||||
}
|
||||
|
||||
/**
|
||||
* Field display on the form front-end.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param array $field Field information.
|
||||
* @param array $deprecated Deprecated parameter, not used anymore.
|
||||
* @param array $form_data Form data and settings.
|
||||
*/
|
||||
public function field_display( $field, $deprecated, $form_data ) {
|
||||
|
||||
// Define data.
|
||||
$format = ! empty( $field['format'] ) ? esc_attr( $field['format'] ) : 'first-last';
|
||||
$primary = ! empty( $field['properties']['inputs']['primary'] ) ? $field['properties']['inputs']['primary'] : '';
|
||||
$first = ! empty( $field['properties']['inputs']['first'] ) ? $field['properties']['inputs']['first'] : '';
|
||||
$middle = ! empty( $field['properties']['inputs']['middle'] ) ? $field['properties']['inputs']['middle'] : '';
|
||||
$last = ! empty( $field['properties']['inputs']['last'] ) ? $field['properties']['inputs']['last'] : '';
|
||||
|
||||
// Simple format.
|
||||
if ( 'simple' === $format ) {
|
||||
|
||||
// Primary field (Simple).
|
||||
printf(
|
||||
'<input type="text" %s %s>',
|
||||
wpforms_html_attributes( $primary['id'], $primary['class'], $primary['data'], $primary['attr'] ),
|
||||
$primary['required']
|
||||
);
|
||||
|
||||
// Expanded formats.
|
||||
} else {
|
||||
|
||||
// Row wrapper.
|
||||
echo '<div class="wpforms-field-row wpforms-field-' . sanitize_html_class( $field['size'] ) . '">';
|
||||
|
||||
// First name.
|
||||
echo '<div ' . wpforms_html_attributes( false, $first['block'] ) . '>';
|
||||
$this->field_display_sublabel( 'first', 'before', $field );
|
||||
printf(
|
||||
'<input type="text" %s %s>',
|
||||
wpforms_html_attributes( $first['id'], $first['class'], $first['data'], $first['attr'] ),
|
||||
$first['required']
|
||||
);
|
||||
$this->field_display_sublabel( 'first', 'after', $field );
|
||||
$this->field_display_error( 'first', $field );
|
||||
echo '</div>';
|
||||
|
||||
// Middle name.
|
||||
if ( 'first-middle-last' === $format ) {
|
||||
echo '<div ' . wpforms_html_attributes( false, $middle['block'] ) . '>';
|
||||
$this->field_display_sublabel( 'middle', 'before', $field );
|
||||
printf(
|
||||
'<input type="text" %s %s>',
|
||||
wpforms_html_attributes( $middle['id'], $middle['class'], $middle['data'], $middle['attr'] ),
|
||||
$middle['required']
|
||||
);
|
||||
$this->field_display_sublabel( 'middle', 'after', $field );
|
||||
$this->field_display_error( 'middle', $field );
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
// Last name.
|
||||
echo '<div ' . wpforms_html_attributes( false, $last['block'] ) . '>';
|
||||
$this->field_display_sublabel( 'last', 'before', $field );
|
||||
printf(
|
||||
'<input type="text" %s %s>',
|
||||
wpforms_html_attributes( $last['id'], $last['class'], $last['data'], $last['attr'] ),
|
||||
$last['required']
|
||||
);
|
||||
$this->field_display_sublabel( 'last', 'after', $field );
|
||||
$this->field_display_error( 'last', $field );
|
||||
echo '</div>';
|
||||
|
||||
echo '</div>';
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate field on form submit.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param int $field_id Field id.
|
||||
* @param array|string $field_submit Field submit.
|
||||
* @param array $form_data Form data.
|
||||
*/
|
||||
public function validate( $field_id, $field_submit, $form_data ) {
|
||||
|
||||
if ( empty( $form_data['fields'][ $field_id ]['required'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Extended validation needed for the different name fields.
|
||||
$form_id = $form_data['id'];
|
||||
$format = $form_data['fields'][ $field_id ]['format'];
|
||||
$required = wpforms_get_required_label();
|
||||
$process = wpforms()->get( 'process' );
|
||||
|
||||
if ( $format === 'simple' && wpforms_is_empty_string( $field_submit ) ) {
|
||||
$process->errors[ $form_id ][ $field_id ] = $required;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! ( $format === 'first-last' || $format === 'first-middle-last' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->validate_complicated_formats( $process, $form_id, $field_id, $field_submit, $required );
|
||||
}
|
||||
|
||||
/**
|
||||
* Format and sanitize field.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param int $field_id Field ID.
|
||||
* @param mixed $field_submit Field value that was submitted.
|
||||
* @param array $form_data Form data and settings.
|
||||
*/
|
||||
public function format( $field_id, $field_submit, $form_data ) {
|
||||
// Define data.
|
||||
$name = isset( $form_data['fields'][ $field_id ]['label'] ) && ! wpforms_is_empty_string( $form_data['fields'][ $field_id ]['label'] ) ? $form_data['fields'][ $field_id ]['label'] : '';
|
||||
$first = isset( $field_submit['first'] ) && ! wpforms_is_empty_string( $field_submit['first'] ) ? $field_submit['first'] : '';
|
||||
$middle = isset( $field_submit['middle'] ) && ! wpforms_is_empty_string( $field_submit['middle'] ) ? $field_submit['middle'] : '';
|
||||
$last = isset( $field_submit['last'] ) && ! wpforms_is_empty_string( $field_submit['last'] ) ? $field_submit['last'] : '';
|
||||
|
||||
if ( is_array( $field_submit ) ) {
|
||||
$value = implode( ' ', array_filter( [ $first, $middle, $last ] ) );
|
||||
} else {
|
||||
$value = $field_submit;
|
||||
}
|
||||
|
||||
// Set final field details.
|
||||
wpforms()->process->fields[ $field_id ] = [
|
||||
'name' => sanitize_text_field( $name ),
|
||||
'value' => sanitize_text_field( $value ),
|
||||
'id' => absint( $field_id ),
|
||||
'type' => $this->type,
|
||||
'first' => sanitize_text_field( $first ),
|
||||
'middle' => sanitize_text_field( $middle ),
|
||||
'last' => sanitize_text_field( $last ),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the field requires fieldset+legend instead of the regular field label.
|
||||
*
|
||||
* @since 1.8.1
|
||||
*
|
||||
* @param bool $requires_fieldset True if requires fieldset.
|
||||
* @param array $field Field data.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @noinspection PhpUnusedParameterInspection
|
||||
*/
|
||||
public function is_field_requires_fieldset( $requires_fieldset, $field ) {
|
||||
|
||||
return isset( $field['format'] ) && $field['format'] !== 'simple';
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate complicated formats.
|
||||
*
|
||||
* @since 1.8.2.3
|
||||
*
|
||||
* @param WPForms_Process $process Process class instance.
|
||||
* @param int|string $form_id Form id.
|
||||
* @param int|string $field_id Field id.
|
||||
* @param array $field_submit Field submit.
|
||||
* @param string $required Required message text.
|
||||
*/
|
||||
private function validate_complicated_formats( $process, $form_id, $field_id, $field_submit, $required ) {
|
||||
|
||||
// Prevent PHP Warning: Illegal string offset ‘first’ or 'last'.
|
||||
if ( isset( $process->errors[ $form_id ][ $field_id ] ) ) {
|
||||
$process->errors[ $form_id ][ $field_id ] = (array) $process->errors[ $form_id ][ $field_id ];
|
||||
}
|
||||
|
||||
if ( isset( $field_submit['first'] ) && wpforms_is_empty_string( $field_submit['first'] ) ) {
|
||||
$process->errors[ $form_id ][ $field_id ]['first'] = $required;
|
||||
}
|
||||
|
||||
if ( isset( $field_submit['last'] ) && wpforms_is_empty_string( $field_submit['last'] ) ) {
|
||||
$process->errors[ $form_id ][ $field_id ]['last'] = $required;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
new WPForms_Field_Name();
|
@@ -0,0 +1,510 @@
|
||||
<?php
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number Slider field.
|
||||
*
|
||||
* @since 1.5.7
|
||||
*/
|
||||
class WPForms_Field_Number_Slider extends WPForms_Field {
|
||||
|
||||
/**
|
||||
* Default minimum value of the field.
|
||||
*
|
||||
* @since 1.5.7
|
||||
*/
|
||||
const SLIDER_MIN = 0;
|
||||
|
||||
/**
|
||||
* Default maximum value of the field.
|
||||
*
|
||||
* @since 1.5.7
|
||||
*/
|
||||
const SLIDER_MAX = 10;
|
||||
|
||||
/**
|
||||
* Default step value of the field.
|
||||
*
|
||||
* @since 1.5.7
|
||||
*/
|
||||
const SLIDER_STEP = 1;
|
||||
|
||||
/**
|
||||
* Primary class constructor.
|
||||
*
|
||||
* @since 1.5.7
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
// Define field type information.
|
||||
$this->name = esc_html__( 'Number Slider', 'wpforms-lite' );
|
||||
$this->type = 'number-slider';
|
||||
$this->icon = 'fa-sliders';
|
||||
$this->order = 180;
|
||||
|
||||
// Customize value format for HTML emails.
|
||||
add_filter( 'wpforms_html_field_value', [ $this, 'html_email_value' ], 10, 4 );
|
||||
|
||||
// Builder strings.
|
||||
add_filter( 'wpforms_builder_strings', [ $this, 'add_builder_strings' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Builder strings.
|
||||
*
|
||||
* @since 1.6.2.3
|
||||
*
|
||||
* @param array $strings Form Builder strings.
|
||||
*
|
||||
* @return array Form Builder strings.
|
||||
*/
|
||||
public function add_builder_strings( $strings ) {
|
||||
|
||||
$strings['error_number_slider_increment'] = esc_html__( 'Increment value should be greater than zero. Decimal fractions allowed.', 'wpforms-lite' );
|
||||
|
||||
return $strings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Customize format for HTML email notifications.
|
||||
*
|
||||
* @since 1.5.7
|
||||
*
|
||||
* @param string $val Field value.
|
||||
* @param array $field Field settings.
|
||||
* @param array $form_data Form data and settings.
|
||||
* @param string $context Value display context.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function html_email_value( $val, $field, $form_data = [], $context = '' ) {
|
||||
|
||||
if ( empty( $field['value_raw'] ) || $field['type'] !== $this->type ) {
|
||||
return $val;
|
||||
}
|
||||
|
||||
$value = isset( $field['value_raw']['value'] ) ? (float) $field['value_raw']['value'] : 0;
|
||||
$min = isset( $field['value_raw']['min'] ) ? (float) $field['value_raw']['min'] : self::SLIDER_MIN;
|
||||
$max = isset( $field['value_raw']['max'] ) ? (float) $field['value_raw']['max'] : self::SLIDER_MAX;
|
||||
|
||||
$html_value = $value;
|
||||
if ( strpos( $field['value_raw']['value_display'], '{value}' ) !== false ) {
|
||||
$html_value = str_replace(
|
||||
'{value}',
|
||||
/* translators: %1$s - Number slider selected value, %2$s - its minimum value, %3$s - its maximum value. */
|
||||
sprintf( esc_html__( '%1$s (%2$s min / %3$s max)', 'wpforms-lite' ), $value, $min, $max ),
|
||||
$field['value_raw']['value_display']
|
||||
);
|
||||
}
|
||||
|
||||
return $html_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Field options panel inside the builder.
|
||||
*
|
||||
* @since 1.5.7
|
||||
*
|
||||
* @param array $field Field settings.
|
||||
*/
|
||||
public function field_options( $field ) {
|
||||
/*
|
||||
* Basic field options.
|
||||
*/
|
||||
|
||||
// Options open markup.
|
||||
$args = [
|
||||
'markup' => 'open',
|
||||
];
|
||||
|
||||
$this->field_option( 'basic-options', $field, $args );
|
||||
|
||||
// Label.
|
||||
$this->field_option( 'label', $field );
|
||||
|
||||
// Description.
|
||||
$this->field_option( 'description', $field );
|
||||
|
||||
// Required toggle disabled.
|
||||
$this->field_element(
|
||||
'text',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'required',
|
||||
'value' => '',
|
||||
'type' => 'hidden',
|
||||
]
|
||||
);
|
||||
|
||||
// Value: min/max.
|
||||
$lbl = $this->field_element(
|
||||
'label',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'value',
|
||||
'value' => esc_html__( 'Value', 'wpforms-lite' ),
|
||||
'tooltip' => esc_html__( 'Define the minimum and the maximum values for the slider.', 'wpforms-lite' ),
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$min = $this->field_element(
|
||||
'text',
|
||||
$field,
|
||||
[
|
||||
'type' => 'number',
|
||||
'slug' => 'min',
|
||||
'class' => 'wpforms-number-slider-min',
|
||||
'value' => ! empty( $field['min'] ) ? (float) $field['min'] : self::SLIDER_MIN,
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$max = $this->field_element(
|
||||
'text',
|
||||
$field,
|
||||
[
|
||||
'type' => 'number',
|
||||
'slug' => 'max',
|
||||
'class' => 'wpforms-number-slider-max',
|
||||
'value' => ! empty( $field['max'] ) ? (float) $field['max'] : self::SLIDER_MAX,
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$this->field_element(
|
||||
'row',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'min_max',
|
||||
'content' => $lbl . wpforms_render(
|
||||
'fields/number-slider/builder-option-min-max',
|
||||
[
|
||||
'label' => $lbl,
|
||||
'input_min' => $min,
|
||||
'input_max' => $max,
|
||||
'field_id' => $field['id'],
|
||||
],
|
||||
true
|
||||
),
|
||||
]
|
||||
);
|
||||
|
||||
// Default value.
|
||||
$lbl = $this->field_element(
|
||||
'label',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'default_value',
|
||||
'value' => esc_html__( 'Default Value', 'wpforms-lite' ),
|
||||
'tooltip' => esc_html__( 'Enter a default value for this field.', 'wpforms-lite' ),
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$fld = $this->field_element(
|
||||
'text',
|
||||
$field,
|
||||
[
|
||||
'type' => 'number',
|
||||
'slug' => 'default_value',
|
||||
'class' => 'wpforms-number-slider-default-value',
|
||||
'value' => ! empty( $field['default_value'] ) ? (float) $field['default_value'] : 0,
|
||||
'attrs' => [
|
||||
'min' => isset( $field['min'] ) && is_numeric( $field['min'] ) ? (float) $field['min'] : self::SLIDER_MIN,
|
||||
'max' => isset( $field['max'] ) && is_numeric( $field['max'] ) ? (float) $field['max'] : self::SLIDER_MAX,
|
||||
'step' => isset( $field['step'] ) && is_numeric( $field['step'] ) ? (float) $field['step'] : self::SLIDER_STEP,
|
||||
],
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$this->field_element(
|
||||
'row',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'default_value',
|
||||
'content' => $lbl . $fld,
|
||||
]
|
||||
);
|
||||
|
||||
// Steps.
|
||||
$lbl = $this->field_element(
|
||||
'label',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'step',
|
||||
'value' => esc_html__( 'Increment', 'wpforms-lite' ),
|
||||
'tooltip' => esc_html__( 'Determines the increment between selectable values on the slider.', 'wpforms-lite' ),
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$fld = $this->field_element(
|
||||
'text',
|
||||
$field,
|
||||
[
|
||||
'type' => 'number',
|
||||
'slug' => 'step',
|
||||
'class' => 'wpforms-number-slider-step',
|
||||
'value' => ! empty( $field['step'] ) ? abs( $field['step'] ) : self::SLIDER_STEP,
|
||||
'attrs' => [
|
||||
'min' => 0,
|
||||
'max' => isset( $field['max'] ) && is_numeric( $field['max'] ) ? abs( (float) $field['max'] ) : self::SLIDER_MAX,
|
||||
],
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$this->field_element(
|
||||
'row',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'step',
|
||||
'content' => $lbl . $fld,
|
||||
]
|
||||
);
|
||||
|
||||
// Options close markup.
|
||||
$args = [
|
||||
'markup' => 'close',
|
||||
];
|
||||
|
||||
$this->field_option( 'basic-options', $field, $args );
|
||||
|
||||
/*
|
||||
* Advanced field options.
|
||||
*/
|
||||
|
||||
// Options open markup.
|
||||
$args = [
|
||||
'markup' => 'open',
|
||||
];
|
||||
|
||||
$this->field_option( 'advanced-options', $field, $args );
|
||||
|
||||
// Size.
|
||||
$this->field_option( 'size', $field );
|
||||
|
||||
// Value display.
|
||||
$lbl = $this->field_element(
|
||||
'label',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'value_display',
|
||||
'value' => esc_html__( 'Value Display', 'wpforms-lite' ),
|
||||
'tooltip' => esc_html__( 'Displays the currently selected value below the slider.', 'wpforms-lite' ),
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$fld = $this->field_element(
|
||||
'text',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'value_display',
|
||||
'class' => 'wpforms-number-slider-value-display',
|
||||
'value' => isset( $field['value_display'] ) ? $field['value_display'] : $this->get_default_display_value(),
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$this->field_element(
|
||||
'row',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'value_display',
|
||||
'content' => $lbl . $fld,
|
||||
]
|
||||
);
|
||||
|
||||
// Custom CSS classes.
|
||||
$this->field_option( 'css', $field );
|
||||
|
||||
// Hide label.
|
||||
$this->field_option( 'label_hide', $field );
|
||||
|
||||
// Options close markup.
|
||||
$args = [
|
||||
'markup' => 'close',
|
||||
];
|
||||
|
||||
$this->field_option( 'advanced-options', $field, $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default display value.
|
||||
*
|
||||
* @since 1.7.1
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_default_display_value() {
|
||||
|
||||
return sprintf( /* translators: %s - value. */
|
||||
esc_html__( 'Selected Value: %s', 'wpforms-lite' ),
|
||||
'{value}'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Field preview inside the builder.
|
||||
*
|
||||
* @since 1.5.7
|
||||
*
|
||||
* @param array $field Field data.
|
||||
*/
|
||||
public function field_preview( $field ) {
|
||||
|
||||
// Label.
|
||||
$this->field_preview_option( 'label', $field );
|
||||
|
||||
$value_display = isset( $field['value_display'] ) ? esc_attr( $field['value_display'] ) : $this->get_default_display_value();
|
||||
$default_value = ! empty( $field['default_value'] ) ? (float) $field['default_value'] : 0;
|
||||
|
||||
echo wpforms_render( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
'fields/number-slider/builder-preview',
|
||||
[
|
||||
'min' => isset( $field['min'] ) && is_numeric( $field['min'] ) ? (float) $field['min'] : self::SLIDER_MIN,
|
||||
'max' => isset( $field['max'] ) && is_numeric( $field['max'] ) ? (float) $field['max'] : self::SLIDER_MAX,
|
||||
'step' => isset( $field['step'] ) && is_numeric( $field['step'] ) ? (float) $field['step'] : self::SLIDER_STEP,
|
||||
'value_display' => $value_display,
|
||||
'default_value' => $default_value,
|
||||
'value_hint' => str_replace( '{value}', '<b>' . $default_value . '</b>', wp_kses( $value_display, wpforms_builder_preview_get_allowed_tags() ) ),
|
||||
'field_id' => $field['id'],
|
||||
],
|
||||
true
|
||||
);
|
||||
|
||||
// Description.
|
||||
$this->field_preview_option( 'description', $field );
|
||||
}
|
||||
|
||||
/**
|
||||
* Field display on the form front-end.
|
||||
*
|
||||
* @since 1.5.7
|
||||
*
|
||||
* @param array $field Field data and settings.
|
||||
* @param array $deprecated Deprecated field attributes. Use $field['properties'] instead.
|
||||
* @param array $form_data Form data and settings.
|
||||
*/
|
||||
public function field_display( $field, $deprecated, $form_data ) {
|
||||
|
||||
// Define data.
|
||||
$primary = $field['properties']['inputs']['primary'];
|
||||
|
||||
$value_display = isset( $field['value_display'] ) ? esc_attr( $field['value_display'] ) : esc_html__( 'Selected Value: {value}', 'wpforms-lite' );
|
||||
$default_value = ! empty( $field['default_value'] ) ? (float) $field['default_value'] : 0;
|
||||
$hint_value = ! empty( $primary['attr']['value'] ) ? (float) $primary['attr']['value'] : $default_value;
|
||||
|
||||
$hint = str_replace( '{value}', '<b>' . $hint_value . '</b>', $value_display );
|
||||
|
||||
// phpcs:ignore
|
||||
echo wpforms_render(
|
||||
'fields/number-slider/frontend',
|
||||
[
|
||||
'atts' => $primary['attr'],
|
||||
'class' => $primary['class'],
|
||||
'datas' => $primary['data'],
|
||||
'default_value' => $default_value,
|
||||
'id' => $primary['id'],
|
||||
'max' => isset( $field['max'] ) && is_numeric( $field['max'] ) ? (float) $field['max'] : self::SLIDER_MAX,
|
||||
'min' => isset( $field['min'] ) && is_numeric( $field['min'] ) ? (float) $field['min'] : self::SLIDER_MIN,
|
||||
'required' => $primary['required'],
|
||||
'step' => isset( $field['step'] ) && is_numeric( $field['step'] ) ? (float) $field['step'] : self::SLIDER_STEP,
|
||||
'value_display' => $value_display,
|
||||
'value_hint' => $hint,
|
||||
],
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate field on form submit.
|
||||
*
|
||||
* @since 1.5.7
|
||||
*
|
||||
* @param int $field_id Field ID.
|
||||
* @param int|float|string $field_submit Submitted field value.
|
||||
* @param array $form_data Form data and settings.
|
||||
*/
|
||||
public function validate( $field_id, $field_submit, $form_data ) {
|
||||
|
||||
$form_id = $form_data['id'];
|
||||
|
||||
$field_submit = (float) $this->sanitize_value( $field_submit );
|
||||
|
||||
// Basic required check - if field is marked as required, check for entry data.
|
||||
if (
|
||||
! empty( $form_data['fields'][ $field_id ]['required'] ) &&
|
||||
empty( $field_submit ) &&
|
||||
(string) $field_submit !== '0'
|
||||
) {
|
||||
wpforms()->process->errors[ $form_id ][ $field_id ] = wpforms_get_required_label();
|
||||
}
|
||||
|
||||
// Check if value is numeric.
|
||||
if ( ! empty( $field_submit ) && ! is_numeric( $field_submit ) ) {
|
||||
wpforms()->process->errors[ $form_id ][ $field_id ] = apply_filters( 'wpforms_valid_number_label', esc_html__( 'Please provide a valid value.', 'wpforms-lite' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format and sanitize field.
|
||||
*
|
||||
* @since 1.5.7
|
||||
*
|
||||
* @param int $field_id Field ID.
|
||||
* @param int|string|float $field_submit Submitted field value.
|
||||
* @param array $form_data Form data and settings.
|
||||
*/
|
||||
public function format( $field_id, $field_submit, $form_data ) {
|
||||
|
||||
// Define data.
|
||||
$name = ! empty( $form_data['fields'][ $field_id ]['label'] ) ? $form_data['fields'][ $field_id ]['label'] : '';
|
||||
$value = (float) $this->sanitize_value( $field_submit );
|
||||
|
||||
$value_raw = [
|
||||
'value' => $value,
|
||||
'min' => (float) $form_data['fields'][ $field_id ]['min'],
|
||||
'max' => (float) $form_data['fields'][ $field_id ]['max'],
|
||||
'value_display' => wp_kses_post( $form_data['fields'][ $field_id ]['value_display'] ),
|
||||
];
|
||||
|
||||
// Set final field details.
|
||||
wpforms()->process->fields[ $field_id ] = [
|
||||
'name' => sanitize_text_field( $name ),
|
||||
'value' => $value,
|
||||
'value_raw' => $value_raw,
|
||||
'id' => absint( $field_id ),
|
||||
'type' => $this->type,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize the value.
|
||||
*
|
||||
* @since 1.5.7
|
||||
*
|
||||
* @param string $value The number field submitted value.
|
||||
*
|
||||
* @return float|int|string
|
||||
*/
|
||||
private function sanitize_value( $value ) {
|
||||
|
||||
// Some browsers allow other non-digit/decimal characters to be submitted
|
||||
// with the num input, which then trips the is_numeric validation below.
|
||||
// To get around this we remove all chars that are not expected.
|
||||
$signed_value = preg_replace( '/[^-0-9.]/', '', $value );
|
||||
$abs_value = abs( $signed_value );
|
||||
$value = strpos( $signed_value, '-' ) === 0 ? '-' . $abs_value : $abs_value;
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
new WPForms_Field_Number_Slider();
|
220
wp-content/plugins/wpforms-lite/includes/fields/class-number.php
Normal file
220
wp-content/plugins/wpforms-lite/includes/fields/class-number.php
Normal file
@@ -0,0 +1,220 @@
|
||||
<?php
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number text field.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class WPForms_Field_Number extends WPForms_Field {
|
||||
|
||||
/**
|
||||
* Primary class constructor.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
// Define field type information.
|
||||
$this->name = esc_html__( 'Numbers', 'wpforms-lite' );
|
||||
$this->type = 'number';
|
||||
$this->icon = 'fa-hashtag';
|
||||
$this->order = 130;
|
||||
}
|
||||
|
||||
/**
|
||||
* Field options panel inside the builder.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param array $field Field data.
|
||||
*/
|
||||
public function field_options( $field ) {
|
||||
/*
|
||||
* Basic field options.
|
||||
*/
|
||||
|
||||
// Options open markup.
|
||||
$args = [
|
||||
'markup' => 'open',
|
||||
];
|
||||
|
||||
$this->field_option( 'basic-options', $field, $args );
|
||||
|
||||
// Label.
|
||||
$this->field_option( 'label', $field );
|
||||
|
||||
// Description.
|
||||
$this->field_option( 'description', $field );
|
||||
|
||||
// Required toggle.
|
||||
$this->field_option( 'required', $field );
|
||||
|
||||
// Options close markup.
|
||||
$args = [
|
||||
'markup' => 'close',
|
||||
];
|
||||
|
||||
$this->field_option( 'basic-options', $field, $args );
|
||||
|
||||
/*
|
||||
* Advanced field options.
|
||||
*/
|
||||
|
||||
// Options open markup.
|
||||
$args = [
|
||||
'markup' => 'open',
|
||||
];
|
||||
|
||||
$this->field_option( 'advanced-options', $field, $args );
|
||||
|
||||
// Size.
|
||||
$this->field_option( 'size', $field );
|
||||
|
||||
// Placeholder.
|
||||
$this->field_option( 'placeholder', $field );
|
||||
|
||||
// Default value.
|
||||
$this->field_option( 'default_value', $field );
|
||||
|
||||
// Custom CSS classes.
|
||||
$this->field_option( 'css', $field );
|
||||
|
||||
// Hide label.
|
||||
$this->field_option( 'label_hide', $field );
|
||||
|
||||
// Options close markup.
|
||||
$args = [
|
||||
'markup' => 'close',
|
||||
];
|
||||
|
||||
$this->field_option( 'advanced-options', $field, $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Field preview inside the builder.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param array $field Field data.
|
||||
*/
|
||||
public function field_preview( $field ) {
|
||||
|
||||
// Define data.
|
||||
$placeholder = ! empty( $field['placeholder'] ) ? $field['placeholder'] : '';
|
||||
$default_value = ! empty( $field['default_value'] ) ? $field['default_value'] : '';
|
||||
|
||||
// Label.
|
||||
$this->field_preview_option( 'label', $field );
|
||||
|
||||
// Primary input.
|
||||
echo '<input type="text" placeholder="' . esc_attr( $placeholder ) . '" value="' . esc_attr( $default_value ) . '" class="primary-input" readonly>';
|
||||
|
||||
// Description.
|
||||
$this->field_preview_option( 'description', $field );
|
||||
}
|
||||
|
||||
/**
|
||||
* Field display on the form front-end.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param array $field Field data.
|
||||
* @param array $deprecated Deprecated, not used.
|
||||
* @param array $form_data Form data.
|
||||
*/
|
||||
public function field_display( $field, $deprecated, $form_data ) {
|
||||
|
||||
// Define data.
|
||||
$primary = $field['properties']['inputs']['primary'];
|
||||
|
||||
// Primary field.
|
||||
printf(
|
||||
'<input type="number" pattern="\d*" %s %s>',
|
||||
wpforms_html_attributes( $primary['id'], $primary['class'], $primary['data'], $primary['attr'] ),
|
||||
esc_attr( $primary['required'] )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate field on form submit.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param int $field_id Field id.
|
||||
* @param string $field_submit Submitted value.
|
||||
* @param array $form_data Form data.
|
||||
*/
|
||||
public function validate( $field_id, $field_submit, $form_data ) {
|
||||
|
||||
$form_id = $form_data['id'];
|
||||
|
||||
$value = $this->sanitize_value( $field_submit );
|
||||
|
||||
// If field is marked as required, check for entry data.
|
||||
if (
|
||||
! empty( $form_data['fields'][ $field_id ]['required'] ) &&
|
||||
empty( $value ) &&
|
||||
! is_numeric( $value )
|
||||
) {
|
||||
wpforms()->process->errors[ $form_id ][ $field_id ] = wpforms_get_required_label();
|
||||
}
|
||||
|
||||
// Check if value is numeric.
|
||||
if ( ! empty( $value ) && ! is_numeric( $value ) ) {
|
||||
wpforms()->process->errors[ $form_id ][ $field_id ] = apply_filters( 'wpforms_valid_number_label', esc_html__( 'Please enter a valid number.', 'wpforms-lite' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format and sanitize field.
|
||||
*
|
||||
* @since 1.3.5
|
||||
*
|
||||
* @param int $field_id Field id.
|
||||
* @param string $field_submit Submitted value.
|
||||
* @param array $form_data Form data.
|
||||
*/
|
||||
public function format( $field_id, $field_submit, $form_data ) {
|
||||
|
||||
// Define data.
|
||||
$name = ! empty( $form_data['fields'][ $field_id ]['label'] ) ? $form_data['fields'][ $field_id ]['label'] : '';
|
||||
|
||||
// Set final field details.
|
||||
wpforms()->process->fields[ $field_id ] = [
|
||||
'name' => sanitize_text_field( $name ),
|
||||
'value' => $this->sanitize_value( $field_submit ),
|
||||
'id' => absint( $field_id ),
|
||||
'type' => $this->type,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize the value.
|
||||
*
|
||||
* @since 1.5.7
|
||||
*
|
||||
* @param string $value The number field submitted value.
|
||||
*
|
||||
* @return float|int|string
|
||||
*/
|
||||
private function sanitize_value( $value ) {
|
||||
|
||||
if ( empty( $value ) && ! is_numeric( $value ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Some browsers allow other non-digit/decimal characters to be submitted
|
||||
// with the num input, which then trips the is_numeric validation below.
|
||||
// To get around this we remove all chars that are not expected.
|
||||
$signed_value = preg_replace( '/[^-0-9.]/', '', $value );
|
||||
$abs_value = str_replace( '-', '', $signed_value );
|
||||
|
||||
return $signed_value < 0 ? '-' . $abs_value : $abs_value;
|
||||
}
|
||||
}
|
||||
|
||||
new WPForms_Field_Number();
|
617
wp-content/plugins/wpforms-lite/includes/fields/class-radio.php
Normal file
617
wp-content/plugins/wpforms-lite/includes/fields/class-radio.php
Normal file
@@ -0,0 +1,617 @@
|
||||
<?php
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiple Choice field.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class WPForms_Field_Radio extends WPForms_Field {
|
||||
|
||||
/**
|
||||
* Primary class constructor.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
// Define field type information.
|
||||
$this->name = esc_html__( 'Multiple Choice', 'wpforms-lite' );
|
||||
$this->keywords = esc_html__( 'radio', 'wpforms-lite' );
|
||||
$this->type = 'radio';
|
||||
$this->icon = 'fa-dot-circle-o';
|
||||
$this->order = 110;
|
||||
$this->defaults = [
|
||||
1 => [
|
||||
'label' => esc_html__( 'First Choice', 'wpforms-lite' ),
|
||||
'value' => '',
|
||||
'image' => '',
|
||||
'icon' => '',
|
||||
'icon_style' => '',
|
||||
'default' => '',
|
||||
],
|
||||
2 => [
|
||||
'label' => esc_html__( 'Second Choice', 'wpforms-lite' ),
|
||||
'value' => '',
|
||||
'image' => '',
|
||||
'icon' => '',
|
||||
'icon_style' => '',
|
||||
'default' => '',
|
||||
],
|
||||
3 => [
|
||||
'label' => esc_html__( 'Third Choice', 'wpforms-lite' ),
|
||||
'value' => '',
|
||||
'image' => '',
|
||||
'icon' => '',
|
||||
'icon_style' => '',
|
||||
'default' => '',
|
||||
],
|
||||
];
|
||||
|
||||
$this->hooks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Hooks.
|
||||
*
|
||||
* @since 1.8.1
|
||||
*/
|
||||
private function hooks() {
|
||||
|
||||
// Customize HTML field values.
|
||||
add_filter( 'wpforms_html_field_value', [ $this, 'field_html_value' ], 10, 4 );
|
||||
|
||||
// Define additional field properties.
|
||||
add_filter( 'wpforms_field_properties_radio', [ $this, 'field_properties' ], 5, 3 );
|
||||
|
||||
// This field requires fieldset+legend instead of the field label.
|
||||
add_filter( "wpforms_frontend_modern_is_field_requires_fieldset_{$this->type}", '__return_true', PHP_INT_MAX, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Define additional field properties.
|
||||
*
|
||||
* @since 1.4.5
|
||||
*
|
||||
* @param array $properties Field properties.
|
||||
* @param array $field Field settings.
|
||||
* @param array $form_data Form data and settings.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function field_properties( $properties, $field, $form_data ) {
|
||||
|
||||
// Remove primary input.
|
||||
unset( $properties['inputs']['primary'] );
|
||||
|
||||
// Define data.
|
||||
$form_id = absint( $form_data['id'] );
|
||||
$field_id = absint( $field['id'] );
|
||||
$choices = $field['choices'];
|
||||
$dynamic = wpforms_get_field_dynamic_choices( $field, $form_id, $form_data );
|
||||
|
||||
if ( $dynamic !== false ) {
|
||||
$choices = $dynamic;
|
||||
$field['show_values'] = true;
|
||||
}
|
||||
|
||||
// Set input container (ul) properties.
|
||||
$properties['input_container'] = [
|
||||
'class' => [ ! empty( $field['random'] ) ? 'wpforms-randomize' : '' ],
|
||||
'data' => [],
|
||||
'attr' => [],
|
||||
'id' => "wpforms-{$form_id}-field_{$field_id}",
|
||||
];
|
||||
|
||||
// Set input properties.
|
||||
foreach ( $choices as $key => $choice ) {
|
||||
|
||||
// Used for dynamic choices.
|
||||
$depth = isset( $choice['depth'] ) ? absint( $choice['depth'] ) : 1;
|
||||
|
||||
$value = isset( $field['show_values'] ) ? $choice['value'] : $choice['label'];
|
||||
/* translators: %s - choice number. */
|
||||
$value = ( $value === '' ) ? sprintf( esc_html__( 'Choice %s', 'wpforms-lite' ), $key ) : $value;
|
||||
|
||||
$properties['inputs'][ $key ] = [
|
||||
'container' => [
|
||||
'attr' => [],
|
||||
'class' => [ "choice-{$key}", "depth-{$depth}" ],
|
||||
'data' => [],
|
||||
'id' => '',
|
||||
],
|
||||
'label' => [
|
||||
'attr' => [
|
||||
'for' => "wpforms-{$form_id}-field_{$field_id}_{$key}",
|
||||
],
|
||||
'class' => [ 'wpforms-field-label-inline' ],
|
||||
'data' => [],
|
||||
'id' => '',
|
||||
'text' => $choice['label'],
|
||||
],
|
||||
'attr' => [
|
||||
'name' => "wpforms[fields][{$field_id}]",
|
||||
'value' => $value,
|
||||
],
|
||||
'class' => [],
|
||||
'data' => [],
|
||||
'id' => "wpforms-{$form_id}-field_{$field_id}_{$key}",
|
||||
'icon' => isset( $choice['icon'] ) ? $choice['icon'] : '',
|
||||
'icon_style' => isset( $choice['icon_style'] ) ? $choice['icon_style'] : '',
|
||||
'image' => isset( $choice['image'] ) ? $choice['image'] : '',
|
||||
'required' => ! empty( $field['required'] ) ? 'required' : '',
|
||||
'default' => isset( $choice['default'] ),
|
||||
];
|
||||
}
|
||||
|
||||
// Required class for pagebreak validation.
|
||||
if ( ! empty( $field['required'] ) ) {
|
||||
$properties['input_container']['class'][] = 'wpforms-field-required';
|
||||
}
|
||||
|
||||
// Custom properties if image choices is enabled.
|
||||
if ( ! $dynamic && ! empty( $field['choices_images'] ) ) {
|
||||
|
||||
$properties['input_container']['class'][] = 'wpforms-image-choices';
|
||||
$properties['input_container']['class'][] = 'wpforms-image-choices-' . sanitize_html_class( $field['choices_images_style'] );
|
||||
|
||||
foreach ( $properties['inputs'] as $key => $inputs ) {
|
||||
$properties['inputs'][ $key ]['container']['class'][] = 'wpforms-image-choices-item';
|
||||
|
||||
if ( in_array( $field['choices_images_style'], [ 'modern', 'classic' ], true ) ) {
|
||||
$properties['inputs'][ $key ]['class'][] = 'wpforms-screen-reader-element';
|
||||
}
|
||||
}
|
||||
} elseif ( ! $dynamic && ! empty( $field['choices_icons'] ) ) {
|
||||
$properties = wpforms()->get( 'icon_choices' )->field_properties( $properties, $field );
|
||||
}
|
||||
|
||||
// Add selected class for choices with defaults.
|
||||
foreach ( $properties['inputs'] as $key => $inputs ) {
|
||||
if ( ! empty( $inputs['default'] ) ) {
|
||||
$properties['inputs'][ $key ]['container']['class'][] = 'wpforms-selected';
|
||||
}
|
||||
}
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Field options panel inside the builder.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param array $field Field settings.
|
||||
*/
|
||||
public function field_options( $field ) {
|
||||
/*
|
||||
* Basic field options.
|
||||
*/
|
||||
|
||||
// Options open markup.
|
||||
$this->field_option(
|
||||
'basic-options',
|
||||
$field,
|
||||
[
|
||||
'markup' => 'open',
|
||||
]
|
||||
);
|
||||
|
||||
// Label.
|
||||
$this->field_option( 'label', $field );
|
||||
|
||||
// Choices.
|
||||
$this->field_option( 'choices', $field );
|
||||
|
||||
// Choices Images.
|
||||
$this->field_option( 'choices_images', $field );
|
||||
|
||||
// Choices Images Style (theme).
|
||||
$this->field_option( 'choices_images_style', $field );
|
||||
|
||||
// Choices Icons.
|
||||
$this->field_option( 'choices_icons', $field );
|
||||
|
||||
// Choices Icons Color.
|
||||
$this->field_option( 'choices_icons_color', $field );
|
||||
|
||||
// Choices Icons Size.
|
||||
$this->field_option( 'choices_icons_size', $field );
|
||||
|
||||
// Choices Icons Style.
|
||||
$this->field_option( 'choices_icons_style', $field );
|
||||
|
||||
// Description.
|
||||
$this->field_option( 'description', $field );
|
||||
|
||||
// Required toggle.
|
||||
$this->field_option( 'required', $field );
|
||||
|
||||
// Options close markup.
|
||||
$this->field_option(
|
||||
'basic-options',
|
||||
$field,
|
||||
[
|
||||
'markup' => 'close',
|
||||
]
|
||||
);
|
||||
|
||||
/*
|
||||
* Advanced field options.
|
||||
*/
|
||||
|
||||
// Options open markup.
|
||||
$this->field_option(
|
||||
'advanced-options',
|
||||
$field,
|
||||
[
|
||||
'markup' => 'open',
|
||||
]
|
||||
);
|
||||
|
||||
// Randomize order of choices.
|
||||
$this->field_element(
|
||||
'row',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'random',
|
||||
'content' => $this->field_element(
|
||||
'toggle',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'random',
|
||||
'value' => isset( $field['random'] ) ? '1' : '0',
|
||||
'desc' => esc_html__( 'Randomize Choices', 'wpforms-lite' ),
|
||||
'tooltip' => esc_html__( 'Check this option to randomize the order of the choices.', 'wpforms-lite' ),
|
||||
],
|
||||
false
|
||||
),
|
||||
]
|
||||
);
|
||||
|
||||
// Show Values toggle option. This option will only show if already used
|
||||
// or if manually enabled by a filter.
|
||||
if ( ! empty( $field['show_values'] ) || wpforms_show_fields_options_setting() ) {
|
||||
$this->field_element(
|
||||
'row',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'show_values',
|
||||
'content' => $this->field_element(
|
||||
'toggle',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'show_values',
|
||||
'value' => isset( $field['show_values'] ) ? $field['show_values'] : '0',
|
||||
'desc' => esc_html__( 'Show Values', 'wpforms-lite' ),
|
||||
'tooltip' => esc_html__( 'Check this option to manually set form field values.', 'wpforms-lite' ),
|
||||
],
|
||||
false
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Display format.
|
||||
$this->field_option( 'input_columns', $field );
|
||||
|
||||
// Dynamic choice auto-populating toggle.
|
||||
$this->field_option( 'dynamic_choices', $field );
|
||||
|
||||
// Dynamic choice source.
|
||||
$this->field_option( 'dynamic_choices_source', $field );
|
||||
|
||||
// Custom CSS classes.
|
||||
$this->field_option( 'css', $field );
|
||||
|
||||
// Hide label.
|
||||
$this->field_option( 'label_hide', $field );
|
||||
|
||||
// Options close markup.
|
||||
$this->field_option(
|
||||
'advanced-options',
|
||||
$field,
|
||||
[
|
||||
'markup' => 'close',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Field preview inside the builder.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param array $field Field settings.
|
||||
*/
|
||||
public function field_preview( $field ) {
|
||||
|
||||
// Label.
|
||||
$this->field_preview_option( 'label', $field );
|
||||
|
||||
// Choices.
|
||||
$this->field_preview_option( 'choices', $field );
|
||||
|
||||
// Description.
|
||||
$this->field_preview_option( 'description', $field );
|
||||
}
|
||||
|
||||
/**
|
||||
* Field display on the form front-end and admin entry edit page.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param array $field Field settings.
|
||||
* @param array $deprecated Deprecated array.
|
||||
* @param array $form_data Form data and settings.
|
||||
*/
|
||||
public function field_display( $field, $deprecated, $form_data ) {
|
||||
|
||||
$using_image_choices = empty( $field['dynamic_choices'] ) && empty( $field['choices_icons'] ) && ! empty( $field['choices_images'] );
|
||||
$using_icon_choices = empty( $field['dynamic_choices'] ) && empty( $field['choices_images'] ) && ! empty( $field['choices_icons'] );
|
||||
|
||||
// Define data.
|
||||
$container = $field['properties']['input_container'];
|
||||
$choices = $field['properties']['inputs'];
|
||||
|
||||
// Do not display the field with empty choices on the frontend.
|
||||
if ( ! $choices && ! is_admin() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Display a warning message on Entry Edit page.
|
||||
if ( ! $choices && is_admin() ) {
|
||||
$this->display_empty_dynamic_choices_message( $field );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$amp_state_id = '';
|
||||
|
||||
if ( wpforms_is_amp() && ( $using_image_choices || $using_icon_choices ) ) {
|
||||
$amp_state_id = str_replace( '-', '_', sanitize_key( $container['id'] ) ) . '_state';
|
||||
$state = [
|
||||
'selected' => null,
|
||||
];
|
||||
|
||||
foreach ( $choices as $key => $choice ) {
|
||||
if ( $choice['default'] ) {
|
||||
$state['selected'] = $choice['attr']['value'];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf(
|
||||
'<amp-state id="%s"><script type="application/json">%s</script></amp-state>',
|
||||
esc_attr( $amp_state_id ),
|
||||
wp_json_encode( $state )
|
||||
);
|
||||
}
|
||||
|
||||
printf(
|
||||
'<ul %s>',
|
||||
wpforms_html_attributes( $container['id'], $container['class'], $container['data'], $container['attr'] )
|
||||
);
|
||||
|
||||
foreach ( $choices as $key => $choice ) {
|
||||
|
||||
if ( wpforms_is_amp() && ( $using_image_choices || $using_icon_choices ) ) {
|
||||
$choice['container']['attr']['[class]'] = sprintf(
|
||||
'%s + ( %s == %s ? " wpforms-selected" : "")',
|
||||
wp_json_encode( implode( ' ', $choice['container']['class'] ) ),
|
||||
$amp_state_id,
|
||||
wp_json_encode( $choice['attr']['value'] )
|
||||
);
|
||||
}
|
||||
|
||||
printf(
|
||||
'<li %s>',
|
||||
wpforms_html_attributes( $choice['container']['id'], $choice['container']['class'], $choice['container']['data'], $choice['container']['attr'] )
|
||||
);
|
||||
|
||||
if ( $using_image_choices ) {
|
||||
|
||||
// Make sure the image choices are keyboard-accessible.
|
||||
$choice['label']['attr']['tabindex'] = 0;
|
||||
|
||||
if ( wpforms_is_amp() ) {
|
||||
$choice['label']['attr']['on'] = sprintf(
|
||||
'tap:AMP.setState(%s)',
|
||||
wp_json_encode( [ $amp_state_id => $choice['attr']['value'] ] )
|
||||
);
|
||||
$choice['label']['attr']['role'] = 'button';
|
||||
}
|
||||
|
||||
// Image choices.
|
||||
printf(
|
||||
'<label %s>',
|
||||
wpforms_html_attributes( $choice['label']['id'], $choice['label']['class'], $choice['label']['data'], $choice['label']['attr'] )
|
||||
);
|
||||
|
||||
echo '<span class="wpforms-image-choices-image">';
|
||||
|
||||
if ( ! empty( $choice['image'] ) ) {
|
||||
printf(
|
||||
'<img src="%s" alt="%s"%s>',
|
||||
esc_url( $choice['image'] ),
|
||||
esc_attr( $choice['label']['text'] ),
|
||||
! empty( $choice['label']['text'] ) ? ' title="' . esc_attr( $choice['label']['text'] ) . '"' : ''
|
||||
);
|
||||
}
|
||||
|
||||
echo '</span>';
|
||||
|
||||
if ( $field['choices_images_style'] === 'none' ) {
|
||||
echo '<br>';
|
||||
}
|
||||
|
||||
$choice['attr']['tabindex'] = '-1';
|
||||
|
||||
if ( wpforms_is_amp() ) {
|
||||
$choice['attr']['[checked]'] = sprintf(
|
||||
'%s == %s',
|
||||
$amp_state_id,
|
||||
wp_json_encode( $choice['attr']['value'] )
|
||||
);
|
||||
}
|
||||
|
||||
printf(
|
||||
'<input type="radio" %s %s %s>',
|
||||
wpforms_html_attributes( $choice['id'], $choice['class'], $choice['data'], $choice['attr'] ),
|
||||
esc_attr( $choice['required'] ),
|
||||
checked( '1', $choice['default'], false )
|
||||
);
|
||||
|
||||
echo '<span class="wpforms-image-choices-label">' . wp_kses_post( $choice['label']['text'] ) . '</span>';
|
||||
|
||||
echo '</label>';
|
||||
|
||||
} elseif ( $using_icon_choices ) {
|
||||
|
||||
if ( wpforms_is_amp() ) {
|
||||
$choice['label']['attr']['on'] = sprintf(
|
||||
'tap:AMP.setState(%s)',
|
||||
wp_json_encode( [ $amp_state_id => $choice['attr']['value'] ] )
|
||||
);
|
||||
$choice['label']['attr']['role'] = 'button';
|
||||
}
|
||||
|
||||
// Icon Choices.
|
||||
wpforms()->get( 'icon_choices' )->field_display( $field, $choice, 'radio' );
|
||||
|
||||
} else {
|
||||
// Normal display.
|
||||
printf(
|
||||
'<input type="radio" %s %s %s>',
|
||||
wpforms_html_attributes( $choice['id'], $choice['class'], $choice['data'], $choice['attr'] ),
|
||||
esc_attr( $choice['required'] ),
|
||||
checked( '1', $choice['default'], false )
|
||||
);
|
||||
|
||||
printf(
|
||||
'<label %s>%s</label>',
|
||||
wpforms_html_attributes( $choice['label']['id'], $choice['label']['class'], $choice['label']['data'], $choice['label']['attr'] ),
|
||||
wp_kses_post( $choice['label']['text'] )
|
||||
);
|
||||
}
|
||||
|
||||
echo '</li>';
|
||||
}
|
||||
|
||||
echo '</ul>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate field.
|
||||
*
|
||||
* @since 1.8.2
|
||||
*
|
||||
* @param int $field_id Field ID.
|
||||
* @param string|array $field_submit Submitted field value (selected option).
|
||||
* @param array $form_data Form data and settings.
|
||||
*/
|
||||
public function validate( $field_id, $field_submit, $form_data ) {
|
||||
|
||||
$field = $form_data['fields'][ $field_id ];
|
||||
|
||||
// Skip validation if field is dynamic and choices are empty.
|
||||
if ( $this->is_dynamic_choices_empty( $field, $form_data ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
parent::validate( $field_id, $field_submit, $form_data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Format and sanitize field.
|
||||
*
|
||||
* @since 1.0.2
|
||||
*
|
||||
* @param int $field_id Field ID.
|
||||
* @param string $field_submit Submitted form data.
|
||||
* @param array $form_data Form data and settings.
|
||||
*/
|
||||
public function format( $field_id, $field_submit, $form_data ) {
|
||||
|
||||
$field = $form_data['fields'][ $field_id ];
|
||||
$dynamic = ! empty( $field['dynamic_choices'] ) ? $field['dynamic_choices'] : false;
|
||||
$name = sanitize_text_field( $field['label'] );
|
||||
$value_raw = sanitize_text_field( $field_submit );
|
||||
|
||||
$data = [
|
||||
'name' => $name,
|
||||
'value' => '',
|
||||
'value_raw' => $value_raw,
|
||||
'id' => absint( $field_id ),
|
||||
'type' => $this->type,
|
||||
];
|
||||
|
||||
if ( 'post_type' === $dynamic && ! empty( $field['dynamic_post_type'] ) ) {
|
||||
|
||||
// Dynamic population is enabled using post type.
|
||||
$data['dynamic'] = 'post_type';
|
||||
$data['dynamic_items'] = absint( $value_raw );
|
||||
$data['dynamic_post_type'] = $field['dynamic_post_type'];
|
||||
$post = get_post( $value_raw );
|
||||
|
||||
if ( ! empty( $post ) && ! is_wp_error( $post ) && $data['dynamic_post_type'] === $post->post_type ) {
|
||||
$data['value'] = esc_html( wpforms_get_post_title( $post ) );
|
||||
}
|
||||
} elseif ( 'taxonomy' === $dynamic && ! empty( $field['dynamic_taxonomy'] ) ) {
|
||||
|
||||
// Dynamic population is enabled using taxonomy.
|
||||
$data['dynamic'] = 'taxonomy';
|
||||
$data['dynamic_items'] = absint( $value_raw );
|
||||
$data['dynamic_taxonomy'] = $field['dynamic_taxonomy'];
|
||||
$term = get_term( $value_raw, $data['dynamic_taxonomy'] );
|
||||
|
||||
if ( ! empty( $term ) && ! is_wp_error( $term ) ) {
|
||||
$data['value'] = esc_html( wpforms_get_term_name( $term ) );
|
||||
}
|
||||
} else {
|
||||
|
||||
// Normal processing, dynamic population is off.
|
||||
$choice_key = '';
|
||||
|
||||
// If show_values is true, that means value posted is the raw value
|
||||
// and not the label. So we need to set label value. Also store
|
||||
// the choice key.
|
||||
if ( ! empty( $field['show_values'] ) ) {
|
||||
foreach ( $field['choices'] as $key => $choice ) {
|
||||
if ( $choice['value'] === $field_submit ) {
|
||||
$data['value'] = sanitize_text_field( $choice['label'] );
|
||||
$choice_key = $key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
$data['value'] = $value_raw;
|
||||
|
||||
// Determine choice key, this is needed for image choices.
|
||||
foreach ( $field['choices'] as $key => $choice ) {
|
||||
/* translators: %s - choice number. */
|
||||
if ( $field_submit === $choice['label'] || $value_raw === sprintf( esc_html__( 'Choice %s', 'wpforms-lite' ), $key ) ) {
|
||||
$choice_key = $key;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Images choices are enabled, lookup and store image URL.
|
||||
if ( ! empty( $choice_key ) && ! empty( $field['choices_images'] ) ) {
|
||||
|
||||
$data['image'] = ! empty( $field['choices'][ $choice_key ]['image'] ) ? esc_url_raw( $field['choices'][ $choice_key ]['image'] ) : '';
|
||||
}
|
||||
}
|
||||
|
||||
// Push field details to be saved.
|
||||
wpforms()->process->fields[ $field_id ] = $data;
|
||||
}
|
||||
}
|
||||
|
||||
new WPForms_Field_Radio();
|
751
wp-content/plugins/wpforms-lite/includes/fields/class-select.php
Normal file
751
wp-content/plugins/wpforms-lite/includes/fields/class-select.php
Normal file
@@ -0,0 +1,751 @@
|
||||
<?php
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dropdown field.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class WPForms_Field_Select extends WPForms_Field {
|
||||
|
||||
/**
|
||||
* Choices JS version.
|
||||
*
|
||||
* @since 1.6.3
|
||||
*/
|
||||
const CHOICES_VERSION = '9.0.1';
|
||||
|
||||
/**
|
||||
* Classic (old) style.
|
||||
*
|
||||
* @since 1.6.1
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const STYLE_CLASSIC = 'classic';
|
||||
|
||||
/**
|
||||
* Modern style.
|
||||
*
|
||||
* @since 1.6.1
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const STYLE_MODERN = 'modern';
|
||||
|
||||
/**
|
||||
* Primary class constructor.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
// Define field type information.
|
||||
$this->name = esc_html__( 'Dropdown', 'wpforms-lite' );
|
||||
$this->keywords = esc_html__( 'choice', 'wpforms-lite' );
|
||||
$this->type = 'select';
|
||||
$this->icon = 'fa-caret-square-o-down';
|
||||
$this->order = 70;
|
||||
$this->defaults = [
|
||||
1 => [
|
||||
'label' => esc_html__( 'First Choice', 'wpforms-lite' ),
|
||||
'value' => '',
|
||||
'default' => '',
|
||||
],
|
||||
2 => [
|
||||
'label' => esc_html__( 'Second Choice', 'wpforms-lite' ),
|
||||
'value' => '',
|
||||
'default' => '',
|
||||
],
|
||||
3 => [
|
||||
'label' => esc_html__( 'Third Choice', 'wpforms-lite' ),
|
||||
'value' => '',
|
||||
'default' => '',
|
||||
],
|
||||
];
|
||||
|
||||
// Define additional field properties.
|
||||
add_filter( 'wpforms_field_properties_' . $this->type, [ $this, 'field_properties' ], 5, 3 );
|
||||
|
||||
// Form frontend CSS enqueues.
|
||||
add_action( 'wpforms_frontend_css', [ $this, 'enqueue_frontend_css' ] );
|
||||
|
||||
// Form frontend JS enqueues.
|
||||
add_action( 'wpforms_frontend_js', [ $this, 'enqueue_frontend_js' ] );
|
||||
|
||||
add_action( 'enqueue_block_editor_assets', [ $this, 'enqueue_block_editor_assets' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Define additional field properties.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*
|
||||
* @param array $properties Field properties.
|
||||
* @param array $field Field settings.
|
||||
* @param array $form_data Form data and settings.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function field_properties( $properties, $field, $form_data ) {
|
||||
|
||||
// Remove primary input.
|
||||
unset( $properties['inputs']['primary'] );
|
||||
|
||||
// Define data.
|
||||
$form_id = absint( $form_data['id'] );
|
||||
$field_id = absint( $field['id'] );
|
||||
$choices = $field['choices'];
|
||||
$dynamic = wpforms_get_field_dynamic_choices( $field, $form_id, $form_data );
|
||||
|
||||
if ( $dynamic !== false ) {
|
||||
$choices = $dynamic;
|
||||
$field['show_values'] = true;
|
||||
}
|
||||
|
||||
// Set options container (<select>) properties.
|
||||
$properties['input_container'] = [
|
||||
'class' => [],
|
||||
'data' => [],
|
||||
'id' => "wpforms-{$form_id}-field_{$field_id}",
|
||||
'attr' => [
|
||||
'name' => "wpforms[fields][{$field_id}]",
|
||||
],
|
||||
];
|
||||
|
||||
// Set properties.
|
||||
foreach ( $choices as $key => $choice ) {
|
||||
|
||||
// Used for dynamic choices.
|
||||
$depth = isset( $choice['depth'] ) ? absint( $choice['depth'] ) : 1;
|
||||
|
||||
$properties['inputs'][ $key ] = [
|
||||
'container' => [
|
||||
'attr' => [],
|
||||
'class' => [ "choice-{$key}", "depth-{$depth}" ],
|
||||
'data' => [],
|
||||
'id' => '',
|
||||
],
|
||||
'label' => [
|
||||
'attr' => [
|
||||
'for' => "wpforms-{$form_id}-field_{$field_id}_{$key}",
|
||||
],
|
||||
'class' => [ 'wpforms-field-label-inline' ],
|
||||
'data' => [],
|
||||
'id' => '',
|
||||
'text' => $choice['label'],
|
||||
],
|
||||
'attr' => [
|
||||
'name' => "wpforms[fields][{$field_id}]",
|
||||
'value' => isset( $field['show_values'] ) ? $choice['value'] : $choice['label'],
|
||||
],
|
||||
'class' => [],
|
||||
'data' => [],
|
||||
'id' => "wpforms-{$form_id}-field_{$field_id}_{$key}",
|
||||
'required' => ! empty( $field['required'] ) ? 'required' : '',
|
||||
'default' => isset( $choice['default'] ),
|
||||
];
|
||||
}
|
||||
|
||||
// Add class that changes the field size.
|
||||
if ( ! empty( $field['size'] ) ) {
|
||||
$properties['input_container']['class'][] = 'wpforms-field-' . esc_attr( $field['size'] );
|
||||
}
|
||||
|
||||
// Required class for pagebreak validation.
|
||||
if ( ! empty( $field['required'] ) ) {
|
||||
$properties['input_container']['class'][] = 'wpforms-field-required';
|
||||
}
|
||||
|
||||
// Add additional class for container.
|
||||
if (
|
||||
! empty( $field['style'] ) &&
|
||||
in_array( $field['style'], [ self::STYLE_CLASSIC, self::STYLE_MODERN ], true )
|
||||
) {
|
||||
$properties['container']['class'][] = "wpforms-field-select-style-{$field['style']}";
|
||||
}
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Field options panel inside the builder.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param array $field Field settings.
|
||||
*/
|
||||
public function field_options( $field ) {
|
||||
|
||||
/*
|
||||
* Basic field options.
|
||||
*/
|
||||
|
||||
// Options open markup.
|
||||
$this->field_option(
|
||||
'basic-options',
|
||||
$field,
|
||||
[
|
||||
'markup' => 'open',
|
||||
]
|
||||
);
|
||||
|
||||
// Label.
|
||||
$this->field_option( 'label', $field );
|
||||
|
||||
// Choices.
|
||||
$this->field_option( 'choices', $field );
|
||||
|
||||
// Description.
|
||||
$this->field_option( 'description', $field );
|
||||
|
||||
// Required toggle.
|
||||
$this->field_option( 'required', $field );
|
||||
|
||||
// Options close markup.
|
||||
$this->field_option(
|
||||
'basic-options',
|
||||
$field,
|
||||
[
|
||||
'markup' => 'close',
|
||||
]
|
||||
);
|
||||
|
||||
/*
|
||||
* Advanced field options.
|
||||
*/
|
||||
|
||||
// Options open markup.
|
||||
$this->field_option(
|
||||
'advanced-options',
|
||||
$field,
|
||||
[
|
||||
'markup' => 'open',
|
||||
]
|
||||
);
|
||||
|
||||
// Show Values toggle option. This option will only show if already used
|
||||
// or if manually enabled by a filter.
|
||||
if ( ! empty( $field['show_values'] ) || wpforms_show_fields_options_setting() ) {
|
||||
$show_values = $this->field_element(
|
||||
'toggle',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'show_values',
|
||||
'value' => isset( $field['show_values'] ) ? $field['show_values'] : '0',
|
||||
'desc' => esc_html__( 'Show Values', 'wpforms-lite' ),
|
||||
'tooltip' => esc_html__( 'Check this option to manually set form field values.', 'wpforms-lite' ),
|
||||
],
|
||||
false
|
||||
);
|
||||
$this->field_element(
|
||||
'row',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'show_values',
|
||||
'content' => $show_values,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Multiple options selection.
|
||||
$fld = $this->field_element(
|
||||
'toggle',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'multiple',
|
||||
'value' => ! empty( $field['multiple'] ),
|
||||
'desc' => esc_html__( 'Multiple Options Selection', 'wpforms-lite' ),
|
||||
'tooltip' => esc_html__( 'Allow users to select multiple choices in this field.', 'wpforms-lite' ) . '<br>' .
|
||||
sprintf(
|
||||
wp_kses( /* translators: %s - URL to WPForms.com doc article. */
|
||||
esc_html__( 'For details, including how this looks and works for your site\'s visitors, please check out <a href="%s" target="_blank" rel="noopener noreferrer">our doc</a>.', 'wpforms-lite' ),
|
||||
[
|
||||
'a' => [
|
||||
'href' => [],
|
||||
'target' => [],
|
||||
'rel' => [],
|
||||
],
|
||||
]
|
||||
),
|
||||
esc_url( wpforms_utm_link( 'https://wpforms.com/docs/how-to-allow-multiple-selections-to-a-dropdown-field-in-wpforms/', 'Field Options', 'Multiple Options Selection Documentation' ) )
|
||||
),
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$this->field_element(
|
||||
'row',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'multiple',
|
||||
'content' => $fld,
|
||||
]
|
||||
);
|
||||
|
||||
// Style.
|
||||
$lbl = $this->field_element(
|
||||
'label',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'style',
|
||||
'value' => esc_html__( 'Style', 'wpforms-lite' ),
|
||||
'tooltip' => esc_html__( 'Classic style is the default one generated by your browser. Modern has a fresh look and displays all selected options in a single row.', 'wpforms-lite' ),
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$fld = $this->field_element(
|
||||
'select',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'style',
|
||||
'value' => ! empty( $field['style'] ) ? $field['style'] : self::STYLE_CLASSIC,
|
||||
'options' => [
|
||||
self::STYLE_CLASSIC => esc_html__( 'Classic', 'wpforms-lite' ),
|
||||
self::STYLE_MODERN => esc_html__( 'Modern', 'wpforms-lite' ),
|
||||
],
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$this->field_element(
|
||||
'row',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'style',
|
||||
'content' => $lbl . $fld,
|
||||
]
|
||||
);
|
||||
|
||||
// Size.
|
||||
$this->field_option( 'size', $field );
|
||||
|
||||
// Placeholder.
|
||||
$this->field_option( 'placeholder', $field );
|
||||
|
||||
// Dynamic choice auto-populating toggle.
|
||||
$this->field_option( 'dynamic_choices', $field );
|
||||
|
||||
// Dynamic choice source.
|
||||
$this->field_option( 'dynamic_choices_source', $field );
|
||||
|
||||
// Custom CSS classes.
|
||||
$this->field_option( 'css', $field );
|
||||
|
||||
// Hide label.
|
||||
$this->field_option( 'label_hide', $field );
|
||||
|
||||
// Options close markup.
|
||||
$this->field_option(
|
||||
'advanced-options',
|
||||
$field,
|
||||
[
|
||||
'markup' => 'close',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Field preview inside the builder.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @since 1.6.1 Added a `Modern` style select support.
|
||||
*
|
||||
* @param array $field Field settings.
|
||||
*/
|
||||
public function field_preview( $field ) {
|
||||
|
||||
$args = [];
|
||||
|
||||
// Label.
|
||||
$this->field_preview_option( 'label', $field );
|
||||
|
||||
// Prepare arguments.
|
||||
$args['modern'] = false;
|
||||
|
||||
if (
|
||||
! empty( $field['style'] ) &&
|
||||
self::STYLE_MODERN === $field['style']
|
||||
) {
|
||||
$args['modern'] = true;
|
||||
$args['class'] = 'choicesjs-select';
|
||||
}
|
||||
|
||||
// Choices.
|
||||
$this->field_preview_option( 'choices', $field, $args );
|
||||
|
||||
// Description.
|
||||
$this->field_preview_option( 'description', $field );
|
||||
}
|
||||
|
||||
/**
|
||||
* Field display on the form front-end and admin entry edit page.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @since 1.5.0 Converted to a new format, where all the data are taken not from $deprecated, but field properties.
|
||||
* @since 1.6.1 Added a multiple select support.
|
||||
*
|
||||
* @param array $field Field data and settings.
|
||||
* @param array $deprecated Deprecated array of field attributes.
|
||||
* @param array $form_data Form data and settings.
|
||||
*/
|
||||
public function field_display( $field, $deprecated, $form_data ) {
|
||||
|
||||
$container = $field['properties']['input_container'];
|
||||
$field_placeholder = ! empty( $field['placeholder'] ) ? $field['placeholder'] : '';
|
||||
$is_multiple = ! empty( $field['multiple'] );
|
||||
$is_modern = ! empty( $field['style'] ) && $field['style'] === self::STYLE_MODERN;
|
||||
$choices = $field['properties']['inputs'];
|
||||
|
||||
// Do not display the field with empty choices on the frontend.
|
||||
if ( ! $choices && ! is_admin() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Display a warning message on Entry Edit page.
|
||||
if ( ! $choices && is_admin() ) {
|
||||
$this->display_empty_dynamic_choices_message( $field );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! empty( $field['required'] ) ) {
|
||||
$container['attr']['required'] = 'required';
|
||||
}
|
||||
|
||||
// If it's a multiple select.
|
||||
if ( $is_multiple ) {
|
||||
$container['attr']['multiple'] = 'multiple';
|
||||
|
||||
// Change a name attribute.
|
||||
if ( ! empty( $container['attr']['name'] ) ) {
|
||||
$container['attr']['name'] .= '[]';
|
||||
}
|
||||
}
|
||||
|
||||
// Add a class for Choices.js initialization.
|
||||
if ( $is_modern ) {
|
||||
$container['class'][] = 'choicesjs-select';
|
||||
|
||||
// Add a size-class to data attribute - it is used when Choices.js is initialized.
|
||||
if ( ! empty( $field['size'] ) ) {
|
||||
$container['data']['size-class'] = 'wpforms-field-row wpforms-field-' . sanitize_html_class( $field['size'] );
|
||||
}
|
||||
|
||||
$container['data']['search-enabled'] = $this->is_choicesjs_search_enabled( count( $choices ) );
|
||||
}
|
||||
|
||||
$has_default = false;
|
||||
|
||||
// Check to see if any of the options were selected by default.
|
||||
foreach ( $choices as $choice ) {
|
||||
if ( ! empty( $choice['default'] ) ) {
|
||||
$has_default = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Fake placeholder for Modern style.
|
||||
if ( $is_modern && empty( $field_placeholder ) ) {
|
||||
$first_choices = reset( $choices );
|
||||
$field_placeholder = $first_choices['label']['text'];
|
||||
}
|
||||
|
||||
// Preselect default if no other choices were marked as default.
|
||||
printf(
|
||||
'<select %s>',
|
||||
wpforms_html_attributes( $container['id'], $container['class'], $container['data'], $container['attr'] )
|
||||
);
|
||||
|
||||
// Optional placeholder.
|
||||
if ( ! empty( $field_placeholder ) ) {
|
||||
printf(
|
||||
'<option value="" class="placeholder" disabled %s>%s</option>',
|
||||
selected( false, $has_default || $is_multiple, false ),
|
||||
esc_html( $field_placeholder )
|
||||
);
|
||||
}
|
||||
|
||||
// Build the select options.
|
||||
foreach ( $choices as $key => $choice ) {
|
||||
printf(
|
||||
'<option value="%s" %s>%s</option>',
|
||||
esc_attr( $choice['attr']['value'] ),
|
||||
selected( true, ! empty( $choice['default'] ), false ),
|
||||
esc_html( $choice['label']['text'] )
|
||||
);
|
||||
}
|
||||
|
||||
echo '</select>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate field.
|
||||
*
|
||||
* @since 1.8.2
|
||||
*
|
||||
* @param int $field_id Field ID.
|
||||
* @param string|array $field_submit Submitted field value (selected option).
|
||||
* @param array $form_data Form data and settings.
|
||||
*/
|
||||
public function validate( $field_id, $field_submit, $form_data ) {
|
||||
|
||||
$field = $form_data['fields'][ $field_id ];
|
||||
|
||||
// Skip validation if field is dynamic and choices are empty.
|
||||
if ( $this->is_dynamic_choices_empty( $field, $form_data ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
parent::validate( $field_id, $field_submit, $form_data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Format and sanitize field.
|
||||
*
|
||||
* @since 1.0.2
|
||||
* @since 1.6.1 Added a support for multiple values.
|
||||
*
|
||||
* @param int $field_id Field ID.
|
||||
* @param string|array $field_submit Submitted field value (selected option).
|
||||
* @param array $form_data Form data and settings.
|
||||
*/
|
||||
public function format( $field_id, $field_submit, $form_data ) {
|
||||
|
||||
$field = $form_data['fields'][ $field_id ];
|
||||
$dynamic = ! empty( $field['dynamic_choices'] ) ? $field['dynamic_choices'] : false;
|
||||
$multiple = ! empty( $field['multiple'] );
|
||||
$name = sanitize_text_field( $field['label'] );
|
||||
$value = [];
|
||||
|
||||
// Convert submitted field value to array.
|
||||
if ( ! is_array( $field_submit ) ) {
|
||||
$field_submit = [ $field_submit ];
|
||||
}
|
||||
|
||||
$value_raw = wpforms_sanitize_array_combine( $field_submit );
|
||||
|
||||
$data = [
|
||||
'name' => $name,
|
||||
'value' => '',
|
||||
'value_raw' => $value_raw,
|
||||
'id' => absint( $field_id ),
|
||||
'type' => $this->type,
|
||||
];
|
||||
|
||||
if ( 'post_type' === $dynamic && ! empty( $field['dynamic_post_type'] ) ) {
|
||||
|
||||
// Dynamic population is enabled using post type (like for a `Checkboxes` field).
|
||||
$value_raw = implode( ',', array_map( 'absint', $field_submit ) );
|
||||
$data['value_raw'] = $value_raw;
|
||||
$data['dynamic'] = 'post_type';
|
||||
$data['dynamic_items'] = $value_raw;
|
||||
$data['dynamic_post_type'] = $field['dynamic_post_type'];
|
||||
$posts = [];
|
||||
|
||||
foreach ( $field_submit as $id ) {
|
||||
$post = get_post( $id );
|
||||
|
||||
if ( ! is_wp_error( $post ) && ! empty( $post ) && $data['dynamic_post_type'] === $post->post_type ) {
|
||||
$posts[] = esc_html( wpforms_get_post_title( $post ) );
|
||||
}
|
||||
}
|
||||
|
||||
$data['value'] = ! empty( $posts ) ? wpforms_sanitize_array_combine( $posts ) : '';
|
||||
|
||||
} elseif ( 'taxonomy' === $dynamic && ! empty( $field['dynamic_taxonomy'] ) ) {
|
||||
|
||||
// Dynamic population is enabled using taxonomy (like for a `Checkboxes` field).
|
||||
$value_raw = implode( ',', array_map( 'absint', $field_submit ) );
|
||||
$data['value_raw'] = $value_raw;
|
||||
$data['dynamic'] = 'taxonomy';
|
||||
$data['dynamic_items'] = $value_raw;
|
||||
$data['dynamic_taxonomy'] = $field['dynamic_taxonomy'];
|
||||
$terms = [];
|
||||
|
||||
foreach ( $field_submit as $id ) {
|
||||
$term = get_term( $id, $field['dynamic_taxonomy'] );
|
||||
|
||||
if ( ! is_wp_error( $term ) && ! empty( $term ) ) {
|
||||
$terms[] = esc_html( wpforms_get_term_name( $term ) );
|
||||
}
|
||||
}
|
||||
|
||||
$data['value'] = ! empty( $terms ) ? wpforms_sanitize_array_combine( $terms ) : '';
|
||||
|
||||
} else {
|
||||
|
||||
// Normal processing, dynamic population is off.
|
||||
|
||||
// If show_values is true, that means values posted are the raw values
|
||||
// and not the labels. So we need to get the label values.
|
||||
if ( ! empty( $field['show_values'] ) && (int) $field['show_values'] === 1 ) {
|
||||
|
||||
foreach ( $field_submit as $item ) {
|
||||
foreach ( $field['choices'] as $choice ) {
|
||||
if ( $item === $choice['value'] ) {
|
||||
$value[] = $choice['label'];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$data['value'] = ! empty( $value ) ? wpforms_sanitize_array_combine( $value ) : '';
|
||||
|
||||
} else {
|
||||
$data['value'] = $value_raw;
|
||||
}
|
||||
}
|
||||
|
||||
// Backward compatibility: for single dropdown save a string, for multiple - array.
|
||||
if ( ! $multiple && is_array( $data ) && ( 1 === count( $data ) ) ) {
|
||||
$data = reset( $data );
|
||||
}
|
||||
|
||||
// Push field details to be saved.
|
||||
wpforms()->process->fields[ $field_id ] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form frontend CSS enqueues.
|
||||
*
|
||||
* @since 1.6.1
|
||||
*
|
||||
* @param array $forms Forms on the current page.
|
||||
*/
|
||||
public function enqueue_frontend_css( $forms ) {
|
||||
|
||||
$has_modern_select = false;
|
||||
|
||||
foreach ( $forms as $form ) {
|
||||
if ( $this->is_field_style( $form, self::STYLE_MODERN ) ) {
|
||||
$has_modern_select = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $has_modern_select || wpforms()->frontend->assets_global() ) {
|
||||
$min = wpforms_get_min_suffix();
|
||||
|
||||
wp_enqueue_style(
|
||||
'wpforms-choicesjs',
|
||||
WPFORMS_PLUGIN_URL . "assets/css/choices{$min}.css",
|
||||
[],
|
||||
self::CHOICES_VERSION
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Form frontend JS enqueues.
|
||||
*
|
||||
* @since 1.6.1
|
||||
*
|
||||
* @param array $forms Forms on the current page.
|
||||
*/
|
||||
public function enqueue_frontend_js( $forms ) {
|
||||
|
||||
$has_modern_select = false;
|
||||
|
||||
foreach ( $forms as $form ) {
|
||||
if ( $this->is_field_style( $form, self::STYLE_MODERN ) ) {
|
||||
$has_modern_select = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $has_modern_select || wpforms()->frontend->assets_global() ) {
|
||||
$this->enqueue_choicesjs_once( $forms );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load WPForms Gutenberg block scripts.
|
||||
*
|
||||
* @since 1.8.1
|
||||
*/
|
||||
public function enqueue_block_editor_assets() {
|
||||
|
||||
$min = wpforms_get_min_suffix();
|
||||
|
||||
wp_enqueue_style(
|
||||
'wpforms-choicesjs',
|
||||
WPFORMS_PLUGIN_URL . "assets/css/choices{$min}.css",
|
||||
[],
|
||||
self::CHOICES_VERSION
|
||||
);
|
||||
|
||||
$this->enqueue_choicesjs_once( [] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the provided form has a dropdown field with a specified style.
|
||||
*
|
||||
* @since 1.6.1
|
||||
*
|
||||
* @param array $form Form data.
|
||||
* @param string $style Desired field style.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function is_field_style( $form, $style ) {
|
||||
|
||||
$is_field_style = false;
|
||||
|
||||
if ( empty( $form['fields'] ) ) {
|
||||
|
||||
return $is_field_style;
|
||||
}
|
||||
|
||||
foreach ( (array) $form['fields'] as $field ) {
|
||||
|
||||
if (
|
||||
! empty( $field['type'] ) &&
|
||||
$field['type'] === $this->type &&
|
||||
! empty( $field['style'] ) &&
|
||||
sanitize_key( $style ) === $field['style']
|
||||
) {
|
||||
$is_field_style = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $is_field_style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get field name for ajax error message.
|
||||
*
|
||||
* @since 1.6.3
|
||||
*
|
||||
* @param string $name Field name for error triggered.
|
||||
* @param array $field Field settings.
|
||||
* @param array $props List of properties.
|
||||
* @param string $error Error message.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function ajax_error_field_name( $name, $field, $props, $error ) {
|
||||
|
||||
if ( ! isset( $field['type'] ) || 'select' !== $field['type'] ) {
|
||||
return $name;
|
||||
}
|
||||
if ( ! empty( $field['multiple'] ) ) {
|
||||
$input = isset( $props['inputs'] ) ? end( $props['inputs'] ) : [];
|
||||
|
||||
return isset( $input['attr']['name'] ) ? $input['attr']['name'] . '[]' : '';
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
}
|
||||
|
||||
new WPForms_Field_Select();
|
548
wp-content/plugins/wpforms-lite/includes/fields/class-text.php
Normal file
548
wp-content/plugins/wpforms-lite/includes/fields/class-text.php
Normal file
@@ -0,0 +1,548 @@
|
||||
<?php
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Single line text field.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class WPForms_Field_Text extends WPForms_Field {
|
||||
|
||||
/**
|
||||
* Primary class constructor.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
// Define field type information.
|
||||
$this->name = esc_html__( 'Single Line Text', 'wpforms-lite' );
|
||||
$this->type = 'text';
|
||||
$this->icon = 'fa-text-width';
|
||||
$this->order = 30;
|
||||
|
||||
// Define additional field properties.
|
||||
add_filter( 'wpforms_field_properties_text', [ $this, 'field_properties' ], 5, 3 );
|
||||
add_action( 'wpforms_frontend_js', [ $this, 'frontend_js' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert mask formatted for jquery.inputmask into the format used by amp-inputmask.
|
||||
*
|
||||
* Note that amp-inputmask does not yet support all of the options that jquery.inputmask provides.
|
||||
* In particular, amp-inputmask doesn't provides:
|
||||
* - Upper-alphabetical mask.
|
||||
* - Upper-alphanumeric mask.
|
||||
* - Advanced Input Masks with arbitrary repeating groups.
|
||||
*
|
||||
* @link https://amp.dev/documentation/components/amp-inputmask
|
||||
* @link https://wpforms.com/docs/how-to-use-custom-input-masks/
|
||||
*
|
||||
* @param string $mask Mask formatted for jquery.inputmask.
|
||||
* @return array {
|
||||
* Mask and placeholder.
|
||||
*
|
||||
* @type string $mask Mask for amp-inputmask.
|
||||
* @type string $placeholder Placeholder derived from mask if one is not supplied.
|
||||
* }
|
||||
*/
|
||||
protected function convert_mask_to_amp_inputmask( $mask ) {
|
||||
$placeholder = '';
|
||||
|
||||
// Convert jquery.inputmask format into amp-inputmask format.
|
||||
$amp_mask = '';
|
||||
$req_mask_mapping = [
|
||||
'9' => '0', // Numeric.
|
||||
'a' => 'L', // Alphabetical (a-z or A-Z).
|
||||
'A' => 'L', // Upper-alphabetical (A-Z). Note: AMP does not have an uppercase-alphabetical mask type, so same as previous.
|
||||
'*' => 'A', // Alphanumeric (0-9, a-z, A-Z).
|
||||
'&' => 'A', // Upper-alphanumeric (A-Z, 0-9). Note: AMP does not have an uppercase-alphanumeric mask type, so same as previous.
|
||||
' ' => '_', // Automatically insert spaces.
|
||||
];
|
||||
$opt_mask_mapping = [
|
||||
'9' => '9', // The user may optionally add a numeric character.
|
||||
'a' => 'l', // The user may optionally add an alphabetical character.
|
||||
'A' => 'l', // The user may optionally add an alphabetical character.
|
||||
'*' => 'a', // The user may optionally add an alphanumeric character.
|
||||
'&' => 'a', // The user may optionally add an alphanumeric character.
|
||||
];
|
||||
$placeholder_mapping = [
|
||||
'9' => '0',
|
||||
'a' => 'a',
|
||||
'A' => 'a',
|
||||
'*' => '_',
|
||||
'&' => '_',
|
||||
];
|
||||
$is_inside_optional = false;
|
||||
$last_mask_token = null;
|
||||
for ( $i = 0, $len = strlen( $mask ); $i < $len; $i++ ) {
|
||||
if ( '[' === $mask[ $i ] ) {
|
||||
$is_inside_optional = true;
|
||||
$placeholder .= $mask[ $i ];
|
||||
continue;
|
||||
} elseif ( ']' === $mask[ $i ] ) {
|
||||
$is_inside_optional = false;
|
||||
$placeholder .= $mask[ $i ];
|
||||
continue;
|
||||
} elseif ( isset( $last_mask_token ) && preg_match( '/^\{(?P<n>\d+)(?:,(?P<m>\d+))?\}/', substr( $mask, $i ), $matches ) ) {
|
||||
$amp_mask .= str_repeat( $req_mask_mapping[ $last_mask_token ], $matches['n'] );
|
||||
$placeholder .= str_repeat( $placeholder_mapping[ $last_mask_token ], $matches['n'] );
|
||||
if ( isset( $matches['m'] ) ) {
|
||||
$amp_mask .= str_repeat( $opt_mask_mapping[ $last_mask_token ], $matches['m'] );
|
||||
$placeholder .= str_repeat( $placeholder_mapping[ $last_mask_token ], $matches['m'] );
|
||||
}
|
||||
$i += strlen( $matches[0] ) - 1;
|
||||
|
||||
$last_mask_token = null; // Reset.
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( '\\' === $mask[ $i ] ) {
|
||||
$amp_mask .= '\\';
|
||||
$i++;
|
||||
if ( ! isset( $mask[ $i ] ) ) {
|
||||
continue;
|
||||
}
|
||||
$amp_mask .= $mask[ $i ];
|
||||
} else {
|
||||
// Remember this token in case it is a mask.
|
||||
if ( isset( $opt_mask_mapping[ $mask[ $i ] ] ) ) {
|
||||
$last_mask_token = $mask[ $i ];
|
||||
}
|
||||
|
||||
if ( $is_inside_optional && isset( $opt_mask_mapping[ $mask[ $i ] ] ) ) {
|
||||
$amp_mask .= $opt_mask_mapping[ $mask[ $i ] ];
|
||||
} elseif ( isset( $req_mask_mapping[ $mask[ $i ] ] ) ) {
|
||||
$amp_mask .= $req_mask_mapping[ $mask[ $i ] ];
|
||||
} else {
|
||||
$amp_mask .= '\\' . $mask[ $i ];
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $placeholder_mapping[ $mask[ $i ] ] ) ) {
|
||||
$placeholder .= $placeholder_mapping[ $mask[ $i ] ];
|
||||
} else {
|
||||
$placeholder .= $mask[ $i ];
|
||||
}
|
||||
}
|
||||
|
||||
return [ $amp_mask, $placeholder ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Define additional field properties.
|
||||
*
|
||||
* @since 1.4.5
|
||||
*
|
||||
* @param array $properties Field properties.
|
||||
* @param array $field Field settings.
|
||||
* @param array $form_data Form data and settings.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function field_properties( $properties, $field, $form_data ) {
|
||||
|
||||
// Input primary: Detect custom input mask.
|
||||
if ( empty( $field['input_mask'] ) ) {
|
||||
return $properties;
|
||||
}
|
||||
|
||||
// Add class that will trigger custom mask.
|
||||
$properties['inputs']['primary']['class'][] = 'wpforms-masked-input';
|
||||
|
||||
if ( wpforms_is_amp() ) {
|
||||
return $this->get_amp_input_mask_properties( $properties, $field );
|
||||
}
|
||||
|
||||
$properties['inputs']['primary']['data']['rule-inputmask-incomplete'] = true;
|
||||
|
||||
if ( strpos( $field['input_mask'], 'alias:' ) !== false ) {
|
||||
$mask = str_replace( 'alias:', '', $field['input_mask'] );
|
||||
$properties['inputs']['primary']['data']['inputmask-alias'] = $mask;
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
if ( strpos( $field['input_mask'], 'regex:' ) !== false ) {
|
||||
$mask = str_replace( 'regex:', '', $field['input_mask'] );
|
||||
$properties['inputs']['primary']['data']['inputmask-regex'] = $mask;
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
if ( strpos( $field['input_mask'], 'date:' ) !== false ) {
|
||||
$mask = str_replace( 'date:', '', $field['input_mask'] );
|
||||
$properties['inputs']['primary']['data']['inputmask-alias'] = 'datetime';
|
||||
$properties['inputs']['primary']['data']['inputmask-inputformat'] = $mask;
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
$properties['inputs']['primary']['data']['inputmask-mask'] = $field['input_mask'];
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define additional field properties for the inputmask on AMP pages.
|
||||
*
|
||||
* @since 1.7.6
|
||||
*
|
||||
* @param array $properties Field properties.
|
||||
* @param array $field Field settings.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_amp_input_mask_properties( $properties, $field ) {
|
||||
|
||||
list( $amp_mask, $placeholder ) = $this->convert_mask_to_amp_inputmask( $field['input_mask'] );
|
||||
|
||||
$properties['inputs']['primary']['attr']['mask'] = $amp_mask;
|
||||
|
||||
if ( empty( $properties['inputs']['primary']['attr']['placeholder'] ) ) {
|
||||
$properties['inputs']['primary']['attr']['placeholder'] = $placeholder;
|
||||
}
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Field options panel inside the builder.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param array $field Field settings.
|
||||
*/
|
||||
public function field_options( $field ) {
|
||||
/*
|
||||
* Basic field options.
|
||||
*/
|
||||
|
||||
// Options open markup.
|
||||
$this->field_option(
|
||||
'basic-options',
|
||||
$field,
|
||||
[
|
||||
'markup' => 'open',
|
||||
]
|
||||
);
|
||||
|
||||
// Label.
|
||||
$this->field_option( 'label', $field );
|
||||
|
||||
// Description.
|
||||
$this->field_option( 'description', $field );
|
||||
|
||||
// Required toggle.
|
||||
$this->field_option( 'required', $field );
|
||||
|
||||
// Options close markup.
|
||||
$this->field_option(
|
||||
'basic-options',
|
||||
$field,
|
||||
[
|
||||
'markup' => 'close',
|
||||
]
|
||||
);
|
||||
|
||||
/*
|
||||
* Advanced field options.
|
||||
*/
|
||||
|
||||
// Options open markup.
|
||||
$this->field_option(
|
||||
'advanced-options',
|
||||
$field,
|
||||
[
|
||||
'markup' => 'open',
|
||||
]
|
||||
);
|
||||
|
||||
// Size.
|
||||
$this->field_option( 'size', $field );
|
||||
|
||||
// Placeholder.
|
||||
$this->field_option( 'placeholder', $field );
|
||||
|
||||
// Limit length.
|
||||
$args = [
|
||||
'slug' => 'limit_enabled',
|
||||
'content' => $this->field_element(
|
||||
'toggle',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'limit_enabled',
|
||||
'value' => isset( $field['limit_enabled'] ),
|
||||
'desc' => esc_html__( 'Limit Length', 'wpforms-lite' ),
|
||||
'tooltip' => esc_html__( 'Check this option to limit text length by characters or words count.', 'wpforms-lite' ),
|
||||
],
|
||||
false
|
||||
),
|
||||
];
|
||||
|
||||
$this->field_element( 'row', $field, $args );
|
||||
|
||||
$count = $this->field_element(
|
||||
'text',
|
||||
$field,
|
||||
[
|
||||
'type' => 'number',
|
||||
'slug' => 'limit_count',
|
||||
'attrs' => [
|
||||
'min' => 1,
|
||||
'step' => 1,
|
||||
'pattern' => '[0-9]',
|
||||
],
|
||||
'value' => ! empty( $field['limit_count'] ) ? absint( $field['limit_count'] ) : 1,
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$mode = $this->field_element(
|
||||
'select',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'limit_mode',
|
||||
'value' => ! empty( $field['limit_mode'] ) ? esc_attr( $field['limit_mode'] ) : 'characters',
|
||||
'options' => [
|
||||
'characters' => esc_html__( 'Characters', 'wpforms-lite' ),
|
||||
'words' => esc_html__( 'Words', 'wpforms-lite' ),
|
||||
],
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$args = [
|
||||
'slug' => 'limit_controls',
|
||||
'class' => ! isset( $field['limit_enabled'] ) ? 'wpforms-hide' : '',
|
||||
'content' => $count . $mode,
|
||||
];
|
||||
|
||||
$this->field_element( 'row', $field, $args );
|
||||
|
||||
// Default value.
|
||||
$this->field_option( 'default_value', $field );
|
||||
|
||||
// Input Mask.
|
||||
$lbl = $this->field_element(
|
||||
'label',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'input_mask',
|
||||
'value' => esc_html__( 'Input Mask', 'wpforms-lite' ),
|
||||
'tooltip' => esc_html__( 'Enter your custom input mask.', 'wpforms-lite' ),
|
||||
'after_tooltip' => '<a href="' . esc_url( wpforms_utm_link( 'https://wpforms.com/docs/how-to-use-custom-input-masks/', 'Field Options', 'Input Mask Documentation' ) ) . '" class="after-label-description" target="_blank" rel="noopener noreferrer">' . esc_html__( 'See Examples & Docs', 'wpforms-lite' ) . '</a>',
|
||||
],
|
||||
false
|
||||
);
|
||||
$fld = $this->field_element(
|
||||
'text',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'input_mask',
|
||||
'value' => ! empty( $field['input_mask'] ) ? esc_attr( $field['input_mask'] ) : '',
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$this->field_element(
|
||||
'row',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'input_mask',
|
||||
'content' => $lbl . $fld,
|
||||
]
|
||||
);
|
||||
|
||||
// Custom CSS classes.
|
||||
$this->field_option( 'css', $field );
|
||||
|
||||
// Hide label.
|
||||
$this->field_option( 'label_hide', $field );
|
||||
|
||||
// Options close markup.
|
||||
$this->field_option(
|
||||
'advanced-options',
|
||||
$field,
|
||||
[
|
||||
'markup' => 'close',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Field preview inside the builder.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param array $field Field settings.
|
||||
*/
|
||||
public function field_preview( $field ) {
|
||||
|
||||
// Define data.
|
||||
$placeholder = ! empty( $field['placeholder'] ) ? $field['placeholder'] : '';
|
||||
$default_value = ! empty( $field['default_value'] ) ? $field['default_value'] : '';
|
||||
|
||||
// Label.
|
||||
$this->field_preview_option( 'label', $field );
|
||||
|
||||
// Primary input.
|
||||
echo '<input type="text" placeholder="' . esc_attr( $placeholder ) . '" value="' . esc_attr( $default_value ) . '" class="primary-input" readonly>';
|
||||
|
||||
// Description.
|
||||
$this->field_preview_option( 'description', $field );
|
||||
}
|
||||
|
||||
/**
|
||||
* Field display on the form front-end.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param array $field Field settings.
|
||||
* @param array $deprecated Deprecated.
|
||||
* @param array $form_data Form data and settings.
|
||||
*/
|
||||
public function field_display( $field, $deprecated, $form_data ) {
|
||||
|
||||
// Define data.
|
||||
$primary = $field['properties']['inputs']['primary'];
|
||||
|
||||
if ( isset( $field['limit_enabled'] ) ) {
|
||||
$limit_count = isset( $field['limit_count'] ) ? absint( $field['limit_count'] ) : 0;
|
||||
$limit_mode = isset( $field['limit_mode'] ) ? sanitize_key( $field['limit_mode'] ) : 'characters';
|
||||
|
||||
$primary['data']['form-id'] = $form_data['id'];
|
||||
$primary['data']['field-id'] = $field['id'];
|
||||
|
||||
if ( 'characters' === $limit_mode ) {
|
||||
$primary['class'][] = 'wpforms-limit-characters-enabled';
|
||||
$primary['attr']['maxlength'] = $limit_count;
|
||||
$primary['data']['text-limit'] = $limit_count;
|
||||
} else {
|
||||
$primary['class'][] = 'wpforms-limit-words-enabled';
|
||||
$primary['data']['text-limit'] = $limit_count;
|
||||
}
|
||||
}
|
||||
|
||||
// Primary field.
|
||||
printf(
|
||||
'<input type="text" %s %s>',
|
||||
wpforms_html_attributes( $primary['id'], $primary['class'], $primary['data'], $primary['attr'] ),
|
||||
$primary['required'] // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue frontend limit option js.
|
||||
*
|
||||
* @since 1.5.6
|
||||
*
|
||||
* @param array $forms Forms on the current page.
|
||||
*/
|
||||
public function frontend_js( $forms ) {
|
||||
|
||||
// Get fields.
|
||||
$fields = array_map(
|
||||
function( $form ) {
|
||||
return empty( $form['fields'] ) ? [] : $form['fields'];
|
||||
},
|
||||
(array) $forms
|
||||
);
|
||||
|
||||
// Make fields flat.
|
||||
$fields = array_reduce(
|
||||
$fields,
|
||||
function( $accumulator, $current ) {
|
||||
return array_merge( $accumulator, $current );
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
// Leave only fields with limit.
|
||||
$fields = array_filter(
|
||||
$fields,
|
||||
function( $field ) {
|
||||
return $field['type'] === $this->type && isset( $field['limit_enabled'] ) && ! empty( $field['limit_count'] );
|
||||
}
|
||||
);
|
||||
|
||||
if ( count( $fields ) ) {
|
||||
$min = wpforms_get_min_suffix();
|
||||
|
||||
wp_enqueue_script(
|
||||
'wpforms-text-limit',
|
||||
WPFORMS_PLUGIN_URL . "assets/js/text-limit.es5{$min}.js",
|
||||
[],
|
||||
WPFORMS_VERSION,
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format and sanitize field.
|
||||
*
|
||||
* @since 1.5.6
|
||||
*
|
||||
* @param int $field_id Field ID.
|
||||
* @param mixed $field_submit Field value that was submitted.
|
||||
* @param array $form_data Form data and settings.
|
||||
*/
|
||||
public function format( $field_id, $field_submit, $form_data ) {
|
||||
|
||||
$field = $form_data['fields'][ $field_id ];
|
||||
$name = ! empty( $field['label'] ) ? sanitize_text_field( $field['label'] ) : '';
|
||||
|
||||
// Sanitize.
|
||||
$value = sanitize_text_field( $field_submit );
|
||||
|
||||
wpforms()->process->fields[ $field_id ] = [
|
||||
'name' => $name,
|
||||
'value' => $value,
|
||||
'id' => absint( $field_id ),
|
||||
'type' => $this->type,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate field on form submit.
|
||||
*
|
||||
* @since 1.6.2
|
||||
*
|
||||
* @param int $field_id Field ID.
|
||||
* @param mixed $field_submit Field value that was submitted.
|
||||
* @param array $form_data Form data and settings.
|
||||
*/
|
||||
public function validate( $field_id, $field_submit, $form_data ) {
|
||||
|
||||
parent::validate( $field_id, $field_submit, $form_data );
|
||||
|
||||
if ( empty( $form_data['fields'][ $field_id ] ) || empty( $form_data['fields'][ $field_id ]['limit_enabled'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$field = $form_data['fields'][ $field_id ];
|
||||
$limit = absint( $field['limit_count'] );
|
||||
$mode = ! empty( $field['limit_mode'] ) ? sanitize_key( $field['limit_mode'] ) : 'characters';
|
||||
$value = sanitize_text_field( $field_submit );
|
||||
|
||||
if ( 'characters' === $mode ) {
|
||||
if ( mb_strlen( str_replace( "\r\n", "\n", $value ) ) > $limit ) {
|
||||
/* translators: %s - limit characters number. */
|
||||
wpforms()->process->errors[ $form_data['id'] ][ $field_id ] = sprintf( _n( 'Text can\'t exceed %d character.', 'Text can\'t exceed %d characters.', $limit, 'wpforms-lite' ), $limit );
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if ( wpforms_count_words( $value ) > $limit ) {
|
||||
/* translators: %s - limit words number. */
|
||||
wpforms()->process->errors[ $form_data['id'] ][ $field_id ] = sprintf( _n( 'Text can\'t exceed %d word.', 'Text can\'t exceed %d words.', $limit, 'wpforms-lite' ), $limit );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
new WPForms_Field_Text();
|
@@ -0,0 +1,372 @@
|
||||
<?php
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Paragraph text field.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class WPForms_Field_Textarea extends WPForms_Field {
|
||||
|
||||
/**
|
||||
* Primary class constructor.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
// Define field type information.
|
||||
$this->name = esc_html__( 'Paragraph Text', 'wpforms-lite' );
|
||||
$this->keywords = esc_html__( 'textarea', 'wpforms-lite' );
|
||||
$this->type = 'textarea';
|
||||
$this->icon = 'fa-paragraph';
|
||||
$this->order = 50;
|
||||
|
||||
add_action( 'wpforms_frontend_js', [ $this, 'frontend_js' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value, that is used to prefill via dynamic or fallback population.
|
||||
* Based on field data and current properties.
|
||||
*
|
||||
* @since 1.6.4
|
||||
*
|
||||
* @param string $raw_value Value from a GET param, always a string.
|
||||
* @param string $input Represent a subfield inside the field. May be empty.
|
||||
* @param array $properties Field properties.
|
||||
* @param array $field Current field specific data.
|
||||
*
|
||||
* @return array Modified field properties.
|
||||
*/
|
||||
protected function get_field_populated_single_property_value( $raw_value, $input, $properties, $field ) {
|
||||
|
||||
if ( ! is_string( $raw_value ) ) {
|
||||
return $properties;
|
||||
}
|
||||
|
||||
if (
|
||||
! empty( $input ) &&
|
||||
isset( $properties['inputs'][ $input ] )
|
||||
) {
|
||||
$properties['inputs'][ $input ]['attr']['value'] = wpforms_sanitize_textarea_field( wp_unslash( $raw_value ) );
|
||||
}
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Field options panel inside the builder.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param array $field Field data and settings.
|
||||
*/
|
||||
public function field_options( $field ) {
|
||||
/*
|
||||
* Basic field options.
|
||||
*/
|
||||
|
||||
// Options open markup.
|
||||
$this->field_option(
|
||||
'basic-options',
|
||||
$field,
|
||||
[
|
||||
'markup' => 'open',
|
||||
]
|
||||
);
|
||||
|
||||
// Label.
|
||||
$this->field_option( 'label', $field );
|
||||
|
||||
// Description.
|
||||
$this->field_option( 'description', $field );
|
||||
|
||||
// Required toggle.
|
||||
$this->field_option( 'required', $field );
|
||||
|
||||
// Options close markup.
|
||||
$this->field_option(
|
||||
'basic-options',
|
||||
$field,
|
||||
[
|
||||
'markup' => 'close',
|
||||
]
|
||||
);
|
||||
|
||||
/*
|
||||
* Advanced field options.
|
||||
*/
|
||||
|
||||
// Options open markup.
|
||||
$args = [
|
||||
'markup' => 'open',
|
||||
];
|
||||
|
||||
$this->field_option( 'advanced-options', $field, $args );
|
||||
|
||||
// Size.
|
||||
$this->field_option( 'size', $field );
|
||||
|
||||
// Placeholder.
|
||||
$this->field_option( 'placeholder', $field );
|
||||
|
||||
// Limit length.
|
||||
$args = [
|
||||
'slug' => 'limit_enabled',
|
||||
'content' => $this->field_element(
|
||||
'toggle',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'limit_enabled',
|
||||
'value' => isset( $field['limit_enabled'] ) ? '1' : '0',
|
||||
'desc' => esc_html__( 'Limit Length', 'wpforms-lite' ),
|
||||
'tooltip' => esc_html__( 'Check this option to limit text length by characters or words count.', 'wpforms-lite' ),
|
||||
],
|
||||
false
|
||||
),
|
||||
];
|
||||
|
||||
$this->field_element( 'row', $field, $args );
|
||||
|
||||
$count = $this->field_element(
|
||||
'text',
|
||||
$field,
|
||||
[
|
||||
'type' => 'number',
|
||||
'slug' => 'limit_count',
|
||||
'attrs' => [
|
||||
'min' => 1,
|
||||
'step' => 1,
|
||||
'pattern' => '[0-9]',
|
||||
],
|
||||
'value' => ! empty( $field['limit_count'] ) ? $field['limit_count'] : 1,
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$mode = $this->field_element(
|
||||
'select',
|
||||
$field,
|
||||
[
|
||||
'slug' => 'limit_mode',
|
||||
'value' => ! empty( $field['limit_mode'] ) ? esc_attr( $field['limit_mode'] ) : 'characters',
|
||||
'options' => [
|
||||
'characters' => esc_html__( 'Characters', 'wpforms-lite' ),
|
||||
'words' => esc_html__( 'Words', 'wpforms-lite' ),
|
||||
],
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$args = [
|
||||
'slug' => 'limit_controls',
|
||||
'class' => ! isset( $field['limit_enabled'] ) ? 'wpforms-hide' : '',
|
||||
'content' => $count . $mode,
|
||||
];
|
||||
|
||||
$this->field_element( 'row', $field, $args );
|
||||
|
||||
// Default value.
|
||||
$this->field_option( 'default_value', $field );
|
||||
|
||||
// Custom CSS classes.
|
||||
$this->field_option( 'css', $field );
|
||||
|
||||
// Hide label.
|
||||
$this->field_option( 'label_hide', $field );
|
||||
|
||||
// Options close markup.
|
||||
$this->field_option(
|
||||
'advanced-options',
|
||||
$field,
|
||||
[
|
||||
'markup' => 'close',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Field preview inside the builder.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param array $field Field data and settings.
|
||||
*/
|
||||
public function field_preview( $field ) {
|
||||
|
||||
// Label.
|
||||
$this->field_preview_option( 'label', $field );
|
||||
|
||||
// Primary input.
|
||||
$placeholder = ! empty( $field['placeholder'] ) ? $field['placeholder'] : '';
|
||||
$default_value = ! empty( $field['default_value'] ) ? $field['default_value'] : '';
|
||||
|
||||
echo '<textarea placeholder="' . esc_attr( $placeholder ) . '" class="primary-input" readonly>' . esc_textarea( $default_value ) . '</textarea>';
|
||||
|
||||
// Description.
|
||||
$this->field_preview_option( 'description', $field );
|
||||
}
|
||||
|
||||
/**
|
||||
* Field display on the form front-end.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param array $field Field data and settings.
|
||||
* @param array $deprecated Deprecated.
|
||||
* @param array $form_data Form data and settings.
|
||||
*/
|
||||
public function field_display( $field, $deprecated, $form_data ) {
|
||||
|
||||
// Define data.
|
||||
$primary = $field['properties']['inputs']['primary'];
|
||||
$value = '';
|
||||
|
||||
if ( isset( $primary['attr']['value'] ) ) {
|
||||
$value = esc_textarea( $primary['attr']['value'] );
|
||||
|
||||
unset( $primary['attr']['value'] );
|
||||
}
|
||||
|
||||
if ( isset( $field['limit_enabled'] ) ) {
|
||||
$limit_count = isset( $field['limit_count'] ) ? absint( $field['limit_count'] ) : 0;
|
||||
$limit_mode = isset( $field['limit_mode'] ) ? sanitize_key( $field['limit_mode'] ) : 'characters';
|
||||
|
||||
$primary['data']['form-id'] = $form_data['id'];
|
||||
$primary['data']['field-id'] = $field['id'];
|
||||
|
||||
if ( 'characters' === $limit_mode ) {
|
||||
$primary['class'][] = 'wpforms-limit-characters-enabled';
|
||||
$primary['attr']['maxlength'] = $limit_count;
|
||||
$primary['data']['text-limit'] = $limit_count;
|
||||
} else {
|
||||
$primary['class'][] = 'wpforms-limit-words-enabled';
|
||||
$primary['data']['text-limit'] = $limit_count;
|
||||
}
|
||||
}
|
||||
|
||||
// Primary field.
|
||||
printf(
|
||||
'<textarea %s %s>%s</textarea>',
|
||||
wpforms_html_attributes( $primary['id'], $primary['class'], $primary['data'], $primary['attr'] ),
|
||||
$primary['required'], // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
$value // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue frontend limit option js.
|
||||
*
|
||||
* @since 1.5.6
|
||||
*
|
||||
* @param array $forms Forms on the current page.
|
||||
*/
|
||||
public function frontend_js( $forms ) {
|
||||
|
||||
// Get fields.
|
||||
$fields = array_map(
|
||||
function( $form ) {
|
||||
return empty( $form['fields'] ) ? [] : $form['fields'];
|
||||
},
|
||||
(array) $forms
|
||||
);
|
||||
|
||||
// Make fields flat.
|
||||
$fields = array_reduce(
|
||||
$fields,
|
||||
function( $accumulator, $current ) {
|
||||
return array_merge( $accumulator, $current );
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
// Leave only fields with limit.
|
||||
$fields = array_filter(
|
||||
$fields,
|
||||
function( $field ) {
|
||||
return $field['type'] === $this->type && isset( $field['limit_enabled'] );
|
||||
}
|
||||
);
|
||||
|
||||
if ( count( $fields ) ) {
|
||||
$min = wpforms_get_min_suffix();
|
||||
|
||||
wp_enqueue_script( 'wpforms-text-limit', WPFORMS_PLUGIN_URL . "assets/js/text-limit.es5{$min}.js", [], WPFORMS_VERSION, true );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format and sanitize field.
|
||||
*
|
||||
* @since 1.5.6
|
||||
*
|
||||
* @param int $field_id Field ID.
|
||||
* @param mixed $field_submit Field value that was submitted.
|
||||
* @param array $form_data Form data and settings.
|
||||
*/
|
||||
public function format( $field_id, $field_submit, $form_data ) {
|
||||
|
||||
$field = $form_data['fields'][ $field_id ];
|
||||
if ( is_array( $field_submit ) ) {
|
||||
$field_submit = implode( "\r\n", array_filter( $field_submit ) );
|
||||
}
|
||||
|
||||
$name = ! empty( $field['label'] ) ? sanitize_text_field( $field['label'] ) : '';
|
||||
|
||||
// Sanitize but keep line breaks.
|
||||
$value = wpforms_sanitize_textarea_field( $field_submit );
|
||||
|
||||
wpforms()->process->fields[ $field_id ] = [
|
||||
'name' => $name,
|
||||
'value' => $value,
|
||||
'id' => absint( $field_id ),
|
||||
'type' => $this->type,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate field on form submit.
|
||||
*
|
||||
* @since 1.6.2
|
||||
*
|
||||
* @param int $field_id Field ID.
|
||||
* @param mixed $field_submit Field value that was submitted.
|
||||
* @param array $form_data Form data and settings.
|
||||
*/
|
||||
public function validate( $field_id, $field_submit, $form_data ) {
|
||||
|
||||
parent::validate( $field_id, $field_submit, $form_data );
|
||||
|
||||
if ( empty( $form_data['fields'][ $field_id ] ) || empty( $form_data['fields'][ $field_id ]['limit_enabled'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( is_array( $field_submit ) ) {
|
||||
$field_submit = implode( "\r\n", array_filter( $field_submit ) );
|
||||
}
|
||||
|
||||
$field = $form_data['fields'][ $field_id ];
|
||||
$limit = absint( $field['limit_count'] );
|
||||
$mode = ! empty( $field['limit_mode'] ) ? sanitize_key( $field['limit_mode'] ) : 'characters';
|
||||
$value = wpforms_sanitize_textarea_field( $field_submit );
|
||||
|
||||
if ( 'characters' === $mode ) {
|
||||
if ( mb_strlen( str_replace( "\r\n", "\n", $value ) ) > $limit ) {
|
||||
/* translators: %s - limit characters number. */
|
||||
wpforms()->process->errors[ $form_data['id'] ][ $field_id ] = sprintf( _n( 'Text can\'t exceed %d character.', 'Text can\'t exceed %d characters.', $limit, 'wpforms-lite' ), $limit );
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if ( wpforms_count_words( $value ) > $limit ) {
|
||||
/* translators: %s - limit words number. */
|
||||
wpforms()->process->errors[ $form_data['id'] ][ $field_id ] = sprintf( _n( 'Text can\'t exceed %d word.', 'Text can\'t exceed %d words.', $limit, 'wpforms-lite' ), $limit );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
new WPForms_Field_Textarea();
|
Reference in New Issue
Block a user