use WPForms\Vendor\TrueBV\Punycode;
class WPForms_Field_Email extends WPForms_Field {
const ENCODING = 'UTF-8';
* Email type of sanitization.
* Rules type of sanitization.
private $restricted_rules = [];
* Primary class constructor.
// Define field type information.
$this->name = esc_html__( 'Email', 'wpforms-lite' );
$this->keywords = esc_html__( 'user', 'wpforms-lite' );
$this->icon = 'fa-envelope-o';
private function hooks() {
// Define additional field properties.
add_filter( 'wpforms_field_properties_email', [ $this, 'field_properties' ], 5, 3 );
// Set field to default to required.
add_filter( 'wpforms_field_new_required', [ $this, 'default_required' ], 10, 2 );
// Set confirmation status to option wrapper class.
add_filter( 'wpforms_builder_field_option_class', [ $this, 'field_option_class' ], 10, 2 );
add_action( 'wp_ajax_wpforms_restricted_email', [ $this, 'ajax_check_restricted_email' ] );
add_action( 'wp_ajax_nopriv_wpforms_restricted_email', [ $this, 'ajax_check_restricted_email' ] );
add_action( 'wp_ajax_wpforms_sanitize_restricted_rules', [ $this, 'ajax_sanitize_restricted_rules' ] );
add_action( 'wp_ajax_wpforms_sanitize_default_email', [ $this, 'ajax_sanitize_default_email' ] );
add_filter( 'wpforms_save_form_args', [ $this, 'save_form_args' ], 11, 3 );
add_filter( 'wpforms_builder_strings', [ $this, 'add_builder_strings' ], 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.
* @param array $properties List field properties.
* @param array $field Field data and settings.
* @param array $form_data Form data and settings.
public function field_properties( $properties, $field, $form_data ) {
// Prevent "spell-jacking" of email addresses.
$properties['inputs']['primary']['attr']['spellcheck'] = 'false';
if ( ! empty( $field['confirmation'] ) ) {
$properties = $this->confirmation_field_properties( $properties, $field, $form_data );
if ( ! empty( $field['filter_type'] ) ) {
$properties = $this->filter_type_field_properties( $properties, $field, $form_data );
* Define the confirmation field properties.
* @param array $properties List field properties.
* @param array $field Field data and settings.
* @param array $form_data Form data and settings.
public function confirmation_field_properties( $properties, $field, $form_data ) {
$form_id = absint( $form_data['id'] );
$field_id = wpforms_validate_field_id( $field['id'] );
// Email confirmation setting enabled.
'wpforms-field-row-block',
'wpforms-field-email-primary',
'hidden' => ! empty( $field['sublabel_hide'] ),
'value' => esc_html__( 'Email', 'wpforms-lite' ),
'name' => "wpforms[fields][{$field_id}][secondary]",
'placeholder' => ! empty( $field['confirmation_placeholder'] ) ? $field['confirmation_placeholder'] : '',
'wpforms-field-row-block',
'wpforms-field-email-secondary',
'rule-confirm' => '#' . $properties['inputs']['primary']['id'],
'id' => "wpforms-{$form_id}-field_{$field_id}-secondary",
'required' => ! empty( $field['required'] ) ? 'required' : '',
'hidden' => ! empty( $field['sublabel_hide'] ),
'value' => esc_html__( 'Confirm Email', 'wpforms-lite' ),
$properties = array_merge_recursive( $properties, $props );
// Input Primary: adjust name.
$properties['inputs']['primary']['attr']['name'] = "wpforms[fields][{$field_id}][primary]";
// Input Primary: remove size and error classes.
$properties['inputs']['primary']['class'] = array_diff(
$properties['inputs']['primary']['class'],
'wpforms-field-' . sanitize_html_class( $field['size'] ),
// Input Primary: add error class if needed.
if ( ! empty( $properties['error']['value']['primary'] ) ) {
$properties['inputs']['primary']['class'][] = 'wpforms-error';
// Input Secondary: add error class if needed.
if ( ! empty( $properties['error']['value']['secondary'] ) ) {
$properties['inputs']['secondary']['class'][] = 'wpforms-error';
// Input Secondary: add required class if needed.
if ( ! empty( $field['required'] ) ) {
$properties['inputs']['secondary']['class'][] = 'wpforms-field-required';
// Remove reference to an input element to prevent duplication.
if ( empty( $field['sublabel_hide'] ) ) {
unset( $properties['label']['attr']['for'] );
* Define the filter field properties.
* @param array $properties List field properties.
* @param array $field Field data and settings.
* @param array $form_data Form data and settings.
public function filter_type_field_properties( $properties, $field, $form_data ) {
if ( ! empty( $field['filter_type'] ) && ! empty( $field[ $field['filter_type'] ] ) ) {
$properties['inputs']['primary']['data']['rule-restricted-email'] = true;
* Field should default to being required.
public function default_required( $required, $field ) {
if ( 'email' === $field['type'] ) {
* Add class to field options wrapper to indicate if field confirmation is
* @param string $class Class strings.
* @param array $field Current field.
public function field_option_class( $class, $field ) {
if ( 'email' !== $field['type'] ) {
$class .= isset( $field['confirmation'] ) ? ' wpforms-confirm-enabled' : ' wpforms-confirm-disabled';
if ( ! empty( $field['filter_type'] ) ) {
$class .= ' wpforms-filter-' . $field['filter_type'];
* Field options panel inside the builder.
public function field_options( $field ) {
$this->field_option( 'basic-options', $field, $args );
$this->field_option( 'label', $field );
$this->field_option( 'description', $field );
$this->field_option( 'required', $field );
$fld = $this->field_element(
'slug' => 'confirmation',
'value' => isset( $field['confirmation'] ) ? '1' : '0',
'desc' => esc_html__( 'Enable Email Confirmation', 'wpforms-lite' ),
'tooltip' => esc_html__( 'Check this option to ask users to provide an email address twice.', 'wpforms-lite' ),
'slug' => 'confirmation',
$this->field_element( 'row', $field, $args );
$this->field_option( 'basic-options', $field, $args );
* Advanced field options.
$this->field_option( 'advanced-options', $field, $args );
$this->field_option( 'size', $field );
$this->field_option( 'placeholder', $field );
// Confirmation Placeholder.
$lbl = $this->field_element(
'slug' => 'confirmation_placeholder',
'value' => esc_html__( 'Confirmation Placeholder Text', 'wpforms-lite' ),
'tooltip' => esc_html__( 'Enter text for the confirmation field placeholder.', 'wpforms-lite' ),
$fld = $this->field_element(
'slug' => 'confirmation_placeholder',
'value' => ! empty( $field['confirmation_placeholder'] ) ? esc_attr( $field['confirmation_placeholder'] ) : '',
'slug' => 'confirmation_placeholder',
'content' => $lbl . $fld,
$this->field_element( 'row', $field, $args );
$this->field_option( 'default_value', $field );
$filter_type_label = $this->field_element(
'value' => esc_html__( 'Allowlist / Denylist', 'wpforms-lite' ),
'tooltip' => esc_html__( 'Restrict which email addresses are allowed. Be sure to separate each email address with a comma.', 'wpforms-lite' ),
$filter_type_field = $this->field_element(
'value' => ! empty( $field['filter_type'] ) ? esc_attr( $field['filter_type'] ) : '',
'' => esc_html__( 'None', 'wpforms-lite' ),
'allowlist' => esc_html__( 'Allowlist', 'wpforms-lite' ),
'denylist' => esc_html__( 'Denylist', 'wpforms-lite' ),
'content' => $filter_type_label . $filter_type_field,
'content' => $this->field_element(
'value' => ! empty( $field['allowlist'] ) ? esc_attr( $this->decode_email_patterns_rules_list( $field['allowlist'] ) ) : '',
'content' => $this->field_element(
'value' => ! empty( $field['denylist'] ) ? esc_attr( $this->decode_email_patterns_rules_list( $field['denylist'] ) ) : '',
$this->field_option( 'css', $field );
$this->field_option( 'label_hide', $field );
$this->field_option( 'sublabel_hide', $field );
// Disable email suggestions.
'slug' => 'disable_suggestions',
'content' => $this->field_element(
'slug' => 'disable_suggestions',
'value' => isset( $field['disable_suggestions'] ) ? '1' : '0',
'desc' => esc_html__( 'Disable Suggestions', 'wpforms-lite' ),
'tooltip' => esc_html__( 'Prevent email suggestions for common typos. Enable this if you find the suggestions distracting.', 'wpforms-lite' ),
$this->field_option( 'advanced-options', $field, $args );
* Field preview inside the builder.
public function field_preview( $field ) {
$placeholder = ! empty( $field['placeholder'] ) ? $field['placeholder'] : '';
$confirm_placeholder = ! empty( $field['confirmation_placeholder'] ) ? $field['confirmation_placeholder'] : '';
$default_value = ! empty( $field['default_value'] ) ? $field['default_value'] : '';
$confirm = ! empty( $field['confirmation'] ) ? 'enabled' : 'disabled';
$this->field_preview_option( 'label', $field );