$attributes Block attributes. * @since 0.0.2 */ public function __construct( $attributes ) { $this->slug = 'multi-choice'; $this->set_properties( $attributes ); $this->set_input_label( __( 'Multi Choice', 'sureforms' ) ); $this->set_error_msg( $attributes, 'srfm_multi_choice_block_required_text' ); $this->single_selection = $attributes['singleSelection'] ?? false; $this->choice_width = $attributes['choiceWidth'] ?? ''; $this->vertical_layout = $attributes['verticalLayout'] ?? false; $this->option_type = ! empty( $attributes['optionType'] ) && in_array( $attributes['optionType'], [ 'icon', 'image' ], true ) ? $attributes['optionType'] : 'icon'; $this->type_attr = $this->single_selection ? 'radio' : 'checkbox'; $this->svg_type = $this->single_selection ? 'circle' : 'square'; $this->name_attr = $this->single_selection ? 'name="srfm-input-' . esc_attr( $this->slug ) . '-' . esc_attr( $this->block_id ) . '"' : ''; $this->choice_width_attr = $this->choice_width ? 'srfm-choice-width-' . str_replace( '.', '-', $this->choice_width ) : ''; $this->show_values = apply_filters( 'srfm_show_options_values', false, $attributes['showValues'] ?? false ); $this->preselected_options = $attributes['preselectedOptions'] ?? []; $this->resolve_dynamic_default( $attributes ); $this->set_markup_properties(); $this->set_aria_described_by(); } /** * Render the sureforms Multichoice classic styling * * @since 0.0.2 * @return string|bool */ public function markup() { $check_svg = Helper::fetch_svg( $this->svg_type . '-checked', 'srfm-' . $this->slug . '-icon', 'aria-hidden="true"' ); $unchecked_svg = Helper::fetch_svg( $this->svg_type . '-unchecked', 'srfm-' . $this->slug . '-icon-unchecked', 'aria-hidden="true"' ); $this->class_name = $this->get_field_classes( [ "srfm-{$this->type_attr}-mode" ] ); $allowed_tags_svg = Helper::$allowed_tags_svg; ob_start(); ?>
data_attribute_markup() ); ?> name="srfm-input-slug ); ?>-block_id ); ?>field_name ); ?>" type="hidden" value=""/> label_markup ); ?> help_markup ); ?> options ) ) { ?>
options as $i => $option ) { ?>
name_attr ); ?> aria_described_by ) ? esc_attr( trim( $this->aria_described_by ) ) : '' ) . '"' : ''; ?> data_require_attr ) ? esc_attr( $this->data_require_attr ) : '' ) . '"' : ''; ?> show_values && isset( $option['value'] ) ? 'option-value="' . esc_attr( $option['value'] ) . '"' : ''; ?> preselected_options ) && in_array( $i, $this->preselected_options, true ) ? 'checked' : ''; ?> />
option_type && ! empty( $option['icon'] ) ) { ?> option_type && ! empty( $option['image'] ) ) { ?>
error_msg_markup ); ?>
$this->slug, 'is_editing' => $this->is_editing, 'field_name' => $this->field_name, 'attributes' => $this->attributes, ] ); } /** * Resolve dynamic default value from smart tags and override preselected options. * * Radio (single-selection) mode matches the resolved value as a single * trimmed string, so option titles that legitimately contain delimiter * characters (commas, pipes, etc.) still match. * * Checkbox mode splits the resolved value on the pipe character (`|`) and * matches every segment (for example "{get_input:a}|{get_input:b}" resolving * to "Red|Blue", or a single `{get_input:colors}` with URL * `?colors=Red|Blue`). The same pipe split applies to multi-character * resolved values from `{get_input:...}` and `{get_cookie:...}`, so cookie * payloads that contain pipes are treated as multi-value in checkbox mode. * * When the `Add Numeric Values to Options` (showValues) setting is on, * each segment is also compared against the option's `value`. * * @param array $attributes Block attributes. * @since 2.8.1 * @since 2.10.0 Added checkbox (pipe-delimited) multi-value matching. * @return void */ protected function resolve_dynamic_default( $attributes ) { // Coalesce first so blocks saved before this attribute existed (pre-2.10.0) // don't trigger an "Undefined array key" warning on every frontend render. $raw_default = $attributes['dynamicDefaultValue'] ?? ''; $dynamic_default = is_string( $raw_default ) ? $raw_default : ''; if ( empty( $dynamic_default ) ) { return; } $smart_tags = new Smart_Tags(); $resolved = $smart_tags->process_smart_tags( $dynamic_default ); if ( empty( $resolved ) || ! is_string( $resolved ) || ! is_array( $this->options ) ) { return; } // START: multi-value dynamic default resolution. if ( ! $this->single_selection ) { $segments = array_filter( array_map( 'trim', explode( '|', $resolved ) ), static function ( $segment ) { return '' !== $segment; } ); // Cap segments to avoid pathological URLs (e.g. ?colors=|||||...) producing thousands of comparisons. $segments = array_slice( $segments, 0, 50 ); } else { $trimmed = trim( $resolved ); $segments = '' === $trimmed ? [] : [ $trimmed ]; } if ( empty( $segments ) ) { return; } $match_value_too = ! empty( $attributes['showValues'] ); $matching_indices = []; foreach ( $segments as $segment ) { foreach ( $this->options as $i => $option ) { if ( ! is_array( $option ) || in_array( $i, $matching_indices, true ) ) { continue; } $option_title = isset( $option['optionTitle'] ) && is_scalar( $option['optionTitle'] ) ? (string) $option['optionTitle'] : ''; $raw_value = $option['value'] ?? ''; $option_value = $match_value_too && is_scalar( $raw_value ) ? (string) $raw_value : ''; $is_match = ( '' !== $option_title && strcasecmp( $option_title, $segment ) === 0 ) || ( $match_value_too && '' !== $option_value && strcasecmp( $option_value, $segment ) === 0 ); if ( $is_match ) { $matching_indices[] = $i; if ( $this->single_selection ) { break 2; } break; } } } if ( ! empty( $matching_indices ) ) { $this->preselected_options = $this->single_selection ? [ $matching_indices[0] ] : $matching_indices; } // END: multi-value dynamic default resolution. } /** * Data attribute markup for min and max value * * @since 0.0.13 * @return string */ protected function data_attribute_markup() { $data_attr = ''; if ( $this->single_selection ) { return ''; } if ( $this->min_selection ) { $data_attr .= 'data-min-selection="' . esc_attr( $this->min_selection ) . '"'; } if ( $this->max_selection ) { $data_attr .= 'data-max-selection="' . esc_attr( $this->max_selection ) . '"'; } return $data_attr; } }