PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 6.2.14
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v6.2.14
6.2.14 6.2.13 6.2.12 6.2.10 6.2.11 6.2.9 6.2.8 6.2.7 6.2.6 6.2.5 6.2.4 6.2.3 6.2.2 3.6.22 3.6.31 3.6.40 3.6.41 3.6.42 3.6.50 3.6.51 3.6.60 3.6.61 3.6.62 3.6.64 3.6.65 All 196 releases
← All changes | app/Services/FormBuilder/Components/Select.php +42 -2 6.2.26.2.14 View file →
@@ -44,10 +44,26 @@
44 44 wp_enqueue_style('ff_choices');
45 45 $data['attributes']['class'] .= ' ff_has_multi_select';
46 46 }
47 47
48 - if ($maxSelection = ArrayHelper::get($data, 'settings.max_selection')) {
48 + $maxSelection = Helper::resolveMaxSelection($data);
49 +
50 + if ($maxSelection) {
49 51 $data['attributes']['data-max_selected_options'] = $maxSelection;
52 +
53 + // Choices.js blocks the pick and draws its own notice, so that notice
54 + // is the only wording a visitor ever sees for this limit. Only a
55 + // message the site owner actually wrote overrides it — Choices' own
56 + // string is translated and carries the count, so a field left on the
57 + // global default is better served by it.
58 + $rules = ArrayHelper::get($data, 'settings.validation_rules', []);
59 + $customMessage = ArrayHelper::isTrue($rules, 'max_selection.global')
60 + ? ''
61 + : ArrayHelper::get($rules, 'max_selection.message', '');
62 +
63 + if ($customMessage) {
64 + $data['attributes']['data-max_selection_message'] = $customMessage;
65 + }
50 66 }
51 67
52 68 $data['attributes']['data-calc_value'] = 0;
53 69
@@ -74,9 +90,9 @@
74 90 if (ArrayHelper::get($data, 'settings.validation_rules.required.value')) {
75 91 $ariaRequired = 'true';
76 92 }
77 93
78 - $ariaLabelledBy = 'label_' . ArrayHelper::get($data, 'attributes.id');
94 + $ariaLabelledBy = esc_attr('label_' . ArrayHelper::get($data, 'attributes.id'));
79 95
80 96 $elMarkup = '<select ' . $atts . ' aria-invalid="false" aria-required="' . $ariaRequired . '" aria-labelledby="' . $ariaLabelledBy .'"'.'>' . $options . '</select>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $atts, $options are escaped before being passed in.
81 97
82 98 $html = $this->buildElementMarkup($elMarkup, $data, $form);
@@ -126,8 +142,32 @@
126 142 $opts .= '<option value="">' . wp_strip_all_tags($data['settings']['placeholder']) . '</option>';
127 143 } elseif (! empty($data['attributes']['placeholder'])) {
128 144 $opts .= '<option value="">' . wp_strip_all_tags($data['attributes']['placeholder']) . '</option>';
129 145 }
146 + foreach ($formattedOptions as $option) {
147 + if (Helper::isOptionGroup($option)) {
148 + $groupLabel = wp_strip_all_tags(ArrayHelper::get($option, 'label', ''));
149 + $groupOptions = $this->buildOptionMarkup(
150 + ArrayHelper::get($option, 'options', []),
151 + $defaultValues
152 + );
153 +
154 + if ($groupOptions) {
155 + $opts .= '<optgroup label="' . esc_attr($groupLabel) . '">' . $groupOptions . '</optgroup>';
156 + }
157 + continue;
158 + }
159 +
160 + $opts .= $this->buildOptionMarkup([$option], $defaultValues);
161 + }
162 +
163 + return $opts;
164 + }
165 +
166 + protected function buildOptionMarkup($formattedOptions, $defaultValues)
167 + {
168 + $opts = '';
169 +
130 170 foreach ($formattedOptions as $option) {
131 171 if (in_array($option['value'], $defaultValues)) {
132 172 $selected = 'selected';
133 173 } else {