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/helpers/FrmFieldsHelper.php +700 -208 6.25 → trunk View file →
@@ -11,11 +11,16 @@
11 11 * @var bool|null
12 12 */
13 13 private static $context_is_safe_to_load_field_options_from_request_data;
14 14
15 + /**
16 + * @param string $type
17 + * @param int|string $form_id
18 + *
19 + * @return array
20 + */
15 21 public static function setup_new_vars( $type = '', $form_id = '' ) {
16 -
17 - if ( strpos( $type, '|' ) ) {
22 + if ( str_contains( $type, '|' ) ) {
18 23 list( $type, $setting ) = explode( '|', $type );
19 24 }
20 25
21 26 $values = self::get_default_field( $type );
@@ -42,31 +47,39 @@
42 47 }
43 48 }
44 49
45 50 // Increase the field order of submit field and fields in the same row.
46 - $last_row_field_ids = FrmAppHelper::get_post_param( 'last_row_field_ids', array() );
47 - if ( $last_row_field_ids ) {
48 - foreach ( $last_row_field_ids as $index => $last_row_field_id ) {
49 - FrmField::update(
50 - $last_row_field_id,
51 - array( 'field_order' => $field_count + $index + 2 )
52 - );
53 - }
54 - }
51 + FrmSubmitHelper::update_last_row_fields_order_when_adding_field( $field_count );
55 52
56 53 return $values;
57 54 }
58 55
56 + /**
57 + * @param array $field
58 + * @param string $plus
59 + *
60 + * @return string
61 + */
59 62 public static function get_html_id( $field, $plus = '' ) {
60 63 return apply_filters( 'frm_field_html_id', 'field_' . $field['field_key'] . $plus, $field );
61 64 }
62 65
66 + /**
67 + * @param object $field
68 + * @param bool $doing_ajax
69 + *
70 + * @return array
71 + */
63 72 public static function setup_edit_vars( $field, $doing_ajax = false ) {
64 73 $values = self::field_object_to_array( $field );
65 -
66 74 return apply_filters( 'frm_setup_edit_field_vars', $values, array( 'doing_ajax' => $doing_ajax ) );
67 75 }
68 76
77 + /**
78 + * @param object $field
79 + *
80 + * @return array
81 + */
69 82 public static function field_object_to_array( $field ) {
70 83 $values = (array) $field;
71 84
72 85 self::fill_field_array( $field, $values );
@@ -75,8 +88,14 @@
75 88
76 89 return $values;
77 90 }
78 91
92 + /**
93 + * @param object $field
94 + * @param array $field_array
95 + *
96 + * @return void
97 + */
79 98 private static function fill_field_array( $field, array &$field_array ) {
80 99 $field_array['options'] = $field->options;
81 100 $field_array['value'] = $field->default_value;
82 101
@@ -85,11 +104,17 @@
85 104 $field_array = array_merge( (array) $field->field_options, $field_array );
86 105 }
87 106
88 107 /**
89 - * Prepare field while creating a new entry
108 + * Prepare field while creating a new entry.
90 109 *
91 110 * @since 3.0
111 + *
112 + * @param array $field_array Field values array, passed by reference.
113 + * @param stdClass $field Field object.
114 + * @param array $args Additional arguments.
115 + *
116 + * @return void
92 117 */
93 118 public static function prepare_new_front_field( &$field_array, $field, $args = array() ) {
94 119 $args['action'] = 'new';
95 120 self::prepare_front_field( $field_array, $field, $args );
@@ -95,11 +120,18 @@
95 120 self::prepare_front_field( $field_array, $field, $args );
96 121 }
97 122
98 123 /**
99 - * Prepare field while editing an entry
124 + * Prepare field while editing an entry.
100 125 *
101 126 * @since 3.0
127 + *
128 + * @param array $field_array Field values array, passed by reference.
129 + * @param array|stdClass $field Field object or array.
130 + * @param int $entry_id Entry ID.
131 + * @param array $args Additional arguments.
132 + *
133 + * @return void
102 134 */
103 135 public static function prepare_edit_front_field( &$field_array, $field, $entry_id = 0, $args = array() ) {
104 136 $args['entry_id'] = $entry_id;
105 137 $args['action'] = 'edit';
@@ -113,8 +145,9 @@
113 145 *
114 146 * @param array $field_array
115 147 * @param stdClass $field
116 148 * @param array $args
149 + *
117 150 * @return void
118 151 */
119 152 private static function prepare_front_field( &$field_array, $field, $args ) {
120 153 self::fill_default_field_opts( $field, $field_array );
@@ -132,16 +165,18 @@
132 165 * @param int|string $entry_id
133 166 * @param array $args
134 167 */
135 168 $field_array = apply_filters( 'frm_setup_edit_fields_vars', $field_array, $field, $args['entry_id'], $args );
136 - } else {
137 - /**
138 - * @param array $field_array
139 - * @param stdClass $field
140 - * @param array $args
141 - */
142 - $field_array = apply_filters( 'frm_setup_new_fields_vars', $field_array, $field, $args );
169 +
170 + return;
143 171 }
172 +
173 + /**
174 + * @param array $field_array
175 + * @param stdClass $field
176 + * @param array $args
177 + */
178 + $field_array = apply_filters( 'frm_setup_new_fields_vars', $field_array, $field, $args );
144 179 }
145 180
146 181 /**
147 182 * @since 3.0
@@ -151,9 +186,8 @@
151 186 * @return array
152 187 */
153 188 public static function get_default_field_options( $type ) {
154 189 $field_type = FrmFieldFactory::get_field_type( $type );
155 -
156 190 return $field_type->get_default_field_options();
157 191 }
158 192
159 193 /**
@@ -160,8 +194,10 @@
160 194 * @since 3.0
161 195 *
162 196 * @param object $field
163 197 * @param array $values
198 + *
199 + * @return void
164 200 */
165 201 private static function fill_default_field_opts( $field, array &$values ) {
166 202 $check_post = self::context_is_safe_to_load_field_options_from_request_data();
167 203 $defaults = self::get_default_field_options_from_field( $field, $values );
@@ -205,8 +241,9 @@
205 241 return false;
206 242 }
207 243
208 244 $action = FrmAppHelper::get_post_param( 'action', '', 'sanitize_title' );
245 +
209 246 if ( 'frm_forms_preview' === $action ) {
210 247 // Never trigger when previewing.
211 248 return false;
212 249 }
@@ -217,8 +254,9 @@
217 254 return wp_verify_nonce( $nonce, 'frm_save_form_nonce' );
218 255 }
219 256
220 257 $action = FrmAppHelper::get_post_param( 'frm_action', '', 'sanitize_title' );
258 +
221 259 if ( 'update_settings' === $action ) {
222 260 $nonce = FrmAppHelper::get_post_param( 'process_form', '', 'sanitize_text_field' );
223 261 return wp_verify_nonce( $nonce, 'process_form_nonce' );
224 262 }
@@ -236,10 +274,13 @@
236 274 * @since 3.0
237 275 *
238 276 * @param object $field
239 277 * @param array $field_array
278 + *
279 + * @return void
240 280 */
241 281 private static function fill_cleared_strings( $field, array &$field_array ) {
282 + // phpcs:ignore Universal.Operators.StrictComparisons
242 283 if ( '' == $field_array['blank'] && '1' === $field_array['required'] ) {
243 284 $field_array['blank'] = self::default_blank_msg();
244 285 }
245 286
@@ -251,8 +292,9 @@
251 292 $field_array['invalid'] = self::default_invalid_msg();
252 293 }
253 294 }
254 295
296 + // phpcs:ignore Universal.Operators.StrictComparisons
255 297 if ( '' == $field_array['custom_html'] ) {
256 298 $field_array['custom_html'] = self::get_default_html( $field->type );
257 299 }
258 300 }
@@ -274,10 +316,9 @@
274 316 */
275 317 public static function default_unique_msg() {
276 318 $frm_settings = FrmAppHelper::get_settings();
277 319 $unique_message = $frm_settings->unique_msg;
278 - $unique_message = str_replace( 'This value', '[field_name]', $unique_message );
279 - return $unique_message;
320 + return str_replace( 'This value', '[field_name]', $unique_message );
280 321 }
281 322
282 323 /**
283 324 * @since 6.8.3
@@ -286,10 +327,9 @@
286 327 */
287 328 public static function default_blank_msg() {
288 329 $frm_settings = FrmAppHelper::get_settings();
289 330 $blank_message = $frm_settings->blank_msg;
290 - $blank_message = str_replace( 'This field', '[field_name]', $blank_message );
291 - return $blank_message;
331 + return str_replace( 'This field', '[field_name]', $blank_message );
292 332 }
293 333
294 334 /**
295 335 * When loading settings for a field, check the $_POST data and possibly use that instead of the DB value.
@@ -297,8 +337,10 @@
297 337 * @since 3.0
298 338 *
299 339 * @param string $setting
300 340 * @param mixed $value
341 + *
342 + * @return void
301 343 */
302 344 private static function get_posted_field_setting( $setting, &$value ) {
303 345 if ( ! isset( $_POST['field_options'][ $setting ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
304 346 return;
@@ -303,20 +345,20 @@
303 345 if ( ! isset( $_POST['field_options'][ $setting ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
304 346 return;
305 347 }
306 348
307 - if ( strpos( $setting, 'html' ) !== false ) {
308 - $value = wp_unslash( $_POST['field_options'][ $setting ] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
349 + if ( str_contains( $setting, 'html' ) ) {
350 + $value = wp_unslash( $_POST['field_options'][ $setting ] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing, SlevomatCodingStandard.Files.LineLength.LineTooLong
309 351
310 352 // Conditionally strip script tags if the user sending $_POST data is not allowed to use unfiltered HTML.
311 353 if ( ! FrmAppHelper::allow_unfiltered_html() ) {
312 354 $value = FrmAppHelper::kses( $value, 'all' );
313 355 }
314 - } elseif ( strpos( $setting, 'format_' ) === 0 ) {
356 + } elseif ( str_starts_with( $setting, 'format_' ) ) {
315 357 // TODO: Remove stripslashes on output, and use on input only.
316 - $value = sanitize_text_field( $_POST['field_options'][ $setting ] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.NonceVerification.Missing
358 + $value = sanitize_text_field( $_POST['field_options'][ $setting ] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.NonceVerification.Missing, SlevomatCodingStandard.Files.LineLength.LineTooLong
317 359 } else {
318 - $value = wp_unslash( $_POST['field_options'][ $setting ] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
360 + $value = wp_unslash( $_POST['field_options'][ $setting ] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing, SlevomatCodingStandard.Files.LineLength.LineTooLong
319 361 FrmAppHelper::sanitize_value( 'wp_kses_post', $value );
320 362 }
321 363 }
322 364
@@ -330,13 +372,11 @@
330 372 */
331 373 public static function get_default_field_options_from_field( $field, $values = array() ) {
332 374 $field_type = self::get_original_field( $field );
333 375 $opts = $field_type->get_default_field_options();
376 + $opts = apply_filters( 'frm_default_field_opts', $opts, $values, $field );
334 377
335 - $opts = apply_filters( 'frm_default_field_opts', $opts, $values, $field );
336 - $opts = apply_filters( 'frm_default_' . $field->type . '_field_opts', $opts, $values, $field );
337 -
338 - return $opts;
378 + return apply_filters( 'frm_default_' . $field->type . '_field_opts', $opts, $values, $field );
339 379 }
340 380
341 381 /**
342 382 * @since 3.0
@@ -346,9 +386,10 @@
346 386 * @return FrmFieldType
347 387 */
348 388 private static function get_original_field( $field ) {
349 389 $original_type = FrmField::get_option( $field, 'original_type' );
350 - if ( ! empty( $original_type ) && $field->type != $original_type ) {
390 +
391 + if ( $original_type && $field->type !== $original_type ) {
351 392 $field->type = $original_type;
352 393 }
353 394
354 395 return FrmFieldFactory::get_field_object( $field );
@@ -359,8 +400,10 @@
359 400 *
360 401 * @param array $field_array
361 402 * @param object $field
362 403 * @param array $atts
404 + *
405 + * @return void
363 406 */
364 407 private static function prepare_field_options_for_display( &$field_array, $field, $atts ) {
365 408 $field_obj = FrmFieldFactory::get_field_object( $field );
366 409 $field_array = $field_obj->prepare_front_field( $field_array, $atts );
@@ -374,12 +417,19 @@
374 417 * @return array
375 418 */
376 419 public static function get_default_field( $type ) {
377 420 $field_type = FrmFieldFactory::get_field_type( $type );
378 -
379 421 return $field_type->get_new_field_defaults();
380 422 }
381 423
424 + /**
425 + * @param array $values
426 + * @param object $field
427 + * @param int|string $form_id
428 + * @param string $new_key
429 + *
430 + * @return void
431 + */
382 432 public static function fill_field( &$values, $field, $form_id, $new_key = '' ) {
383 433 global $wpdb;
384 434
385 435 $values['field_key'] = FrmAppHelper::get_unique_key( $new_key, $wpdb->prefix . 'frm_fields', 'field_key' );
@@ -401,11 +451,10 @@
401 451 * @return string
402 452 */
403 453 public static function get_error_msg( $field, $error ) {
404 454 $frm_settings = FrmAppHelper::get_settings();
405 -
406 - $conf_msg = __( 'The entered values do not match', 'formidable' );
407 - $defaults = array(
455 + $conf_msg = __( 'The entered values do not match', 'formidable' );
456 + $defaults = array(
408 457 'unique_msg' => array(
409 458 'full' => self::default_unique_msg(),
410 459 /* translators: %s: Field name */
411 460 'part' => sprintf( __( '%s must be unique', 'formidable' ), '[field_name]' ),
@@ -424,15 +473,21 @@
424 473 'part' => $conf_msg,
425 474 ),
426 475 );
427 476
477 + /**
478 + * @since 6.28
479 + *
480 + * @param array $defaults
481 + * @param array|object $field
482 + */
483 + $defaults = apply_filters( 'frm_default_field_validation_messages', $defaults, $field );
484 +
428 485 $msg = FrmField::get_option( $field, $error );
429 - $msg = empty( $msg ) ? $defaults[ $error ]['part'] : $msg;
486 + $msg = $msg ? $msg : $defaults[ $error ]['part'];
430 487 $msg = do_shortcode( $msg );
431 488
432 - $msg = self::maybe_replace_substrings_with_field_name( $msg, $error, $field );
433 -
434 - return $msg;
489 + return self::maybe_replace_substrings_with_field_name( $msg, $error, $field );
435 490 }
436 491
437 492 /**
438 493 * @since 6.8.3
@@ -439,8 +494,10 @@
439 494 *
440 495 * @param string $msg
441 496 * @param string $error
442 497 * @param array|object $field
498 + *
499 + * @return string
443 500 */
444 501 private static function maybe_replace_substrings_with_field_name( $msg, $error, $field ) {
445 502 $field_name = is_array( $field ) ? $field['name'] : $field->name;
446 503 $field_name = FrmAppHelper::maybe_kses( $field_name );
@@ -447,17 +504,12 @@
447 504 $substrings = self::get_substrings_to_replace_with_field_name( $field_name, compact( 'msg', 'error', 'field' ) );
448 505
449 506 // Use the "This value"/"This field" placeholder strings if field name is empty.
450 507 if ( ! $field_name ) {
451 - if ( 'unique_msg' === $error ) {
452 - $field_name = __( 'This value', 'formidable' );
453 - } else {
454 - $field_name = __( 'This field', 'formidable' );
455 - }
508 + $field_name = 'unique_msg' === $error ? __( 'This value', 'formidable' ) : __( 'This field', 'formidable' );
456 509 }
457 510
458 - $msg = str_replace( $substrings, $field_name, $msg );
459 - return $msg;
511 + return str_replace( $substrings, $field_name, $msg );
460 512 }
461 513
462 514 /**
463 515 * @since 6.8.3
@@ -469,12 +521,14 @@
469 521 * @type string $msg The current error message before the substrings are replaced.
470 522 * @type string $error A key including 'unique_msg', 'invalid', 'blank', or 'conf_msg'.
471 523 * @type array|object $field The field with the error.
472 524 * }
525 + *
473 526 * @return array
474 527 */
475 528 private static function get_substrings_to_replace_with_field_name( $field_name, $filter_args ) {
476 529 $substrings = array( '[field_name]' );
530 +
477 531 if ( $field_name ) {
478 532 array_push( $substrings, 'This value', 'This field' );
479 533 }
480 534
@@ -494,19 +548,32 @@
494 548
495 549 return $substrings;
496 550 }
497 551
552 + /**
553 + * @param int|string $form_id
554 + * @param array $error
555 + *
556 + * @return array
557 + */
498 558 public static function get_form_fields( $form_id, $error = array() ) {
499 559 $fields = FrmField::get_all_for_form( $form_id );
500 560
561 + FrmFieldName::track_first_name_field( $fields );
562 +
501 563 return apply_filters( 'frm_get_paged_fields', $fields, $form_id, $error );
502 564 }
503 565
566 + /**
567 + * @param string $type
568 + *
569 + * @return string
570 + */
504 571 public static function get_default_html( $type = 'text' ) {
505 572 $field = FrmFieldFactory::get_field_type( $type );
506 573 $default_html = $field->default_html();
507 574
508 - // these hooks are here for reverse compatibility since 3.0
575 + // These hooks are here for reverse compatibility since 3.0
509 576 if ( ! apply_filters( 'frm_normal_field_type_html', true, $type ) ) {
510 577 $default_html = apply_filters( 'frm_other_custom_html', '', $type );
511 578 }
512 579
@@ -517,11 +584,17 @@
517 584 * @param array $fields
518 585 * @param array $errors
519 586 * @param object $form
520 587 * @param object $form_action
588 + *
589 + * @return void
521 590 */
522 591 public static function show_fields( $fields, $errors, $form, $form_action ) {
523 592 foreach ( $fields as $field ) {
593 + if ( ! is_array( $field ) ) {
594 + continue;
595 + }
596 +
524 597 $field_obj = FrmFieldFactory::get_field_type( $field['type'], $field );
525 598 $field_obj->show_field( compact( 'errors', 'form', 'form_action' ) );
526 599 }
527 600 }
@@ -530,17 +603,23 @@
530 603 * @since 3.0
531 604 *
532 605 * @param array $atts
533 606 * @param array|string $value
607 + *
608 + * @return void
534 609 */
535 610 public static function run_wpautop( $atts, &$value ) {
536 611 $autop = $atts['wpautop'] ?? true;
537 - if ( apply_filters( 'frm_use_wpautop', $autop ) ) {
538 - if ( is_array( $value ) ) {
539 - $value = implode( "\n", $value );
540 - }
541 - $value = wpautop( $value );
612 +
613 + if ( ! apply_filters( 'frm_use_wpautop', $autop ) ) {
614 + return;
542 615 }
616 +
617 + if ( is_array( $value ) ) {
618 + $value = implode( "\n", $value );
619 + }
620 +
621 + $value = wpautop( $value );
543 622 }
544 623
545 624 /**
546 625 * Get the class to use for the label position
@@ -545,13 +624,19 @@
545 624 /**
546 625 * Get the class to use for the label position
547 626 *
548 627 * @since 2.05
628 + *
629 + * @param string $position
630 + * @param array $field
631 + * @param bool|object|string $form
632 + *
633 + * @return string
549 634 */
550 - public static function &label_position( $position, $field, $form ) {
551 - if ( $position && $position != '' ) {
635 + public static function label_position( $position, $field, $form ) {
636 + if ( $position ) {
552 637 if ( $position === 'inside' && ! self::is_placeholder_field_type( $field['type'] ) ) {
553 - $position = 'top';
638 + return 'top';
554 639 }
555 640
556 641 return $position;
557 642 }
@@ -556,8 +641,9 @@
556 641 return $position;
557 642 }
558 643
559 644 $position = FrmStylesController::get_style_val( 'position', $form );
645 +
560 646 if ( $position === 'none' ) {
561 647 $position = 'top';
562 648 } elseif ( $position === 'no_label' ) {
563 649 $position = 'none';
@@ -565,11 +651,9 @@
565 651 $position = 'top';
566 652 }
567 653
568 654 $position = apply_filters( 'frm_html_label_position', $position, $field, $form );
569 - $position = ! empty( $position ) ? $position : 'top';
570 -
571 - return $position;
655 + return $position ? $position : 'top';
572 656 }
573 657
574 658 /**
575 659 * Check if this field type allows placeholders
@@ -574,9 +658,11 @@
574 658 /**
575 659 * Check if this field type allows placeholders
576 660 *
577 661 * @since 2.05
662 + *
578 663 * @param string $type
664 + *
579 665 * @return bool
580 666 */
581 667 public static function is_placeholder_field_type( $type ) {
582 668 return ! in_array( $type, array( 'radio', 'checkbox', 'hidden', 'file' ), true );
@@ -581,11 +667,19 @@
581 667 public static function is_placeholder_field_type( $type ) {
582 668 return ! in_array( $type, array( 'radio', 'checkbox', 'hidden', 'file' ), true );
583 669 }
584 670
671 + /**
672 + * @param array $field
673 + * @param int|string $opt_key
674 + * @param string $type
675 + *
676 + * @return string
677 + */
585 678 public static function get_checkbox_id( $field, $opt_key, $type = 'checkbox' ) {
586 679 $id = $field['id'];
587 - if ( isset( $field['in_section'] ) && $field['in_section'] && ! FrmAppHelper::is_admin_page( 'formidable' ) ) {
680 +
681 + if ( ! empty( $field['in_section'] ) && ! FrmAppHelper::is_admin_page( 'formidable' ) ) {
588 682 $id .= '-' . $field['in_section'];
589 683 }
590 684
591 685 return 'frm_' . $type . '_' . $id . '-' . $opt_key;
@@ -590,8 +684,13 @@
590 684
591 685 return 'frm_' . $type . '_' . $id . '-' . $opt_key;
592 686 }
593 687
688 + /**
689 + * @param array $field
690 + *
691 + * @return void
692 + */
594 693 public static function show_single_option( $field ) {
595 694 self::hidden_field_option( $field );
596 695
597 696 if ( ! is_array( $field['options'] ) ) {
@@ -597,21 +696,20 @@
597 696 if ( ! is_array( $field['options'] ) ) {
598 697 return;
599 698 }
600 699
601 - $base_name = 'default_value_' . $field['id'];
602 - $html_id = $field['html_id'] ?? self::get_html_id( $field );
603 -
700 + $base_name = 'default_value_' . $field['id'];
701 + $html_id = $field['html_id'] ?? self::get_html_id( $field );
604 702 $default_type = self::get_default_value_type( $field );
605 703 $options_count = count( $field['options'] );
606 704
607 705 foreach ( $field['options'] as $opt_key => $opt ) {
608 - $field_val = self::get_value_from_array( $opt, $opt_key, $field );
609 - $opt = self::get_label_from_array( $opt, $opt_key, $field );
610 -
706 + $field_val = self::get_value_from_array( $opt, $opt_key, $field );
707 + $opt = self::get_label_from_array( $opt, $opt_key, $field );
611 708 $field_name = $base_name . ( $default_type === 'checkbox' ? '[' . $opt_key . ']' : '' );
612 709
613 - $checked = ( isset( $field['default_value'] ) && ( ( ! is_array( $field['default_value'] ) && $field['default_value'] == $field_val ) || ( is_array( $field['default_value'] ) && in_array( $field_val, $field['default_value'] ) ) ) );
710 + // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict, Universal.Operators.StrictComparisons, SlevomatCodingStandard.Files.LineLength.LineTooLong
711 + $checked = isset( $field['default_value'] ) && ( is_array( $field['default_value'] ) ? in_array( $field_val, $field['default_value'] ) : $field['default_value'] == $field_val );
614 712
615 713 // If this is an "Other" option, get the HTML for it.
616 714 if ( self::is_other_opt( $opt_key ) ) {
617 715 if ( FrmAppHelper::pro_is_installed() ) {
@@ -628,26 +726,29 @@
628 726 /**
629 727 * Include hidden row for javascript to duplicate.
630 728 *
631 729 * @since 4.0
730 + *
632 731 * @param array $field
732 + *
733 + * @return void
633 734 */
634 735 private static function hidden_field_option( $field ) {
635 736 // Don't duplicate during an ajax add option.
636 737 $ajax_action = FrmAppHelper::get_param( 'action', '', 'post', 'sanitize_text_field' );
738 +
637 739 if ( $ajax_action === 'frm_add_field_option' ) {
638 740 return;
639 741 }
640 742
641 - $opt_key = '000';
642 - $field_val = __( 'New Option', 'formidable' );
643 - $opt = __( 'New Option', 'formidable' );
644 - $checked = false;
645 - $field_name = 'default_value_' . $field['id'];
646 - $html_id = $field['html_id'] ?? self::get_html_id( $field );
647 -
743 + $opt_key = '000';
744 + $field_val = __( 'New Option', 'formidable' );
745 + $opt = __( 'New Option', 'formidable' );
746 + $checked = false;
747 + $field_name = 'default_value_' . $field['id'];
748 + $html_id = $field['html_id'] ?? self::get_html_id( $field );
648 749 $default_type = self::get_default_value_type( $field );
649 - $field_name .= ( $default_type === 'checkbox' ? '[' . $opt_key . ']' : '' );
750 + $field_name .= $default_type === 'checkbox' ? '[' . $opt_key . ']' : '';
650 751
651 752 require FrmAppHelper::plugin_path() . '/classes/views/frm-fields/single-option.php';
652 753 }
653 754
@@ -654,27 +755,39 @@
654 755 /**
655 756 * @since 4.0
656 757 *
657 758 * @param array $field
759 + *
658 760 * @return string radio or checkbox
659 761 */
660 762 private static function get_default_value_type( $field ) {
661 - $default_type = $field['type'];
662 763 if ( $field['type'] === 'select' ) {
663 - $default_type = FrmField::is_multiple_select( $field ) ? 'checkbox' : 'radio';
764 + return FrmField::is_multiple_select( $field ) ? 'checkbox' : 'radio';
664 765 }
665 - return $default_type;
766 + return $field['type'];
666 767 }
667 768
769 + /**
770 + * @param array|string $opt
771 + * @param int|string $opt_key
772 + * @param array $field
773 + *
774 + * @return mixed
775 + */
668 776 public static function get_value_from_array( $opt, $opt_key, $field ) {
669 777 $opt = apply_filters( 'frm_field_value_saved', $opt, $opt_key, $field );
670 -
671 778 return FrmFieldsController::check_value( $opt, $opt_key, $field );
672 779 }
673 780
781 + /**
782 + * @param array|string $opt
783 + * @param int|string $opt_key
784 + * @param array $field
785 + *
786 + * @return string
787 + */
674 788 public static function get_label_from_array( $opt, $opt_key, $field ) {
675 789 $opt = apply_filters( 'frm_field_label_seen', $opt, $opt_key, $field );
676 -
677 790 return FrmFieldsController::check_label( $opt );
678 791 }
679 792
680 793 /**
@@ -683,8 +796,10 @@
683 796 * @since 4.0
684 797 * @since 6.4.1 Added `inside_class` in the arguments.
685 798 *
686 799 * @param array $args The arguments.
800 + *
801 + * @return void
687 802 */
688 803 public static function inline_modal( $args ) {
689 804 $defaults = array(
690 805 'id' => '',
@@ -702,22 +817,29 @@
702 817 }
703 818
704 819 /**
705 820 * @since 4.0
821 + *
822 + * @return void
706 823 */
707 824 public static function smart_values() {
708 825 $continue = apply_filters( 'frm_smart_values_box', true );
709 - if ( $continue === true ) {
710 - $upgrade_link = array(
711 - 'medium' => 'builder',
712 - 'content' => 'smart-tags',
713 - );
714 - include FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/smart-values.php';
826 +
827 + if ( $continue !== true ) {
828 + return;
715 829 }
830 +
831 + $upgrade_link = array(
832 + 'medium' => 'builder',
833 + 'content' => 'smart-tags',
834 + );
835 + include FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/smart-values.php';
716 836 }
717 837
718 838 /**
719 839 * @since 4.0
840 + *
841 + * @return void
720 842 */
721 843 public static function input_mask() {
722 844 include FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/input-mask-info.php';
723 845 }
@@ -723,8 +845,10 @@
723 845 }
724 846
725 847 /**
726 848 * @since 4.0
849 + *
850 + * @return void
727 851 */
728 852 public static function layout_classes() {
729 853 include FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/layout-classes.php';
730 854 }
@@ -735,25 +859,30 @@
735 859 * @return string
736 860 */
737 861 public static function get_term_link( $tax_id ) {
738 862 $tax = get_taxonomy( $tax_id );
863 +
739 864 if ( ! $tax ) {
740 865 return '';
741 866 }
742 867
743 - $link = sprintf(
868 + return sprintf(
744 869 /* translators: %1$s: Start HTML link, %2$s: Content type label, %3$s: Content type, %4$s: End HTML link */
745 870 esc_html__( 'Options are dynamically created from your %1$s%2$s: %3$s%4$s', 'formidable' ),
746 871 '<a href="' . esc_url( admin_url( 'edit-tags.php?taxonomy=' . $tax->name ) ) . '" target="_blank">',
747 872 esc_html__( 'taxonomy', 'formidable' ),
748 - empty( $tax->labels->name ) ? esc_html__( 'Categories', 'formidable' ) : $tax->labels->name,
873 + ! empty( $tax->labels->name ) ? $tax->labels->name : esc_html__( 'Categories', 'formidable' ),
749 874 '</a>'
750 875 );
751 - unset( $tax );
752 -
753 - return $link;
754 876 }
755 877
878 + /**
879 + * @param array|string $observed_value
880 + * @param string $cond
881 + * @param array|string $hide_opt
882 + *
883 + * @return bool
884 + */
756 885 public static function value_meets_condition( $observed_value, $cond, $hide_opt ) {
757 886 $hide_opt = self::get_value_for_comparison( $hide_opt );
758 887 $observed_value = self::get_value_for_comparison( $observed_value );
759 888
@@ -761,12 +890,13 @@
761 890 return self::array_value_condition( $observed_value, $cond, $hide_opt );
762 891 }
763 892
764 893 $m = false;
894 +
765 895 if ( $cond === '==' ) {
766 - $m = $observed_value == $hide_opt;
896 + $m = $observed_value == $hide_opt; // phpcs:ignore Universal.Operators.StrictComparisons
767 897 } elseif ( $cond === '!=' ) {
768 - $m = $observed_value != $hide_opt;
898 + $m = $observed_value != $hide_opt; // phpcs:ignore Universal.Operators.StrictComparisons
769 899 } elseif ( $cond === '>' ) {
770 900 $m = $observed_value > $hide_opt;
771 901 } elseif ( $cond === '>=' ) {
772 902 $m = $observed_value >= $hide_opt;
@@ -775,20 +905,16 @@
775 905 } elseif ( $cond === '<=' ) {
776 906 $m = $observed_value <= $hide_opt;
777 907 } elseif ( $cond === 'LIKE' || $cond === 'not LIKE' ) {
778 908 $m = stripos( $observed_value, $hide_opt );
779 - if ( $cond === 'not LIKE' ) {
780 - $m = $m === false;
781 - } else {
782 - $m = $m !== false;
783 - }
909 + $m = $cond === 'not LIKE' ? $m === false : $m !== false;
784 910 } elseif ( $cond === '%LIKE' ) {
785 - // ends with
911 + // Ends with
786 912 $length = strlen( $hide_opt );
787 913 $substr = substr( $observed_value, strlen( $observed_value ) - $length );
788 914 $m = 0 === strcasecmp( $substr, $hide_opt );
789 915 } elseif ( 'LIKE%' === $cond ) {
790 - // starts with
916 + // Starts with
791 917 $length = strlen( $hide_opt );
792 918 $substr = substr( $observed_value, 0, $length );
793 919 $m = 0 === strcasecmp( $substr, $hide_opt );
794 920 }//end if
@@ -799,8 +925,12 @@
799 925 /**
800 926 * Trim and sanitize the values
801 927 *
802 928 * @since 2.05
929 + *
930 + * @param array|string $value
931 + *
932 + * @return array|string
803 933 */
804 934 private static function get_value_for_comparison( $value ) {
805 935 // Remove white space from hide_opt
806 936 if ( ! is_array( $value ) ) {
@@ -811,28 +941,37 @@
811 941
812 942 return $value;
813 943 }
814 944
945 + /**
946 + * @param array $observed_value
947 + * @param string $cond
948 + * @param array|string $hide_opt
949 + *
950 + * @return bool
951 + */
815 952 public static function array_value_condition( $observed_value, $cond, $hide_opt ) {
816 953 $m = false;
954 +
817 955 if ( $cond === '==' ) {
818 956 if ( is_array( $hide_opt ) ) {
819 957 $m = array_intersect( $hide_opt, $observed_value );
820 - $m = ! empty( $m );
958 + $m = $m !== array();
821 959 } else {
960 + // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
822 961 $m = in_array( $hide_opt, $observed_value );
823 962 }
824 963 } elseif ( $cond === '!=' ) {
964 + // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
825 965 $m = ! in_array( $hide_opt, $observed_value );
826 966 } elseif ( $cond === '>' ) {
827 - $min = min( $observed_value );
828 - $m = $min > $hide_opt;
967 + $m = min( $observed_value ) > $hide_opt;
829 968 } elseif ( $cond === '<' ) {
830 - $max = max( $observed_value );
831 - $m = $max < $hide_opt;
969 + $m = max( $observed_value ) < $hide_opt;
832 970 } elseif ( $cond === 'LIKE' || $cond === 'not LIKE' ) {
833 971 foreach ( $observed_value as $ob ) {
834 972 $m = strpos( $ob, $hide_opt );
973 +
835 974 if ( $m !== false ) {
836 975 $m = true;
837 976 break;
838 977 }
@@ -841,9 +980,9 @@
841 980 if ( $cond === 'not LIKE' ) {
842 981 $m = $m === false;
843 982 }
844 983 } elseif ( $cond === '%LIKE' ) {
845 - // ends with
984 + // Ends with
846 985 foreach ( $observed_value as $ob ) {
847 986 if ( $hide_opt === substr( $ob, strlen( $ob ) - strlen( $hide_opt ) ) ) {
848 987 $m = true;
849 988 break;
@@ -849,11 +988,11 @@
849 988 break;
850 989 }
851 990 }
852 991 } elseif ( $cond === 'LIKE%' ) {
853 - // starts with
992 + // Starts with
854 993 foreach ( $observed_value as $ob ) {
855 - if ( $hide_opt === substr( $ob, 0, strlen( $hide_opt ) ) ) {
994 + if ( str_starts_with( $ob, $hide_opt ) ) {
856 995 $m = true;
857 996 break;
858 997 }
859 998 }
@@ -865,22 +1004,32 @@
865 1004 /**
866 1005 * Replace a few basic shortcodes and field ids
867 1006 *
868 1007 * @since 2.0
1008 + *
1009 + * @param string $value
1010 + * @param object $form
1011 + * @param object $entry
1012 + *
869 1013 * @return string
870 1014 */
871 1015 public static function basic_replace_shortcodes( $value, $form, $entry ) {
872 - if ( strpos( $value, '[sitename]' ) !== false ) {
1016 + if ( str_contains( $value, '[sitename]' ) ) {
873 1017 $new_value = wp_specialchars_decode( FrmAppHelper::site_name(), ENT_QUOTES );
874 1018 $value = str_replace( '[sitename]', $new_value, $value );
875 1019 }
876 1020
877 1021 $value = apply_filters( 'frm_content', $value, $form, $entry );
878 - $value = do_shortcode( $value );
879 1022
880 - return $value;
1023 + return do_shortcode( $value );
881 1024 }
882 1025
1026 + /**
1027 + * @param string $content
1028 + * @param int|string $form_id
1029 + *
1030 + * @return array
1031 + */
883 1032 public static function get_shortcodes( $content, $form_id ) {
884 1033 if ( FrmAppHelper::pro_is_installed() ) {
885 1034 return FrmProDisplaysHelper::get_shortcodes( $content, $form_id );
886 1035 }
@@ -898,8 +1047,13 @@
898 1047
899 1048 return $matches;
900 1049 }
901 1050
1051 + /**
1052 + * @param array $fields
1053 + *
1054 + * @return string
1055 + */
902 1056 public static function allowed_shortcodes( $fields = array() ) {
903 1057 $tagregexp = array(
904 1058 'editlink',
905 1059 'id',
@@ -922,16 +1076,21 @@
922 1076 $tagregexp[] = $field->id;
923 1077 $tagregexp[] = $field->field_key;
924 1078 }
925 1079
926 - $tagregexp = implode( '|', $tagregexp );
927 -
928 - return $tagregexp;
1080 + return implode( '|', $tagregexp );
929 1081 }
930 1082
1083 + /**
1084 + * @param string $content
1085 + * @param false|object $entry
1086 + * @param array $shortcodes
1087 + *
1088 + * @return string
1089 + */
931 1090 public static function replace_content_shortcodes( $content, $entry, $shortcodes ) {
932 1091 foreach ( $shortcodes[0] as $short_key => $tag ) {
933 - if ( empty( $tag ) ) {
1092 + if ( ! $tag ) {
934 1093 continue;
935 1094 }
936 1095
937 1096 $atts = FrmShortcodeHelper::get_shortcode_attribute_array( $shortcodes[3][ $short_key ] );
@@ -955,21 +1114,25 @@
955 1114
956 1115 /**
957 1116 * @param string $replace_with
958 1117 * @param array $atts
1118 + *
959 1119 * @return string
960 1120 */
961 1121 private static function trigger_shortcode_atts( $replace_with, $atts ) {
962 1122 $supported_atts = array( 'remove_accents', 'sanitize', 'sanitize_url' );
963 1123 $included_atts = array_intersect( $supported_atts, array_keys( $atts ) );
1124 +
964 1125 foreach ( $included_atts as $included_att ) {
965 1126 if ( '0' === $atts[ $included_att ] ) {
966 1127 // Skip any option that uses 0 so sanitize_url=0 does not encode.
967 1128 continue;
968 1129 }
1130 +
969 1131 $function = 'atts_' . $included_att;
970 - $replace_with = self::$function( $replace_with, $atts );
1132 + $replace_with = self::$function( $replace_with );
971 1133 }
1134 +
972 1135 return $replace_with;
973 1136 }
974 1137
975 1138 /**
@@ -986,8 +1149,9 @@
986 1149 }
987 1150
988 1151 /**
989 1152 * @param string $replace_with
1153 + *
990 1154 * @return string
991 1155 */
992 1156 private static function atts_sanitize( $replace_with ) {
993 1157 return sanitize_title_with_dashes( $replace_with );
@@ -994,8 +1158,9 @@
994 1158 }
995 1159
996 1160 /**
997 1161 * @param string $replace_with
1162 + *
998 1163 * @return string
999 1164 */
1000 1165 private static function atts_sanitize_url( $replace_with ) {
1001 1166 return urlencode( $replace_with );
@@ -1007,8 +1172,9 @@
1007 1172 * @since 3.01.02
1008 1173 *
1009 1174 * @param array $atts Includes entry object.
1010 1175 * @param string|null $value
1176 + *
1011 1177 * @return void
1012 1178 */
1013 1179 public static function sanitize_embedded_shortcodes( $atts, &$value ) {
1014 1180 if ( is_null( $value ) ) {
@@ -1016,8 +1182,9 @@
1016 1182 }
1017 1183
1018 1184 $atts['value'] = $value;
1019 1185 $should_sanitize = apply_filters( 'frm_sanitize_shortcodes', true, $atts );
1186 +
1020 1187 if ( $should_sanitize ) {
1021 1188 $value = str_replace( '[', '&#91;', $value );
1022 1189 }
1023 1190 }
@@ -1085,9 +1252,10 @@
1085 1252 * @return string|null
1086 1253 */
1087 1254 private static function get_field_shortcode_value( $atts ) {
1088 1255 $field = FrmField::getOne( $atts['tag'] );
1089 - if ( empty( $field ) ) {
1256 +
1257 + if ( ! $field ) {
1090 1258 return null;
1091 1259 }
1092 1260
1093 1261 if ( isset( $atts['show'] ) && $atts['show'] === 'field_label' ) {
@@ -1096,14 +1264,16 @@
1096 1264 $replace_with = $field->description;
1097 1265 } else {
1098 1266 $replace_with = FrmEntryMeta::get_meta_value( $atts['entry'], $field->id );
1099 1267 $string_value = $replace_with;
1268 +
1100 1269 if ( is_array( $replace_with ) ) {
1101 1270 $sep = $atts['sep'] ?? ', ';
1102 1271 $string_value = FrmAppHelper::safe_implode( $sep, $replace_with );
1103 1272 }
1104 1273
1105 - if ( empty( $string_value ) && $string_value != '0' ) {
1274 + // phpcs:ignore Universal.Operators.StrictComparisons
1275 + if ( ! $string_value && $string_value != '0' ) {
1106 1276 $replace_with = '';
1107 1277 } else {
1108 1278 $atts['entry_id'] = $atts['entry']->id;
1109 1279 $atts['entry_key'] = $atts['entry']->item_key;
@@ -1108,9 +1278,9 @@
1108 1278 $atts['entry_id'] = $atts['entry']->id;
1109 1279 $atts['entry_key'] = $atts['entry']->item_key;
1110 1280 $replace_with = self::get_display_value( $replace_with, $field, $atts );
1111 1281 }
1112 - }
1282 + }//end if
1113 1283
1114 1284 return $replace_with;
1115 1285 }
1116 1286
@@ -1117,8 +1287,13 @@
1117 1287 /**
1118 1288 * Get the value to replace a few standard shortcodes
1119 1289 *
1120 1290 * @since 2.0
1291 + *
1292 + * @param string $tag
1293 + * @param array $atts
1294 + * @param bool $return_array
1295 + *
1121 1296 * @return string
1122 1297 */
1123 1298 public static function dynamic_default_values( $tag, $atts = array(), $return_array = false ) {
1124 1299 $new_value = '';
@@ -1153,8 +1328,12 @@
1153 1328 /**
1154 1329 * Process the [get] shortcode
1155 1330 *
1156 1331 * @since 2.0
1332 + *
1333 + * @param array $atts
1334 + * @param bool $return_array
1335 + *
1157 1336 * @return array|string
1158 1337 */
1159 1338 public static function process_get_shortcode( $atts, $return_array = false ) {
1160 1339 if ( ! isset( $atts['param'] ) ) {
@@ -1160,9 +1339,9 @@
1160 1339 if ( ! isset( $atts['param'] ) ) {
1161 1340 return '';
1162 1341 }
1163 1342
1164 - if ( strpos( $atts['param'], '&#91;' ) ) {
1343 + if ( str_contains( $atts['param'], '&#91;' ) ) {
1165 1344 $atts['param'] = str_replace( '&#91;', '[', $atts['param'] );
1166 1345 $atts['param'] = str_replace( '&#93;', ']', $atts['param'] );
1167 1346 }
1168 1347
@@ -1168,8 +1347,9 @@
1168 1347
1169 1348 $new_value = FrmAppHelper::get_param( $atts['param'], '', 'get', 'sanitize_text_field' );
1170 1349 $new_value = FrmAppHelper::get_query_var( $new_value, $atts['param'] );
1171 1350
1351 + // phpcs:ignore Universal.Operators.StrictComparisons
1172 1352 if ( $new_value == '' ) {
1173 1353 if ( ! isset( $atts['prev_val'] ) ) {
1174 1354 $atts['prev_val'] = '';
1175 1355 }
@@ -1177,19 +1357,24 @@
1177 1357 $new_value = $atts['default'] ?? $atts['prev_val'];
1178 1358 }
1179 1359
1180 1360 if ( is_array( $new_value ) && ! $return_array ) {
1181 - $new_value = implode( ', ', $new_value );
1361 + return implode( ', ', $new_value );
1182 1362 }
1183 1363
1184 1364 return $new_value;
1185 1365 }
1186 1366
1367 + /**
1368 + * @param mixed $value
1369 + * @param object $field
1370 + * @param array $atts
1371 + *
1372 + * @return mixed
1373 + */
1187 1374 public static function get_display_value( $value, $field, $atts = array() ) {
1188 -
1189 1375 $value = apply_filters( 'frm_get_' . $field->type . '_display_value', $value, $field, $atts );
1190 1376 $value = apply_filters( 'frm_get_display_value', $value, $field, $atts );
1191 -
1192 1377 $value = self::get_unfiltered_display_value( compact( 'value', 'field', 'atts' ) );
1193 1378
1194 1379 return apply_filters( 'frm_display_value', $value, $field, $atts );
1195 1380 }
@@ -1195,8 +1380,10 @@
1195 1380 }
1196 1381
1197 1382 /**
1198 1383 * @param array $atts Includes value, field, and atts.
1384 + *
1385 + * @return mixed
1199 1386 */
1200 1387 public static function get_unfiltered_display_value( $atts ) {
1201 1388 $value = $atts['value'];
1202 1389 $field = $atts['field'];
@@ -1215,8 +1402,12 @@
1215 1402 * Get a value from the user profile from the user ID
1216 1403 *
1217 1404 * @since 3.0
1218 1405 *
1406 + * @param int|string $user_id
1407 + * @param string $user_info
1408 + * @param array $args
1409 + *
1219 1410 * @return string
1220 1411 */
1221 1412 public static function get_user_display_name( $user_id, $user_info = 'display_name', $args = array() ) {
1222 1413 $defaults = array(
@@ -1225,9 +1416,8 @@
1225 1416 'size' => 96,
1226 1417 );
1227 1418
1228 1419 $args = wp_parse_args( $args, $defaults );
1229 -
1230 1420 $user = get_userdata( $user_id );
1231 1421 $info = '';
1232 1422
1233 1423 if ( $user ) {
@@ -1238,15 +1428,15 @@
1238 1428 } else {
1239 1429 $info = $user->$user_info ?? '';
1240 1430 }
1241 1431
1242 - if ( 'display_name' === $user_info && empty( $info ) && ! $args['blank'] ) {
1432 + if ( 'display_name' === $user_info && ! $info && ! $args['blank'] ) {
1243 1433 $info = $user->user_login;
1244 1434 }
1245 1435 }
1246 1436
1247 1437 if ( $args['link'] ) {
1248 - $info = '<a href="' . esc_url( admin_url( 'user-edit.php?user_id=' . $user_id ) ) . '">' . $info . '</a>';
1438 + return '<a href="' . esc_url( admin_url( 'user-edit.php?user_id=' . $user_id ) ) . '">' . $info . '</a>';
1249 1439 }
1250 1440
1251 1441 return $info;
1252 1442 }
@@ -1252,8 +1442,9 @@
1252 1442 }
1253 1443
1254 1444 /**
1255 1445 * @param string $type
1446 + *
1256 1447 * @return array
1257 1448 */
1258 1449 public static function get_field_types( $type ) {
1259 1450 $single_input = self::single_input_fields();
@@ -1268,11 +1459,9 @@
1268 1459 } elseif ( isset( $field_selection[ $type ] ) ) {
1269 1460 $field_types[ $type ] = $field_selection[ $type ];
1270 1461 }
1271 1462
1272 - $field_types = apply_filters( 'frm_switch_field_types', $field_types, compact( 'type', 'field_selection' ) );
1273 -
1274 - return $field_types;
1463 + return apply_filters( 'frm_switch_field_types', $field_types, compact( 'type', 'field_selection' ) );
1275 1464 }
1276 1465
1277 1466 /**
1278 1467 * Get a list of all fields that use a single value input.
@@ -1277,8 +1466,10 @@
1277 1466 /**
1278 1467 * Get a list of all fields that use a single value input.
1279 1468 *
1280 1469 * @since 4.0
1470 + *
1471 + * @return array
1281 1472 */
1282 1473 public static function single_input_fields() {
1283 1474 $fields = array(
1284 1475 'text',
@@ -1301,8 +1492,9 @@
1301 1492 /**
1302 1493 * @param string[] $inputs
1303 1494 * @param array $fields
1304 1495 * @param array $field_types
1496 + *
1305 1497 * @return void
1306 1498 */
1307 1499 private static function field_types_for_input( $inputs, $fields, &$field_types ) {
1308 1500 foreach ( $inputs as $input ) {
@@ -1323,9 +1515,9 @@
1323 1515 *
1324 1516 * @return bool Returns true if current field option is an "Other" option
1325 1517 */
1326 1518 public static function is_other_opt( $opt_key ) {
1327 - return $opt_key && strpos( $opt_key, 'other_' ) === 0;
1519 + return $opt_key && str_starts_with( $opt_key, 'other_' );
1328 1520 }
1329 1521
1330 1522 /**
1331 1523 * Get value that belongs in "Other" text box
@@ -1332,18 +1524,19 @@
1332 1524 *
1333 1525 * @since 2.0.6
1334 1526 *
1335 1527 * @param array $args
1528 + *
1529 + * @return string
1336 1530 */
1337 - public static function get_other_val( $args ) {
1338 - $defaults = array(
1531 + public static function get_other_val( $args ) { // phpcs:ignore SlevomatCodingStandard.Complexity.Cognitive.ComplexityTooHigh
1532 + $defaults = array(
1339 1533 'opt_key' => 0,
1340 1534 'field' => array(),
1341 1535 'parent' => false,
1342 1536 'pointer' => false,
1343 1537 );
1344 - $args = wp_parse_args( $args, $defaults );
1345 -
1538 + $args = wp_parse_args( $args, $defaults );
1346 1539 $opt_key = $args['opt_key'];
1347 1540 $field = $args['field'];
1348 1541 $parent = $args['parent'];
1349 1542 $pointer = $args['pointer'];
@@ -1349,9 +1542,9 @@
1349 1542 $pointer = $args['pointer'];
1350 1543 $other_val = '';
1351 1544
1352 1545 // If option is an "other" option and there is a value set for this field,
1353 - // check if the value belongs in the current "Other" option text field
1546 + // Check if the value belongs in the current "Other" option text field
1354 1547 if ( ! self::is_other_opt( $opt_key ) || ! FrmField::is_option_true( $field, 'value' ) ) {
1355 1548 return $other_val;
1356 1549 }
1357 1550
@@ -1358,12 +1551,12 @@
1358 1551 // Check posted vals before checking saved values
1359 1552 // For fields inside repeating sections - note, don't check if $pointer is true because it will often be zero
1360 1553 if ( $parent && isset( $_POST['item_meta'][ $parent ][ $pointer ]['other'][ $field['id'] ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
1361 1554 if ( FrmField::is_field_with_multiple_values( $field ) ) {
1555 + $other_val = isset( $_POST['item_meta'][ $parent ][ $pointer ]['other'][ $field['id'] ][ $opt_key ] ) ? sanitize_text_field( wp_unslash( $_POST['item_meta'][ $parent ][ $pointer ]['other'][ $field['id'] ][ $opt_key ] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing, SlevomatCodingStandard.Files.LineLength.LineTooLong
1556 + } else {
1362 1557 // phpcs:ignore WordPress.Security.NonceVerification.Missing
1363 - $other_val = isset( $_POST['item_meta'][ $parent ][ $pointer ]['other'][ $field['id'] ][ $opt_key ] ) ? sanitize_text_field( wp_unslash( $_POST['item_meta'][ $parent ][ $pointer ]['other'][ $field['id'] ][ $opt_key ] ) ) : '';
1364 - } else {
1365 - $other_val = sanitize_text_field( wp_unslash( $_POST['item_meta'][ $parent ][ $pointer ]['other'][ $field['id'] ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
1558 + $other_val = sanitize_text_field( wp_unslash( $_POST['item_meta'][ $parent ][ $pointer ]['other'][ $field['id'] ] ) );
1366 1559 }
1367 1560
1368 1561 return $other_val;
1369 1562 }
@@ -1371,9 +1564,9 @@
1371 1564 if ( isset( $field['id'] ) && isset( $_POST['item_meta']['other'][ $field['id'] ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
1372 1565 // For normal fields
1373 1566
1374 1567 if ( FrmField::is_field_with_multiple_values( $field ) ) {
1375 - // phpcs:ignore WordPress.Security.NonceVerification.Missing
1568 + // phpcs:ignore WordPress.Security.NonceVerification.Missing, SlevomatCodingStandard.Files.LineLength.LineTooLong
1376 1569 $other_val = isset( $_POST['item_meta']['other'][ $field['id'] ][ $opt_key ] ) ? sanitize_text_field( wp_unslash( $_POST['item_meta']['other'][ $field['id'] ][ $opt_key ] ) ) : '';
1377 1570 } else {
1378 1571 $other_val = sanitize_text_field( wp_unslash( $_POST['item_meta']['other'][ $field['id'] ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
1379 1572 }
@@ -1384,8 +1577,9 @@
1384 1577 // For checkboxes
1385 1578 if ( $field['type'] === 'checkbox' && is_array( $field['value'] ) ) {
1386 1579 // Check if there is an "other" val in saved value and make sure the
1387 1580 // "other" val is not equal to the Other checkbox option
1581 + // phpcs:ignore Universal.Operators.StrictComparisons
1388 1582 if ( isset( $field['value'][ $opt_key ] ) && $field['options'][ $opt_key ] != $field['value'][ $opt_key ] ) {
1389 1583 $other_val = $field['value'][ $opt_key ];
1390 1584 }
1391 1585 } else {
@@ -1394,15 +1588,18 @@
1394 1588 * Check if saved value equals any of the options. If not, set it as the other value.
1395 1589 */
1396 1590 foreach ( $field['options'] as $opt_val ) {
1397 1591 $temp_val = is_array( $opt_val ) ? $opt_val['value'] : $opt_val;
1592 +
1398 1593 // Multi-select dropdowns - key is not preserved
1399 1594 if ( is_array( $field['value'] ) ) {
1595 + // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
1400 1596 $o_key = array_search( $temp_val, $field['value'] );
1597 +
1401 1598 if ( isset( $field['value'][ $o_key ] ) ) {
1402 1599 unset( $field['value'][ $o_key ], $o_key );
1403 1600 }
1404 - } elseif ( $temp_val == $field['value'] ) {
1601 + } elseif ( $temp_val == $field['value'] ) { // phpcs:ignore Universal.Operators.StrictComparisons
1405 1602 // For radio and regular dropdowns
1406 1603 return '';
1407 1604 } else {
1408 1605 $other_val = $field['value'];
@@ -1408,10 +1605,11 @@
1408 1605 $other_val = $field['value'];
1409 1606 }
1410 1607 unset( $opt_val, $temp_val );
1411 1608 }
1609 +
1412 1610 // For multi-select dropdowns only
1413 - if ( is_array( $field['value'] ) && ! empty( $field['value'] ) ) {
1611 + if ( is_array( $field['value'] ) && $field['value'] ) {
1414 1612 $other_val = reset( $field['value'] );
1415 1613 }
1416 1614 }//end if
1417 1615
@@ -1427,9 +1625,9 @@
1427 1625 * @param array $args Should include field, opt_key and field name.
1428 1626 * @param bool $other_opt
1429 1627 * @param string $checked
1430 1628 *
1431 - * @return array $other_args
1629 + * @return array Other args.
1432 1630 */
1433 1631 public static function prepare_other_input( $args, &$other_opt, &$checked ) {
1434 1632 $other_args = array(
1435 1633 'name' => '',
@@ -1464,10 +1662,13 @@
1464 1662 }
1465 1663
1466 1664 /**
1467 1665 * @since 2.0.6
1666 + *
1468 1667 * @param array $args
1469 1668 * @param array $other_args
1669 + *
1670 + * @return void
1470 1671 */
1471 1672 private static function set_other_name( $args, &$other_args ) {
1472 1673 // Set up name for other field
1473 1674 $other_args['name'] = str_replace( '[]', '', $args['field_name'] );
@@ -1484,10 +1685,13 @@
1484 1685 /**
1485 1686 * Find the parent and pointer, and get text for "other" text field
1486 1687 *
1487 1688 * @since 2.0.6
1689 + *
1488 1690 * @param array $args
1489 1691 * @param array $other_args
1692 + *
1693 + * @return void
1490 1694 */
1491 1695 private static function set_other_value( $args, &$other_args ) {
1492 1696 $parent = '';
1493 1697 $pointer = '';
@@ -1515,9 +1719,12 @@
1515 1719 /**
1516 1720 * If this field includes an other option, show it
1517 1721 *
1518 1722 * @since 2.0.6
1723 + *
1519 1724 * @param array $args
1725 + *
1726 + * @return void
1520 1727 */
1521 1728 public static function include_other_input( $args ) {
1522 1729 if ( ! $args['other_opt'] ) {
1523 1730 return;
@@ -1523,12 +1730,14 @@
1523 1730 return;
1524 1731 }
1525 1732
1526 1733 $classes = array( 'frm_other_input' );
1527 - if ( ! $args['checked'] || trim( $args['checked'] ) == '' ) {
1528 - // hide the field if the other option is not selected
1734 +
1735 + if ( ! $args['checked'] || trim( $args['checked'] ) === '' ) {
1736 + // Hide the field if the other option is not selected
1529 1737 $classes[] = 'frm_pos_none';
1530 1738 }
1739 +
1531 1740 if ( $args['field']['type'] === 'select' && ! empty( $args['field']['multiple'] ) ) {
1532 1741 $classes[] = 'frm_other_full';
1533 1742 }
1534 1743
@@ -1536,8 +1745,9 @@
1536 1745 $other_id = self::get_other_field_html_id( $args['field']['type'], $args['html_id'], $args['opt_key'] );
1537 1746
1538 1747 $label = $args['opt_label'] ?? $args['field']['name'];
1539 1748
1749 + // phpcs:disable Generic.WhiteSpace.ScopeIndent
1540 1750 echo '<label for="' . esc_attr( $other_id ) . '" class="frm_screen_reader frm_hidden">' .
1541 1751 esc_html( $label ) .
1542 1752 '</label>' .
1543 1753 '<input type="text" id="' . esc_attr( $other_id ) . '" class="' . esc_attr( implode( ' ', $classes ) ) . '" ' .
@@ -1542,8 +1752,9 @@
1542 1752 '</label>' .
1543 1753 '<input type="text" id="' . esc_attr( $other_id ) . '" class="' . esc_attr( implode( ' ', $classes ) ) . '" ' .
1544 1754 ( $args['read_only'] ? ' readonly="readonly" disabled="disabled"' : '' ) .
1545 1755 ' name="' . esc_attr( $args['name'] ) . '" value="' . esc_attr( $args['value'] ) . '" />';
1756 + // phpcs:enable Generic.WhiteSpace.ScopeIndent
1546 1757 }
1547 1758
1548 1759 /**
1549 1760 * Get the HTML id for an "Other" text field
@@ -1554,9 +1765,9 @@
1554 1765 * @param string $type Field type.
1555 1766 * @param string $html_id
1556 1767 * @param bool|string $opt_key
1557 1768 *
1558 - * @return string $other_id
1769 + * @return string Other ID.
1559 1770 */
1560 1771 public static function get_other_field_html_id( $type, $html_id, $opt_key = false ) {
1561 1772 $other_id = $html_id;
1562 1773
@@ -1568,17 +1779,21 @@
1568 1779 if ( $opt_key !== false ) {
1569 1780 $other_id .= '-' . $opt_key;
1570 1781 }
1571 1782
1572 - $other_id .= '-otext';
1573 -
1574 - return $other_id;
1783 + return $other_id . '-otext';
1575 1784 }
1576 1785
1786 + /**
1787 + * @param array|string $val
1788 + *
1789 + * @return array|string
1790 + */
1577 1791 public static function switch_field_ids( $val ) {
1578 1792 global $frm_duplicate_ids;
1579 1793 $replace = array();
1580 1794 $replace_with = array();
1795 +
1581 1796 foreach ( (array) $frm_duplicate_ids as $old => $new ) {
1582 1797 $replace[] = '[if ' . $old . ']';
1583 1798 $replace_with[] = '[if ' . $new . ']';
1584 1799 $replace[] = '[if ' . $old . ' ';
@@ -1605,22 +1820,26 @@
1605 1820 $replace[] = '_field":"' . $old . '","';
1606 1821 $replace_with[] = '_field":"' . $new . '","';
1607 1822 unset( $old, $new );
1608 1823 }//end foreach
1609 - if ( is_array( $val ) ) {
1610 - foreach ( $val as $k => $v ) {
1611 - if ( is_string( $v ) ) {
1612 - if ( 'custom_html' === $k ) {
1613 - $val[ $k ] = self::switch_ids_except_strings( $replace, $replace_with, array( '[if description]', '[description]', '[/if description]' ), $v );
1614 - unset( $k, $v );
1615 - continue;
1616 - }
1617 - $val[ $k ] = str_replace( $replace, $replace_with, $v );
1618 - unset( $k, $v );
1619 - }
1824 +
1825 + if ( ! is_array( $val ) ) {
1826 + return str_replace( $replace, $replace_with, $val );
1827 + }
1828 +
1829 + foreach ( $val as $k => $v ) {
1830 + if ( ! is_string( $v ) ) {
1831 + continue;
1620 1832 }
1621 - } else {
1622 - $val = str_replace( $replace, $replace_with, $val );
1833 +
1834 + if ( 'custom_html' === $k ) {
1835 + $val[ $k ] = self::switch_ids_except_strings( $replace, $replace_with, array( '[if description]', '[description]', '[/if description]' ), $v );
1836 + unset( $k, $v );
1837 + continue;
1838 + }
1839 +
1840 + $val[ $k ] = str_replace( $replace, $replace_with, $v );
1841 + unset( $k, $v );
1623 1842 }
1624 1843
1625 1844 return $val;
1626 1845 }
@@ -1639,8 +1858,9 @@
1639 1858 */
1640 1859 private static function switch_ids_except_strings( $replace, $replace_with, $exceptions, $value ) {
1641 1860 foreach ( $exceptions as $exception ) {
1642 1861 $index = array_search( $exception, $replace, true );
1862 +
1643 1863 if ( false === $index ) {
1644 1864 continue;
1645 1865 }
1646 1866 unset( $replace[ $index ] );
@@ -1645,14 +1865,16 @@
1645 1865 }
1646 1866 unset( $replace[ $index ] );
1647 1867 unset( $replace_with[ $index ] );
1648 1868 }
1649 - $value = str_replace( $replace, $replace_with, $value );
1650 - return $value;
1869 +
1870 + return str_replace( $replace, $replace_with, $value );
1651 1871 }
1652 1872
1653 1873 /**
1654 1874 * @since 4.0
1875 + *
1876 + * @return void
1655 1877 */
1656 1878 public static function bulk_options_overlay() {
1657 1879 $prepop = array();
1658 1880 self::get_bulk_prefilled_opts( $prepop, true );
@@ -1659,8 +1881,11 @@
1659 1881
1660 1882 include FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/bulk-options-overlay.php';
1661 1883 }
1662 1884
1885 + /**
1886 + * @return array
1887 + */
1663 1888 public static function get_us_states() {
1664 1889 $states = array(
1665 1890 'AL' => 'Alabama',
1666 1891 'AK' => 'Alaska',
@@ -1717,8 +1942,11 @@
1717 1942
1718 1943 return apply_filters( 'frm_us_states', $states );
1719 1944 }
1720 1945
1946 + /**
1947 + * @return array
1948 + */
1721 1949 public static function get_countries() {
1722 1950 $countries = array(
1723 1951 __( 'Afghanistan', 'formidable' ),
1724 1952 __( 'Aland Islands', 'formidable' ),
@@ -1983,12 +2211,15 @@
1983 2211 * @since 5.0.04 Add `$include_class` param.
1984 2212 *
1985 2213 * @param array $prepop Bulk options.
1986 2214 * @param array|false $include_class Include the class in the bulk options.
2215 + *
2216 + * @return void
1987 2217 */
1988 2218 public static function get_bulk_prefilled_opts( array &$prepop, $include_class = false ) {
1989 2219 // Countries.
1990 2220 $countries = self::get_countries();
2221 +
1991 2222 if ( $include_class ) {
1992 2223 $countries['class'] = 'frm-countries-opts';
1993 2224 }
1994 2225
@@ -1997,8 +2228,9 @@
1997 2228 // State abv.
1998 2229 $states = self::get_us_states();
1999 2230 $state_abv = array_keys( $states );
2000 2231 sort( $state_abv );
2232 +
2001 2233 if ( $include_class ) {
2002 2234 $state_abv['class'] = 'frm-state-abv-opts';
2003 2235 }
2004 2236
@@ -2006,8 +2238,9 @@
2006 2238
2007 2239 // States.
2008 2240 $states = array_values( $states );
2009 2241 sort( $states );
2242 +
2010 2243 if ( $include_class ) {
2011 2244 $states['class'] = 'frm-states-opts';
2012 2245 }
2013 2246
@@ -2024,8 +2257,9 @@
2024 2257 __( '55-64', 'formidable' ),
2025 2258 __( '65 or Above', 'formidable' ),
2026 2259 __( 'Prefer Not to Answer', 'formidable' ),
2027 2260 );
2261 +
2028 2262 if ( $include_class ) {
2029 2263 $ages['class'] = 'frm-age-opts';
2030 2264 }
2031 2265
@@ -2039,8 +2273,9 @@
2039 2273 __( 'Satisfied', 'formidable' ),
2040 2274 __( 'Very Satisfied', 'formidable' ),
2041 2275 __( 'N/A', 'formidable' ),
2042 2276 );
2277 +
2043 2278 if ( $include_class ) {
2044 2279 $satisfaction['class'] = 'frm-satisfaction-opts';
2045 2280 }
2046 2281
@@ -2054,8 +2289,9 @@
2054 2289 __( 'Important', 'formidable' ),
2055 2290 __( 'Very Important', 'formidable' ),
2056 2291 __( 'N/A', 'formidable' ),
2057 2292 );
2293 +
2058 2294 if ( $include_class ) {
2059 2295 $importance['class'] = 'frm-importance-opts';
2060 2296 }
2061 2297
@@ -2069,8 +2305,9 @@
2069 2305 __( 'Agree', 'formidable' ),
2070 2306 __( 'Strongly Agree', 'formidable' ),
2071 2307 __( 'N/A', 'formidable' ),
2072 2308 );
2309 +
2073 2310 if ( $include_class ) {
2074 2311 $agreement['class'] = 'frm-agreement-opts';
2075 2312 }
2076 2313
@@ -2084,8 +2321,9 @@
2084 2321 __( 'Likely', 'formidable' ),
2085 2322 __( 'Extremely Likely', 'formidable' ),
2086 2323 __( 'N/A', 'formidable' ),
2087 2324 );
2325 +
2088 2326 if ( $include_class ) {
2089 2327 $likely['class'] = 'frm-likely-opts';
2090 2328 }
2091 2329
@@ -2100,8 +2338,10 @@
2100 2338 * @since 2.03.05
2101 2339 *
2102 2340 * @param int $selector_field_id
2103 2341 * @param array $selector_args
2342 + *
2343 + * @return void
2104 2344 */
2105 2345 public static function display_field_value_selector( $selector_field_id, $selector_args ) {
2106 2346 $field_value_selector = FrmFieldFactory::create_field_value_selector( $selector_field_id, $selector_args );
2107 2347 $field_value_selector->display();
@@ -2124,11 +2364,43 @@
2124 2364 return $field_array + $field_options;
2125 2365 }
2126 2366
2127 2367 /**
2368 + * Shows add field link.
2369 + *
2370 + * @since 6.30
2371 + *
2372 + * @param array $field_type See file `classes/views/frm-forms/add_field_links.php`.
2373 + *
2374 + * @return void
2375 + */
2376 + public static function show_add_field_link( $field_type ) {
2377 + $field_label = FrmFormsHelper::get_field_link_name( $field_type );
2378 + $classes = 'frmbutton frm6 frm_t' . $field_type['key'];
2379 +
2380 + if ( ! empty( $field_type['hide'] ) ) {
2381 + $classes .= ' frm_hidden';
2382 + }
2383 + ?>
2384 +<li class="<?php echo esc_attr( $classes ); ?>" id="<?php echo esc_attr( $field_type['key'] ); ?>">
2385 + <a href="#" class="frm_add_field" title="<?php echo esc_attr( $field_label ); ?>" role="button" aria-label="<?php echo esc_attr( $field_label ); ?>">
2386 + <?php FrmAppHelper::icon_by_class( FrmFormsHelper::get_field_link_icon( $field_type ) ); ?>
2387 + <span><?php echo esc_html( $field_label ); ?></span>
2388 + <?php
2389 + if ( 'credit_card' === $field_type['key'] && ! FrmTransLiteAppHelper::payments_table_exists() ) {
2390 + FrmAppHelper::show_pill_text();
2391 + }
2392 + ?>
2393 + </a>
2394 +</li>
2395 + <?php
2396 + }
2397 +
2398 + /**
2128 2399 * @since 4.04
2129 2400 *
2130 2401 * @param array $args
2402 + *
2131 2403 * @return void
2132 2404 */
2133 2405 public static function show_add_field_buttons( $args ) {
2134 2406 $field_key = $args['field_key'];
@@ -2143,33 +2415,25 @@
2143 2415 $field_label .= ob_get_clean();
2144 2416 }
2145 2417
2146 2418 // If the individual field isn't allowed, disable it.
2147 - $run_filter = true;
2148 - $single_no_allow = ' ';
2149 - $install_data = '';
2150 - $requires = '';
2151 - $link = isset( $field_type['link'] ) ? esc_url_raw( $field_type['link'] ) : '';
2152 - $has_show_upgrade_class = isset( $field_type['icon'] ) && strpos( $field_type['icon'], ' frm_show_upgrade' );
2153 - $show_upgrade = $has_show_upgrade_class || false !== strpos( $args['no_allow_class'], 'frm_show_upgrade' );
2419 + $link = isset( $field_type['link'] ) ? esc_url_raw( $field_type['link'] ) : '';
2154 2420
2155 - if ( $has_show_upgrade_class ) {
2156 - $single_no_allow .= 'frm_show_upgrade';
2157 - $field_type['icon'] = str_replace( ' frm_show_upgrade', '', $field_type['icon'] );
2158 - $run_filter = false;
2159 - if ( isset( $field_type['addon'] ) ) {
2160 - $upgrading = FrmAddonsController::install_link( $field_type['addon'] );
2161 - if ( isset( $upgrading['url'] ) ) {
2162 - $install_data = json_encode( $upgrading );
2163 - }
2164 - $requires = FrmFormsHelper::get_plan_required( $upgrading );
2165 - } elseif ( isset( $field_type['require'] ) ) {
2166 - $requires = $field_type['require'];
2167 - }
2168 - }
2421 + list(
2422 + $run_filter,
2423 + $single_no_allow,
2424 + $install_data,
2425 + $requires,
2426 + $has_show_upgrade_class,
2427 + $has_show_update_class,
2428 + $upgrading,
2429 + $update_addon_name
2430 + ) = self::get_field_upgrade_state( $field_type );
2169 2431
2432 + $show_upgrade = $has_show_upgrade_class || $has_show_update_class || str_contains( $args['no_allow_class'], 'frm_show_upgrade' );
2170 2433 $upgrade_label = '';
2171 2434 $upgrade_message = '';
2435 +
2172 2436 if ( $show_upgrade ) {
2173 2437 /* translators: %s: Field name */
2174 2438 $upgrade_label = sprintf( esc_html__( '%s fields', 'formidable' ), $field_name );
2175 2439
@@ -2192,15 +2456,41 @@
2192 2456 if ( ! empty( $field_type['hide'] ) ) {
2193 2457 $li_params['class'] .= ' frm_hidden';
2194 2458 }
2195 2459
2460 + if ( ! $show_upgrade && ! empty( $field_type['limit'] ) ) {
2461 + $li_params = self::update_params_with_limit_data( $li_params, $args['id'], $field_key, $field_type['limit'] );
2462 + }
2463 +
2196 2464 if ( ! empty( $field_type['upsell_image'] ) ) {
2197 2465 $li_params['data-upsell-image'] = $field_type['upsell_image'];
2198 2466 }
2199 2467
2200 - if ( $upgrade_message ) {
2468 + if ( ! empty( $field_type['learn-more'] ) ) {
2469 + $li_params['data-learn-more'] = FrmAppHelper::get_doc_url(
2470 + $field_type['learn-more'],
2471 + 'form-builder-add-fields',
2472 + str_contains( $field_type['learn-more'], '/' )
2473 + );
2474 + }
2475 +
2476 + if ( $has_show_update_class ) {
2477 + $li_params['data-message'] = sprintf(
2478 + // translators: %1$s: Add-on name, %2$s: Field type name.
2479 + esc_html__( 'You need a newer version of %1$s for %2$s fields.', 'formidable' ),
2480 + $update_addon_name,
2481 + $field_name
2482 + );
2483 + } elseif ( isset( $upgrading['url'] ) ) {
2484 + $li_params['data-message'] = sprintf(
2485 + // translators: %s: Field name
2486 + esc_html__( 'You already have access to %s fields, you\'ll just need to activate to start using them.', 'formidable' ),
2487 + $field_name
2488 + );
2489 + } elseif ( $upgrade_message ) {
2201 2490 $li_params['data-message'] = $upgrade_message;
2202 2491 }
2492 + // phpcs:disable Generic.WhiteSpace.ScopeIndent
2203 2493 ?>
2204 2494 <li <?php FrmAppHelper::array_to_html_params( $li_params, true ); ?>>
2205 2495 <?php
2206 2496 if ( $run_filter ) {
@@ -2205,26 +2495,130 @@
2205 2495 <?php
2206 2496 if ( $run_filter ) {
2207 2497 $field_label = apply_filters( 'frmpro_field_links', $field_label, $args['id'], $field_key );
2208 2498 }
2499 +
2209 2500 FrmAppHelper::kses_echo( $field_label, array( 'a', 'i', 'span', 'use', 'svg' ) );
2210 2501 ?>
2211 2502 </li>
2212 2503 <?php
2504 + // phpcs:enable Generic.WhiteSpace.ScopeIndent
2213 2505 }
2214 2506
2215 2507 /**
2508 + * Parse the upgrade and update flags from a field type's icon class.
2509 + *
2510 + * @since 6.29
2511 + *
2512 + * @param array $field_type Field type configuration, modified in place to strip icon flag classes.
2513 + *
2514 + * @return array Upgrade and update state values for the field button, in positional order.
2515 + */
2516 + private static function get_field_upgrade_state( &$field_type ) {
2517 + $single_no_allow = ' ';
2518 + $run_filter = true;
2519 + $has_show_upgrade_class = false;
2520 + $has_show_update_class = false;
2521 + $install_data = '';
2522 + $requires = '';
2523 + $upgrading = array();
2524 + $update_addon_name = '';
2525 +
2526 + if ( isset( $field_type['icon'] ) ) {
2527 + $has_show_upgrade_class = str_contains( $field_type['icon'], ' frm_show_upgrade' );
2528 + $has_show_update_class = str_contains( $field_type['icon'], ' frm_show_update' );
2529 + }
2530 +
2531 + if ( $has_show_upgrade_class ) {
2532 + $single_no_allow .= 'frm_show_upgrade';
2533 + $field_type['icon'] = str_replace( ' frm_show_upgrade', '', $field_type['icon'] );
2534 + $run_filter = false;
2535 +
2536 + if ( isset( $field_type['addon'] ) ) {
2537 + $upgrading = FrmAddonsController::install_link( $field_type['addon'] );
2538 +
2539 + if ( isset( $upgrading['url'] ) ) {
2540 + $install_data = json_encode( $upgrading );
2541 + }
2542 +
2543 + $requires = FrmFormsHelper::get_plan_required( $upgrading );
2544 + } elseif ( isset( $field_type['require'] ) ) {
2545 + $requires = $field_type['require'];
2546 + }
2547 + }
2548 +
2549 + if ( $has_show_update_class ) {
2550 + $single_no_allow .= ' frm_show_update';
2551 + $field_type['icon'] = str_replace( ' frm_show_update', '', $field_type['icon'] );
2552 + $run_filter = false;
2553 + $addon_slug = $field_type['addon'] ?? 'pro';
2554 +
2555 + if ( 'pro' === $addon_slug ) {
2556 + $update_addon_name = __( 'Formidable Pro', 'formidable' );
2557 + } else {
2558 + $addon_data = FrmAddonsController::get_addon( $addon_slug );
2559 + $update_addon_name = $addon_data && ! empty( $addon_data['title'] ) ? $addon_data['title'] : ucfirst( $addon_slug );
2560 + }
2561 +
2562 + $install_data = FrmAddonsController::get_update_install_data( $addon_slug );
2563 + }
2564 +
2565 + return array(
2566 + $run_filter,
2567 + $single_no_allow,
2568 + $install_data,
2569 + $requires,
2570 + $has_show_upgrade_class,
2571 + $has_show_update_class,
2572 + $upgrading,
2573 + $update_addon_name,
2574 + );
2575 + }
2576 +
2577 + /**
2578 + * Updates the params with limit data (the data-limit attribute, and possibly the frm_at_limit class).
2579 + * Some field types are limited to a certain number per form, including coupon fields.
2580 + *
2581 + * @since 6.27
2582 + *
2583 + * @param array $li_params The params.
2584 + * @param int $form_id The form ID.
2585 + * @param string $field_type The field type.
2586 + * @param int $limit The limit.
2587 + *
2588 + * @return array The updated params.
2589 + */
2590 + private static function update_params_with_limit_data( $li_params, $form_id, $field_type, $limit ) {
2591 + $fields_in_form = FrmDb::get_count(
2592 + 'frm_fields',
2593 + array(
2594 + 'form_id' => $form_id,
2595 + 'type' => $field_type,
2596 + )
2597 + );
2598 +
2599 + if ( $fields_in_form >= $limit ) {
2600 + $li_params['class'] .= ' frm_at_limit';
2601 + }
2602 +
2603 + $li_params['data-limit'] = $limit;
2604 +
2605 + return $li_params;
2606 + }
2607 +
2608 + /**
2216 2609 * Shows Display format option.
2217 2610 *
2218 2611 * @since 5.0.04
2219 2612 *
2220 2613 * @param array $field Field data.
2614 + *
2615 + * @return void
2221 2616 */
2222 2617 public static function show_radio_display_format( $field ) {
2223 2618 $options = self::get_display_format_options( $field );
2619 + $args = self::get_display_format_args( $field, $options );
2224 2620
2225 - $args = self::get_display_format_args( $field, $options );
2226 -
2227 2621 include FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/radio-display-format.php';
2228 2622 }
2229 2623
2230 2624 /**
@@ -2246,9 +2640,9 @@
2246 2640 'text' => __( 'Images', 'formidable' ),
2247 2641 'svg' => 'frm_image_as_option',
2248 2642 'addon' => 'pro',
2249 2643 'upgrade' => __( 'Image Options', 'formidable' ),
2250 - 'message' => __( 'Show images instead of radio buttons or check boxes. This is ideal for polls, surveys, segmenting questionnaires and more.', 'formidable' ) . '<img src="' . esc_url( FrmAppHelper::plugin_url() ) . '/images/image-options.png" />',
2644 + 'message' => __( 'Show images instead of radio buttons or check boxes. This is ideal for polls, surveys, segmenting questionnaires and more.', 'formidable' ) . '<img src="' . esc_url( FrmAppHelper::plugin_url() ) . '/images/image-options.png" />', // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
2251 2645 'content' => 'image-options',
2252 2646 ),
2253 2647 'buttons' => array(
2254 2648 'text' => __( 'Buttons', 'formidable' ),
@@ -2259,8 +2653,12 @@
2259 2653 'content' => 'button-options',
2260 2654 ),
2261 2655 );
2262 2656
2657 + if ( 'product' === FrmField::get_field_type( $field ) ) {
2658 + unset( $options['buttons'] );
2659 + }
2660 +
2263 2661 /**
2264 2662 * Allows modifying the options of Display format setting of Radio field.
2265 2663 *
2266 2664 * @since 5.0.04
@@ -2267,11 +2665,9 @@
2267 2665 *
2268 2666 * @param array $options Options.
2269 2667 * @param array $field
2270 2668 */
2271 - $options = apply_filters( 'frm_' . $field['type'] . '_display_format_options', $options, $field );
2272 -
2273 - return $options;
2669 + return apply_filters( 'frm_' . $field['type'] . '_display_format_options', $options, $field );
2274 2670 }
2275 2671
2276 2672 /**
2277 2673 * Gets display format arguments to pass to the images_dropdown() method.
@@ -2279,8 +2675,9 @@
2279 2675 * @since 5.0.04
2280 2676 *
2281 2677 * @param array $field Field data.
2282 2678 * @param array $options Options array.
2679 + *
2283 2680 * @return array
2284 2681 */
2285 2682 public static function get_display_format_args( $field, $options ) {
2286 2683 $args = array(
@@ -2306,8 +2703,13 @@
2306 2703 }
2307 2704
2308 2705 /**
2309 2706 * @since 5.0.04
2707 + *
2708 + * @param array $options Options.
2709 + * @param array $args Arguments.
2710 + *
2711 + * @return void
2310 2712 */
2311 2713 private static function fill_image_setting_options( $options, &$args ) {
2312 2714 foreach ( $options as $key => $option ) {
2313 2715 $args['options'][ $key ] = $option;
@@ -2317,8 +2719,9 @@
2317 2719 }
2318 2720
2319 2721 unset( $args['options'][ $key ]['addon'] );
2320 2722 $fill = array( 'upgrade', 'message', 'content' );
2723 +
2321 2724 foreach ( $fill as $f ) {
2322 2725 unset( $args['options'][ $key ][ $f ], $f );
2323 2726 }
2324 2727 }
@@ -2326,8 +2729,10 @@
2326 2729
2327 2730 /**
2328 2731 * @since 5.0.04
2329 2732 *
2733 + * @param array $option Option.
2734 + *
2330 2735 * @return array
2331 2736 */
2332 2737 private static function fill_image_setting_addon_link( $option ) {
2333 2738 $custom_attrs = array(
@@ -2338,8 +2743,9 @@
2338 2743 // translators: Add-on name.
2339 2744 $custom_attrs['data-upgrade'] = sprintf( __( 'Formidable %s', 'formidable' ), ucwords( $option['addon'] ) );
2340 2745
2341 2746 $fill = array( 'upgrade', 'message', 'content' );
2747 +
2342 2748 foreach ( $fill as $f ) {
2343 2749 if ( isset( $option[ $f ] ) ) {
2344 2750 $custom_attrs[ 'data-' . $f ] = $option[ $f ];
2345 2751 }
@@ -2349,15 +2755,10 @@
2349 2755 return $custom_attrs;
2350 2756 }
2351 2757
2352 2758 $upgrading = FrmAddonsController::install_link( $option['addon'] );
2353 - if ( isset( $upgrading['url'] ) ) {
2354 - $install_data = wp_json_encode( $upgrading );
2355 - } else {
2356 - $install_data = '';
2357 - }
2358 2759
2359 - $custom_attrs['data-oneclick'] = $install_data;
2760 + $custom_attrs['data-oneclick'] = isset( $upgrading['url'] ) ? wp_json_encode( $upgrading ) : '';
2360 2761 $custom_attrs['data-requires'] = FrmFormsHelper::get_plan_required( $upgrading );
2361 2762
2362 2763 return $custom_attrs;
2363 2764 }
@@ -2370,8 +2771,9 @@
2370 2771 * @since 6.2
2371 2772 *
2372 2773 * @param mixed $value
2373 2774 * @param string $field_type
2775 + *
2374 2776 * @return void
2375 2777 */
2376 2778 public static function prepare_field_value( &$value, $field_type ) {
2377 2779 $field_object = FrmFieldFactory::get_field_type( $field_type );
@@ -2382,8 +2784,9 @@
2382 2784 * @since 6.8
2383 2785 *
2384 2786 * @param int|string $form_id
2385 2787 * @param array $field_ids If this is not empty, the results will be filtered by field id.
2788 + *
2386 2789 * @return array
2387 2790 */
2388 2791 public static function get_draft_field_results( $form_id, $field_ids = array() ) {
2389 2792 if ( FrmAppHelper::pro_is_installed() ) {
@@ -2420,8 +2823,9 @@
2420 2823 *
2421 2824 * @since 6.8
2422 2825 *
2423 2826 * @param int|string $form_id
2827 + *
2424 2828 * @return array
2425 2829 */
2426 2830 public static function get_all_draft_field_ids( $form_id ) {
2427 2831 $draft_field_rows = self::get_draft_field_results( $form_id );
@@ -2434,13 +2838,19 @@
2434 2838 * @since 6.24
2435 2839 *
2436 2840 * @param array $args Field arguments.
2437 2841 * @param bool $should_hide_bulk_edit Whether to hide bulk edit.
2842 + *
2843 + * @return void
2438 2844 */
2439 2845 public static function render_ai_generate_options_button( $args, $should_hide_bulk_edit = false ) {
2440 - $attributes = array( 'class' => self::get_ai_generate_options_button_class() );
2846 + $attributes = array(
2847 + 'type' => 'button',
2848 + );
2441 2849
2442 - if ( ! empty( $should_hide_bulk_edit ) ) {
2850 + $attributes['class'] = ! empty( $args['class'] ) ? $args['class'] : self::get_ai_generate_options_button_class();
2851 +
2852 + if ( $should_hide_bulk_edit ) {
2443 2853 $attributes['class'] .= ' frm-force-hidden';
2444 2854 }
2445 2855
2446 2856 $data = FrmAppHelper::get_upgrade_data_params(
@@ -2446,9 +2856,9 @@
2446 2856 $data = FrmAppHelper::get_upgrade_data_params(
2447 2857 'ai',
2448 2858 array(
2449 2859 'requires' => 'Business',
2450 - 'upgrade' => __( 'Generate options with AI', 'formidable' ),
2860 + 'upgrade' => $args['upgrade_text'] ?? __( 'Generate options with AI', 'formidable' ),
2451 2861 'medium' => 'builder',
2452 2862 'content' => 'generate-options-with-ai',
2453 2863 ),
2454 2864 true
@@ -2455,21 +2865,22 @@
2455 2865 );
2456 2866
2457 2867 if ( in_array( FrmAddonsController::license_type(), array( 'elite', 'business' ), true ) && 'active' === $data['plugin-status'] ) {
2458 2868 // Backwards compatibility "@since 6.24".
2459 - if ( ! method_exists( 'FrmAIAppController', 'get_ai_generated_options_summary' ) ) {
2869 + if ( method_exists( 'FrmAIAppController', 'get_ai_generated_options_summary' ) ) {
2870 + $attributes['class'] .= ' frm-ai-generate-options-modal-trigger';
2871 + $attributes['data-fid'] = $args['likert_id'] ?? $args['field']['id'];
2872 + } else {
2460 2873 $data = array(
2461 2874 'modal-title' => __( 'Generate options with AI', 'formidable' ),
2462 2875 'modal-content' => __( 'Update the Formidable AI add-on to the last version to use this feature.', 'formidable' ),
2463 2876 );
2464 - } else {
2465 - $attributes['class'] .= ' frm-ai-generate-options-modal-trigger';
2466 - $attributes['data-fid'] = $args['likert_id'] ?? $args['field']['id'];
2467 2877 }
2468 2878 }
2469 2879
2470 2880 if ( empty( $attributes['data-fid'] ) ) {
2471 2881 unset( $data['plugin-status'] );
2882 +
2472 2883 foreach ( $data as $key => $value ) {
2473 2884 $attributes[ 'data-' . $key ] = $value;
2474 2885 }
2475 2886 }
@@ -2503,6 +2914,87 @@
2503 2914 'frm-mt-xs',
2504 2915 'frm-mb-12',
2505 2916 )
2506 2917 );
2918 + }
2919 +
2920 + /**
2921 + * Checks if the field choice should be hidden due to choice limit being reached.
2922 + *
2923 + * @since 6.28
2924 + *
2925 + * @param string $choice_key
2926 + * @param array $field
2927 + *
2928 + * @return bool
2929 + */
2930 + public static function should_hide_field_choice( $choice_key, $field ) {
2931 + /**
2932 + * @since 6.28
2933 + *
2934 + * @param bool $hide_field_choice
2935 + * @param string $choice_key
2936 + * @param array $field
2937 + */
2938 + return (bool) apply_filters( 'frm_hide_field_choice', false, $choice_key, $field );
2939 + }
2940 +
2941 + /**
2942 + * @since 6.28
2943 + *
2944 + * @param array $field
2945 + *
2946 + * @return bool
2947 + */
2948 + public static function should_skip_rendering_choices_for_field( $field ) {
2949 + /**
2950 + * @since 6.28
2951 + *
2952 + * @param bool $skip_rendering_options_for_field
2953 + * @param array $field
2954 + */
2955 + return (bool) apply_filters( 'frm_should_skip_rendering_choices_for_field', false, $field );
2956 + }
2957 +
2958 + /**
2959 + * Determine if 'disabled' attribute should be echoed in a field choice's HTML.
2960 + *
2961 + * @since 6.28
2962 + *
2963 + * @param string $choice_key
2964 + * @param bool $is_selected_choice
2965 + * @param array $field
2966 + *
2967 + * @return bool
2968 + */
2969 + public static function should_disable_choice( $choice_key, $is_selected_choice, $field ) {
2970 + /**
2971 + * @since 6.28
2972 + *
2973 + * @param bool $echo_disabled_attribute
2974 + * @param string $choice_key
2975 + * @param bool $is_selected_choice
2976 + * @param array $field
2977 + */
2978 + return (bool) apply_filters( 'frm_disable_choice', false, $choice_key, $is_selected_choice, $field );
2979 + }
2980 +
2981 + /**
2982 + * @since 6.28
2983 + *
2984 + * @param array $field
2985 + * @param string $choice_key
2986 + *
2987 + * @return void
2988 + */
2989 + public static function after_choice_input( $field, $choice_key ) {
2990 + /**
2991 + * Allows adding content after checkbox, radio button, or dropdown fields.
2992 + *
2993 + * @since 6.28
2994 + *
2995 + * @param array $field The field data.
2996 + * @param string $choice_key The option key.
2997 + */
2998 + do_action( 'frm_after_choice_input', $field, $choice_key );
2507 2999 }
2508 3000 }