PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.9
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.9
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
formidable / classes / helpers / FrmFieldsHelper.php

FrmFieldsHelper.php in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More 6.9, at classes/helpers/FrmFieldsHelper.php

2,383 lines 70.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 die( 'You are not allowed to call this page directly.' );
4 }
5
6 class FrmFieldsHelper {
7
8 public static function setup_new_vars( $type = '', $form_id = '' ) {
9
10 if ( strpos( $type, '|' ) ) {
11 list( $type, $setting ) = explode( '|', $type );
12 }
13
14 $values = self::get_default_field( $type );
15
16 global $wpdb;
17 $field_count = FrmDb::get_var(
18 'frm_fields',
19 array( 'form_id' => $form_id ),
20 'field_order',
21 array( 'order_by' => 'field_order DESC' )
22 );
23
24 $values['field_key'] = FrmAppHelper::get_unique_key( '', $wpdb->prefix . 'frm_fields', 'field_key' );
25 $values['form_id'] = $form_id;
26 $values['field_order'] = $field_count + 1;
27
28 $values['field_options']['custom_html'] = self::get_default_html( $type );
29
30 if ( ! empty( $setting ) ) {
31 if ( in_array( $type, array( 'data', 'lookup' ), true ) ) {
32 $values['field_options']['data_type'] = $setting;
33 } else {
34 $values['field_options'][ $setting ] = 1;
35 }
36 }
37
38 // Increase the field order of submit field and fields in the same row.
39 $last_row_field_ids = FrmAppHelper::get_post_param( 'last_row_field_ids', array() );
40 if ( $last_row_field_ids ) {
41 foreach ( $last_row_field_ids as $index => $last_row_field_id ) {
42 FrmField::update(
43 $last_row_field_id,
44 array( 'field_order' => $field_count + $index + 2 )
45 );
46 }
47 }
48
49 return $values;
50 }
51
52 public static function get_html_id( $field, $plus = '' ) {
53 return apply_filters( 'frm_field_html_id', 'field_' . $field['field_key'] . $plus, $field );
54 }
55
56 public static function setup_edit_vars( $field, $doing_ajax = false ) {
57 $values = self::field_object_to_array( $field );
58
59 return apply_filters( 'frm_setup_edit_field_vars', $values, array( 'doing_ajax' => $doing_ajax ) );
60 }
61
62 public static function field_object_to_array( $field ) {
63 $values = (array) $field;
64
65 self::fill_field_array( $field, $values );
66
67 $values['custom_html'] = ( isset( $field->field_options['custom_html'] ) ) ? $field->field_options['custom_html'] : self::get_default_html( $field->type );
68
69 return $values;
70 }
71
72 private static function fill_field_array( $field, array &$field_array ) {
73 $field_array['options'] = $field->options;
74 $field_array['value'] = $field->default_value;
75
76 self::prepare_edit_front_field( $field_array, $field );
77
78 $field_array = array_merge( (array) $field->field_options, $field_array );
79 }
80
81 /**
82 * Prepare field while creating a new entry
83 *
84 * @since 3.0
85 */
86 public static function prepare_new_front_field( &$field_array, $field, $args = array() ) {
87 $args['action'] = 'new';
88 self::prepare_front_field( $field_array, $field, $args );
89 }
90
91 /**
92 * Prepare field while editing an entry
93 *
94 * @since 3.0
95 */
96 public static function prepare_edit_front_field( &$field_array, $field, $entry_id = 0, $args = array() ) {
97 $args['entry_id'] = $entry_id;
98 $args['action'] = 'edit';
99 self::prepare_front_field( $field_array, $field, $args );
100 }
101
102 /**
103 * Prepare field while creating a new entry
104 *
105 * @since 3.0
106 */
107 private static function prepare_front_field( &$field_array, $field, $args ) {
108 self::fill_default_field_opts( $field, $field_array );
109 self::fill_cleared_strings( $field, $field_array );
110
111 // Track the original field's type
112 $field_array['original_type'] = isset( $field->field_options['original_type'] ) ? $field->field_options['original_type'] : $field->type;
113
114 self::prepare_field_options_for_display( $field_array, $field, $args );
115
116 if ( $args['action'] == 'edit' ) {
117 $field_array = apply_filters( 'frm_setup_edit_fields_vars', $field_array, $field, $args['entry_id'], $args );
118 } else {
119 $field_array = apply_filters( 'frm_setup_new_fields_vars', $field_array, $field, $args );
120 }
121 }
122
123 /**
124 * @since 3.0
125 *
126 * @param string $type
127 *
128 * @return array
129 */
130 public static function get_default_field_options( $type ) {
131 $field_type = FrmFieldFactory::get_field_type( $type );
132
133 return $field_type->get_default_field_options();
134 }
135
136 /**
137 * @since 3.0
138 *
139 * @param object $field
140 * @param array $values
141 */
142 private static function fill_default_field_opts( $field, array &$values ) {
143 $check_post = FrmAppHelper::is_admin_page() && $_POST && isset( $_POST['field_options'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
144
145 $defaults = self::get_default_field_options_from_field( $field, $values );
146 if ( ! $check_post ) {
147 $defaults['required_indicator'] = '';
148 $defaults['original_type'] = $field->type;
149 }
150
151 foreach ( $defaults as $opt => $default ) {
152 $values[ $opt ] = isset( $field->field_options[ $opt ] ) ? $field->field_options[ $opt ] : $default;
153
154 if ( $check_post ) {
155 self::get_posted_field_setting( $opt . '_' . $field->id, $values[ $opt ] );
156 }
157
158 unset( $opt, $default );
159 }
160 }
161
162 /**
163 * Fill the required message, invalid message,
164 * and refill the HTML when cleared
165 *
166 * @since 3.0
167 *
168 * @param object $field
169 * @param array $field_array
170 */
171 private static function fill_cleared_strings( $field, array &$field_array ) {
172 if ( '' == $field_array['blank'] && '1' === $field_array['required'] ) {
173 $field_array['blank'] = self::default_blank_msg();
174 }
175
176 if ( '' === $field_array['invalid'] ) {
177 if ( 'captcha' === $field->type ) {
178 $frm_settings = FrmAppHelper::get_settings();
179 $field_array['invalid'] = $frm_settings->re_msg;
180 } else {
181 $field_array['invalid'] = self::default_invalid_msg();
182 }
183 }
184
185 if ( '' == $field_array['custom_html'] ) {
186 $field_array['custom_html'] = self::get_default_html( $field->type );
187 }
188 }
189
190 /**
191 * @since 6.8.3
192 *
193 * @return string
194 */
195 public static function default_invalid_msg() {
196 /* translators: %s: [field_name] shortcode (Which gets replaced by a Field Name) */
197 return sprintf( __( '%s is invalid', 'formidable' ), '[field_name]' );
198 }
199
200 /**
201 * @since 6.8.3
202 *
203 * @return string
204 */
205 public static function default_unique_msg() {
206 $frm_settings = FrmAppHelper::get_settings();
207 $unique_message = $frm_settings->unique_msg;
208 $unique_message = str_replace( 'This value', '[field_name]', $unique_message );
209 return $unique_message;
210 }
211
212 /**
213 * @since 6.8.3
214 *
215 * @return string
216 */
217 public static function default_blank_msg() {
218 $frm_settings = FrmAppHelper::get_settings();
219 $blank_message = $frm_settings->blank_msg;
220 $blank_message = str_replace( 'This field', '[field_name]', $blank_message );
221 return $blank_message;
222 }
223
224 /**
225 * @since 3.0
226 *
227 * @param string $setting
228 * @param mixed $value
229 */
230 private static function get_posted_field_setting( $setting, &$value ) {
231 if ( ! isset( $_POST['field_options'][ $setting ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
232 return;
233 }
234
235 if ( strpos( $setting, 'html' ) !== false ) {
236 // Strip slashes from HTML but not regex or script tags.
237 $value = wp_unslash( $_POST['field_options'][ $setting ] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
238 } elseif ( strpos( $setting, 'format_' ) === 0 ) {
239 // TODO: Remove stripslashes on output, and use on input only.
240 $value = sanitize_text_field( $_POST['field_options'][ $setting ] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.NonceVerification.Missing
241 } else {
242 $value = wp_unslash( $_POST['field_options'][ $setting ] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
243 FrmAppHelper::sanitize_value( 'wp_kses_post', $value );
244 }
245 }
246
247 /**
248 * @since 3.0
249 *
250 * @param object $field
251 * @param array $values The field array is needed for hooks.
252 *
253 * @return array
254 */
255 public static function get_default_field_options_from_field( $field, $values = array() ) {
256 $field_type = self::get_original_field( $field );
257 $opts = $field_type->get_default_field_options();
258
259 $opts = apply_filters( 'frm_default_field_opts', $opts, $values, $field );
260 $opts = apply_filters( 'frm_default_' . $field->type . '_field_opts', $opts, $values, $field );
261
262 return $opts;
263 }
264
265 /**
266 * @since 3.0
267 *
268 * @param object $field
269 *
270 * @return array
271 */
272 private static function get_original_field( $field ) {
273 $original_type = FrmField::get_option( $field, 'original_type' );
274 if ( ! empty( $original_type ) && $field->type != $original_type ) {
275 $field->type = $original_type;
276 }
277
278 return FrmFieldFactory::get_field_object( $field );
279 }
280
281 /**
282 * @since 3.0
283 *
284 * @param array $field_array
285 * @param object $field
286 * @param array $atts
287 */
288 private static function prepare_field_options_for_display( &$field_array, $field, $atts ) {
289 $field_obj = FrmFieldFactory::get_field_object( $field );
290 $field_array = $field_obj->prepare_front_field( $field_array, $atts );
291 }
292
293 /**
294 * @since 3.0
295 *
296 * @param string $type
297 *
298 * @return array
299 */
300 public static function get_default_field( $type ) {
301 $field_type = FrmFieldFactory::get_field_type( $type );
302
303 return $field_type->get_new_field_defaults();
304 }
305
306 public static function fill_field( &$values, $field, $form_id, $new_key = '' ) {
307 global $wpdb;
308
309 $values['field_key'] = FrmAppHelper::get_unique_key( $new_key, $wpdb->prefix . 'frm_fields', 'field_key' );
310 $values['form_id'] = $form_id;
311 $values['options'] = maybe_serialize( $field->options );
312 $values['default_value'] = FrmAppHelper::maybe_json_encode( $field->default_value );
313
314 foreach ( array( 'name', 'description', 'type', 'field_order', 'field_options', 'required' ) as $col ) {
315 $values[ $col ] = $field->{$col};
316 }
317 }
318
319 /**
320 * @since 2.0
321 *
322 * @param object|array $field
323 * @param string $error
324 *
325 * @return string
326 */
327 public static function get_error_msg( $field, $error ) {
328 $frm_settings = FrmAppHelper::get_settings();
329 $default_settings = $frm_settings->default_options();
330
331 $conf_msg = __( 'The entered values do not match', 'formidable' );
332 $defaults = array(
333 'unique_msg' => array(
334 'full' => self::default_unique_msg(),
335 /* translators: %s: Field name */
336 'part' => sprintf( __( '%s must be unique', 'formidable' ), '[field_name]' ),
337 ),
338 'invalid' => array(
339 'full' => __( 'This field is invalid', 'formidable' ),
340 /* translators: %s: Field name */
341 'part' => sprintf( __( '%s is invalid', 'formidable' ), '[field_name]' ),
342 ),
343 'blank' => array(
344 'full' => $frm_settings->blank_msg,
345 'part' => $frm_settings->blank_msg,
346 ),
347 'conf_msg' => array(
348 'full' => $conf_msg,
349 'part' => $conf_msg,
350 ),
351 );
352
353 $msg = FrmField::get_option( $field, $error );
354 $msg = empty( $msg ) ? $defaults[ $error ]['part'] : $msg;
355 $msg = do_shortcode( $msg );
356
357 $msg = self::maybe_replace_substrings_with_field_name( $msg, $error, $field );
358
359 return $msg;
360 }
361
362 /**
363 * @since 6.8.3
364 *
365 * @param string $msg
366 * @param string $error
367 * @param array|object $field
368 */
369 private static function maybe_replace_substrings_with_field_name( $msg, $error, $field ) {
370 $field_name = is_array( $field ) ? $field['name'] : $field->name;
371 $field_name = FrmAppHelper::maybe_kses( $field_name );
372 $substrings = self::get_substrings_to_replace_with_field_name( $field_name, compact( 'msg', 'error', 'field' ) );
373
374 // Use the "This value"/"This field" placeholder strings if field name is empty.
375 if ( ! $field_name ) {
376 if ( 'unique_msg' === $error ) {
377 $field_name = __( 'This value', 'formidable' );
378 } else {
379 $field_name = __( 'This field', 'formidable' );
380 }
381 }
382
383 $msg = str_replace( $substrings, $field_name, $msg );
384 return $msg;
385 }
386
387 /**
388 * @since 6.8.3
389 *
390 * @param string $field_name
391 * @param array $filter_args {
392 * Filter arguments.
393 *
394 * @type string $msg The current error message before the substrings are replaced.
395 * @type string $error A key including 'unique_msg', 'invalid', 'blank', or 'conf_msg'.
396 * @type array|object $field The field with the error.
397 * }
398 * @return array
399 */
400 private static function get_substrings_to_replace_with_field_name( $field_name, $filter_args ) {
401 $substrings = array( '[field_name]' );
402 if ( $field_name ) {
403 array_push( $substrings, 'This value', 'This field' );
404 }
405
406 /**
407 * @since 6.8.3
408 *
409 * @param array<string> $substrings
410 * @param array $filter_args
411 */
412 $filtered_substrings = apply_filters( 'frm_error_substrings_to_replace_with_field_name', $substrings, $filter_args );
413
414 if ( is_array( $filtered_substrings ) ) {
415 $substrings = $filtered_substrings;
416 } else {
417 _doing_it_wrong( __FUNCTION__, 'Only arrays should be returned when using the frm_error_substrings_to_replace_with_field_name filter.', '6.8.3' );
418 }
419
420 return $substrings;
421 }
422
423 public static function get_form_fields( $form_id, $error = array() ) {
424 $fields = FrmField::get_all_for_form( $form_id );
425
426 return apply_filters( 'frm_get_paged_fields', $fields, $form_id, $error );
427 }
428
429 public static function get_default_html( $type = 'text' ) {
430 $field = FrmFieldFactory::get_field_type( $type );
431 $default_html = $field->default_html();
432
433 // these hooks are here for reverse compatibility since 3.0
434 if ( ! apply_filters( 'frm_normal_field_type_html', true, $type ) ) {
435 $default_html = apply_filters( 'frm_other_custom_html', '', $type );
436 }
437
438 return apply_filters( 'frm_custom_html', $default_html, $type );
439 }
440
441 /**
442 * @param array $fields
443 * @param array $errors
444 * @param object $form
445 * @param object $form_action
446 */
447 public static function show_fields( $fields, $errors, $form, $form_action ) {
448 foreach ( $fields as $field ) {
449 $field_obj = FrmFieldFactory::get_field_type( $field['type'], $field );
450 $field_obj->show_field( compact( 'errors', 'form', 'form_action' ) );
451 }
452 }
453
454 /**
455 * @since 3.0
456 *
457 * @param array $atts
458 * @param string|array $value
459 */
460 public static function run_wpautop( $atts, &$value ) {
461 $autop = isset( $atts['wpautop'] ) ? $atts['wpautop'] : true;
462 if ( apply_filters( 'frm_use_wpautop', $autop ) ) {
463 if ( is_array( $value ) ) {
464 $value = implode( "\n", $value );
465 }
466 $value = wpautop( $value );
467 }
468 }
469
470 /**
471 * Get the class to use for the label position
472 *
473 * @since 2.05
474 */
475 public static function &label_position( $position, $field, $form ) {
476 if ( $position && $position != '' ) {
477 if ( $position == 'inside' && ! self::is_placeholder_field_type( $field['type'] ) ) {
478 $position = 'top';
479 }
480
481 return $position;
482 }
483
484 $position = FrmStylesController::get_style_val( 'position', $form );
485 if ( $position == 'none' ) {
486 $position = 'top';
487 } elseif ( $position == 'no_label' ) {
488 $position = 'none';
489 } elseif ( $position == 'inside' && ! self::is_placeholder_field_type( $field['type'] ) ) {
490 $position = 'top';
491 }
492
493 $position = apply_filters( 'frm_html_label_position', $position, $field, $form );
494 $position = ( ! empty( $position ) ) ? $position : 'top';
495
496 return $position;
497 }
498
499 /**
500 * Check if this field type allows placeholders
501 *
502 * @since 2.05
503 * @param string $type
504 * @return bool
505 */
506 public static function is_placeholder_field_type( $type ) {
507 return ! in_array( $type, array( 'radio', 'checkbox', 'hidden', 'file' ), true );
508 }
509
510 public static function get_checkbox_id( $field, $opt_key, $type = 'checkbox' ) {
511 $id = $field['id'];
512 if ( isset( $field['in_section'] ) && $field['in_section'] && ! FrmAppHelper::is_admin_page( 'formidable' ) ) {
513 $id .= '-' . $field['in_section'];
514 }
515
516 return 'frm_' . $type . '_' . $id . '-' . $opt_key;
517 }
518
519 public static function show_single_option( $field ) {
520 self::hidden_field_option( $field );
521
522 if ( ! is_array( $field['options'] ) ) {
523 return;
524 }
525
526 $base_name = 'default_value_' . $field['id'];
527 $html_id = isset( $field['html_id'] ) ? $field['html_id'] : self::get_html_id( $field );
528
529 $default_type = self::get_default_value_type( $field );
530
531 foreach ( $field['options'] as $opt_key => $opt ) {
532 $field_val = self::get_value_from_array( $opt, $opt_key, $field );
533 $opt = self::get_label_from_array( $opt, $opt_key, $field );
534
535 $field_name = $base_name . ( $default_type === 'checkbox' ? '[' . $opt_key . ']' : '' );
536
537 $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'] ) ) ) );
538
539 // If this is an "Other" option, get the HTML for it.
540 if ( self::is_other_opt( $opt_key ) ) {
541 if ( FrmAppHelper::pro_is_installed() ) {
542 require FrmProAppHelper::plugin_path() . '/classes/views/frmpro-fields/other-option.php';
543 }
544 } else {
545 require FrmAppHelper::plugin_path() . '/classes/views/frm-fields/single-option.php';
546 }
547
548 unset( $checked );
549 }
550 }
551
552 /**
553 * Include hidden row for javascript to duplicate.
554 *
555 * @since 4.0
556 * @param array $field
557 */
558 private static function hidden_field_option( $field ) {
559 // Don't duplicate during an ajax add option.
560 $ajax_action = FrmAppHelper::get_param( 'action', '', 'post', 'sanitize_text_field' );
561 if ( $ajax_action === 'frm_add_field_option' ) {
562 return;
563 }
564
565 $opt_key = '000';
566 $field_val = __( 'New Option', 'formidable' );
567 $opt = __( 'New Option', 'formidable' );
568 $checked = false;
569 $field_name = 'default_value_' . $field['id'];
570 $html_id = isset( $field['html_id'] ) ? $field['html_id'] : self::get_html_id( $field );
571
572 $default_type = self::get_default_value_type( $field );
573 $field_name .= ( $default_type === 'checkbox' ? '[' . $opt_key . ']' : '' );
574
575 require FrmAppHelper::plugin_path() . '/classes/views/frm-fields/single-option.php';
576 }
577
578 /**
579 * @since 4.0
580 *
581 * @param array $field
582 * @return string radio or checkbox
583 */
584 private static function get_default_value_type( $field ) {
585 $default_type = $field['type'];
586 if ( $field['type'] === 'select' ) {
587 $default_type = FrmField::is_multiple_select( $field ) ? 'checkbox' : 'radio';
588 }
589 return $default_type;
590 }
591
592 public static function get_value_from_array( $opt, $opt_key, $field ) {
593 $opt = apply_filters( 'frm_field_value_saved', $opt, $opt_key, $field );
594
595 return FrmFieldsController::check_value( $opt, $opt_key, $field );
596 }
597
598 public static function get_label_from_array( $opt, $opt_key, $field ) {
599 $opt = apply_filters( 'frm_field_label_seen', $opt, $opt_key, $field );
600
601 return FrmFieldsController::check_label( $opt );
602 }
603
604 /**
605 * Shows the inline modal.
606 *
607 * @since 4.0
608 * @since 6.4.1 Added `inside_class` in the arguments.
609 *
610 * @param array $args The arguments.
611 */
612 public static function inline_modal( $args ) {
613 $defaults = array(
614 'id' => '',
615 'class' => '',
616 'show' => 0,
617 'callback' => array(),
618 'args' => array(),
619 'title' => '',
620 'inside_class' => 'inside',
621 );
622 $args = array_merge( $defaults, $args );
623
624 include FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/inline-modal.php';
625 }
626
627 /**
628 * @since 4.0
629 */
630 public static function smart_values() {
631 $continue = apply_filters( 'frm_smart_values_box', true );
632 if ( $continue === true ) {
633 $upgrade_link = array(
634 'medium' => 'builder',
635 'content' => 'smart-tags',
636 );
637 include FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/smart-values.php';
638 }
639 }
640
641 /**
642 * @since 4.0
643 */
644 public static function input_mask() {
645 include FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/input-mask-info.php';
646 }
647
648 /**
649 * @since 4.0
650 */
651 public static function layout_classes() {
652 include FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/layout-classes.php';
653 }
654
655 /**
656 * @param int $tax_id
657 *
658 * @return string
659 */
660 public static function get_term_link( $tax_id ) {
661 $tax = get_taxonomy( $tax_id );
662 if ( ! $tax ) {
663 return '';
664 }
665
666 $link = sprintf(
667 /* translators: %1$s: Start HTML link, %2$s: Content type label, %3$s: Content type, %4$s: End HTML link */
668 esc_html__( 'Options are dynamically created from your %1$s%2$s: %3$s%4$s', 'formidable' ),
669 '<a href="' . esc_url( admin_url( 'edit-tags.php?taxonomy=' . $tax->name ) ) . '" target="_blank">',
670 esc_html__( 'taxonomy', 'formidable' ),
671 empty( $tax->labels->name ) ? esc_html__( 'Categories', 'formidable' ) : $tax->labels->name,
672 '</a>'
673 );
674 unset( $tax );
675
676 return $link;
677 }
678
679 public static function value_meets_condition( $observed_value, $cond, $hide_opt ) {
680 $hide_opt = self::get_value_for_comparision( $hide_opt );
681 $observed_value = self::get_value_for_comparision( $observed_value );
682
683 if ( is_array( $observed_value ) ) {
684 return self::array_value_condition( $observed_value, $cond, $hide_opt );
685 }
686
687 $m = false;
688 if ( $cond === '==' ) {
689 $m = $observed_value == $hide_opt;
690 } elseif ( $cond === '!=' ) {
691 $m = $observed_value != $hide_opt;
692 } elseif ( $cond === '>' ) {
693 $m = $observed_value > $hide_opt;
694 } elseif ( $cond === '>=' ) {
695 $m = $observed_value >= $hide_opt;
696 } elseif ( $cond === '<' ) {
697 $m = $observed_value < $hide_opt;
698 } elseif ( $cond === '<=' ) {
699 $m = $observed_value <= $hide_opt;
700 } elseif ( $cond === 'LIKE' || $cond === 'not LIKE' ) {
701 $m = stripos( $observed_value, $hide_opt );
702 if ( $cond === 'not LIKE' ) {
703 $m = ( $m === false ) ? true : false;
704 } else {
705 $m = ( $m === false ) ? false : true;
706 }
707 } elseif ( $cond === '%LIKE' ) {
708 // ends with
709 $length = strlen( $hide_opt );
710 $substr = substr( $observed_value, strlen( $observed_value ) - $length );
711 $m = 0 === strcasecmp( $substr, $hide_opt );
712 } elseif ( 'LIKE%' === $cond ) {
713 // starts with
714 $length = strlen( $hide_opt );
715 $substr = substr( $observed_value, 0, $length );
716 $m = 0 === strcasecmp( $substr, $hide_opt );
717 }//end if
718
719 return $m;
720 }
721
722 /**
723 * Trim and sanitize the values
724 *
725 * @since 2.05
726 */
727 private static function get_value_for_comparision( $value ) {
728 // Remove white space from hide_opt
729 if ( ! is_array( $value ) ) {
730 $value = trim( $value );
731 }
732
733 FrmAppHelper::sanitize_value( 'wp_kses_post', $value );
734
735 return $value;
736 }
737
738 public static function array_value_condition( $observed_value, $cond, $hide_opt ) {
739 $m = false;
740 if ( $cond === '==' ) {
741 if ( is_array( $hide_opt ) ) {
742 $m = array_intersect( $hide_opt, $observed_value );
743 $m = empty( $m ) ? false : true;
744 } else {
745 $m = in_array( $hide_opt, $observed_value );
746 }
747 } elseif ( $cond === '!=' ) {
748 $m = ! in_array( $hide_opt, $observed_value );
749 } elseif ( $cond === '>' ) {
750 $min = min( $observed_value );
751 $m = $min > $hide_opt;
752 } elseif ( $cond === '<' ) {
753 $max = max( $observed_value );
754 $m = $max < $hide_opt;
755 } elseif ( $cond === 'LIKE' || $cond === 'not LIKE' ) {
756 foreach ( $observed_value as $ob ) {
757 $m = strpos( $ob, $hide_opt );
758 if ( $m !== false ) {
759 $m = true;
760 break;
761 }
762 }
763
764 if ( $cond === 'not LIKE' ) {
765 $m = ( $m === false ) ? true : false;
766 }
767 } elseif ( $cond === '%LIKE' ) {
768 // ends with
769 foreach ( $observed_value as $ob ) {
770 if ( $hide_opt === substr( $ob, strlen( $ob ) - strlen( $hide_opt ) ) ) {
771 $m = true;
772 break;
773 }
774 }
775 } elseif ( $cond === 'LIKE%' ) {
776 // starts with
777 foreach ( $observed_value as $ob ) {
778 if ( $hide_opt === substr( $ob, 0, strlen( $hide_opt ) ) ) {
779 $m = true;
780 break;
781 }
782 }
783 }//end if
784
785 return $m;
786 }
787
788 /**
789 * Replace a few basic shortcodes and field ids
790 *
791 * @since 2.0
792 * @return string
793 */
794 public static function basic_replace_shortcodes( $value, $form, $entry ) {
795 if ( strpos( $value, '[sitename]' ) !== false ) {
796 $new_value = wp_specialchars_decode( FrmAppHelper::site_name(), ENT_QUOTES );
797 $value = str_replace( '[sitename]', $new_value, $value );
798 }
799
800 $value = apply_filters( 'frm_content', $value, $form, $entry );
801 $value = do_shortcode( $value );
802
803 return $value;
804 }
805
806 public static function get_shortcodes( $content, $form_id ) {
807 if ( FrmAppHelper::pro_is_installed() ) {
808 return FrmProDisplaysHelper::get_shortcodes( $content, $form_id );
809 }
810
811 $fields = FrmField::getAll(
812 array(
813 'fi.form_id' => (int) $form_id,
814 'fi.type not' => FrmField::no_save_fields(),
815 )
816 );
817
818 $tagregexp = self::allowed_shortcodes( $fields );
819
820 preg_match_all( "/\[(if )?($tagregexp)\b(.*?)(?:(\/))?\](?:(.+?)\[\/\2\])?/s", $content, $matches, PREG_PATTERN_ORDER );
821
822 return $matches;
823 }
824
825 public static function allowed_shortcodes( $fields = array() ) {
826 $tagregexp = array(
827 'editlink',
828 'id',
829 'key',
830 'ip',
831 'siteurl',
832 'sitename',
833 'admin_email',
834 'post[-|_]id',
835 'created[-|_]at',
836 'updated[-|_]at',
837 'updated[-|_]by',
838 'parent[-|_]id',
839 );
840
841 foreach ( $fields as $field ) {
842 $tagregexp[] = $field->id;
843 $tagregexp[] = $field->field_key;
844 }
845
846 $tagregexp = implode( '|', $tagregexp );
847
848 return $tagregexp;
849 }
850
851 public static function replace_content_shortcodes( $content, $entry, $shortcodes ) {
852 foreach ( $shortcodes[0] as $short_key => $tag ) {
853 if ( empty( $tag ) ) {
854 continue;
855 }
856
857 $atts = FrmShortcodeHelper::get_shortcode_attribute_array( $shortcodes[3][ $short_key ] );
858 $tag = FrmShortcodeHelper::get_shortcode_tag( $shortcodes, $short_key );
859
860 $atts['entry'] = $entry;
861 $atts['tag'] = $tag;
862 $replace_with = self::get_value_for_shortcode( $atts );
863
864 if ( $replace_with !== null ) {
865 $replace_with = self::trigger_shortcode_atts( $replace_with, $atts );
866 self::sanitize_embedded_shortcodes( compact( 'entry' ), $replace_with );
867 $content = str_replace( $shortcodes[0][ $short_key ], $replace_with, $content );
868 }
869
870 unset( $atts, $replace_with );
871 }
872
873 return $content;
874 }
875
876 /**
877 * @param string $replace_with
878 * @param array $atts
879 * @return string
880 */
881 private static function trigger_shortcode_atts( $replace_with, $atts ) {
882 $supported_atts = array( 'remove_accents', 'sanitize', 'sanitize_url' );
883 $included_atts = array_intersect( $supported_atts, array_keys( $atts ) );
884 foreach ( $included_atts as $included_att ) {
885 if ( '0' === $atts[ $included_att ] ) {
886 // Skip any option that uses 0 so sanitize_url=0 does not encode.
887 continue;
888 }
889 $function = 'atts_' . $included_att;
890 $replace_with = self::$function( $replace_with, $atts );
891 }
892 return $replace_with;
893 }
894
895 /**
896 * Converts all accent characters to ASCII characters.
897 *
898 * @since 6.3.1
899 *
900 * @param string $replace_with The text to remove accents from.
901 *
902 * @return string
903 */
904 public static function atts_remove_accents( $replace_with ) {
905 return remove_accents( $replace_with );
906 }
907
908 /**
909 * @param string $replace_with
910 * @return string
911 */
912 private static function atts_sanitize( $replace_with ) {
913 return sanitize_title_with_dashes( $replace_with );
914 }
915
916 /**
917 * @param string $replace_with
918 * @return string
919 */
920 private static function atts_sanitize_url( $replace_with ) {
921 return urlencode( $replace_with );
922 }
923
924 /**
925 * Prevent shortcodes in fields from being processed
926 *
927 * @since 3.01.02
928 *
929 * @param array $atts Includes entry object.
930 * @param string $value
931 */
932 public static function sanitize_embedded_shortcodes( $atts, &$value ) {
933 $atts['value'] = $value;
934 $should_sanitize = apply_filters( 'frm_sanitize_shortcodes', true, $atts );
935 if ( $should_sanitize ) {
936 $value = str_replace( '[', '&#91;', $value );
937 }
938 }
939
940 /**
941 * @since 3.0
942 *
943 * @param array $atts
944 *
945 * @return string
946 */
947 private static function get_value_for_shortcode( $atts ) {
948 $clean_tag = str_replace( '-', '_', $atts['tag'] );
949
950 $shortcode_values = array(
951 'id' => $atts['entry']->id,
952 'key' => $atts['entry']->item_key,
953 'ip' => $atts['entry']->ip,
954 );
955
956 $dynamic_default = array( 'admin_email', 'siteurl', 'frmurl', 'sitename', 'get' );
957
958 if ( isset( $shortcode_values[ $atts['tag'] ] ) ) {
959 $replace_with = $shortcode_values[ $atts['tag'] ];
960 } elseif ( in_array( $atts['tag'], $dynamic_default ) ) {
961 $replace_with = self::dynamic_default_values( $atts['tag'], $atts );
962 } elseif ( $clean_tag === 'user_agent' ) {
963 $description = $atts['entry']->description;
964 $replace_with = FrmEntriesHelper::get_browser( $description['browser'] );
965 } elseif ( $clean_tag === 'created_at' || $clean_tag === 'updated_at' ) {
966 $atts['tag'] = $clean_tag;
967 $replace_with = self::get_entry_timestamp( $atts );
968 } elseif ( $clean_tag === 'created_by' || $clean_tag === 'updated_by' ) {
969 $replace_with = self::get_display_value( $atts['entry']->{$clean_tag}, (object) array( 'type' => 'user_id' ), $atts );
970 } else {
971 $replace_with = self::get_field_shortcode_value( $atts );
972 }
973
974 return $replace_with;
975 }
976
977 /**
978 * @since 3.0
979 *
980 * @param array $atts
981 *
982 * @return string
983 */
984 private static function get_entry_timestamp( $atts ) {
985 if ( isset( $atts['format'] ) ) {
986 $time_format = ' ';
987 } else {
988 $atts['format'] = get_option( 'date_format' );
989 $time_format = '';
990 }
991
992 return FrmAppHelper::get_formatted_time( $atts['entry']->{$atts['tag']}, $atts['format'], $time_format );
993 }
994
995 /**
996 * @since 3.0
997 *
998 * @param array $atts
999 *
1000 * @return null|string
1001 */
1002 private static function get_field_shortcode_value( $atts ) {
1003 $field = FrmField::getOne( $atts['tag'] );
1004 if ( empty( $field ) ) {
1005 return null;
1006 }
1007
1008 if ( isset( $atts['show'] ) && $atts['show'] === 'field_label' ) {
1009 $replace_with = $field->name;
1010 } elseif ( isset( $atts['show'] ) && $atts['show'] === 'description' ) {
1011 $replace_with = $field->description;
1012 } else {
1013 $replace_with = FrmEntryMeta::get_meta_value( $atts['entry'], $field->id );
1014 $string_value = $replace_with;
1015 if ( is_array( $replace_with ) ) {
1016 $sep = isset( $atts['sep'] ) ? $atts['sep'] : ', ';
1017 $string_value = implode( $sep, $replace_with );
1018 }
1019
1020 if ( empty( $string_value ) && $string_value != '0' ) {
1021 $replace_with = '';
1022 } else {
1023 $atts['entry_id'] = $atts['entry']->id;
1024 $atts['entry_key'] = $atts['entry']->item_key;
1025 $replace_with = self::get_display_value( $replace_with, $field, $atts );
1026 }
1027 }
1028
1029 return $replace_with;
1030 }
1031
1032 /**
1033 * Get the value to replace a few standard shortcodes
1034 *
1035 * @since 2.0
1036 * @return string
1037 */
1038 public static function dynamic_default_values( $tag, $atts = array(), $return_array = false ) {
1039 $new_value = '';
1040 switch ( $tag ) {
1041 case 'admin_email':
1042 $new_value = get_option( 'admin_email' );
1043 break;
1044 case 'siteurl':
1045 $new_value = FrmAppHelper::site_url();
1046 break;
1047 case 'frmurl':
1048 $new_value = FrmAppHelper::plugin_url();
1049 break;
1050 case 'sitename':
1051 $new_value = FrmAppHelper::site_name();
1052 break;
1053 case 'get':
1054 $new_value = self::process_get_shortcode( $atts, $return_array );
1055 }
1056
1057 return $new_value;
1058 }
1059
1060 /**
1061 * Process the [get] shortcode
1062 *
1063 * @since 2.0
1064 * @return string|array
1065 */
1066 public static function process_get_shortcode( $atts, $return_array = false ) {
1067 if ( ! isset( $atts['param'] ) ) {
1068 return '';
1069 }
1070
1071 if ( strpos( $atts['param'], '&#91;' ) ) {
1072 $atts['param'] = str_replace( '&#91;', '[', $atts['param'] );
1073 $atts['param'] = str_replace( '&#93;', ']', $atts['param'] );
1074 }
1075
1076 $new_value = FrmAppHelper::get_param( $atts['param'], '', 'get', 'sanitize_text_field' );
1077 $new_value = FrmAppHelper::get_query_var( $new_value, $atts['param'] );
1078
1079 if ( $new_value == '' ) {
1080 if ( ! isset( $atts['prev_val'] ) ) {
1081 $atts['prev_val'] = '';
1082 }
1083
1084 $new_value = isset( $atts['default'] ) ? $atts['default'] : $atts['prev_val'];
1085 }
1086
1087 if ( is_array( $new_value ) && ! $return_array ) {
1088 $new_value = implode( ', ', $new_value );
1089 }
1090
1091 return $new_value;
1092 }
1093
1094 public static function get_display_value( $value, $field, $atts = array() ) {
1095
1096 $value = apply_filters( 'frm_get_' . $field->type . '_display_value', $value, $field, $atts );
1097 $value = apply_filters( 'frm_get_display_value', $value, $field, $atts );
1098
1099 $value = self::get_unfiltered_display_value( compact( 'value', 'field', 'atts' ) );
1100
1101 return apply_filters( 'frm_display_value', $value, $field, $atts );
1102 }
1103
1104 /**
1105 * @param array $atts Includes value, field, and atts.
1106 */
1107 public static function get_unfiltered_display_value( $atts ) {
1108 $value = $atts['value'];
1109 $field = $atts['field'];
1110 $atts = isset( $atts['atts'] ) ? $atts['atts'] : $atts;
1111
1112 if ( is_array( $field ) ) {
1113 $field = $field['id'];
1114 }
1115
1116 $field_obj = FrmFieldFactory::get_field_object( $field );
1117
1118 return $field_obj->get_display_value( $value, $atts );
1119 }
1120
1121 /**
1122 * Get a value from the user profile from the user ID
1123 *
1124 * @since 3.0
1125 */
1126 public static function get_user_display_name( $user_id, $user_info = 'display_name', $args = array() ) {
1127 $defaults = array(
1128 'blank' => false,
1129 'link' => false,
1130 'size' => 96,
1131 );
1132
1133 $args = wp_parse_args( $args, $defaults );
1134
1135 $user = get_userdata( $user_id );
1136 $info = '';
1137
1138 if ( $user ) {
1139 if ( $user_info == 'avatar' ) {
1140 $info = get_avatar( $user_id, $args['size'] );
1141 } elseif ( $user_info == 'author_link' ) {
1142 $info = get_author_posts_url( $user_id );
1143 } else {
1144 $info = isset( $user->$user_info ) ? $user->$user_info : '';
1145 }
1146
1147 if ( 'display_name' === $user_info && empty( $info ) && ! $args['blank'] ) {
1148 $info = $user->user_login;
1149 }
1150 }
1151
1152 if ( $args['link'] ) {
1153 $info = '<a href="' . esc_url( admin_url( 'user-edit.php?user_id=' . $user_id ) ) . '">' . $info . '</a>';
1154 }
1155
1156 return $info;
1157 }
1158
1159 public static function get_field_types( $type ) {
1160 $single_input = self::single_input_fields();
1161 $multiple_input = array( 'radio', 'checkbox', 'select', 'scale', 'star', 'lookup' );
1162
1163 $field_selection = FrmField::all_field_selection();
1164
1165 $field_types = array();
1166 if ( in_array( $type, $single_input ) ) {
1167 self::field_types_for_input( $single_input, $field_selection, $field_types );
1168 } elseif ( in_array( $type, $multiple_input ) ) {
1169 self::field_types_for_input( $multiple_input, $field_selection, $field_types );
1170 } elseif ( isset( $field_selection[ $type ] ) ) {
1171 $field_types[ $type ] = $field_selection[ $type ];
1172 }
1173
1174 $field_types = apply_filters( 'frm_switch_field_types', $field_types, compact( 'type', 'field_selection' ) );
1175
1176 return $field_types;
1177 }
1178
1179 /**
1180 * Get a list of all fields that use a single value input.
1181 *
1182 * @since 4.0
1183 */
1184 public static function single_input_fields() {
1185 $fields = array(
1186 'text',
1187 'textarea',
1188 'rte',
1189 'number',
1190 'email',
1191 'url',
1192 'date',
1193 'phone',
1194 'hidden',
1195 'time',
1196 'tag',
1197 'password',
1198 );
1199 return apply_filters( 'frm_single_input_fields', $fields );
1200 }
1201
1202 private static function field_types_for_input( $inputs, $fields, &$field_types ) {
1203 foreach ( $inputs as $input ) {
1204 $field_types[ $input ] = $fields[ $input ];
1205 unset( $input );
1206 }
1207 }
1208
1209 /**
1210 * Check if current field option is an "other" option
1211 *
1212 * @since 2.0.6
1213 *
1214 * @param string $opt_key
1215 *
1216 * @return boolean Returns true if current field option is an "Other" option
1217 */
1218 public static function is_other_opt( $opt_key ) {
1219 return $opt_key && strpos( $opt_key, 'other_' ) === 0;
1220 }
1221
1222 /**
1223 * Get value that belongs in "Other" text box
1224 *
1225 * @since 2.0.6
1226 *
1227 * @param array $args
1228 */
1229 public static function get_other_val( $args ) {
1230 $defaults = array(
1231 'opt_key' => 0,
1232 'field' => array(),
1233 'parent' => false,
1234 'pointer' => false,
1235 );
1236 $args = wp_parse_args( $args, $defaults );
1237
1238 $opt_key = $args['opt_key'];
1239 $field = $args['field'];
1240 $parent = $args['parent'];
1241 $pointer = $args['pointer'];
1242 $other_val = '';
1243
1244 // If option is an "other" option and there is a value set for this field,
1245 // check if the value belongs in the current "Other" option text field
1246 if ( ! self::is_other_opt( $opt_key ) || ! FrmField::is_option_true( $field, 'value' ) ) {
1247 return $other_val;
1248 }
1249
1250 // Check posted vals before checking saved values
1251 // For fields inside repeating sections - note, don't check if $pointer is true because it will often be zero
1252 if ( $parent && isset( $_POST['item_meta'][ $parent ][ $pointer ]['other'][ $field['id'] ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
1253 if ( FrmField::is_field_with_multiple_values( $field ) ) {
1254 // phpcs:ignore WordPress.Security.NonceVerification.Missing
1255 $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 ] ) ) : '';
1256 } else {
1257 $other_val = sanitize_text_field( wp_unslash( $_POST['item_meta'][ $parent ][ $pointer ]['other'][ $field['id'] ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
1258 }
1259
1260 return $other_val;
1261
1262 } elseif ( isset( $field['id'] ) && isset( $_POST['item_meta']['other'][ $field['id'] ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
1263 // For normal fields
1264
1265 if ( FrmField::is_field_with_multiple_values( $field ) ) {
1266 // phpcs:ignore WordPress.Security.NonceVerification.Missing
1267 $other_val = isset( $_POST['item_meta']['other'][ $field['id'] ][ $opt_key ] ) ? sanitize_text_field( wp_unslash( $_POST['item_meta']['other'][ $field['id'] ][ $opt_key ] ) ) : '';
1268 } else {
1269 $other_val = sanitize_text_field( wp_unslash( $_POST['item_meta']['other'][ $field['id'] ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
1270 }
1271
1272 return $other_val;
1273 }//end if
1274
1275 // For checkboxes
1276 if ( $field['type'] === 'checkbox' && is_array( $field['value'] ) ) {
1277 // Check if there is an "other" val in saved value and make sure the
1278 // "other" val is not equal to the Other checkbox option
1279 if ( isset( $field['value'][ $opt_key ] ) && $field['options'][ $opt_key ] != $field['value'][ $opt_key ] ) {
1280 $other_val = $field['value'][ $opt_key ];
1281 }
1282 } else {
1283 /**
1284 * For radio buttons and dropdowns
1285 * Check if saved value equals any of the options. If not, set it as the other value.
1286 */
1287 foreach ( $field['options'] as $opt_key => $opt_val ) {
1288 $temp_val = is_array( $opt_val ) ? $opt_val['value'] : $opt_val;
1289 // Multi-select dropdowns - key is not preserved
1290 if ( is_array( $field['value'] ) ) {
1291 $o_key = array_search( $temp_val, $field['value'] );
1292 if ( isset( $field['value'][ $o_key ] ) ) {
1293 unset( $field['value'][ $o_key ], $o_key );
1294 }
1295 } elseif ( $temp_val == $field['value'] ) {
1296 // For radio and regular dropdowns
1297 return '';
1298 } else {
1299 $other_val = $field['value'];
1300 }
1301 unset( $opt_key, $opt_val, $temp_val );
1302 }
1303 // For multi-select dropdowns only
1304 if ( is_array( $field['value'] ) && ! empty( $field['value'] ) ) {
1305 $other_val = reset( $field['value'] );
1306 }
1307 }//end if
1308
1309 return $other_val;
1310 }
1311
1312 /**
1313 * Check if there is a saved value for the "Other" text field. If so, set it as the $other_val.
1314 * Intended for front-end use
1315 *
1316 * @since 2.0.6
1317 *
1318 * @param array $args Should include field, opt_key and field name.
1319 * @param boolean $other_opt
1320 * @param string $checked
1321 *
1322 * @return array $other_args
1323 */
1324 public static function prepare_other_input( $args, &$other_opt, &$checked ) {
1325 $other_args = array(
1326 'name' => '',
1327 'value' => '',
1328 );
1329
1330 // Check if this is an "Other" option.
1331 if ( ! self::is_other_opt( $args['opt_key'] ) ) {
1332 return $other_args;
1333 }
1334
1335 $other_opt = true;
1336
1337 self::set_other_name( $args, $other_args );
1338 self::set_other_value( $args, $other_args );
1339
1340 if ( '' !== $other_args['value'] ) {
1341 $checked = 'checked="checked" ';
1342 }
1343
1344 // If 'other' is selected as one of the default values for a checkbox field, 'checked' attribute should be on.
1345 if ( ! $checked &&
1346 $args['field']['type'] === 'checkbox' &&
1347 is_array( $args['field']['value'] ) &&
1348 isset( $args['field_val'] ) &&
1349 in_array( $args['field_val'], $args['field']['value'], true )
1350 ) {
1351 $checked = 'checked="checked" ';
1352 }
1353
1354 return $other_args;
1355 }
1356
1357 /**
1358 * @param array $args
1359 * @param array $other_args
1360 *
1361 * @since 2.0.6
1362 */
1363 private static function set_other_name( $args, &$other_args ) {
1364 // Set up name for other field
1365 $other_args['name'] = str_replace( '[]', '', $args['field_name'] );
1366 $other_args['name'] = preg_replace( '/\[' . $args['field']['id'] . '\]$/', '', $other_args['name'] );
1367 $other_args['name'] = $other_args['name'] . '[other][' . $args['field']['id'] . ']';
1368
1369 // Converts item_meta[field_id] => item_meta[other][field_id] and
1370 // item_meta[parent][0][field_id] => item_meta[parent][0][other][field_id]
1371 if ( FrmField::is_field_with_multiple_values( $args['field'] ) ) {
1372 $other_args['name'] .= '[' . $args['opt_key'] . ']';
1373 }
1374 }
1375
1376 /**
1377 * Find the parent and pointer, and get text for "other" text field
1378 *
1379 * @param array $args
1380 * @param array $other_args
1381 *
1382 * @since 2.0.6
1383 */
1384 private static function set_other_value( $args, &$other_args ) {
1385 $parent = '';
1386 $pointer = '';
1387
1388 // Check for parent ID and pointer
1389 $temp_array = explode( '[', $args['field_name'] );
1390
1391 // Count should only be greater than 3 if inside of a repeating section
1392 if ( count( $temp_array ) > 3 ) {
1393 $parent = str_replace( ']', '', $temp_array[1] );
1394 $pointer = str_replace( ']', '', $temp_array[2] );
1395 }
1396
1397 // Get text for "other" text field
1398 $other_args['value'] = self::get_other_val(
1399 array(
1400 'opt_key' => $args['opt_key'],
1401 'field' => $args['field'],
1402 'parent' => $parent,
1403 'pointer' => $pointer,
1404 )
1405 );
1406 }
1407
1408 /**
1409 * If this field includes an other option, show it
1410 *
1411 * @param array $args
1412 *
1413 * @since 2.0.6
1414 */
1415 public static function include_other_input( $args ) {
1416 if ( ! $args['other_opt'] ) {
1417 return;
1418 }
1419
1420 $classes = array( 'frm_other_input' );
1421 if ( ! $args['checked'] || trim( $args['checked'] ) == '' ) {
1422 // hide the field if the other option is not selected
1423 $classes[] = 'frm_pos_none';
1424 }
1425 if ( $args['field']['type'] == 'select' && $args['field']['multiple'] ) {
1426 $classes[] = 'frm_other_full';
1427 }
1428
1429 // Set up HTML ID for Other field
1430 $other_id = self::get_other_field_html_id( $args['field']['type'], $args['html_id'], $args['opt_key'] );
1431
1432 $label = isset( $args['opt_label'] ) ? $args['opt_label'] : $args['field']['name'];
1433
1434 echo '<label for="' . esc_attr( $other_id ) . '" class="frm_screen_reader frm_hidden">' .
1435 esc_html( $label ) .
1436 '</label>' .
1437 '<input type="text" id="' . esc_attr( $other_id ) . '" class="' . esc_attr( implode( ' ', $classes ) ) . '" ' .
1438 ( $args['read_only'] ? ' readonly="readonly" disabled="disabled"' : '' ) .
1439 ' name="' . esc_attr( $args['name'] ) . '" value="' . esc_attr( $args['value'] ) . '" />';
1440 }
1441
1442 /**
1443 * Get the HTML id for an "Other" text field
1444 * Note: This does not affect fields in repeating sections
1445 *
1446 * @since 2.0.08
1447 *
1448 * @param string $type Field type.
1449 * @param string $html_id
1450 * @param string|boolean $opt_key
1451 *
1452 * @return string $other_id
1453 */
1454 public static function get_other_field_html_id( $type, $html_id, $opt_key = false ) {
1455 $other_id = $html_id;
1456
1457 // If hidden radio field, add an opt key of 0
1458 if ( $type == 'radio' && $opt_key === false ) {
1459 $opt_key = 0;
1460 }
1461
1462 if ( $opt_key !== false ) {
1463 $other_id .= '-' . $opt_key;
1464 }
1465
1466 $other_id .= '-otext';
1467
1468 return $other_id;
1469 }
1470
1471 public static function switch_field_ids( $val ) {
1472 global $frm_duplicate_ids;
1473 $replace = array();
1474 $replace_with = array();
1475 foreach ( (array) $frm_duplicate_ids as $old => $new ) {
1476 $replace[] = '[if ' . $old . ']';
1477 $replace_with[] = '[if ' . $new . ']';
1478 $replace[] = '[if ' . $old . ' ';
1479 $replace_with[] = '[if ' . $new . ' ';
1480 $replace[] = '[/if ' . $old . ']';
1481 $replace_with[] = '[/if ' . $new . ']';
1482 $replace[] = '[\/if ' . $old . ']';
1483 $replace_with[] = '[\/if ' . $new . ']';
1484 $replace[] = '[foreach ' . $old . ']';
1485 $replace_with[] = '[foreach ' . $new . ']';
1486 $replace[] = '[/foreach ' . $old . ']';
1487 $replace_with[] = '[/foreach ' . $new . ']';
1488 $replace[] = '[\/foreach ' . $old . ']';
1489 $replace_with[] = '[\/foreach ' . $new . ']';
1490 $replace[] = '[' . $old . ']';
1491 $replace_with[] = '[' . $new . ']';
1492 $replace[] = '[' . $old . ' ';
1493 $replace_with[] = '[' . $new . ' ';
1494 $replace[] = 'field_id="' . $old . '"';
1495 $replace_with[] = 'field_id="' . $new . '"';
1496 $replace[] = 'field_id=\"' . $old . '\"';
1497 $replace_with[] = 'field_id=\"' . $new . '\"';
1498 unset( $old, $new );
1499 }//end foreach
1500 if ( is_array( $val ) ) {
1501 foreach ( $val as $k => $v ) {
1502 if ( is_string( $v ) ) {
1503 $val[ $k ] = str_replace( $replace, $replace_with, $v );
1504 unset( $k, $v );
1505 }
1506 }
1507 } else {
1508 $val = str_replace( $replace, $replace_with, $val );
1509 }
1510
1511 return $val;
1512 }
1513
1514 /**
1515 * @since 4.0
1516 */
1517 public static function bulk_options_overlay() {
1518 $prepop = array();
1519 self::get_bulk_prefilled_opts( $prepop, true );
1520
1521 include FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/bulk-options-overlay.php';
1522 }
1523
1524 public static function get_us_states() {
1525 $states = array(
1526 'AL' => 'Alabama',
1527 'AK' => 'Alaska',
1528 'AR' => 'Arkansas',
1529 'AZ' => 'Arizona',
1530 'CA' => 'California',
1531 'CO' => 'Colorado',
1532 'CT' => 'Connecticut',
1533 'DE' => 'Delaware',
1534 'DC' => 'District of Columbia',
1535 'FL' => 'Florida',
1536 'GA' => 'Georgia',
1537 'HI' => 'Hawaii',
1538 'ID' => 'Idaho',
1539 'IL' => 'Illinois',
1540 'IN' => 'Indiana',
1541 'IA' => 'Iowa',
1542 'KS' => 'Kansas',
1543 'KY' => 'Kentucky',
1544 'LA' => 'Louisiana',
1545 'ME' => 'Maine',
1546 'MD' => 'Maryland',
1547 'MA' => 'Massachusetts',
1548 'MI' => 'Michigan',
1549 'MN' => 'Minnesota',
1550 'MS' => 'Mississippi',
1551 'MO' => 'Missouri',
1552 'MT' => 'Montana',
1553 'NE' => 'Nebraska',
1554 'NV' => 'Nevada',
1555 'NH' => 'New Hampshire',
1556 'NJ' => 'New Jersey',
1557 'NM' => 'New Mexico',
1558 'NY' => 'New York',
1559 'NC' => 'North Carolina',
1560 'ND' => 'North Dakota',
1561 'OH' => 'Ohio',
1562 'OK' => 'Oklahoma',
1563 'OR' => 'Oregon',
1564 'PA' => 'Pennsylvania',
1565 'RI' => 'Rhode Island',
1566 'SC' => 'South Carolina',
1567 'SD' => 'South Dakota',
1568 'TN' => 'Tennessee',
1569 'TX' => 'Texas',
1570 'UT' => 'Utah',
1571 'VT' => 'Vermont',
1572 'VA' => 'Virginia',
1573 'WA' => 'Washington',
1574 'WV' => 'West Virginia',
1575 'WI' => 'Wisconsin',
1576 'WY' => 'Wyoming',
1577 );
1578
1579 return apply_filters( 'frm_us_states', $states );
1580 }
1581
1582 public static function get_countries() {
1583 $countries = array(
1584 __( 'Afghanistan', 'formidable' ),
1585 __( 'Aland Islands', 'formidable' ),
1586 __( 'Albania', 'formidable' ),
1587 __( 'Algeria', 'formidable' ),
1588 __( 'American Samoa', 'formidable' ),
1589 __( 'Andorra', 'formidable' ),
1590 __( 'Angola', 'formidable' ),
1591 __( 'Anguilla', 'formidable' ),
1592 __( 'Antarctica', 'formidable' ),
1593 __( 'Antigua and Barbuda', 'formidable' ),
1594 __( 'Argentina', 'formidable' ),
1595 __( 'Armenia', 'formidable' ),
1596 __( 'Aruba', 'formidable' ),
1597 __( 'Australia', 'formidable' ),
1598 __( 'Austria', 'formidable' ),
1599 __( 'Azerbaijan', 'formidable' ),
1600 __( 'Bahamas', 'formidable' ),
1601 __( 'Bahrain', 'formidable' ),
1602 __( 'Bangladesh', 'formidable' ),
1603 __( 'Barbados', 'formidable' ),
1604 __( 'Belarus', 'formidable' ),
1605 __( 'Belgium', 'formidable' ),
1606 __( 'Belize', 'formidable' ),
1607 __( 'Benin', 'formidable' ),
1608 __( 'Bermuda', 'formidable' ),
1609 __( 'Bhutan', 'formidable' ),
1610 __( 'Bolivia', 'formidable' ),
1611 __( 'Bonaire, Sint Eustatius and Saba', 'formidable' ),
1612 __( 'Bosnia and Herzegovina', 'formidable' ),
1613 __( 'Botswana', 'formidable' ),
1614 __( 'Bouvet Island', 'formidable' ),
1615 __( 'Brazil', 'formidable' ),
1616 __( 'British Indian Ocean Territory', 'formidable' ),
1617 __( 'Brunei', 'formidable' ),
1618 __( 'Bulgaria', 'formidable' ),
1619 __( 'Burkina Faso', 'formidable' ),
1620 __( 'Burundi', 'formidable' ),
1621 __( 'Cambodia', 'formidable' ),
1622 __( 'Cameroon', 'formidable' ),
1623 __( 'Canada', 'formidable' ),
1624 __( 'Cape Verde', 'formidable' ),
1625 __( 'Cayman Islands', 'formidable' ),
1626 __( 'Central African Republic', 'formidable' ),
1627 __( 'Chad', 'formidable' ),
1628 __( 'Chile', 'formidable' ),
1629 __( 'China', 'formidable' ),
1630 __( 'Christmas Island', 'formidable' ),
1631 __( 'Cocos (Keeling) Islands', 'formidable' ),
1632 __( 'Colombia', 'formidable' ),
1633 __( 'Comoros', 'formidable' ),
1634 __( 'Congo', 'formidable' ),
1635 __( 'Cook Islands', 'formidable' ),
1636 __( 'Costa Rica', 'formidable' ),
1637 __( 'C&ocirc;te d\'Ivoire', 'formidable' ),
1638 __( 'Croatia', 'formidable' ),
1639 __( 'Cuba', 'formidable' ),
1640 __( 'Curacao', 'formidable' ),
1641 __( 'Cyprus', 'formidable' ),
1642 __( 'Czech Republic', 'formidable' ),
1643 __( 'Denmark', 'formidable' ),
1644 __( 'Djibouti', 'formidable' ),
1645 __( 'Dominica', 'formidable' ),
1646 __( 'Dominican Republic', 'formidable' ),
1647 __( 'East Timor', 'formidable' ),
1648 __( 'Ecuador', 'formidable' ),
1649 __( 'Egypt', 'formidable' ),
1650 __( 'El Salvador', 'formidable' ),
1651 __( 'Equatorial Guinea', 'formidable' ),
1652 __( 'Eritrea', 'formidable' ),
1653 __( 'Estonia', 'formidable' ),
1654 __( 'Ethiopia', 'formidable' ),
1655 __( 'Falkland Islands (Malvinas)', 'formidable' ),
1656 __( 'Faroe Islands', 'formidable' ),
1657 __( 'Fiji', 'formidable' ),
1658 __( 'Finland', 'formidable' ),
1659 __( 'France', 'formidable' ),
1660 __( 'French Guiana', 'formidable' ),
1661 __( 'French Polynesia', 'formidable' ),
1662 __( 'French Southern Territories', 'formidable' ),
1663 __( 'Gabon', 'formidable' ),
1664 __( 'Gambia', 'formidable' ),
1665 __( 'Georgia', 'formidable' ),
1666 __( 'Germany', 'formidable' ),
1667 __( 'Ghana', 'formidable' ),
1668 __( 'Gibraltar', 'formidable' ),
1669 __( 'Greece', 'formidable' ),
1670 __( 'Greenland', 'formidable' ),
1671 __( 'Grenada', 'formidable' ),
1672 __( 'Guadeloupe', 'formidable' ),
1673 __( 'Guam', 'formidable' ),
1674 __( 'Guatemala', 'formidable' ),
1675 __( 'Guernsey', 'formidable' ),
1676 __( 'Guinea', 'formidable' ),
1677 __( 'Guinea-Bissau', 'formidable' ),
1678 __( 'Guyana', 'formidable' ),
1679 __( 'Haiti', 'formidable' ),
1680 __( 'Heard Island and McDonald Islands', 'formidable' ),
1681 __( 'Holy See', 'formidable' ),
1682 __( 'Honduras', 'formidable' ),
1683 __( 'Hong Kong', 'formidable' ),
1684 __( 'Hungary', 'formidable' ),
1685 __( 'Iceland', 'formidable' ),
1686 __( 'India', 'formidable' ),
1687 __( 'Indonesia', 'formidable' ),
1688 __( 'Iran', 'formidable' ),
1689 __( 'Iraq', 'formidable' ),
1690 __( 'Ireland', 'formidable' ),
1691 __( 'Israel', 'formidable' ),
1692 __( 'Isle of Man', 'formidable' ),
1693 __( 'Italy', 'formidable' ),
1694 __( 'Jamaica', 'formidable' ),
1695 __( 'Japan', 'formidable' ),
1696 __( 'Jersey', 'formidable' ),
1697 __( 'Jordan', 'formidable' ),
1698 __( 'Kazakhstan', 'formidable' ),
1699 __( 'Kenya', 'formidable' ),
1700 __( 'Kiribati', 'formidable' ),
1701 __( 'North Korea', 'formidable' ),
1702 __( 'South Korea', 'formidable' ),
1703 __( 'Kosovo', 'formidable' ),
1704 __( 'Kuwait', 'formidable' ),
1705 __( 'Kyrgyzstan', 'formidable' ),
1706 __( 'Laos', 'formidable' ),
1707 __( 'Latvia', 'formidable' ),
1708 __( 'Lebanon', 'formidable' ),
1709 __( 'Lesotho', 'formidable' ),
1710 __( 'Liberia', 'formidable' ),
1711 __( 'Libya', 'formidable' ),
1712 __( 'Liechtenstein', 'formidable' ),
1713 __( 'Lithuania', 'formidable' ),
1714 __( 'Luxembourg', 'formidable' ),
1715 __( 'Macao', 'formidable' ),
1716 __( 'Macedonia', 'formidable' ),
1717 __( 'Madagascar', 'formidable' ),
1718 __( 'Malawi', 'formidable' ),
1719 __( 'Malaysia', 'formidable' ),
1720 __( 'Maldives', 'formidable' ),
1721 __( 'Mali', 'formidable' ),
1722 __( 'Malta', 'formidable' ),
1723 __( 'Marshall Islands', 'formidable' ),
1724 __( 'Martinique', 'formidable' ),
1725 __( 'Mauritania', 'formidable' ),
1726 __( 'Mauritius', 'formidable' ),
1727 __( 'Mayotte', 'formidable' ),
1728 __( 'Mexico', 'formidable' ),
1729 __( 'Micronesia', 'formidable' ),
1730 __( 'Moldova', 'formidable' ),
1731 __( 'Monaco', 'formidable' ),
1732 __( 'Mongolia', 'formidable' ),
1733 __( 'Montenegro', 'formidable' ),
1734 __( 'Montserrat', 'formidable' ),
1735 __( 'Morocco', 'formidable' ),
1736 __( 'Mozambique', 'formidable' ),
1737 __( 'Myanmar', 'formidable' ),
1738 __( 'Namibia', 'formidable' ),
1739 __( 'Nauru', 'formidable' ),
1740 __( 'Nepal', 'formidable' ),
1741 __( 'Netherlands', 'formidable' ),
1742 __( 'New Caledonia', 'formidable' ),
1743 __( 'New Zealand', 'formidable' ),
1744 __( 'Nicaragua', 'formidable' ),
1745 __( 'Niger', 'formidable' ),
1746 __( 'Nigeria', 'formidable' ),
1747 __( 'Niue', 'formidable' ),
1748 __( 'Norfolk Island', 'formidable' ),
1749 __( 'Northern Mariana Islands', 'formidable' ),
1750 __( 'Norway', 'formidable' ),
1751 __( 'Oman', 'formidable' ),
1752 __( 'Pakistan', 'formidable' ),
1753 __( 'Palau', 'formidable' ),
1754 __( 'Palestine', 'formidable' ),
1755 __( 'Panama', 'formidable' ),
1756 __( 'Papua New Guinea', 'formidable' ),
1757 __( 'Paraguay', 'formidable' ),
1758 __( 'Peru', 'formidable' ),
1759 __( 'Philippines', 'formidable' ),
1760 __( 'Pitcairn', 'formidable' ),
1761 __( 'Poland', 'formidable' ),
1762 __( 'Portugal', 'formidable' ),
1763 __( 'Puerto Rico', 'formidable' ),
1764 __( 'Qatar', 'formidable' ),
1765 __( 'Reunion', 'formidable' ),
1766 __( 'Romania', 'formidable' ),
1767 __( 'Russia', 'formidable' ),
1768 __( 'Rwanda', 'formidable' ),
1769 __( 'Saint Barthelemy', 'formidable' ),
1770 __( 'Saint Helena, Ascension and Tristan da Cunha', 'formidable' ),
1771 __( 'Saint Kitts and Nevis', 'formidable' ),
1772 __( 'Saint Lucia', 'formidable' ),
1773 __( 'Saint Martin (French part)', 'formidable' ),
1774 __( 'Saint Pierre and Miquelon', 'formidable' ),
1775 __( 'Saint Vincent and the Grenadines', 'formidable' ),
1776 __( 'Samoa', 'formidable' ),
1777 __( 'San Marino', 'formidable' ),
1778 __( 'Sao Tome and Principe', 'formidable' ),
1779 __( 'Saudi Arabia', 'formidable' ),
1780 __( 'Senegal', 'formidable' ),
1781 __( 'Serbia', 'formidable' ),
1782 __( 'Seychelles', 'formidable' ),
1783 __( 'Sierra Leone', 'formidable' ),
1784 __( 'Singapore', 'formidable' ),
1785 __( 'Sint Maarten (Dutch part)', 'formidable' ),
1786 __( 'Slovakia', 'formidable' ),
1787 __( 'Slovenia', 'formidable' ),
1788 __( 'Solomon Islands', 'formidable' ),
1789 __( 'Somalia', 'formidable' ),
1790 __( 'South Africa', 'formidable' ),
1791 __( 'South Georgia and the South Sandwich Islands', 'formidable' ),
1792 __( 'South Sudan', 'formidable' ),
1793 __( 'Spain', 'formidable' ),
1794 __( 'Sri Lanka', 'formidable' ),
1795 __( 'Sudan', 'formidable' ),
1796 __( 'Suriname', 'formidable' ),
1797 __( 'Svalbard and Jan Mayen', 'formidable' ),
1798 __( 'Swaziland', 'formidable' ),
1799 __( 'Sweden', 'formidable' ),
1800 __( 'Switzerland', 'formidable' ),
1801 __( 'Syria', 'formidable' ),
1802 __( 'Taiwan', 'formidable' ),
1803 __( 'Tajikistan', 'formidable' ),
1804 __( 'Tanzania', 'formidable' ),
1805 __( 'Thailand', 'formidable' ),
1806 __( 'Timor-Leste', 'formidable' ),
1807 __( 'Togo', 'formidable' ),
1808 __( 'Tokelau', 'formidable' ),
1809 __( 'Tonga', 'formidable' ),
1810 __( 'Trinidad and Tobago', 'formidable' ),
1811 __( 'Tunisia', 'formidable' ),
1812 __( 'Turkey', 'formidable' ),
1813 __( 'Turkmenistan', 'formidable' ),
1814 __( 'Turks and Caicos Islands', 'formidable' ),
1815 __( 'Tuvalu', 'formidable' ),
1816 __( 'Uganda', 'formidable' ),
1817 __( 'Ukraine', 'formidable' ),
1818 __( 'United Arab Emirates', 'formidable' ),
1819 __( 'United Kingdom', 'formidable' ),
1820 __( 'United States', 'formidable' ),
1821 __( 'United States Minor Outlying Islands', 'formidable' ),
1822 __( 'Uruguay', 'formidable' ),
1823 __( 'Uzbekistan', 'formidable' ),
1824 __( 'Vanuatu', 'formidable' ),
1825 __( 'Vatican City', 'formidable' ),
1826 __( 'Venezuela', 'formidable' ),
1827 __( 'Vietnam', 'formidable' ),
1828 __( 'Virgin Islands, British', 'formidable' ),
1829 __( 'Virgin Islands, U.S.', 'formidable' ),
1830 __( 'Wallis and Futuna', 'formidable' ),
1831 __( 'Western Sahara', 'formidable' ),
1832 __( 'Yemen', 'formidable' ),
1833 __( 'Zambia', 'formidable' ),
1834 __( 'Zimbabwe', 'formidable' ),
1835 );
1836
1837 sort( $countries, SORT_LOCALE_STRING );
1838 return apply_filters( 'frm_countries', $countries );
1839 }
1840
1841 /**
1842 * Gets bulk prefilled options.
1843 *
1844 * @since 5.0.04 Add `$include_class` param.
1845 *
1846 * @param array $prepop Bulk options.
1847 * @param array|false $include_class Include the class in the bulk options.
1848 */
1849 public static function get_bulk_prefilled_opts( array &$prepop, $include_class = false ) {
1850 // Countries.
1851 $countries = self::get_countries();
1852 if ( $include_class ) {
1853 $countries['class'] = 'frm-countries-opts';
1854 }
1855
1856 $prepop[ __( 'Countries', 'formidable' ) ] = $countries;
1857
1858 // State abv.
1859 $states = self::get_us_states();
1860 $state_abv = array_keys( $states );
1861 sort( $state_abv );
1862 if ( $include_class ) {
1863 $state_abv['class'] = 'frm-state-abv-opts';
1864 }
1865
1866 $prepop[ __( 'U.S. State Abbreviations', 'formidable' ) ] = $state_abv;
1867
1868 // States.
1869 $states = array_values( $states );
1870 sort( $states );
1871 if ( $include_class ) {
1872 $states['class'] = 'frm-states-opts';
1873 }
1874
1875 $prepop[ __( 'U.S. States', 'formidable' ) ] = $states;
1876 unset( $state_abv, $states );
1877
1878 // Age.
1879 $ages = array(
1880 __( 'Under 18', 'formidable' ),
1881 __( '18-24', 'formidable' ),
1882 __( '25-34', 'formidable' ),
1883 __( '35-44', 'formidable' ),
1884 __( '45-54', 'formidable' ),
1885 __( '55-64', 'formidable' ),
1886 __( '65 or Above', 'formidable' ),
1887 __( 'Prefer Not to Answer', 'formidable' ),
1888 );
1889 if ( $include_class ) {
1890 $ages['class'] = 'frm-age-opts';
1891 }
1892
1893 $prepop[ __( 'Age', 'formidable' ) ] = $ages;
1894
1895 // Satisfaction.
1896 $satisfaction = array(
1897 __( 'Very Unsatisfied', 'formidable' ),
1898 __( 'Unsatisfied', 'formidable' ),
1899 __( 'Neutral', 'formidable' ),
1900 __( 'Satisfied', 'formidable' ),
1901 __( 'Very Satisfied', 'formidable' ),
1902 __( 'N/A', 'formidable' ),
1903 );
1904 if ( $include_class ) {
1905 $satisfaction['class'] = 'frm-satisfaction-opts';
1906 }
1907
1908 $prepop[ __( 'Satisfaction', 'formidable' ) ] = $satisfaction;
1909
1910 // Importance.
1911 $importance = array(
1912 __( 'Not at all Important', 'formidable' ),
1913 __( 'Somewhat Important', 'formidable' ),
1914 __( 'Neutral', 'formidable' ),
1915 __( 'Important', 'formidable' ),
1916 __( 'Very Important', 'formidable' ),
1917 __( 'N/A', 'formidable' ),
1918 );
1919 if ( $include_class ) {
1920 $importance['class'] = 'frm-importance-opts';
1921 }
1922
1923 $prepop[ __( 'Importance', 'formidable' ) ] = $importance;
1924
1925 // Agreement.
1926 $agreement = array(
1927 __( 'Strongly Disagree', 'formidable' ),
1928 __( 'Disagree', 'formidable' ),
1929 __( 'Neutral', 'formidable' ),
1930 __( 'Agree', 'formidable' ),
1931 __( 'Strongly Agree', 'formidable' ),
1932 __( 'N/A', 'formidable' ),
1933 );
1934 if ( $include_class ) {
1935 $agreement['class'] = 'frm-agreement-opts';
1936 }
1937
1938 $prepop[ __( 'Agreement', 'formidable' ) ] = $agreement;
1939
1940 // Likely.
1941 $likely = array(
1942 __( 'Extremely Unlikely', 'formidable' ),
1943 __( 'Unlikely', 'formidable' ),
1944 __( 'Neutral', 'formidable' ),
1945 __( 'Likely', 'formidable' ),
1946 __( 'Extremely Likely', 'formidable' ),
1947 __( 'N/A', 'formidable' ),
1948 );
1949 if ( $include_class ) {
1950 $likely['class'] = 'frm-likely-opts';
1951 }
1952
1953 $prepop[ __( 'Likely', 'formidable' ) ] = $likely;
1954
1955 $prepop = apply_filters( 'frm_bulk_field_choices', $prepop );
1956 }
1957
1958 /**
1959 * Display a field value selector
1960 *
1961 * @since 2.03.05
1962 *
1963 * @param int $selector_field_id
1964 * @param array $selector_args
1965 */
1966 public static function display_field_value_selector( $selector_field_id, $selector_args ) {
1967 $field_value_selector = FrmFieldFactory::create_field_value_selector( $selector_field_id, $selector_args );
1968 $field_value_selector->display();
1969 }
1970
1971 /**
1972 * Convert a field object to a flat array
1973 *
1974 * @since 2.03.05
1975 *
1976 * @param object $field
1977 *
1978 * @return array
1979 */
1980 public static function convert_field_object_to_flat_array( $field ) {
1981 $field_options = $field->field_options;
1982 $field_array = get_object_vars( $field );
1983 unset( $field_array['field_options'] );
1984
1985 return $field_array + $field_options;
1986 }
1987
1988 /**
1989 * @since 4.04
1990 *
1991 * @param array $args
1992 * @return void
1993 */
1994 public static function show_add_field_buttons( $args ) {
1995 $field_key = $args['field_key'];
1996 $field_type = $args['field_type'];
1997 $field_label = FrmAppHelper::icon_by_class( FrmFormsHelper::get_field_link_icon( $field_type ), array( 'echo' => false ) );
1998 $field_name = FrmFormsHelper::get_field_link_name( $field_type );
1999 $field_label .= ' <span>' . $field_name . '</span>';
2000
2001 if ( ! empty( $field_type['is_new'] ) ) {
2002 ob_start();
2003 FrmAppHelper::show_pill_text();
2004 $field_label .= ob_get_clean();
2005 }
2006
2007 // If the individual field isn't allowed, disable it.
2008 $run_filter = true;
2009 $single_no_allow = ' ';
2010 $install_data = '';
2011 $requires = '';
2012 $link = isset( $field_type['link'] ) ? esc_url_raw( $field_type['link'] ) : '';
2013 $has_show_upgrade_class = strpos( $field_type['icon'], ' frm_show_upgrade' );
2014 $show_upgrade = $has_show_upgrade_class || false !== strpos( $args['no_allow_class'], 'frm_show_upgrade' );
2015
2016 if ( $has_show_upgrade_class ) {
2017 $single_no_allow .= 'frm_show_upgrade';
2018 $field_type['icon'] = str_replace( ' frm_show_upgrade', '', $field_type['icon'] );
2019 $run_filter = false;
2020 if ( isset( $field_type['addon'] ) ) {
2021 $upgrading = FrmAddonsController::install_link( $field_type['addon'] );
2022 if ( isset( $upgrading['url'] ) ) {
2023 $install_data = json_encode( $upgrading );
2024 }
2025 $requires = FrmFormsHelper::get_plan_required( $upgrading );
2026 } elseif ( isset( $field_type['require'] ) ) {
2027 $requires = $field_type['require'];
2028 }
2029 }
2030
2031 $upgrade_label = '';
2032 $upgrade_message = '';
2033 if ( $show_upgrade ) {
2034 /* translators: %s: Field name */
2035 $upgrade_label = sprintf( esc_html__( '%s fields', 'formidable' ), $field_name );
2036
2037 if ( isset( $field_type['message'] ) ) {
2038 $upgrade_message = FrmAppHelper::kses( $field_type['message'], array( 'a', 'img' ) );
2039 }
2040 }
2041
2042 $li_params = array(
2043 'class' => 'frmbutton frm6 ' . $args['no_allow_class'] . $single_no_allow . ' frm_t' . str_replace( '|', '-', $field_key ),
2044 'id' => $field_key,
2045 'data-upgrade' => $upgrade_label,
2046 'data-link' => $link,
2047 'data-medium' => 'builder',
2048 'data-oneclick' => $install_data,
2049 'data-content' => $field_key,
2050 'data-requires' => $requires,
2051 );
2052
2053 if ( ! empty( $field_type['hide'] ) ) {
2054 $li_params['class'] .= ' frm_hidden';
2055 }
2056
2057 if ( ! empty( $field_type['upsell_image'] ) ) {
2058 $li_params['data-upsell-image'] = $field_type['upsell_image'];
2059 }
2060
2061 if ( $upgrade_message ) {
2062 $li_params['data-message'] = $upgrade_message;
2063 }
2064 ?>
2065 <li <?php FrmAppHelper::array_to_html_params( $li_params, true ); ?>>
2066 <?php
2067 if ( $run_filter ) {
2068 $field_label = apply_filters( 'frmpro_field_links', $field_label, $args['id'], $field_key );
2069 }
2070 echo FrmAppHelper::kses( $field_label, array( 'a', 'i', 'span', 'use', 'svg' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
2071 ?>
2072 </li>
2073 <?php
2074 }
2075
2076 /**
2077 * Shows Display format option.
2078 *
2079 * @since 5.0.04
2080 *
2081 * @param array $field Field data.
2082 */
2083 public static function show_radio_display_format( $field ) {
2084 $options = self::get_display_format_options( $field );
2085
2086 $args = self::get_display_format_args( $field, $options );
2087
2088 include FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/radio-display-format.php';
2089 }
2090
2091 /**
2092 * Creates an array that contains variables used for display format options setting.
2093 *
2094 * @since 6.3.2
2095 *
2096 * @param array $field The field.
2097 *
2098 * @return array
2099 */
2100 public static function get_display_format_options( $field ) {
2101 $options = array(
2102 '0' => array(
2103 'text' => __( 'Simple', 'formidable' ),
2104 'svg' => 'frm_simple_radio',
2105 ),
2106 '1' => array(
2107 'text' => __( 'Images', 'formidable' ),
2108 'svg' => 'frm_image_as_option',
2109 'addon' => 'pro',
2110 'upgrade' => __( 'Image Options', 'formidable' ),
2111 '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" />',
2112 'content' => 'image-options',
2113 ),
2114 'buttons' => array(
2115 'text' => __( 'Buttons', 'formidable' ),
2116 'svg' => 'frm_button_as_option',
2117 'addon' => 'surveys',
2118 'upgrade' => __( 'Button Options', 'formidable' ),
2119 'message' => __( 'Show buttons for radio buttons or check boxes. This is ideal for polls, surveys, segmenting questionnaires and more.', 'formidable' ),
2120 'content' => 'button-options',
2121 ),
2122 );
2123
2124 /**
2125 * Allows modifying the options of Display format setting of Radio field.
2126 *
2127 * @since 5.0.04
2128 *
2129 * @param array $options Options.
2130 * @param array $field
2131 */
2132 $options = apply_filters( 'frm_' . $field['type'] . '_display_format_options', $options, $field );
2133
2134 return $options;
2135 }
2136
2137 /**
2138 * Gets display format arguments to pass to the images_dropdown() method.
2139 *
2140 * @since 5.0.04
2141 *
2142 * @param array $field Field data.
2143 * @param array $options Options array.
2144 * @return array
2145 */
2146 public static function get_display_format_args( $field, $options ) {
2147 $args = array(
2148 'selected' => '0',
2149 'options' => array(),
2150 'name' => 'field_options[image_options_' . $field['id'] . ']',
2151 'input_attrs' => array(
2152 'class' => 'frm_toggle_image_options',
2153 ),
2154 );
2155
2156 self::fill_image_setting_options( $options, $args );
2157
2158 /**
2159 * Allows modifying the arguments of Display format setting of Radio field.
2160 *
2161 * @since 5.0.04
2162 *
2163 * @param array $args Arguments.
2164 * @param array $method_args The arguments from the method. Contains `field`, `options`.
2165 */
2166 return apply_filters( 'frm_' . $field['type'] . '_display_format_args', $args, compact( 'field', 'options' ) );
2167 }
2168
2169 /**
2170 * @since 5.0.04
2171 */
2172 private static function fill_image_setting_options( $options, &$args ) {
2173 foreach ( $options as $key => $option ) {
2174 $args['options'][ $key ] = $option;
2175
2176 if ( ! empty( $option['addon'] ) ) {
2177 $args['options'][ $key ]['custom_attrs'] = self::fill_image_setting_addon_link( $option );
2178 }
2179
2180 unset( $args['options'][ $key ]['addon'] );
2181 $fill = array( 'upgrade', 'message', 'content' );
2182 foreach ( $fill as $f ) {
2183 unset( $args['options'][ $key ][ $f ], $f );
2184 }
2185 }
2186 }
2187
2188 /**
2189 * @since 5.0.04
2190 *
2191 * @return array
2192 */
2193 private static function fill_image_setting_addon_link( $option ) {
2194 $custom_attrs = array(
2195 'class' => 'frm_noallow frm_show_upgrade',
2196 'data-medium' => 'builder',
2197 );
2198
2199 // translators: Add-on name.
2200 $custom_attrs['data-upgrade'] = sprintf( __( 'Formidable %s', 'formidable' ), ucwords( $option['addon'] ) );
2201
2202 $fill = array( 'upgrade', 'message', 'content' );
2203 foreach ( $fill as $f ) {
2204 if ( isset( $option[ $f ] ) ) {
2205 $custom_attrs[ 'data-' . $f ] = $option[ $f ];
2206 }
2207 }
2208
2209 if ( 'pro' === $option['addon'] ) {
2210 return $custom_attrs;
2211 }
2212
2213 $upgrading = FrmAddonsController::install_link( $option['addon'] );
2214 if ( isset( $upgrading['url'] ) ) {
2215 $install_data = wp_json_encode( $upgrading );
2216 } else {
2217 $install_data = '';
2218 }
2219
2220 $custom_attrs['data-oneclick'] = $install_data;
2221 $custom_attrs['data-requires'] = FrmFormsHelper::get_plan_required( $upgrading );
2222
2223 return $custom_attrs;
2224 }
2225
2226 /**
2227 * Maybe adjust a field value based on type.
2228 * Some types require unserializing an array (@see self::field_type_requires_unserialize).
2229 *
2230 * @since 6.2
2231 *
2232 * @param mixed $value
2233 * @param string $field_type
2234 * @return void
2235 */
2236 public static function prepare_field_value( &$value, $field_type ) {
2237 $field_object = FrmFieldFactory::get_field_type( $field_type );
2238 $value = $field_object->maybe_decode_value( $value );
2239 }
2240
2241 /**
2242 * @since 6.8
2243 *
2244 * @param string|int $form_id
2245 * @param array $field_ids If this is not empty, the results will be filtered by field id.
2246 * @return array
2247 */
2248 public static function get_draft_field_results( $form_id, $field_ids = array() ) {
2249 if ( FrmAppHelper::pro_is_installed() ) {
2250 $child_form_ids = FrmDb::get_col( 'frm_forms', array( 'parent_form_id' => $form_id ) );
2251 $form_ids = array_merge( array( $form_id ), $child_form_ids );
2252 } else {
2253 $form_ids = array( $form_id );
2254 }
2255
2256 $where = array(
2257 'form_id' => $form_ids,
2258 // Do a soft check for fields that look like drafts only.
2259 'field_options LIKE' => 's:5:"draft";i:1;',
2260 );
2261
2262 if ( $field_ids ) {
2263 $where['id'] = $field_ids;
2264 }
2265
2266 $rows = FrmDb::get_results( 'frm_fields', $where, 'id, field_options' );
2267
2268 return array_filter(
2269 $rows,
2270 function ( $row ) {
2271 FrmAppHelper::unserialize_or_decode( $row->field_options );
2272 return is_array( $row->field_options ) && ! empty( $row->field_options['draft'] );
2273 }
2274 );
2275 }
2276
2277 /**
2278 * This is called when loading the form builder.
2279 * Any unsaved draft fields get added to a hidden draft_fields input on load.
2280 *
2281 * @since 6.8
2282 *
2283 * @param string|int $form_id
2284 * @return array
2285 */
2286 public static function get_all_draft_field_ids( $form_id ) {
2287 $draft_field_rows = self::get_draft_field_results( $form_id );
2288 return wp_list_pluck( $draft_field_rows, 'id' );
2289 }
2290
2291 /**
2292 * @deprecated 4.0
2293 */
2294 public static function show_icon_link_js( $atts ) {
2295 _deprecated_function( __METHOD__, '4.0' );
2296 $atts['icon'] .= $atts['is_selected'] ? ' ' : ' frm_inactive_icon ';
2297 if ( isset( $atts['has_default'] ) && ! $atts['has_default'] ) {
2298 $atts['icon'] .= 'frm_hidden ';
2299 }
2300 echo '<a href="javascript:void(0)" class="frm_bstooltip ' . esc_attr( $atts['icon'] ) . 'frm_default_val_icons frm_action_icon frm_icon_font" title="' . esc_attr( $atts['message'] ) . '"></a>';
2301 }
2302
2303 /**
2304 * @deprecated 4.0
2305 */
2306 public static function show_default_blank_js( $is_selected, $has_default_value = true ) {
2307 _deprecated_function( __METHOD__, '4.0' );
2308 }
2309
2310 /**
2311 * @deprecated 4.0
2312 */
2313 public static function clear_on_focus_html( $field, $display, $id = '' ) {
2314 _deprecated_function( __METHOD__, '4.0' );
2315 }
2316
2317 /**
2318 * @deprecated 4.0
2319 */
2320 public static function show_onfocus_js( $is_selected, $has_default_value = true ) {
2321 _deprecated_function( __METHOD__, '4.0' );
2322 }
2323
2324 /**
2325 * @deprecated 3.0
2326 * @codeCoverageIgnore
2327 */
2328 public static function display_recaptcha() {
2329 _deprecated_function( __FUNCTION__, '3.0', 'FrmFieldCaptcha::field_input' );
2330 }
2331
2332 /**
2333 * @deprecated 3.0
2334 * @codeCoverageIgnore
2335 */
2336 public static function remove_inline_conditions( $no_vars, $code, $replace_with, &$html ) {
2337 FrmDeprecated::remove_inline_conditions( $no_vars, $code, $replace_with, $html );
2338 }
2339
2340 /**
2341 * @deprecated 3.0
2342 * @codeCoverageIgnore
2343 */
2344 public static function get_shortcode_tag( $shortcodes, $short_key, $args ) {
2345 return FrmDeprecated::get_shortcode_tag( $shortcodes, $short_key, $args );
2346 }
2347
2348 /**
2349 * @deprecated 3.0
2350 * @codeCoverageIgnore
2351 *
2352 * @param string $html
2353 * @param array $field
2354 * @param array $errors
2355 * @param object|false $form
2356 * @param array $args
2357 *
2358 * @return string
2359 */
2360 public static function replace_shortcodes( $html, $field, $errors = array(), $form = false, $args = array() ) {
2361 return FrmDeprecated::replace_shortcodes( $html, $field, $errors, $form, $args );
2362 }
2363
2364 /**
2365 * @deprecated 3.0
2366 * @codeCoverageIgnore
2367 */
2368 public static function get_default_field_opts( $type, $field = null, $limit = false ) {
2369 return FrmDeprecated::get_default_field_opts( $type, $field, $limit );
2370 }
2371
2372 /**
2373 * @deprecated 2.02.07 This is still referenced in the Highrise add on as of v1.06.
2374 * @codeCoverageIgnore
2375 *
2376 * @param array $args
2377 * @return string
2378 */
2379 public static function dropdown_categories( $args ) {
2380 return FrmDeprecated::dropdown_categories( $args );
2381 }
2382 }
2383