PluginProbe
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz / 2.12.8
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz v2.12.8
2.12.8 2.12.7 2.12.6 2.12.5 2.12.4 2.12.3 2.12.2 2.12.1 2.12.0 2.11.1 2.11.0 2.10.1 2.10.0 2.9.1 2.9.0 2.8.2 2.8.1 2.7.0 2.7.1 2.8.0 trunk 0.0.10 0.0.11 0.0.12 0.0.13 All 98 releases
← All changes | inc/fields/multichoice-markup.php +65 -9 2.8.2 → 2.12.8 View file →
@@ -205,15 +205,33 @@
205 205
206 206 /**
207 207 * Resolve dynamic default value from smart tags and override preselected options.
208 208 *
209 + * Radio (single-selection) mode matches the resolved value as a single
210 + * trimmed string, so option titles that legitimately contain delimiter
211 + * characters (commas, pipes, etc.) still match.
212 + *
213 + * Checkbox mode splits the resolved value on the pipe character (`|`) and
214 + * matches every segment (for example "{get_input:a}|{get_input:b}" resolving
215 + * to "Red|Blue", or a single `{get_input:colors}` with URL
216 + * `?colors=Red|Blue`). The same pipe split applies to multi-character
217 + * resolved values from `{get_input:...}` and `{get_cookie:...}`, so cookie
218 + * payloads that contain pipes are treated as multi-value in checkbox mode.
219 + *
220 + * When the `Add Numeric Values to Options` (showValues) setting is on,
221 + * each segment is also compared against the option's `value`.
222 + *
209 223 * @param array<mixed> $attributes Block attributes.
210 224 * @since 2.8.1
225 + * @since 2.10.0 Added checkbox (pipe-delimited) multi-value matching.
211 226 * @return void
212 227 */
213 228 protected function resolve_dynamic_default( $attributes ) {
214 - $dynamic_default = is_string( $attributes['dynamicDefaultValue'] ?? '' ) ? $attributes['dynamicDefaultValue'] : '';
215 - if ( empty( $dynamic_default ) || ! $this->single_selection ) {
229 + // Coalesce first so blocks saved before this attribute existed (pre-2.10.0)
230 + // don't trigger an "Undefined array key" warning on every frontend render.
231 + $raw_default = $attributes['dynamicDefaultValue'] ?? '';
232 + $dynamic_default = is_string( $raw_default ) ? $raw_default : '';
233 + if ( empty( $dynamic_default ) ) {
216 234 return;
217 235 }
218 236
219 237 $smart_tags = new Smart_Tags();
@@ -218,23 +236,61 @@
218 236
219 237 $smart_tags = new Smart_Tags();
220 238 $resolved = $smart_tags->process_smart_tags( $dynamic_default );
221 239
222 - if ( empty( $resolved ) || ! is_string( $resolved ) ) {
240 + if ( empty( $resolved ) || ! is_string( $resolved ) || ! is_array( $this->options ) ) {
223 241 return;
224 242 }
225 243
226 - $resolved = trim( $resolved );
244 + // START: multi-value dynamic default resolution.
245 + if ( ! $this->single_selection ) {
246 + $segments = array_filter(
247 + array_map( 'trim', explode( '|', $resolved ) ),
248 + static function ( $segment ) {
249 + return '' !== $segment;
250 + }
251 + );
252 + // Cap segments to avoid pathological URLs (e.g. ?colors=|||||...) producing thousands of comparisons.
253 + $segments = array_slice( $segments, 0, 50 );
254 + } else {
255 + $trimmed = trim( $resolved );
256 + $segments = '' === $trimmed ? [] : [ $trimmed ];
257 + }
227 258
228 - if ( is_array( $this->options ) ) {
259 + if ( empty( $segments ) ) {
260 + return;
261 + }
262 +
263 + $match_value_too = ! empty( $attributes['showValues'] );
264 + $matching_indices = [];
265 +
266 + foreach ( $segments as $segment ) {
229 267 foreach ( $this->options as $i => $option ) {
230 - $option_title = $option['optionTitle'] ?? '';
231 - if ( strcasecmp( $option_title, $resolved ) === 0 ) {
232 - $this->preselected_options = [ $i ];
233 - return;
268 + if ( ! is_array( $option ) || in_array( $i, $matching_indices, true ) ) {
269 + continue;
234 270 }
271 +
272 + $option_title = isset( $option['optionTitle'] ) && is_scalar( $option['optionTitle'] ) ? (string) $option['optionTitle'] : '';
273 + $raw_value = $option['value'] ?? '';
274 + $option_value = $match_value_too && is_scalar( $raw_value ) ? (string) $raw_value : '';
275 +
276 + $is_match = ( '' !== $option_title && strcasecmp( $option_title, $segment ) === 0 )
277 + || ( $match_value_too && '' !== $option_value && strcasecmp( $option_value, $segment ) === 0 );
278 +
279 + if ( $is_match ) {
280 + $matching_indices[] = $i;
281 + if ( $this->single_selection ) {
282 + break 2;
283 + }
284 + break;
285 + }
235 286 }
236 287 }
288 +
289 + if ( ! empty( $matching_indices ) ) {
290 + $this->preselected_options = $this->single_selection ? [ $matching_indices[0] ] : $matching_indices;
291 + }
292 + // END: multi-value dynamic default resolution.
237 293 }
238 294
239 295 /**
240 296 * Data attribute markup for min and max value