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

941 lines 25.9 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" role="alert" id="frm_error_field_[key]">[error]</div>',
747 '<div class="frm_error">[error]</div>',
748 '<div class="frm_error" role="alert">[error]</div>',
749 );
750
751 if ( in_array( $error_body, $default_html, true ) ) {
752 return false;
753 }
754
755 return $error_body;
756 }
757
758 /**
759 * If 'required' is added to a conditionally hidden field, the form won't
760 * submit in many browsers. Check to make sure the javascript to conditionally
761 * remove it is present if needed.
762 *
763 * @since 3.06.01
764 * @param array $field
765 * @param array $add_html
766 */
767 private static function maybe_add_html_required( $field, array &$add_html ) {
768 if ( in_array( $field['type'], array( 'file', 'data', 'lookup' ), true ) ) {
769 return;
770 }
771
772 $include_html = FrmAppHelper::meets_min_pro_version( '3.06.01' );
773 if ( $include_html ) {
774 $add_html['aria-required'] = 'aria-required="true"';
775 }
776 }
777
778 private static function add_shortcodes_to_html( $field, array &$add_html ) {
779 if ( FrmField::is_option_empty( $field, 'shortcodes' ) ) {
780 return;
781 }
782
783 foreach ( $field['shortcodes'] as $k => $v ) {
784 if ( 'opt' === $k ) {
785 continue;
786 }
787
788 if ( is_numeric( $k ) && strpos( $v, '=' ) ) {
789 $add_html[] = $v;
790 } elseif ( ! empty( $k ) && isset( $add_html[ $k ] ) ) {
791 $add_html[ $k ] = str_replace( $k . '="', $k . '="' . $v, $add_html[ $k ] );
792 } else {
793 $add_html[ $k ] = $k . '="' . esc_attr( $v ) . '"';
794 }
795
796 unset( $k, $v );
797 }
798 }
799
800 /**
801 * Add pattern attribute
802 *
803 * @since 3.0
804 *
805 * @param array $field
806 * @param array $add_html
807 */
808 private static function add_pattern_attribute( $field, array &$add_html ) {
809 $has_format = FrmField::is_option_true_in_array( $field, 'format' );
810 $format_field = FrmField::is_field_type( $field, 'text' );
811
812 if ( $field['type'] == 'phone' || ( $has_format && $format_field ) ) {
813 $frm_settings = FrmAppHelper::get_settings();
814
815 if ( $frm_settings->use_html ) {
816 $format = FrmEntryValidate::phone_format( $field );
817 $format = substr( $format, 2, - 1 );
818
819 $add_html['pattern'] = 'pattern="' . esc_attr( $format ) . '"';
820 }
821 }
822 }
823
824 public static function check_value( $opt, $opt_key, $field ) {
825 if ( is_array( $opt ) ) {
826 if ( FrmField::is_option_true( $field, 'separate_value' ) ) {
827 $opt = isset( $opt['value'] ) ? $opt['value'] : ( isset( $opt['label'] ) ? $opt['label'] : reset( $opt ) );
828 } else {
829 $opt = isset( $opt['label'] ) ? $opt['label'] : reset( $opt );
830 }
831 }
832
833 return $opt;
834 }
835
836 public static function check_label( $opt ) {
837 if ( is_array( $opt ) ) {
838 $opt = ( isset( $opt['label'] ) ? $opt['label'] : reset( $opt ) );
839 }
840
841 return $opt;
842 }
843
844 /**
845 * @deprecated 4.0
846 */
847 public static function update_ajax_option() {
848 _deprecated_function( __METHOD__, '4.0' );
849 FrmAppHelper::permission_check( 'frm_edit_forms' );
850 check_ajax_referer( 'frm_ajax', 'nonce' );
851
852 $field_id = FrmAppHelper::get_post_param( 'field', 0, 'absint' );
853 if ( ! $field_id ) {
854 wp_die();
855 }
856
857 $field = FrmField::getOne( $field_id );
858
859 if ( isset( $_POST['separate_value'] ) ) {
860 $new_val = FrmField::is_option_true( $field, 'separate_value' ) ? 0 : 1;
861
862 $field->field_options['separate_value'] = $new_val;
863 unset( $new_val );
864 }
865
866 FrmField::update(
867 $field_id,
868 array(
869 'field_options' => $field->field_options,
870 'form_id' => $field->form_id,
871 )
872 );
873 wp_die();
874 }
875
876 /**
877 * @deprecated 4.0
878 */
879 public static function import_choices() {
880 _deprecated_function( __METHOD__, '4.0' );
881 wp_die();
882 }
883
884 /**
885 * Add Single Option or Other Option.
886 *
887 * @deprecated 4.0 Moved to Pro for Other option only.
888 */
889 public static function add_option() {
890 _deprecated_function( __METHOD__, '4.0', 'FrmProFormsController::add_other_option' );
891 if ( is_callable( 'FrmProFormsController::add_other_option' ) ) {
892 FrmProFormsController::add_other_option();
893 }
894 }
895
896 /**
897 * @deprecated 4.0
898 */
899 public static function update_order() {
900 FrmDeprecated::update_order();
901 }
902
903 /**
904 * @deprecated 3.0
905 * @codeCoverageIgnore
906 */
907 public static function edit_name( $field = 'name', $id = '' ) {
908 FrmDeprecated::edit_name( $field, $id );
909 }
910
911 /**
912 * @deprecated 3.0
913 * @codeCoverageIgnore
914 *
915 * @param int $field_id
916 * @param array $values
917 * @param int $form_id
918 *
919 * @return array
920 */
921 public static function include_single_field( $field_id, $values, $form_id = 0 ) {
922 return FrmDeprecated::include_single_field( $field_id, $values, $form_id );
923 }
924
925 /**
926 * @deprecated 2.3
927 * @codeCoverageIgnore
928 */
929 public static function edit_option() {
930 FrmDeprecated::deprecated( __METHOD__, '2.3' );
931 }
932
933 /**
934 * @deprecated 2.3
935 * @codeCoverageIgnore
936 */
937 public static function delete_option() {
938 FrmDeprecated::deprecated( __METHOD__, '2.3' );
939 }
940 }
941