PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / trunk
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More vtrunk
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
← All changes | classes/models/FrmFieldFormHtml.php +161 -66 6.4.1 → trunk View file →
@@ -5,13 +5,18 @@
5 5
6 6 /**
7 7 * @since 3.0
8 8 */
9 -
10 9 class FrmFieldFormHtml {
11 10
11 + /**
12 + * @var string
13 + */
12 14 private $html;
13 15
16 + /**
17 + * @var string
18 + */
14 19 private $html_id;
15 20
16 21 /**
17 22 * @var FrmFieldType
@@ -17,12 +22,21 @@
17 22 * @var FrmFieldType
18 23 */
19 24 private $field_obj;
20 25
26 + /**
27 + * @var int|string
28 + */
21 29 private $field_id;
22 30
31 + /**
32 + * @var array|object
33 + */
23 34 private $form = array();
24 35
36 + /**
37 + * @var array
38 + */
25 39 private $pass_args = array();
26 40
27 41 /**
28 42 * @since 3.0
@@ -41,9 +55,11 @@
41 55 /**
42 56 * @since 3.0
43 57 *
44 58 * @param string $param
45 - * @param array $atts
59 + * @param array $atts
60 + *
61 + * @return void
46 62 */
47 63 private function _set( $param, $atts ) {
48 64 if ( isset( $atts[ $param ] ) ) {
49 65 $this->{$param} = $atts[ $param ];
@@ -53,8 +69,10 @@
53 69 /**
54 70 * @since 3.0
55 71 *
56 72 * @param array $atts
73 + *
74 + * @return void
57 75 */
58 76 private function set_html( $atts ) {
59 77 $this->set_from_field(
60 78 $atts,
@@ -68,8 +86,10 @@
68 86 /**
69 87 * @since 3.0
70 88 *
71 89 * @param array $atts
90 + *
91 + * @return void
72 92 */
73 93 private function set_field_id( $atts ) {
74 94 $this->set_from_field(
75 95 $atts,
@@ -83,13 +103,16 @@
83 103 /**
84 104 * @since 3.0
85 105 *
86 106 * @param array $atts
107 + *
108 + * @return void
87 109 */
88 110 private function set_pass_args( $atts ) {
89 111 $this->pass_args = $atts;
90 112
91 113 $exclude = array( 'field_obj', 'html' );
114 +
92 115 foreach ( $exclude as $ex ) {
93 116 if ( isset( $atts[ $ex ] ) ) {
94 117 unset( $this->pass_args[ $ex ] );
95 118 }
@@ -100,8 +123,10 @@
100 123 * @since 3.0
101 124 *
102 125 * @param array $atts
103 126 * @param array $set
127 + *
128 + * @return void
104 129 */
105 130 private function set_from_field( $atts, $set ) {
106 131 if ( isset( $atts[ $set['param'] ] ) ) {
107 132 $this->{$set['param']} = $atts[ $set['param'] ];
@@ -109,8 +134,11 @@
109 134 $this->{$set['param']} = $this->field_obj->get_field_column( $set['default'] );
110 135 }
111 136 }
112 137
138 + /**
139 + * @return string
140 + */
113 141 public function get_html() {
114 142 $this->replace_shortcodes_before_input();
115 143 $this->replace_shortcodes_with_atts();
116 144 $this->replace_shortcodes_after_input();
@@ -119,8 +147,10 @@
119 147 }
120 148
121 149 /**
122 150 * @since 3.0
151 + *
152 + * @return void
123 153 */
124 154 private function replace_shortcodes_before_input() {
125 155 $this->html = apply_filters( 'frm_before_replace_shortcodes', $this->html, $this->field_obj->get_field(), $this->pass_args['errors'], $this->form );
126 156
@@ -142,25 +172,29 @@
142 172 }
143 173
144 174 /**
145 175 * @since 3.0
176 + *
177 + * @return void
146 178 */
147 179 private function replace_field_values() {
148 - //replace [id]
180 + // Replace [id].
149 181 $this->html = str_replace( '[id]', $this->field_id, $this->html );
150 182
151 - // set the label for
183 + // Set the label for
152 184 $this->html = str_replace( 'field_[key]', $this->html_id, $this->html );
153 185
154 - //replace [key]
186 + // Replace [key].
155 187 $this->html = str_replace( '[key]', $this->field_obj->get_field_column( 'field_key' ), $this->html );
156 188
157 - //replace [field_name]
189 + // Replace [field_name].
158 190 $this->html = str_replace( '[field_name]', FrmAppHelper::maybe_kses( $this->field_obj->get_field_column( 'name' ) ), $this->html );
159 191 }
160 192
161 193 /**
162 194 * @since 3.0
195 + *
196 + * @return void
163 197 */
164 198 private function replace_required_label_shortcode() {
165 199 $required = FrmField::is_required( $this->field_obj->get_field() ) ? $this->field_obj->get_field_column( 'required_indicator' ) : '';
166 200 FrmShortcodeHelper::remove_inline_conditions( ! empty( $required ), 'required_label', $required, $this->html );
@@ -170,12 +204,17 @@
170 204 * If this is an HTML field, the values are included in the description.
171 205 * In this case, we don't want to run the wp shortcodes with the description included.
172 206 *
173 207 * @since 3.0
208 + *
209 + * @param bool $wp_processed
210 + *
211 + * @return void
174 212 */
175 213 private function maybe_replace_description_shortcode( $wp_processed = false ) {
176 214 $is_html = 'html' === $this->field_obj->get_field_column( 'type' );
177 - $should_replace = ( $is_html && $wp_processed ) || ( ! $is_html && ! $wp_processed );
215 + $should_replace = $is_html ? $wp_processed : ! $wp_processed;
216 +
178 217 if ( $should_replace ) {
179 218 $this->replace_description_shortcode();
180 219 }
181 220 }
@@ -181,13 +220,16 @@
181 220 }
182 221
183 222 /**
184 223 * @since 3.0
224 + *
225 + * @return void
185 226 */
186 227 private function replace_description_shortcode() {
187 228 $this->maybe_add_description_id();
188 229 $description = FrmAppHelper::maybe_kses( $this->field_obj->get_field_column( 'description' ) );
189 - FrmShortcodeHelper::remove_inline_conditions( ( $description && $description != '' ), 'description', $description, $this->html );
230 + // phpcs:ignore Universal.Operators.StrictComparisons
231 + FrmShortcodeHelper::remove_inline_conditions( $description && $description != '', 'description', $description, $this->html );
190 232 }
191 233
192 234 /**
193 235 * Add an ID to the description for aria-describedby.
@@ -193,11 +235,15 @@
193 235 * Add an ID to the description for aria-describedby.
194 236 * This ID was added to the HTML in v3.0.
195 237 *
196 238 * @since 3.0
239 + *
240 + * @return void
197 241 */
198 242 private function maybe_add_description_id() {
199 243 $description = $this->field_obj->get_field_column( 'description' );
244 +
245 + // phpcs:ignore Universal.Operators.StrictComparisons
200 246 if ( $description != '' ) {
201 247 $this->add_element_id( 'description', 'desc' );
202 248 }
203 249 }
@@ -205,11 +251,17 @@
205 251 /**
206 252 * Insert an ID if it doesn't exist.
207 253 *
208 254 * @since 3.06.02
255 + *
256 + * @param string $param
257 + * @param string $id
258 + *
259 + * @return void
209 260 */
210 261 private function add_element_id( $param, $id ) {
211 262 preg_match_all( '/(\[if\s+' . $param . '\])(.*?)(\[\/if\s+' . $param . '\])/mis', $this->html, $inner_html );
263 +
212 264 if ( ! isset( $inner_html[2] ) ) {
213 265 return;
214 266 }
215 267
@@ -216,33 +268,51 @@
216 268 if ( ! is_string( $inner_html[2] ) && count( $inner_html[2] ) === 1 ) {
217 269 $inner_html[2] = $inner_html[2][0];
218 270 }
219 271
220 - if ( is_string( $inner_html[2] ) ) {
221 - $has_id = strpos( $inner_html[2], ' id=' );
222 - if ( ! $has_id ) {
223 - $id = 'frm_' . $id . '_' . $this->html_id;
224 - $this->html = str_replace( 'class="frm_' . $param, 'id="' . esc_attr( $id ) . '" class="frm_' . esc_attr( $param ), $this->html );
225 - }
272 + if ( ! is_string( $inner_html[2] ) ) {
273 + return;
226 274 }
275 +
276 + $has_id = str_contains( $inner_html[2], ' id=' );
277 +
278 + if ( $has_id ) {
279 + return;
280 + }
281 +
282 + $id = 'frm_' . $id . '_' . $this->html_id;
283 + $this->html = str_replace( 'class="frm_' . $param, 'id="' . esc_attr( $id ) . '" class="frm_' . esc_attr( $param ), $this->html );
227 284 }
228 285
229 286 /**
230 287 * @since 3.0
288 + *
289 + * @return void
231 290 */
232 291 private function replace_error_shortcode() {
233 292 $this->maybe_add_error_id();
234 - $error = isset( $this->pass_args['errors'][ 'field' . $this->field_id ] ) ? $this->pass_args['errors'][ 'field' . $this->field_id ] : false;
293 + $error = $this->pass_args['errors'][ 'field' . $this->field_id ] ?? false;
235 294
236 - if ( ! empty( $error ) && false === strpos( $this->html, 'role="alert"' ) && FrmAppHelper::should_include_alert_role_on_field_errors() ) {
295 + if ( ! $error ) {
296 + FrmShortcodeHelper::remove_inline_conditions( false, 'error', $error, $this->html );
297 + return;
298 + }
299 +
300 + $include_alert_role_on_field_errors = FrmAppHelper::should_include_alert_role_on_field_errors();
301 + $has_alert_role = str_contains( $this->html, 'role="alert"' );
302 +
303 + if ( ! $has_alert_role && $include_alert_role_on_field_errors ) {
237 304 $error_body = self::get_error_body( $this->html );
238 - if ( is_string( $error_body ) && false === strpos( $error_body, 'role=' ) ) {
305 +
306 + if ( is_string( $error_body ) && ! str_contains( $error_body, 'role=' ) ) {
239 307 $new_error_body = preg_replace( '/class="frm_error/', 'role="alert" class="frm_error', $error_body, 1 );
240 308 $this->html = str_replace( '[if error]' . $error_body . '[/if error]', '[if error]' . $new_error_body . '[/if error]', $this->html );
241 309 }
310 + } elseif ( ! $include_alert_role_on_field_errors && $has_alert_role ) {
311 + $this->html = str_replace( 'role="alert"', '', $this->html );
242 312 }
243 313
244 - FrmShortcodeHelper::remove_inline_conditions( ! empty( $error ), 'error', $error, $this->html );
314 + FrmShortcodeHelper::remove_inline_conditions( true, 'error', $error, $this->html );
245 315 }
246 316
247 317 /**
248 318 * Pull the HTML between [if error] and [/if error] shortcodes.
@@ -247,23 +317,25 @@
247 317 /**
248 318 * Pull the HTML between [if error] and [/if error] shortcodes.
249 319 *
250 320 * @param string $html
251 - * @return string|false
321 + *
322 + * @return false|string
252 323 */
253 324 private static function get_error_body( $html ) {
254 325 $start = strpos( $html, '[if error]' );
326 +
255 327 if ( false === $start ) {
256 328 return false;
257 329 }
258 330
259 331 $end = strpos( $html, '[/if error]', $start );
332 +
260 333 if ( false === $end ) {
261 334 return false;
262 335 }
263 336
264 - $error_body = substr( $html, $start + 10, $end - $start - 10 );
265 - return $error_body;
337 + return substr( $html, $start + 10, $end - $start - 10 );
266 338 }
267 339
268 340 /**
269 341 * Add an ID to the error message for aria-describedby.
@@ -269,8 +341,10 @@
269 341 * Add an ID to the error message for aria-describedby.
270 342 * This ID was added to the HTML in v3.06.02.
271 343 *
272 344 * @since 3.06.02
345 + *
346 + * @return void
273 347 */
274 348 private function maybe_add_error_id() {
275 349 if ( ! isset( $this->pass_args['errors'][ 'field' . $this->field_id ] ) ) {
276 350 return;
@@ -282,8 +356,10 @@
282 356 /**
283 357 * Replace [required_class]
284 358 *
285 359 * @since 3.0
360 + *
361 + * @return void
286 362 */
287 363 private function replace_required_class() {
288 364 $required_class = FrmField::is_required( $this->field_obj->get_field() ) ? ' frm_required_field' : '';
289 365 $this->html = str_replace( '[required_class]', $required_class, $this->html );
@@ -290,29 +366,35 @@
290 366 }
291 367
292 368 /**
293 369 * @since 3.0
370 + *
371 + * @return void
294 372 */
295 373 private function replace_form_shortcodes() {
296 - if ( ! empty( $this->form ) ) {
297 - $form = (array) $this->form;
374 + if ( ! $this->form ) {
375 + return;
376 + }
298 377
299 - //replace [form_key]
300 - $this->html = str_replace( '[form_key]', $form['form_key'], $this->html );
378 + $form = (array) $this->form;
301 379
302 - //replace [form_name]
303 - $this->html = str_replace( '[form_name]', $form['name'], $this->html );
304 - }
380 + // Replace [form_key].
381 + $this->html = str_replace( '[form_key]', $form['form_key'], $this->html );
382 +
383 + // Replace [form_name].
384 + $this->html = str_replace( '[form_name]', $form['name'], $this->html );
305 385 }
306 386
307 387 /**
308 388 * @since 3.0
389 + *
390 + * @return void
309 391 */
310 392 public function replace_shortcodes_after_input() {
311 393 $this->html .= "\n";
312 394
313 395 // Stop html filtering on confirmation field to prevent loop
314 - if ( $this->field_obj->get_field_column( 'conf_field' ) != 'stop' ) {
396 + if ( $this->field_obj->get_field_column( 'conf_field' ) !== 'stop' ) {
315 397 $this->filter_for_more_shortcodes();
316 398 }
317 399 }
318 400
@@ -317,13 +399,15 @@
317 399 }
318 400
319 401 /**
320 402 * @since 3.0
403 + *
404 + * @return void
321 405 */
322 406 private function filter_for_more_shortcodes() {
323 407 $atts = $this->pass_args;
324 408
325 - //If field is not in repeating section
409 + // If field is not in repeating section.
326 410 if ( empty( $atts['section_id'] ) ) {
327 411 $atts = array(
328 412 'errors' => $this->pass_args['errors'],
329 413 'form' => $this->form,
@@ -337,11 +421,13 @@
337 421 *
338 422 * @since 3.0
339 423 *
340 424 * @param string $html
425 + *
426 + * @return void
341 427 */
342 428 public function remove_collapse_shortcode( &$html ) {
343 - if ( strpos( $html, '[collapse_this]' ) ) {
429 + if ( str_contains( $html, '[collapse_this]' ) ) {
344 430 $html = str_replace( '[collapse_this]', '', $html );
345 431 }
346 432 }
347 433
@@ -346,8 +432,10 @@
346 432 }
347 433
348 434 /**
349 435 * @since 3.0
436 + *
437 + * @return void
350 438 */
351 439 private function replace_shortcodes_with_atts() {
352 440 preg_match_all( "/\[(input|deletelink)\b(.*?)(?:(\/))?\]/s", $this->html, $shortcodes, PREG_PATTERN_ORDER );
353 441
@@ -353,14 +441,13 @@
353 441
354 442 foreach ( $shortcodes[0] as $short_key => $tag ) {
355 443 $shortcode_atts = FrmShortcodeHelper::get_shortcode_attribute_array( $shortcodes[2][ $short_key ] );
356 444 $tag = FrmShortcodeHelper::get_shortcode_tag( $shortcodes, $short_key );
445 + $replace_with = '';
357 446
358 - $replace_with = '';
359 -
360 - if ( $tag == 'deletelink' && FrmAppHelper::pro_is_installed() ) {
447 + if ( $tag === 'deletelink' && FrmAppHelper::pro_is_installed() ) {
361 448 $replace_with = FrmProEntriesController::entry_delete_link( $shortcode_atts );
362 - } elseif ( $tag == 'input' ) {
449 + } elseif ( $tag === 'input' ) {
363 450 $replace_with = $this->replace_input_shortcode( $shortcode_atts );
364 451 }
365 452
366 453 $this->html = str_replace( $shortcodes[0][ $short_key ], $replace_with, $this->html );
@@ -373,9 +460,8 @@
373 460 * @return string
374 461 */
375 462 private function replace_input_shortcode( $shortcode_atts ) {
376 463 $shortcode_atts = $this->prepare_input_shortcode_atts( $shortcode_atts );
377 -
378 464 return $this->field_obj->include_front_field_input( $this->pass_args, $shortcode_atts );
379 465 }
380 466
381 467 /**
@@ -384,12 +470,12 @@
384 470 * @return array
385 471 */
386 472 private function prepare_input_shortcode_atts( $shortcode_atts ) {
387 473 if ( isset( $shortcode_atts['opt'] ) ) {
388 - $shortcode_atts['opt'] --;
474 + --$shortcode_atts['opt'];
389 475 }
390 476
391 - $field_class = isset( $shortcode_atts['class'] ) ? $shortcode_atts['class'] : '';
477 + $field_class = $shortcode_atts['class'] ?? '';
392 478 $this->field_obj->set_field_column( 'input_class', $field_class );
393 479
394 480 if ( isset( $shortcode_atts['class'] ) ) {
395 481 unset( $shortcode_atts['class'] );
@@ -394,9 +480,9 @@
394 480 if ( isset( $shortcode_atts['class'] ) ) {
395 481 unset( $shortcode_atts['class'] );
396 482 }
397 483
398 - $shortcode_atts['aria-invalid'] = isset( $this->pass_args['errors'][ 'field' . $this->field_id ] ) ? 'true' : 'false';
484 + $this->field_obj->set_aria_invalid_error( $shortcode_atts, $this->pass_args );
399 485
400 486 $this->field_obj->set_field_column( 'shortcodes', $shortcode_atts );
401 487
402 488 return $shortcode_atts;
@@ -406,8 +492,10 @@
406 492 * Add the label position class into the HTML
407 493 * If the label position is inside, add a class to show the label if the field has a value.
408 494 *
409 495 * @since 3.0
496 + *
497 + * @return void
410 498 */
411 499 private function add_class_to_label() {
412 500 $label_class = $this->field_obj->get_label_class();
413 501 $this->html = str_replace( '[label_position]', $label_class, $this->html );
@@ -416,8 +504,10 @@
416 504 /**
417 505 * Replace [entry_key]
418 506 *
419 507 * @since 3.0
508 + *
509 + * @return void
420 510 */
421 511 private function replace_entry_key() {
422 512 $entry_key = FrmAppHelper::simple_get( 'entry', 'sanitize_title' );
423 513 $this->html = str_replace( '[entry_key]', $entry_key, $this->html );
@@ -426,17 +516,21 @@
426 516 /**
427 517 * Add classes to a field div
428 518 *
429 519 * @since 3.0
520 + *
521 + * @return void
430 522 */
431 523 private function add_field_div_classes() {
432 524 $classes = $this->get_field_div_classes();
433 525
434 - if ( $this->field_obj->get_field_column( 'type' ) == 'html' && strpos( $this->html, '[error_class]' ) === false ) {
435 - // there is no error_class shortcode for HTML fields
436 - $this->html = str_replace( 'class="frm_form_field', 'class="frm_form_field ' . $classes, $this->html );
526 + if ( in_array( $this->field_obj->get_field_column( 'type' ), array( 'html', 'summary' ), true ) && ! str_contains( $this->html, '[error_class]' ) ) {
527 + // There is no error_class shortcode for HTML fields
528 + $this->html = str_replace( 'class="frm_form_field', 'class="frm_form_field ' . esc_attr( $classes ), $this->html );
529 + return;
437 530 }
438 - $this->html = str_replace( '[error_class]', $classes, $this->html );
531 +
532 + $this->html = str_replace( '[error_class]', esc_attr( $classes ), $this->html );
439 533 }
440 534
441 535 /**
442 536 * Get the classes for a field div
@@ -442,9 +536,9 @@
442 536 * Get the classes for a field div
443 537 *
444 538 * @since 3.0
445 539 *
446 - * @return string $classes
540 + * @return string Classes.
447 541 */
448 542 private function get_field_div_classes() {
449 543 // Add error class
450 544 $classes = isset( $this->pass_args['errors'][ 'field' . $this->field_id ] ) ? ' frm_blank_field' : '';
@@ -450,11 +544,12 @@
450 544 $classes = isset( $this->pass_args['errors'][ 'field' . $this->field_id ] ) ? ' frm_blank_field' : '';
451 545
452 546 // Add label position class
453 547 $settings = $this->field_obj->display_field_settings();
454 - if ( isset( $settings['label_position'] ) && $settings['label_position'] ) {
548 +
549 + if ( ! empty( $settings['label_position'] ) ) {
455 550 $label_position = $this->field_obj->get_field_column( 'label' );
456 - $classes .= ' frm_' . $label_position . '_container';
551 + $classes .= ' frm_' . $label_position . '_container';
457 552
458 553 // Add class if field has value, to be used for floating label styling.
459 554 if ( 'inside' === $label_position && $this->field_obj->get_field_column( 'value' ) ) {
460 555 $classes .= ' frm_label_float_top';
@@ -462,12 +557,14 @@
462 557 }
463 558
464 559 // Add CSS layout classes
465 560 $extra_classes = $this->field_obj->get_field_column( 'classes' );
466 - if ( ! empty( $extra_classes ) ) {
467 - if ( ! strpos( $this->html, 'frm_form_field ' ) ) {
561 +
562 + if ( $extra_classes ) {
563 + if ( ! str_contains( $this->html, 'frm_form_field ' ) ) {
468 564 $classes .= ' frm_form_field';
469 565 }
566 +
470 567 $classes .= ' ' . $extra_classes;
471 568 }
472 569
473 570 $classes .= $this->field_obj->get_container_class();
@@ -472,9 +569,12 @@
472 569
473 570 $classes .= $this->field_obj->get_container_class();
474 571
475 572 // Get additional classes
476 - return apply_filters( 'frm_field_div_classes', $classes, $this->field_obj->get_field(), array( 'field_id' => $this->field_id ) );
573 + $classes = apply_filters( 'frm_field_div_classes', $classes, $this->field_obj->get_field(), array( 'field_id' => $this->field_id ) );
574 +
575 + // Remove unexpected characters from class.
576 + return implode( ' ', array_map( 'FrmFormsHelper::sanitize_layout_class', explode( ' ', $classes ) ) );
477 577 }
478 578
479 579 /**
480 580 * This filters shortcodes in the field HTML
@@ -479,8 +579,10 @@
479 579 /**
480 580 * This filters shortcodes in the field HTML
481 581 *
482 582 * @since 3.0
583 + *
584 + * @return void
483 585 */
484 586 private function process_wp_shortcodes() {
485 587 if ( apply_filters( 'frm_do_html_shortcodes', true ) ) {
486 588 $this->html = do_shortcode( $this->html );
@@ -490,8 +592,9 @@
490 592 /**
491 593 * Adds multiple input attributes.
492 594 *
493 595 * @since 6.4.1
596 + *
494 597 * @return void
495 598 */
496 599 private function add_multiple_input_attributes() {
497 600 $field_type = $this->field_obj->get_field_column( 'type' );
@@ -500,25 +603,17 @@
500 603 if ( ! in_array( $field_type, array( 'radio', 'checkbox', 'data', 'product', 'scale' ), true ) ) {
501 604 return;
502 605 }
503 606
504 - $field = (array) $this->field_obj->get_field();
505 - $attributes = array();
506 - $is_radio = 'radio' === $field_type || 'scale' === $field_type;
507 - $type_requires_aria_required = true;
607 + $field = (array) $this->field_obj->get_field();
608 + $attributes = array();
508 609
509 610 // Check if the field type is 'data' or 'product'.
510 611 if ( in_array( $field_type, array( 'data', 'product' ), true ) ) {
511 612 $data_type = FrmField::get_option( $field, 'data_type' );
512 - // Check if the data type isn't 'radio' or 'checkbox'.
513 - if ( 'radio' !== $data_type && 'checkbox' !== $data_type ) {
514 - // If data type aren't 'radio' or 'checkbox', doesn't need to add 'aria-required' to multiple input container.
515 - $type_requires_aria_required = false;
516 - }
517 - // Check if data type is 'radio'
518 - if ( 'radio' === $data_type ) {
519 - $is_radio = true;
520 - }
613 + $is_radio = 'radio' === $data_type;
614 + } else {
615 + $is_radio = 'radio' === $field_type || 'scale' === $field_type;
521 616 }
522 617
523 618 // Add 'role' attribute to the field.
524 619 $attributes['role'] = $is_radio ? 'radiogroup' : 'group';
@@ -523,15 +618,15 @@
523 618 // Add 'role' attribute to the field.
524 619 $attributes['role'] = $is_radio ? 'radiogroup' : 'group';
525 620
526 621 // Add 'aria-required' attribute to the field if required.
527 - if ( $type_requires_aria_required && '1' === $field['required'] ) {
622 + if ( $is_radio && '1' === $field['required'] ) {
528 623 $attributes['aria-required'] = 'true';
529 624 }
530 625
531 - // Add 'tabindex = "0"' attribute to the radio field.
532 - if ( $is_radio ) {
533 - $attributes['tabindex'] = 0;
626 + // Add 'aria-invalid' attribute to the group if there are errors.
627 + if ( isset( $this->pass_args['errors'][ 'field' . $this->field_id ] ) ) {
628 + $attributes['aria-invalid'] = 'true';
534 629 }
535 630
536 631 // Concatenate attributes into a string, and replace the role="group" in the HTML with the attributes string.
537 632 $html_attributes = FrmAppHelper::array_to_html_params( $attributes );