• File: class-checkbox.php
  • Full Path: /home/matthif/www/wp-content/plugins/wpforms-lite/includes/fields/class-checkbox.php
  • Date Modified: 02/16/2024 11:45 AM
  • File size: 21.72 KB
  • MIME-type: text/x-php
  • Charset: utf-8
<?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 = [
            
=> [
                
'label'      => esc_html__'First Choice''wpforms-lite' ),
                
'value'      => '',
                
'image'      => '',
                
'icon'       => '',
                
'icon_style' => '',
                
'default'    => '',
            ],
            
=> [
                
'label'      => esc_html__'Second Choice''wpforms-lite' ),
                
'value'      => '',
                
'image'      => '',
                
'icon'       => '',
                
'icon_style' => '',
                
'default'    => '',
            ],
            
=> [
                
'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);

        
// Define additional field properties.
        
add_filter'wpforms_field_properties_checkbox', [ $this'field_properties' ], 5);

        
// 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);
    }

    
/**
     * 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'] ) ? : (int) $field['choice_limit'];
        if ( 
$field['choice_limit'] > ) {
            
$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 ( 
=== count$choices ) ) {
                    
$value esc_html__'Checked''wpforms-lite' );
                } else {
                    
/* translators: %s - choice number. */
                    
$value sprintfesc_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'] > ) {
                
$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'] ) ? : (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'] > $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 ) {
                
$label $this->get_choices_label$choice['label']['text'] ?? ''$key );

                if ( 
wpforms_is_amp() && ( $using_image_choices || $using_icon_choices ) ) {
                    
$choice['container']['attr']['[class]'] = sprintf(
                        
'%s + ( %s[%s] ? " wpforms-selected" : "")',
                        
wp_json_encodeimplode' '$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 ) > '' $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$label ),
                                    ! empty( 
$label ) ? ' title="' esc_attr$label ) . '"' ''
                                
);
                            }

                            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$label ) . '</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$label ),
                            
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'] ) ? : (int) $form_data['fields'][ $field_id ]['choice_limit'];
        
$count_choices count$field_submit );

        if ( 
$choice_limit && $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 ) === &&
                    ( ! isset( 
$field_submit[0] ) || (string) $field_submit[0] === '' )
                )
            )
        ) {
            
$error wpforms_get_required_label();
        }

        if ( ! empty( 
$error ) ) {
            
wpforms()->get'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_htmlwpforms_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_htmlwpforms_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'] === ) {

                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 === sprintfesc_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()->get'process' )->fields$field_id ] = $data;
    }
}

new 
WPForms_Field_Checkbox();