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

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