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

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