PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 5.0.14
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v5.0.14
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 / controllers / FrmFieldsController.php

FrmFieldsController.php in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More 5.0.14, at classes/controllers/FrmFieldsController.php

939 lines 25.8 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 FrmFieldsController {
7
8 public static function load_field() {
9 FrmAppHelper::permission_check( 'frm_edit_forms' );
10 check_ajax_referer( 'frm_ajax', 'nonce' );
11
12 // Javascript may be included in some field settings.
13 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
14 $fields = isset( $_POST['field'] ) ? wp_unslash( $_POST['field'] ) : array();
15 if ( empty( $fields ) ) {
16 wp_die();
17 }
18
19 $_GET['page'] = 'formidable';
20
21 $values = array(
22 'id' => FrmAppHelper::get_post_param( 'form_id', '', 'absint' ),
23 'doing_ajax' => true,
24 );
25 $field_html = array();
26
27 foreach ( $fields as $field ) {
28 $field = htmlspecialchars_decode( nl2br( $field ) );
29 $field = json_decode( $field );
30 if ( ! isset( $field->id ) || ! is_numeric( $field->id ) ) {
31 // this field may have already been loaded
32 continue;
33 }
34
35 if ( ! isset( $field->value ) ) {
36 $field->value = '';
37 }
38 $field->field_options = json_decode( json_encode( $field->field_options ), true );
39 $field->options = json_decode( json_encode( $field->options ), true );
40 $field->default_value = json_decode( json_encode( $field->default_value ), true );
41
42 ob_start();
43 self::load_single_field( $field, $values );
44 $field_html[ absint( $field->id ) ] = ob_get_contents();
45 ob_end_clean();
46 }
47
48 echo json_encode( $field_html );
49
50 wp_die();
51 }
52
53 /**
54 * Create a new field with ajax
55 */
56 public static function create() {
57 FrmAppHelper::permission_check( 'frm_edit_forms' );
58 check_ajax_referer( 'frm_ajax', 'nonce' );
59
60 $field_type = FrmAppHelper::get_post_param( 'field_type', '', 'sanitize_text_field' );
61 $form_id = FrmAppHelper::get_post_param( 'form_id', 0, 'absint' );
62
63 do_action( 'frm_before_create_field', $field_type, $form_id );
64
65 $field = self::include_new_field( $field_type, $form_id );
66
67 // this hook will allow for multiple fields to be added at once
68 do_action( 'frm_after_field_created', $field, $form_id );
69
70 wp_die();
71 }
72
73 /**
74 * Set up and create a new field
75 *
76 * @param string $field_type
77 * @param integer $form_id
78 *
79 * @return array|bool
80 */
81 public static function include_new_field( $field_type, $form_id ) {
82 $field_values = FrmFieldsHelper::setup_new_vars( $field_type, $form_id );
83 $field_values = apply_filters( 'frm_before_field_created', $field_values );
84
85 $field_id = FrmField::create( $field_values );
86
87 if ( ! $field_id ) {
88 return false;
89 }
90
91 $field = self::get_field_array_from_id( $field_id );
92
93 $values = array();
94 if ( FrmAppHelper::pro_is_installed() ) {
95 $values['post_type'] = FrmProFormsHelper::post_type( $form_id );
96
97 $parent_form_id = FrmDb::get_var( 'frm_forms', array( 'id' => $form_id ), 'parent_form_id' );
98 if ( $parent_form_id ) {
99 $field['parent_form_id'] = $parent_form_id;
100 }
101 }
102
103 self::load_single_field( $field, $values, $form_id );
104
105 return $field;
106 }
107
108 public static function duplicate() {
109 FrmAppHelper::permission_check( 'frm_edit_forms' );
110 check_ajax_referer( 'frm_ajax', 'nonce' );
111
112 $field_id = FrmAppHelper::get_post_param( 'field_id', 0, 'absint' );
113 $form_id = FrmAppHelper::get_post_param( 'form_id', 0, 'absint' );
114
115 $new_field = FrmField::duplicate_single_field( $field_id, $form_id );
116
117 if ( is_array( $new_field ) && ! empty( $new_field['field_id'] ) ) {
118 self::load_single_field( $new_field['field_id'], $new_field['values'] );
119 }
120
121 wp_die();
122 }
123
124 /**
125 * @since 3.0
126 *
127 * @param int $field_id
128 *
129 * @return array
130 */
131 public static function get_field_array_from_id( $field_id ) {
132 $field = FrmField::getOne( $field_id );
133
134 return FrmFieldsHelper::setup_edit_vars( $field );
135 }
136
137 /**
138 * @since 3.0
139 *
140 * @param int|array|object $field_object
141 * @param array $values
142 * @param int $form_id
143 */
144 public static function load_single_field( $field_object, $values, $form_id = 0 ) {
145 global $frm_vars;
146 $frm_vars['is_admin'] = true;
147
148 if ( is_numeric( $field_object ) ) {
149 $field_object = FrmField::getOne( $field_object );
150 } elseif ( is_array( $field_object ) ) {
151 $field = $field_object;
152 $field_object = FrmField::getOne( $field['id'] );
153 }
154
155 $field_obj = FrmFieldFactory::get_field_factory( $field_object );
156 $display = self::display_field_options( array(), $field_obj );
157
158 $ajax_loading = isset( $values['ajax_load'] ) && $values['ajax_load'];
159 $ajax_this_field = isset( $values['count'] ) && $values['count'] > 10 && ! in_array( $field_object->type, array( 'divider', 'end_divider' ) );
160
161 if ( $ajax_loading && $ajax_this_field ) {
162 $li_classes = self::get_classes_for_builder_field( array(), $display, $field_obj );
163 include( FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/ajax-field-placeholder.php' );
164 } else {
165 if ( ! isset( $field ) && is_object( $field_object ) ) {
166 $field_object->parent_form_id = isset( $values['id'] ) ? $values['id'] : $field_object->form_id;
167
168 $field = FrmFieldsHelper::setup_edit_vars( $field_object );
169 }
170
171 $li_classes = self::get_classes_for_builder_field( $field, $display, $field_obj );
172 $li_classes .= ' ui-state-default widgets-holder-wrap';
173
174 require( FrmAppHelper::plugin_path() . '/classes/views/frm-forms/add_field.php' );
175 }
176 }
177
178 /**
179 * @since 3.0
180 */
181 private static function get_classes_for_builder_field( $field, $display, $field_info ) {
182 $li_classes = $field_info->form_builder_classes( $display['type'] );
183 $li_classes .= ' frm_form_field frmstart ';
184
185 if ( isset( $field['classes'] ) ) {
186 $li_classes .= trim( $field['classes'] ) . ' ';
187 }
188
189 $li_classes .= 'frmend';
190
191 if ( $field ) {
192 $li_classes = apply_filters( 'frm_build_field_class', $li_classes, $field );
193 }
194
195 return $li_classes;
196 }
197
198 public static function destroy() {
199 FrmAppHelper::permission_check( 'frm_edit_forms' );
200 check_ajax_referer( 'frm_ajax', 'nonce' );
201
202 $field_id = FrmAppHelper::get_post_param( 'field_id', 0, 'absint' );
203 FrmField::destroy( $field_id );
204 wp_die();
205 }
206
207 /* Field Options */
208
209 public static function import_options() {
210 FrmAppHelper::permission_check( 'frm_edit_forms' );
211 check_ajax_referer( 'frm_ajax', 'nonce' );
212
213 if ( ! is_admin() || ! current_user_can( 'frm_edit_forms' ) ) {
214 return;
215 }
216
217 $field_id = FrmAppHelper::get_param( 'field_id', '', 'post', 'absint' );
218 $field = FrmField::getOne( $field_id );
219
220 if ( ! in_array( $field->type, array( 'radio', 'checkbox', 'select' ) ) ) {
221 return;
222 }
223
224 $field = FrmFieldsHelper::setup_edit_vars( $field );
225 $opts = FrmAppHelper::get_param( 'opts', '', 'post', 'wp_kses_post' );
226 $opts = explode( "\n", rtrim( $opts, "\n" ) );
227 $opts = array_map( 'trim', $opts );
228
229 $separate = FrmAppHelper::get_param( 'separate', '', 'post', 'sanitize_text_field' );
230 $field['separate_value'] = ( $separate === 'true' );
231
232 if ( $field['separate_value'] ) {
233 foreach ( $opts as $opt_key => $opt ) {
234 if ( strpos( $opt, '|' ) !== false ) {
235 $vals = explode( '|', $opt );
236 $opts[ $opt_key ] = array(
237 'label' => trim( $vals[0] ),
238 'value' => trim( $vals[1] ),
239 );
240 unset( $vals );
241 }
242 unset( $opt_key, $opt );
243 }
244 }
245
246 // Keep other options after bulk update.
247 if ( isset( $field['field_options']['other'] ) && $field['field_options']['other'] == true ) {
248 $other_array = array();
249 foreach ( $field['options'] as $opt_key => $opt ) {
250 if ( FrmFieldsHelper::is_other_opt( $opt_key ) ) {
251 $other_array[ $opt_key ] = $opt;
252 }
253 unset( $opt_key, $opt );
254 }
255 if ( ! empty( $other_array ) ) {
256 $opts = array_merge( $opts, $other_array );
257 }
258 }
259
260 $field['options'] = $opts;
261
262 FrmFieldsHelper::show_single_option( $field );
263
264 wp_die();
265 }
266
267 /**
268 * @since 4.0
269 *
270 * @param array $atts - Includes field array, field_obj, display array, values array.
271 */
272 public static function load_single_field_settings( $atts ) {
273 $field = $atts['field'];
274 $field_obj = $atts['field_obj'];
275 $values = $atts['values'];
276 $display = $atts['display'];
277 unset( $atts );
278
279 if ( ! isset( $field['unique'] ) ) {
280 $field['unique'] = false;
281 }
282
283 if ( ! isset( $field['read_only'] ) ) {
284 $field['read_only'] = false;
285 }
286
287 $field_types = FrmFieldsHelper::get_field_types( $field['type'] );
288 $pro_field_selection = FrmField::pro_field_selection();
289 $all_field_types = array_merge( $pro_field_selection, FrmField::field_selection() );
290 $disabled_fields = FrmAppHelper::pro_is_installed() ? array() : $pro_field_selection;
291 $frm_settings = FrmAppHelper::get_settings();
292
293 if ( ! isset( $all_field_types[ $field['type'] ] ) ) {
294 // Add fallback for an add-on field type that has been deactivated.
295 $all_field_types[ $field['type'] ] = array(
296 'name' => ucfirst( $field['type'] ),
297 'icon' => 'frm_icon_font frm_pencil_icon',
298 );
299 } elseif ( ! is_array( $all_field_types[ $field['type'] ] ) ) {
300 // Fallback for fields added in a more basic way.
301 FrmFormsHelper::prepare_field_type( $all_field_types[ $field['type'] ] );
302 }
303
304 $type_name = $all_field_types[ $field['type'] ]['name'];
305 if ( $field['type'] === 'divider' && FrmField::is_option_true( $field, 'repeat' ) ) {
306 $type_name = $all_field_types['divider|repeat']['name'];
307 }
308
309 if ( $display['default'] ) {
310 $default_value_types = self::default_value_types( $field, compact( 'display' ) );
311 }
312
313 if ( $display['clear_on_focus'] && is_array( $field['placeholder'] ) ) {
314 $field['placeholder'] = implode( ', ', $field['placeholder'] );
315 }
316 include( FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/settings.php' );
317 }
318
319 /**
320 * Get the list of default value types that can be toggled in the builder.
321 *
322 * @since 4.0
323 * @return array
324 */
325 private static function default_value_types( $field, $atts ) {
326 $types = array(
327 'default_value' => array(
328 'class' => '',
329 'icon' => 'frm_icon_font frm_text2_icon',
330 'title' => __( 'Default Value (Text)', 'formidable' ),
331 'data' => array(
332 'frmshow' => '#default-value-for-',
333 ),
334 ),
335 'calc' => array(
336 'class' => 'frm_show_upgrade frm_noallow',
337 'title' => __( 'Default Value (Calculation)', 'formidable' ),
338 'icon' => 'frm_icon_font frm_calculator_icon',
339 'data' => array(
340 'medium' => 'calculations',
341 'upgrade' => __( 'Calculator forms', 'formidable' ),
342 ),
343 ),
344 'get_values_field' => array(
345 'class' => 'frm_show_upgrade frm_noallow',
346 'title' => __( 'Default Value (Lookup)', 'formidable' ),
347 'icon' => 'frm_icon_font frm_search_icon',
348 'data' => array(
349 'medium' => 'lookup',
350 'upgrade' => __( 'Lookup fields', 'formidable' ),
351 ),
352 ),
353 );
354
355 $types = apply_filters( 'frm_default_value_types', $types, $atts );
356
357 if ( FrmAppHelper::pro_is_installed() && ! FrmAppHelper::meets_min_pro_version( '4.0' ) ) {
358 // Prevent settings from showing in 2 spots.
359 unset( $types['calc'], $types['get_values_field'] );
360 }
361
362 // Set active class.
363 $settings = array_keys( $types );
364 $active = 'default_value';
365
366 foreach ( $settings as $type ) {
367 if ( ! empty( $field[ $type ] ) ) {
368 $active = $type;
369 }
370 }
371
372 $types[ $active ]['class'] .= ' current';
373 $types[ $active ]['current'] = true;
374
375 return $types;
376 }
377
378 public static function change_type( $type ) {
379 $type_switch = array(
380 'scale' => 'radio',
381 'star' => 'radio',
382 '10radio' => 'radio',
383 'rte' => 'textarea',
384 'website' => 'url',
385 'image' => 'url',
386 );
387 if ( isset( $type_switch[ $type ] ) ) {
388 $type = $type_switch[ $type ];
389 }
390
391 $pro_fields = FrmField::pro_field_selection();
392 $types = array_keys( $pro_fields );
393 if ( in_array( $type, $types ) ) {
394 $type = 'text';
395 }
396
397 return $type;
398 }
399
400 /**
401 * @param array $settings
402 * @param object $field_info
403 *
404 * @return array
405 */
406 public static function display_field_options( $settings, $field_info = null ) {
407 if ( $field_info ) {
408 $settings = $field_info->display_field_settings();
409 $settings['field_data'] = $field_info->field;
410 }
411
412 return apply_filters( 'frm_display_field_options', $settings );
413 }
414
415 /**
416 * Display the format option
417 *
418 * @since 3.0
419 *
420 * @param array $field
421 */
422 public static function show_format_option( $field ) {
423 include( FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/value-format.php' );
424 }
425
426 public static function input_html( $field, $echo = true ) {
427 $class = array();
428 self::add_input_classes( $field, $class );
429
430 $add_html = array();
431 self::add_html_size( $field, $add_html );
432 self::add_html_length( $field, $add_html );
433 self::add_html_placeholder( $field, $add_html, $class );
434 self::add_validation_messages( $field, $add_html );
435
436 $class = apply_filters( 'frm_field_classes', implode( ' ', $class ), $field );
437
438 FrmFormsHelper::add_html_attr( $class, 'class', $add_html );
439
440 self::add_shortcodes_to_html( $field, $add_html );
441 self::add_pattern_attribute( $field, $add_html );
442
443 $add_html = apply_filters( 'frm_field_extra_html', $add_html, $field );
444 $add_html = ' ' . implode( ' ', $add_html ) . ' ';
445
446 if ( $echo ) {
447 echo $add_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
448 }
449
450 return $add_html;
451 }
452
453 private static function add_input_classes( $field, array &$class ) {
454 if ( isset( $field['input_class'] ) && ! empty( $field['input_class'] ) ) {
455 $class[] = $field['input_class'];
456 }
457
458 if ( $field['type'] == 'hidden' || $field['type'] == 'user_id' ) {
459 return;
460 }
461
462 if ( isset( $field['size'] ) && $field['size'] > 0 ) {
463 $class[] = 'auto_width';
464 }
465 }
466
467 private static function add_html_size( $field, array &$add_html ) {
468 $size_fields = array(
469 'select',
470 'data',
471 'time',
472 'hidden',
473 'file',
474 'lookup',
475 );
476
477 if ( ! isset( $field['size'] ) || $field['size'] <= 0 || in_array( $field['type'], $size_fields ) ) {
478 return;
479 }
480
481 if ( FrmAppHelper::is_admin_page( 'formidable' ) ) {
482 return;
483 }
484
485 if ( is_numeric( $field['size'] ) ) {
486 $field['size'] .= 'px';
487 }
488
489 $important = apply_filters( 'frm_use_important_width', 1, $field );
490 // Note: This inline styling must stay since we cannot realistically set a class for every possible field size.
491 $add_html['style'] = 'style="width:' . esc_attr( $field['size'] ) . ( $important ? ' !important' : '' ) . '"';
492
493 self::add_html_cols( $field, $add_html );
494 }
495
496 private static function add_html_cols( $field, array &$add_html ) {
497 if ( ! in_array( $field['type'], array( 'textarea', 'rte' ) ) ) {
498 return;
499 }
500
501 // Convert to cols for textareas.
502 $calc = array(
503 '' => 9,
504 'px' => 9,
505 'rem' => 0.444,
506 'em' => 0.544,
507 );
508
509 // include "col" for valid html
510 $unit = trim( preg_replace( '/[0-9]+/', '', $field['size'] ) );
511
512 if ( ! isset( $calc[ $unit ] ) ) {
513 return;
514 }
515
516 $size = (float) str_replace( $unit, '', $field['size'] ) / $calc[ $unit ];
517
518 $add_html['cols'] = 'cols="' . absint( $size ) . '"';
519 }
520
521 private static function add_html_length( $field, array &$add_html ) {
522 // Check for max setting and if this field accepts maxlength.
523 $fields = array(
524 'textarea',
525 'rte',
526 'hidden',
527 'file',
528 );
529
530 if ( FrmField::is_option_empty( $field, 'max' ) || in_array( $field['type'], $fields ) ) {
531 return;
532 }
533
534 if ( FrmAppHelper::is_admin_page( 'formidable' ) ) {
535 // Don't load on form builder page.
536 return;
537 }
538
539 $add_html['maxlength'] = 'maxlength="' . esc_attr( $field['max'] ) . '"';
540 }
541
542 private static function add_html_placeholder( $field, array &$add_html, array &$class ) {
543 if ( $field['default_value'] != '' ) {
544 if ( is_array( $field['default_value'] ) ) {
545 $add_html['data-frmval'] = 'data-frmval="' . esc_attr( json_encode( $field['default_value'] ) ) . '"';
546 } else {
547 self::add_frmval_to_input( $field, $add_html );
548 }
549 }
550
551 $field['placeholder'] = self::prepare_placeholder( $field );
552 if ( $field['placeholder'] == '' || is_array( $field['placeholder'] ) ) {
553 // don't include a json placeholder
554 return;
555 }
556
557 $frm_settings = FrmAppHelper::get_settings();
558
559 if ( $frm_settings->use_html ) {
560 self::add_placeholder_to_input( $field, $add_html );
561 } else {
562 self::add_frmval_to_input( $field, $add_html );
563
564 $class[] = 'frm_toggle_default';
565
566 if ( $field['value'] == $field['placeholder'] ) {
567 $class[] = 'frm_default';
568 }
569 }
570 }
571
572 /**
573 * @param array $field
574 * @return string
575 */
576 private static function prepare_placeholder( $field ) {
577 $placeholder = isset( $field['placeholder'] ) ? $field['placeholder'] : '';
578 $placeholder_is_blank = empty( $placeholder ) && '0' !== $placeholder;
579 $is_placeholder_field = FrmFieldsHelper::is_placeholder_field_type( $field['type'] );
580 $is_combo_field = in_array( $field['type'], array( 'address', 'credit_card' ), true );
581
582 if ( $placeholder_is_blank && $is_placeholder_field && ! $is_combo_field ) {
583 $placeholder = self::get_default_value_from_name( $field );
584 }
585
586 return $placeholder;
587 }
588
589 /**
590 * If the label position is "inside",
591 * get the label to use as the placeholder
592 *
593 * @since 2.05
594 *
595 * @param array $field
596 *
597 * @return string
598 */
599 public static function get_default_value_from_name( $field ) {
600 $position = FrmField::get_option( $field, 'label' );
601 if ( $position == 'inside' ) {
602 $default_value = $field['name'];
603 if ( FrmField::is_required( $field ) ) {
604 $default_value .= ' ' . $field['required_indicator'];
605 }
606 } else {
607 $default_value = '';
608 }
609
610 return $default_value;
611 }
612
613 /**
614 * Maybe add a blank placeholder option before any options
615 * in a dropdown.
616 *
617 * @since 4.04
618 * @return bool True if placeholder was added.
619 */
620 public static function add_placeholder_to_select( $field ) {
621 $placeholder = FrmField::get_option( $field, 'placeholder' );
622 if ( empty( $placeholder ) ) {
623 $placeholder = self::get_default_value_from_name( $field );
624 }
625
626 if ( $placeholder !== '' ) {
627 ?>
628 <option value="">
629 <?php echo esc_html( FrmField::get_option( $field, 'autocom' ) ? '' : $placeholder ); ?>
630 </option>
631 <?php
632 return true;
633 }
634
635 return false;
636 }
637
638 /**
639 * Use HMTL5 placeholder with js fallback
640 *
641 * @param array $field
642 * @param array $add_html
643 */
644 private static function add_placeholder_to_input( $field, &$add_html ) {
645 if ( FrmFieldsHelper::is_placeholder_field_type( $field['type'] ) ) {
646 $add_html['placeholder'] = 'placeholder="' . esc_attr( $field['placeholder'] ) . '"';
647 }
648 }
649
650 private static function add_frmval_to_input( $field, &$add_html ) {
651 if ( $field['placeholder'] != '' ) {
652 $add_html['data-frmval'] = 'data-frmval="' . esc_attr( $field['placeholder'] ) . '"';
653
654 if ( 'select' === $field['type'] ) {
655 $add_html['data-frmplaceholder'] = 'data-frmplaceholder="' . esc_attr( $field['placeholder'] ) . '"';
656 }
657 }
658
659 if ( $field['default_value'] != '' ) {
660 $add_html['data-frmval'] = 'data-frmval="' . esc_attr( $field['default_value'] ) . '"';
661 }
662 }
663
664 private static function add_validation_messages( $field, array &$add_html ) {
665 if ( FrmField::is_required( $field ) ) {
666 $required_message = FrmFieldsHelper::get_error_msg( $field, 'blank' );
667 $add_html['data-reqmsg'] = 'data-reqmsg="' . esc_attr( $required_message ) . '"';
668 self::maybe_add_html_required( $field, $add_html );
669 }
670
671 if ( ! FrmField::is_option_empty( $field, 'invalid' ) ) {
672 $invalid_message = FrmFieldsHelper::get_error_msg( $field, 'invalid' );
673 $add_html['data-invmsg'] = 'data-invmsg="' . esc_attr( $invalid_message ) . '"';
674 }
675
676 if ( ! empty( $add_html['data-reqmsg'] ) || ! empty( $add_html['data-invmsg'] ) ) {
677 self::maybe_add_error_html_for_js_validation( $field, $add_html );
678 }
679 }
680
681 /**
682 * @since 5.0.03
683 *
684 * @param array $field
685 * @param array $add_html
686 */
687 private static function maybe_add_error_html_for_js_validation( $field, array &$add_html ) {
688 $form = self::get_form_for_js_validation( $field );
689 if ( false === $form ) {
690 return;
691 }
692
693 $error_body = self::pull_custom_error_body_from_custom_html( $form, $field );
694 if ( false !== $error_body ) {
695 $error_body = urlencode( $error_body );
696 $add_html['data-error-html'] = 'data-error-html="' . esc_attr( $error_body ) . '"';
697 }
698 }
699
700 /**
701 * @since 5.0.03
702 *
703 * @param array $field
704 * @return stdClass|false false if there is no form object found with JS validation active.
705 */
706 private static function get_form_for_js_validation( $field ) {
707 global $frm_vars;
708 if ( ! empty( $frm_vars['js_validate_forms'] ) ) {
709 if ( isset( $frm_vars['js_validate_forms'][ $field['form_id'] ] ) ) {
710 return $frm_vars['js_validate_forms'][ $field['form_id'] ];
711 }
712 if ( ! empty( $field['parent_form_id'] ) && isset( $frm_vars['js_validate_forms'][ $field['parent_form_id'] ] ) ) {
713 return $frm_vars['js_validate_forms'][ $field['parent_form_id'] ];
714 }
715 }
716 return false;
717 }
718
719 /**
720 * @param stdClass $form
721 * @param array $field
722 * @param array $errors
723 * @return string|false
724 */
725 public static function pull_custom_error_body_from_custom_html( $form, $field, $errors = array() ) {
726 if ( empty( $field['custom_html'] ) ) {
727 return false;
728 }
729
730 $custom_html = $field['custom_html'];
731 $custom_html = apply_filters( 'frm_before_replace_shortcodes', $custom_html, $field, $errors, $form );
732
733 $start = strpos( $custom_html, '[if error]' );
734 if ( false === $start ) {
735 return false;
736 }
737
738 $end = strpos( $custom_html, '[/if error]' );
739 if ( false === $end || $end < $start ) {
740 return false;
741 }
742
743 $error_body = substr( $custom_html, $start + 10, $end - $start - 10 );
744 $default_html = array(
745 '<div class="frm_error" id="frm_error_field_[key]">[error]</div>',
746 '<div class="frm_error">[error]</div>',
747 );
748
749 if ( in_array( $error_body, $default_html, true ) ) {
750 return false;
751 }
752
753 return $error_body;
754 }
755
756 /**
757 * If 'required' is added to a conditionally hidden field, the form won't
758 * submit in many browsers. Check to make sure the javascript to conditionally
759 * remove it is present if needed.
760 *
761 * @since 3.06.01
762 * @param array $field
763 * @param array $add_html
764 */
765 private static function maybe_add_html_required( $field, array &$add_html ) {
766 if ( in_array( $field['type'], array( 'file', 'data', 'lookup' ), true ) ) {
767 return;
768 }
769
770 $include_html = FrmAppHelper::meets_min_pro_version( '3.06.01' );
771 if ( $include_html ) {
772 $add_html['aria-required'] = 'aria-required="true"';
773 }
774 }
775
776 private static function add_shortcodes_to_html( $field, array &$add_html ) {
777 if ( FrmField::is_option_empty( $field, 'shortcodes' ) ) {
778 return;
779 }
780
781 foreach ( $field['shortcodes'] as $k => $v ) {
782 if ( 'opt' === $k ) {
783 continue;
784 }
785
786 if ( is_numeric( $k ) && strpos( $v, '=' ) ) {
787 $add_html[] = $v;
788 } elseif ( ! empty( $k ) && isset( $add_html[ $k ] ) ) {
789 $add_html[ $k ] = str_replace( $k . '="', $k . '="' . $v, $add_html[ $k ] );
790 } else {
791 $add_html[ $k ] = $k . '="' . esc_attr( $v ) . '"';
792 }
793
794 unset( $k, $v );
795 }
796 }
797
798 /**
799 * Add pattern attribute
800 *
801 * @since 3.0
802 *
803 * @param array $field
804 * @param array $add_html
805 */
806 private static function add_pattern_attribute( $field, array &$add_html ) {
807 $has_format = FrmField::is_option_true_in_array( $field, 'format' );
808 $format_field = FrmField::is_field_type( $field, 'text' );
809
810 if ( $field['type'] == 'phone' || ( $has_format && $format_field ) ) {
811 $frm_settings = FrmAppHelper::get_settings();
812
813 if ( $frm_settings->use_html ) {
814 $format = FrmEntryValidate::phone_format( $field );
815 $format = substr( $format, 2, - 1 );
816
817 $add_html['pattern'] = 'pattern="' . esc_attr( $format ) . '"';
818 }
819 }
820 }
821
822 public static function check_value( $opt, $opt_key, $field ) {
823 if ( is_array( $opt ) ) {
824 if ( FrmField::is_option_true( $field, 'separate_value' ) ) {
825 $opt = isset( $opt['value'] ) ? $opt['value'] : ( isset( $opt['label'] ) ? $opt['label'] : reset( $opt ) );
826 } else {
827 $opt = isset( $opt['label'] ) ? $opt['label'] : reset( $opt );
828 }
829 }
830
831 return $opt;
832 }
833
834 public static function check_label( $opt ) {
835 if ( is_array( $opt ) ) {
836 $opt = ( isset( $opt['label'] ) ? $opt['label'] : reset( $opt ) );
837 }
838
839 return $opt;
840 }
841
842 /**
843 * @deprecated 4.0
844 */
845 public static function update_ajax_option() {
846 _deprecated_function( __METHOD__, '4.0' );
847 FrmAppHelper::permission_check( 'frm_edit_forms' );
848 check_ajax_referer( 'frm_ajax', 'nonce' );
849
850 $field_id = FrmAppHelper::get_post_param( 'field', 0, 'absint' );
851 if ( ! $field_id ) {
852 wp_die();
853 }
854
855 $field = FrmField::getOne( $field_id );
856
857 if ( isset( $_POST['separate_value'] ) ) {
858 $new_val = FrmField::is_option_true( $field, 'separate_value' ) ? 0 : 1;
859
860 $field->field_options['separate_value'] = $new_val;
861 unset( $new_val );
862 }
863
864 FrmField::update(
865 $field_id,
866 array(
867 'field_options' => $field->field_options,
868 'form_id' => $field->form_id,
869 )
870 );
871 wp_die();
872 }
873
874 /**
875 * @deprecated 4.0
876 */
877 public static function import_choices() {
878 _deprecated_function( __METHOD__, '4.0' );
879 wp_die();
880 }
881
882 /**
883 * Add Single Option or Other Option.
884 *
885 * @deprecated 4.0 Moved to Pro for Other option only.
886 */
887 public static function add_option() {
888 _deprecated_function( __METHOD__, '4.0', 'FrmProFormsController::add_other_option' );
889 if ( is_callable( 'FrmProFormsController::add_other_option' ) ) {
890 FrmProFormsController::add_other_option();
891 }
892 }
893
894 /**
895 * @deprecated 4.0
896 */
897 public static function update_order() {
898 FrmDeprecated::update_order();
899 }
900
901 /**
902 * @deprecated 3.0
903 * @codeCoverageIgnore
904 */
905 public static function edit_name( $field = 'name', $id = '' ) {
906 FrmDeprecated::edit_name( $field, $id );
907 }
908
909 /**
910 * @deprecated 3.0
911 * @codeCoverageIgnore
912 *
913 * @param int $field_id
914 * @param array $values
915 * @param int $form_id
916 *
917 * @return array
918 */
919 public static function include_single_field( $field_id, $values, $form_id = 0 ) {
920 return FrmDeprecated::include_single_field( $field_id, $values, $form_id );
921 }
922
923 /**
924 * @deprecated 2.3
925 * @codeCoverageIgnore
926 */
927 public static function edit_option() {
928 FrmDeprecated::deprecated( __METHOD__, '2.3' );
929 }
930
931 /**
932 * @deprecated 2.3
933 * @codeCoverageIgnore
934 */
935 public static function delete_option() {
936 FrmDeprecated::deprecated( __METHOD__, '2.3' );
937 }
938 }
939