PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.24
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.24
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/controllers/FrmFieldsController.php +284 -186 6.4.26.24 View file →
@@ -4,8 +4,15 @@
4 4 }
5 5
6 6 class FrmFieldsController {
7 7
8 + /**
9 + * This is stored statically so we can re-use this data for every field.
10 + *
11 + * @var FrmFieldSelectionData|null
12 + */
13 + private static $field_selection_data;
14 +
8 15 public static function load_field() {
9 16 FrmAppHelper::permission_check( 'frm_edit_forms' );
10 17 check_ajax_referer( 'frm_ajax', 'nonce' );
11 18
@@ -56,14 +63,15 @@
56 63 public static function create() {
57 64 FrmAppHelper::permission_check( 'frm_edit_forms' );
58 65 check_ajax_referer( 'frm_ajax', 'nonce' );
59 66
60 - $field_type = FrmAppHelper::get_post_param( 'field_type', '', 'sanitize_text_field' );
61 - $form_id = FrmAppHelper::get_post_param( 'form_id', 0, 'absint' );
67 + $field_type = FrmAppHelper::get_post_param( 'field_type', '', 'sanitize_text_field' );
68 + $form_id = FrmAppHelper::get_post_param( 'form_id', 0, 'absint' );
69 + $field_options = FrmAppHelper::get_post_param( 'field_options', array(), 'wp_kses_post' );
62 70
63 71 do_action( 'frm_before_create_field', $field_type, $form_id );
64 72
65 - $field = self::include_new_field( $field_type, $form_id );
73 + $field = self::include_new_field( $field_type, $form_id, $field_options );
66 74
67 75 // this hook will allow for multiple fields to be added at once
68 76 do_action( 'frm_after_field_created', $field, $form_id );
69 77
@@ -73,18 +81,29 @@
73 81 /**
74 82 * Set up and create a new field
75 83 *
76 84 * @param string $field_type
77 - * @param integer $form_id
85 + * @param int $form_id
86 + * @param array $field_options
78 87 *
79 - * @return array|bool
88 + * @return array|false
80 89 */
81 - public static function include_new_field( $field_type, $form_id ) {
90 + public static function include_new_field( $field_type, $form_id, $field_options = array() ) {
82 91 $field_values = FrmFieldsHelper::setup_new_vars( $field_type, $form_id );
92 +
93 + if ( ! empty( $field_options ) ) {
94 + $field_values['field_options'] = array_merge( $field_values['field_options'], $field_options );
95 + }
96 +
97 + // When a new field is added to the form, flag it as draft and hide it from the front-end.
98 + $field_values['field_options']['draft'] = 1;
99 +
100 + /**
101 + * @param array $field_values
102 + */
83 103 $field_values = apply_filters( 'frm_before_field_created', $field_values );
104 + $field_id = FrmField::create( $field_values );
84 105
85 - $field_id = FrmField::create( $field_values );
86 -
87 106 if ( ! $field_id ) {
88 107 return false;
89 108 }
90 109
@@ -136,11 +155,11 @@
136 155
137 156 /**
138 157 * @since 3.0
139 158 *
140 - * @param int|array|object $field_object
141 - * @param array $values
142 - * @param int $form_id
159 + * @param array|int|object $field_object
160 + * @param array $values
161 + * @param int $form_id
143 162 */
144 163 public static function load_single_field( $field_object, $values, $form_id = 0 ) {
145 164 global $frm_vars;
146 165 $frm_vars['is_admin'] = true;
@@ -154,30 +173,46 @@
154 173
155 174 $field_obj = FrmFieldFactory::get_field_factory( $field_object );
156 175 $display = self::display_field_options( array(), $field_obj );
157 176
158 - $ajax_loading = isset( $values['ajax_load'] ) && $values['ajax_load'];
159 - $ajax_this_field = isset( $values['count'] ) && $values['count'] > 10 && ! in_array( $field_object->type, array( 'divider', 'end_divider' ) );
177 + $ajax_loading = ! empty( $values['ajax_load'] );
178 + $ajax_this_field = isset( $values['count'] ) && $values['count'] > 10 && ! in_array( $field_object->type, array( 'divider', 'end_divider' ), true );
160 179
161 180 if ( $ajax_loading && $ajax_this_field ) {
162 181 $li_classes = self::get_classes_for_builder_field( array(), $display, $field_obj );
163 - include( FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/ajax-field-placeholder.php' );
164 - } else {
165 - if ( ! isset( $field ) && is_object( $field_object ) ) {
166 - $field_object->parent_form_id = isset( $values['id'] ) ? $values['id'] : $field_object->form_id;
182 + include FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/ajax-field-placeholder.php';
183 + return;
184 + }
167 185
168 - $field = FrmFieldsHelper::setup_edit_vars( $field_object );
169 - }
186 + if ( ! isset( $field ) && is_object( $field_object ) ) {
187 + $field_object->parent_form_id = isset( $values['id'] ) ? $values['id'] : $field_object->form_id;
188 + $field = FrmFieldsHelper::setup_edit_vars( $field_object );
189 + }
170 190
171 - $li_classes = self::get_classes_for_builder_field( $field, $display, $field_obj );
172 - $li_classes .= ' ui-state-default widgets-holder-wrap';
191 + /**
192 + * Filter for adding extra attributes to the field container.
193 + *
194 + * @since 6.23
195 + *
196 + * @param array $extra_field_attributes
197 + * @param array $field
198 + * @param array $display
199 + */
200 + $extra_field_attributes = apply_filters( 'frm_field_container_extra_attributes', array(), $field, $display );
173 201
174 - require( FrmAppHelper::plugin_path() . '/classes/views/frm-forms/add_field.php' );
175 - }
202 + $li_classes = self::get_classes_for_builder_field( $field, $display, $field_obj );
203 + $li_classes .= ' ui-state-default widgets-holder-wrap';
204 +
205 + require FrmAppHelper::plugin_path() . '/classes/views/frm-forms/add_field.php';
176 206 }
177 207
178 208 /**
179 209 * @since 3.0
210 + *
211 + * @param array $field
212 + * @param array $display
213 + * @param FrmFieldType $field_info
214 + * @return string
180 215 */
181 216 private static function get_classes_for_builder_field( $field, $display, $field_info ) {
182 217 $li_classes = $field_info->form_builder_classes( $display['type'] );
183 218 $li_classes .= ' frm_form_field frmstart ';
@@ -203,10 +238,11 @@
203 238 FrmField::destroy( $field_id );
204 239 wp_die();
205 240 }
206 241
207 - /* Field Options */
208 -
242 + /**
243 + * Field Options.
244 + */
209 245 public static function import_options() {
210 246 FrmAppHelper::permission_check( 'frm_edit_forms' );
211 247 check_ajax_referer( 'frm_ajax', 'nonce' );
212 248
@@ -213,12 +249,23 @@
213 249 if ( ! is_admin() || ! current_user_can( 'frm_edit_forms' ) ) {
214 250 return;
215 251 }
216 252
217 - $field_id = FrmAppHelper::get_param( 'field_id', '', 'post', 'absint' );
218 - $field = FrmField::getOne( $field_id );
253 + $field_id = FrmAppHelper::get_param( 'field_id', '', 'post', 'absint' );
254 + $field = FrmField::getOne( $field_id );
255 + $bulk_edit_types = array( 'radio', 'checkbox', 'select' );
219 256
220 - if ( ! in_array( $field->type, array( 'radio', 'checkbox', 'select' ) ) ) {
257 + /**
258 + * Filter to add new fields that will support import_options/Bulk Edit Options.
259 + *
260 + * @since 6.8.4
261 + *
262 + * @param array $bulk_edit_types
263 + * @return array
264 + */
265 + $bulk_edit_types = apply_filters( 'frm_bulk_edit_field_types', $bulk_edit_types );
266 +
267 + if ( ! in_array( $field->type, $bulk_edit_types, true ) ) {
221 268 return;
222 269 }
223 270
224 271 $field = FrmFieldsHelper::setup_edit_vars( $field );
@@ -225,15 +272,15 @@
225 272 $opts = FrmAppHelper::get_param( 'opts', '', 'post', 'wp_kses_post' );
226 273 $opts = explode( "\n", rtrim( $opts, "\n" ) );
227 274 $opts = array_map( 'trim', $opts );
228 275
229 - $separate = FrmAppHelper::get_param( 'separate', '', 'post', 'sanitize_text_field' );
230 - $field['separate_value'] = ( $separate === 'true' );
276 + $separate = FrmAppHelper::get_param( 'separate', '', 'post', 'sanitize_text_field' );
277 + $field['separate_value'] = $separate === 'true';
231 278
232 279 if ( $field['separate_value'] ) {
233 280 foreach ( $opts as $opt_key => $opt ) {
234 281 if ( strpos( $opt, '|' ) !== false ) {
235 - $vals = explode( '|', $opt );
282 + $vals = explode( '|', $opt );
236 283 $opts[ $opt_key ] = array(
237 284 'label' => trim( $vals[0] ),
238 285 'value' => trim( $vals[1] ),
239 286 );
@@ -267,8 +314,9 @@
267 314 /**
268 315 * @since 4.0
269 316 *
270 317 * @param array $atts - Includes field array, field_obj, display array, values array.
318 + * @return void
271 319 */
272 320 public static function load_single_field_settings( $atts ) {
273 321 $field = $atts['field'];
274 322 $field_obj = $atts['field_obj'];
@@ -283,13 +331,13 @@
283 331 if ( ! isset( $field['read_only'] ) ) {
284 332 $field['read_only'] = false;
285 333 }
286 334
287 - $field_types = FrmFieldsHelper::get_field_types( $field['type'] );
288 - $pro_field_selection = FrmField::pro_field_selection();
289 - $all_field_types = array_merge( $pro_field_selection, FrmField::field_selection() );
290 - $disabled_fields = FrmAppHelper::pro_is_installed() ? array() : $pro_field_selection;
291 - $frm_settings = FrmAppHelper::get_settings();
335 + $field_selection_data = self::maybe_define_field_selection_data();
336 + $all_field_types = $field_selection_data->all_field_types;
337 + $disabled_fields = $field_selection_data->disabled_fields;
338 + $frm_settings = FrmAppHelper::get_settings();
339 + $field_types = FrmFieldTypeOptionData::get_field_types( $field['type'] );
292 340
293 341 if ( ! isset( $all_field_types[ $field['type'] ] ) ) {
294 342 // Add fallback for an add-on field type that has been deactivated.
295 343 $all_field_types[ $field['type'] ] = array(
@@ -312,61 +360,76 @@
312 360
313 361 if ( $display['clear_on_focus'] && is_array( $field['placeholder'] ) ) {
314 362 $field['placeholder'] = implode( ', ', $field['placeholder'] );
315 363 }
316 - include( FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/settings.php' );
364 +
365 + include FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/settings.php';
317 366 }
318 367
319 368 /**
369 + * @since 6.9.1
370 + *
371 + * @return FrmFieldSelectionData
372 + */
373 + private static function maybe_define_field_selection_data() {
374 + if ( ! isset( self::$field_selection_data ) ) {
375 + self::$field_selection_data = new FrmFieldSelectionData();
376 + }
377 + return self::$field_selection_data;
378 + }
379 +
380 + /**
320 381 * Get the list of default value types that can be toggled in the builder.
321 382 *
322 383 * @since 4.0
384 + *
385 + * @param array $field
386 + * @param array $atts
323 387 * @return array
324 388 */
325 389 private static function default_value_types( $field, $atts ) {
326 390 $types = array(
327 - 'default_value' => array(
391 + 'default_value' => array(
328 392 'class' => '',
329 393 'icon' => 'frm_icon_font frm_text2_icon',
330 - 'title' => __( 'Default Value (Text)', 'formidable' ),
394 + 'title' => __( 'Default Value', 'formidable' ),
331 395 'data' => array(
332 396 'frmshow' => '#default-value-for-',
333 397 ),
334 398 ),
335 - 'calc' => array(
336 - 'class' => 'frm_show_upgrade frm_noallow',
337 - 'title' => __( 'Default Value (Calculation)', 'formidable' ),
338 - 'icon' => 'frm_icon_font frm_calculator_icon',
339 - 'data' => array(
399 + 'calc' => array(
400 + 'class' => 'frm_show_upgrade frm_noallow',
401 + 'title' => __( 'Calculate Value', 'formidable' ),
402 + 'icon' => 'frm_icon_font frm_calculator_icon',
403 + 'data' => array(
340 404 'medium' => 'calculations',
341 405 'upgrade' => __( 'Calculator forms', 'formidable' ),
342 406 ),
407 + 'tooltip' => __( 'Automatically calculate the value of this field based on values from other fields.', 'formidable' ),
343 408 ),
344 409 'get_values_field' => array(
345 - 'class' => 'frm_show_upgrade frm_noallow',
346 - 'title' => __( 'Default Value (Lookup)', 'formidable' ),
347 - 'icon' => 'frm_icon_font frm_search_icon',
348 - 'data' => array(
410 + 'class' => 'frm_show_upgrade frm_noallow',
411 + 'title' => __( 'Lookup', 'formidable' ),
412 + 'icon' => 'frm_icon_font frm_search_icon',
413 + 'data' => array(
349 414 'medium' => 'lookup',
350 415 'upgrade' => __( 'Lookup fields', 'formidable' ),
351 416 ),
417 + 'tooltip' => __( 'Dynamically retrieve the value of this field from a lookup field.', 'formidable' ),
352 418 ),
353 419 );
354 420
355 421 $types = apply_filters( 'frm_default_value_types', $types, $atts );
356 422
357 - if ( FrmAppHelper::pro_is_installed() && ! FrmAppHelper::meets_min_pro_version( '4.0' ) ) {
358 - // Prevent settings from showing in 2 spots.
359 - unset( $types['calc'], $types['get_values_field'] );
360 - }
361 -
362 423 // Set active class.
363 424 $settings = array_keys( $types );
364 425 $active = 'default_value';
365 426
366 - foreach ( $settings as $type ) {
367 - if ( ! empty( $field[ $type ] ) ) {
368 - $active = $type;
427 + if ( FrmAppHelper::pro_is_connected() ) {
428 + foreach ( $settings as $type ) {
429 + if ( ! empty( $field[ $type ] ) ) {
430 + $active = $type;
431 + }
369 432 }
370 433 }
371 434
372 435 $types[ $active ]['class'] .= ' current';
@@ -374,8 +437,12 @@
374 437
375 438 return $types;
376 439 }
377 440
441 + /**
442 + * @param string $type
443 + * @return string
444 + */
378 445 public static function change_type( $type ) {
379 446 $type_switch = array(
380 447 'scale' => 'radio',
381 448 'star' => 'radio',
@@ -388,10 +455,13 @@
388 455 $type = $type_switch[ $type ];
389 456 }
390 457
391 458 $pro_fields = FrmField::pro_field_selection();
392 - $types = array_keys( $pro_fields );
393 - if ( in_array( $type, $types ) ) {
459 + // We want to keep credit_card types as credit card types for Stripe Lite.
460 + // The credit_card key is set for backward compatibility.
461 + unset( $pro_fields['credit_card'] );
462 +
463 + if ( array_key_exists( $type, $pro_fields ) ) {
394 464 $type = 'text';
395 465 }
396 466
397 467 return $type;
@@ -397,16 +467,18 @@
397 467 return $type;
398 468 }
399 469
400 470 /**
401 - * @param array $settings
402 - * @param object $field_info
471 + * @param array $settings
472 + * @param FrmFieldType|null $field_info
403 473 *
404 474 * @return array
405 475 */
406 476 public static function display_field_options( $settings, $field_info = null ) {
407 477 if ( $field_info ) {
408 - $settings = $field_info->display_field_settings();
478 + $settings = $field_info->display_field_settings();
479 +
480 + // Field appears to be protected but there is a __get function in FrmFieldType that makes this public.
409 481 $settings['field_data'] = $field_info->field;
410 482 }
411 483
412 484 return apply_filters( 'frm_display_field_options', $settings );
@@ -416,12 +488,23 @@
416 488 * Display the format option
417 489 *
418 490 * @since 3.0
419 491 *
420 - * @param array $field
492 + * @param array $field Field data.
493 + * @param bool $is_hidden Whether the format option should be hidden.
494 + * @return void
421 495 */
422 - public static function show_format_option( $field ) {
423 - include( FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/value-format.php' );
496 + public static function show_format_option( $field, $is_hidden = false ) {
497 + $attributes = array(
498 + 'class' => 'frm-has-modal',
499 + 'id' => 'frm-field-format-custom-' . $field['id'],
500 + );
501 +
502 + if ( $is_hidden ) {
503 + $attributes['class'] .= ' frm_hidden';
504 + }
505 +
506 + include FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/value-format.php';
424 507 }
425 508
426 509 public static function input_html( $field, $echo = true ) {
427 510 $class = array();
@@ -449,14 +532,19 @@
449 532
450 533 return $add_html;
451 534 }
452 535
536 + /**
537 + * @param array $field
538 + * @param array $class
539 + * @return void
540 + */
453 541 private static function add_input_classes( $field, array &$class ) {
454 - if ( isset( $field['input_class'] ) && ! empty( $field['input_class'] ) ) {
542 + if ( ! empty( $field['input_class'] ) ) {
455 543 $class[] = $field['input_class'];
456 544 }
457 545
458 - if ( $field['type'] == 'hidden' || $field['type'] == 'user_id' ) {
546 + if ( $field['type'] === 'hidden' || $field['type'] === 'user_id' ) {
459 547 return;
460 548 }
461 549
462 550 if ( isset( $field['size'] ) && $field['size'] > 0 ) {
@@ -463,8 +551,13 @@
463 551 $class[] = 'auto_width';
464 552 }
465 553 }
466 554
555 + /**
556 + * @param array $field
557 + * @param array $add_html
558 + * @return void
559 + */
467 560 private static function add_html_size( $field, array &$add_html ) {
468 561 $size_fields = array(
469 562 'select',
470 563 'data',
@@ -473,9 +566,9 @@
473 566 'file',
474 567 'lookup',
475 568 );
476 569
477 - if ( ! isset( $field['size'] ) || $field['size'] <= 0 || in_array( $field['type'], $size_fields ) ) {
570 + if ( ! isset( $field['size'] ) || $field['size'] <= 0 || in_array( $field['type'], $size_fields, true ) ) {
478 571 return;
479 572 }
480 573
481 574 if ( FrmAppHelper::is_admin_page( 'formidable' ) ) {
@@ -492,10 +585,15 @@
492 585
493 586 self::add_html_cols( $field, $add_html );
494 587 }
495 588
589 + /**
590 + * @param array $field
591 + * @param array $add_html
592 + * @return void
593 + */
496 594 private static function add_html_cols( $field, array &$add_html ) {
497 - if ( ! in_array( $field['type'], array( 'textarea', 'rte' ) ) ) {
595 + if ( ! in_array( $field['type'], array( 'textarea', 'rte' ), true ) ) {
498 596 return;
499 597 }
500 598
501 599 // Convert to cols for textareas.
@@ -517,8 +615,13 @@
517 615
518 616 $add_html['cols'] = 'cols="' . absint( $size ) . '"';
519 617 }
520 618
619 + /**
620 + * @param array $field
621 + * @param array $add_html
622 + * @return void
623 + */
521 624 private static function add_html_length( $field, array &$add_html ) {
522 625 // Check for max setting and if this field accepts maxlength.
523 626 $fields = array(
524 627 'textarea',
@@ -526,9 +629,9 @@
526 629 'hidden',
527 630 'file',
528 631 );
529 632
530 - if ( FrmField::is_option_empty( $field, 'max' ) || in_array( $field['type'], $fields ) ) {
633 + if ( FrmField::is_option_empty( $field, 'max' ) || in_array( $field['type'], $fields, true ) ) {
531 634 return;
532 635 }
533 636
534 637 if ( FrmAppHelper::is_admin_page( 'formidable' ) ) {
@@ -538,8 +641,14 @@
538 641
539 642 $add_html['maxlength'] = 'maxlength="' . esc_attr( $field['max'] ) . '"';
540 643 }
541 644
645 + /**
646 + * @param array $field
647 + * @param array $add_html
648 + * @param array $class
649 + * @return void
650 + */
542 651 private static function add_html_placeholder( $field, array &$add_html, array &$class ) {
543 652 if ( $field['default_value'] != '' ) {
544 653 if ( is_array( $field['default_value'] ) ) {
545 654 $add_html['data-frmval'] = 'data-frmval="' . esc_attr( json_encode( $field['default_value'] ) ) . '"';
@@ -553,21 +662,9 @@
553 662 // don't include a json placeholder
554 663 return;
555 664 }
556 665
557 - $frm_settings = FrmAppHelper::get_settings();
558 -
559 - if ( $frm_settings->use_html ) {
560 - self::add_placeholder_to_input( $field, $add_html );
561 - } else {
562 - self::add_frmval_to_input( $field, $add_html );
563 -
564 - $class[] = 'frm_toggle_default';
565 -
566 - if ( $field['value'] == $field['placeholder'] ) {
567 - $class[] = 'frm_default';
568 - }
569 - }
666 + self::add_placeholder_to_input( $field, $add_html );
570 667 }
571 668
572 669 /**
573 670 * Prepares field placeholder.
@@ -610,14 +707,26 @@
610 707 if ( empty( $placeholder ) ) {
611 708 $placeholder = self::get_default_value_from_name( $field );
612 709 }
613 710
711 + $use_placeholder = $placeholder;
712 + $autocomplete = FrmField::get_option( $field, 'autocom' );
713 +
714 + if ( $autocomplete ) {
715 + $use_chosen = ! is_callable( 'FrmProAppHelper::use_chosen_js' ) || FrmProAppHelper::use_chosen_js();
716 + if ( $use_chosen ) {
717 + $use_placeholder = '';
718 + }
719 + }
720 +
614 721 if ( $placeholder !== '' ) {
615 - ?>
616 - <option value="">
617 - <?php echo esc_html( FrmField::get_option( $field, 'autocom' ) ? '' : $placeholder ); ?>
618 - </option>
619 - <?php
722 + $placeholder_attributes = array(
723 + 'class' => 'frm-select-placeholder',
724 + 'value' => '',
725 + 'data-placeholder' => 'true',
726 + );
727 +
728 + FrmHtmlHelper::echo_dropdown_option( $use_placeholder, false, $placeholder_attributes );
620 729 return true;
621 730 }
622 731
623 732 return false;
@@ -623,12 +732,13 @@
623 732 return false;
624 733 }
625 734
626 735 /**
627 - * Use HMTL5 placeholder with js fallback
736 + * Use HTML5 placeholder with js fallback.
628 737 *
629 738 * @param array $field
630 739 * @param array $add_html
740 + * @return void
631 741 */
632 742 private static function add_placeholder_to_input( $field, &$add_html ) {
633 743 if ( FrmFieldsHelper::is_placeholder_field_type( $field['type'] ) ) {
634 744 $add_html['placeholder'] = 'placeholder="' . esc_attr( $field['placeholder'] ) . '"';
@@ -634,8 +744,13 @@
634 744 $add_html['placeholder'] = 'placeholder="' . esc_attr( $field['placeholder'] ) . '"';
635 745 }
636 746 }
637 747
748 + /**
749 + * @param array $field
750 + * @param array $add_html
751 + * @return void
752 + */
638 753 private static function add_frmval_to_input( $field, &$add_html ) {
639 754 if ( $field['placeholder'] != '' ) {
640 755 $add_html['data-frmval'] = 'data-frmval="' . esc_attr( $field['placeholder'] ) . '"';
641 756
@@ -649,15 +764,17 @@
649 764 }
650 765 }
651 766
652 767 private static function add_validation_messages( $field, array &$add_html ) {
653 - if ( FrmField::is_required( $field ) ) {
768 + $field_validation_messages_status = self::get_validation_data_attribute_visibility_info( $field );
769 +
770 + if ( FrmField::is_required( $field ) && ! empty( $field_validation_messages_status['data-reqmsg'] ) ) {
654 771 $required_message = FrmFieldsHelper::get_error_msg( $field, 'blank' );
655 772 $add_html['data-reqmsg'] = 'data-reqmsg="' . esc_attr( $required_message ) . '"';
656 773 self::maybe_add_html_required( $field, $add_html );
657 774 }
658 775
659 - if ( ! FrmField::is_option_empty( $field, 'invalid' ) ) {
776 + if ( ! FrmField::is_option_empty( $field, 'invalid' ) && ! empty( $field_validation_messages_status['data-invmsg'] ) ) {
660 777 $invalid_message = FrmFieldsHelper::get_error_msg( $field, 'invalid' );
661 778 $add_html['data-invmsg'] = 'data-invmsg="' . esc_attr( $invalid_message ) . '"';
662 779 }
663 780
@@ -666,12 +783,45 @@
666 783 }
667 784 }
668 785
669 786 /**
787 + * Returns an array that contains field validation messages status.
788 + *
789 + * @since 6.9
790 + *
791 + * @param array|object $field
792 + * @return array
793 + */
794 + private static function get_validation_data_attribute_visibility_info( $field ) {
795 + if ( FrmField::get_field_type( $field ) === 'hidden' ) {
796 + $field_validation_data_attributes = array(
797 + 'data-invmsg' => false,
798 + 'data-reqmsg' => false,
799 + );
800 + } else {
801 + $field_validation_data_attributes = array(
802 + 'data-invmsg' => true,
803 + 'data-reqmsg' => true,
804 + );
805 + }
806 +
807 + /**
808 + * Allows controlling which field validation messages would be included in the field html.
809 + *
810 + * @since 6.9
811 + *
812 + * @param array $field_validation_messages_status
813 + * @param array|object $field
814 + */
815 + return apply_filters( 'frm_field_validation_include_data_attributes', $field_validation_data_attributes, $field );
816 + }
817 +
818 + /**
670 819 * @since 5.0.03
671 820 *
672 821 * @param array $field
673 822 * @param array $add_html
823 + * @return void
674 824 */
675 825 private static function maybe_add_error_html_for_js_validation( $field, array &$add_html ) {
676 826 $form = self::get_form_for_js_validation( $field );
677 827 if ( false === $form ) {
@@ -688,9 +838,9 @@
688 838 /**
689 839 * @since 5.0.03
690 840 *
691 841 * @param array $field
692 - * @return stdClass|false false if there is no form object found with JS validation active.
842 + * @return false|stdClass false if there is no form object found with JS validation active.
693 843 */
694 844 private static function get_form_for_js_validation( $field ) {
695 845 global $frm_vars;
696 846 if ( ! empty( $frm_vars['js_validate_forms'] ) ) {
@@ -707,9 +857,9 @@
707 857 /**
708 858 * @param stdClass $form
709 859 * @param array $field
710 860 * @param array $errors
711 - * @return string|false
861 + * @return false|string
712 862 */
713 863 public static function pull_custom_error_body_from_custom_html( $form, $field, $errors = array() ) {
714 864 if ( empty( $field['custom_html'] ) ) {
715 865 return false;
@@ -750,8 +900,9 @@
750 900 *
751 901 * @since 3.06.01
752 902 * @param array $field
753 903 * @param array $add_html
904 + * @return void
754 905 */
755 906 private static function maybe_add_html_required( $field, array &$add_html ) {
756 907 $excluded_field_types =
757 908 FrmField::is_radio( $field ) ||
@@ -763,14 +914,16 @@
763 914 if ( $excluded_field_types ) {
764 915 return;
765 916 }
766 917
767 - $include_html = FrmAppHelper::meets_min_pro_version( '3.06.01' );
768 - if ( $include_html ) {
769 - $add_html['aria-required'] = 'aria-required="true"';
770 - }
918 + $add_html['aria-required'] = 'aria-required="true"';
771 919 }
772 920
921 + /**
922 + * @param array $field
923 + * @param array $add_html
924 + * @return void
925 + */
773 926 private static function add_shortcodes_to_html( $field, array &$add_html ) {
774 927 if ( FrmField::is_option_empty( $field, 'shortcodes' ) ) {
775 928 return;
776 929 }
@@ -779,9 +932,19 @@
779 932 unset( $field['shortcodes']['autocomplete'] );
780 933 }
781 934
782 935 foreach ( $field['shortcodes'] as $k => $v ) {
783 - if ( 'opt' === $k ) {
936 + if ( isset( $field['subfield_name'] ) && 0 === strpos( $k, 'aria-invalid' ) ) {
937 + $subfield_name = $field['subfield_name'];
938 + if ( ! isset( $field['shortcodes'][ 'aria-invalid-' . $subfield_name ] ) ) {
939 + continue;
940 + }
941 + // Change the key to the correct aria-invalid value so that $add_html is set correctly for the current subfield of a combo field.
942 + $k = 'aria-invalid';
943 + $v = $field['shortcodes'][ 'aria-invalid-' . $subfield_name ];
944 + unset( $field['shortcodes'][ 'aria-invalid-' . $subfield_name ] );
945 + }
946 + if ( 'opt' === $k || ! self::should_allow_input_attribute( $k ) ) {
784 947 continue;
785 948 }
786 949
787 950 if ( is_numeric( $k ) && strpos( $v, '=' ) ) {
@@ -792,32 +955,45 @@
792 955 $add_html[ $k ] = $k . '="' . esc_attr( $v ) . '"';
793 956 }
794 957
795 958 unset( $k, $v );
959 + }//end foreach
960 + }
961 +
962 + /**
963 + * Disallow possibly unsafe attributees (that trigger JavaScript) when unasfe HTML is not allowed.
964 + *
965 + * @since 6.11.2
966 + *
967 + * @param string $key The option key.
968 + * @return bool
969 + */
970 + private static function should_allow_input_attribute( $key ) {
971 + if ( ! FrmAppHelper::should_never_allow_unfiltered_html() ) {
972 + return true;
796 973 }
974 + return FrmAppHelper::input_key_is_safe( $key );
797 975 }
798 976
799 977 /**
800 - * Add pattern attribute
978 + * Add pattern attribute.
801 979 *
802 980 * @since 3.0
803 981 *
804 982 * @param array $field
805 983 * @param array $add_html
984 + * @return void
806 985 */
807 986 private static function add_pattern_attribute( $field, array &$add_html ) {
808 - $has_format = FrmField::is_option_true_in_array( $field, 'format' );
987 + $format_value = FrmField::get_option( $field, 'format' );
988 + $has_format = $format_value && ! FrmCurrencyHelper::is_currency_format( $format_value );
809 989 $format_field = FrmField::is_field_type( $field, 'text' );
810 990
811 - if ( $field['type'] == 'phone' || ( $has_format && $format_field ) ) {
812 - $frm_settings = FrmAppHelper::get_settings();
991 + if ( $field['type'] === 'phone' || ( $has_format && $format_field ) ) {
992 + $format = FrmEntryValidate::phone_format( $field );
993 + $format = substr( $format, 2, - 1 );
813 994
814 - if ( $frm_settings->use_html ) {
815 - $format = FrmEntryValidate::phone_format( $field );
816 - $format = substr( $format, 2, - 1 );
817 -
818 - $add_html['pattern'] = 'pattern="' . esc_attr( $format ) . '"';
819 - }
995 + $add_html['pattern'] = 'pattern="' . esc_attr( $format ) . '"';
820 996 }
821 997 }
822 998
823 999 public static function check_value( $opt, $opt_key, $field ) {
@@ -833,88 +1009,10 @@
833 1009 }
834 1010
835 1011 public static function check_label( $opt ) {
836 1012 if ( is_array( $opt ) ) {
837 - $opt = ( isset( $opt['label'] ) ? $opt['label'] : reset( $opt ) );
1013 + $opt = isset( $opt['label'] ) ? $opt['label'] : reset( $opt );
838 1014 }
839 1015
840 1016 return $opt;
841 - }
842 -
843 - /**
844 - * @deprecated 4.0
845 - */
846 - public static function update_ajax_option() {
847 - _deprecated_function( __METHOD__, '4.0' );
848 - FrmAppHelper::permission_check( 'frm_edit_forms' );
849 - check_ajax_referer( 'frm_ajax', 'nonce' );
850 -
851 - $field_id = FrmAppHelper::get_post_param( 'field', 0, 'absint' );
852 - if ( ! $field_id ) {
853 - wp_die();
854 - }
855 -
856 - $field = FrmField::getOne( $field_id );
857 -
858 - if ( isset( $_POST['separate_value'] ) ) {
859 - $new_val = FrmField::is_option_true( $field, 'separate_value' ) ? 0 : 1;
860 -
861 - $field->field_options['separate_value'] = $new_val;
862 - unset( $new_val );
863 - }
864 -
865 - FrmField::update(
866 - $field_id,
867 - array(
868 - 'field_options' => $field->field_options,
869 - 'form_id' => $field->form_id,
870 - )
871 - );
872 - wp_die();
873 - }
874 -
875 - /**
876 - * @deprecated 4.0
877 - */
878 - public static function import_choices() {
879 - _deprecated_function( __METHOD__, '4.0' );
880 - wp_die();
881 - }
882 -
883 - /**
884 - * Add Single Option or Other Option.
885 - *
886 - * @deprecated 4.0 Moved to Pro for Other option only.
887 - */
888 - public static function add_option() {
889 - _deprecated_function( __METHOD__, '4.0', 'FrmProFieldsController::add_other_option' );
890 - }
891 -
892 - /**
893 - * @deprecated 4.0
894 - */
895 - public static function update_order() {
896 - FrmDeprecated::update_order();
897 - }
898 -
899 - /**
900 - * @deprecated 3.0
901 - * @codeCoverageIgnore
902 - */
903 - public static function edit_name( $field = 'name', $id = '' ) {
904 - FrmDeprecated::edit_name( $field, $id );
905 - }
906 -
907 - /**
908 - * @deprecated 3.0
909 - * @codeCoverageIgnore
910 - *
911 - * @param int $field_id
912 - * @param array $values
913 - * @param int $form_id
914 - *
915 - * @return array
916 - */
917 - public static function include_single_field( $field_id, $values, $form_id = 0 ) {
918 - return FrmDeprecated::include_single_field( $field_id, $values, $form_id );
919 1017 }
920 1018 }