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

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