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

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