PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 5.4.2
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v5.4.2
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
formidable / classes / controllers / FrmFieldsController.php

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

929 lines 25.4 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 * Prepares field placeholder.
574 *
575 * @since 5.4 This doesn't call `FrmFieldsController::get_default_value_from_name()` anymore.
576 *
577 * @param array $field Field array.
578 * @return string
579 */
580 private static function prepare_placeholder( $field ) {
581 $placeholder = isset( $field['placeholder'] ) ? $field['placeholder'] : '';
582
583 return $placeholder;
584 }
585
586 /**
587 * If the label position is "inside",
588 * get the label to use as the placeholder
589 *
590 * @since 2.05
591 * @since 5.4 Remove the logic code for "inside" label position.
592 *
593 * @param array $field
594 *
595 * @return string
596 */
597 public static function get_default_value_from_name( $field ) {
598 return '';
599 }
600
601 /**
602 * Maybe add a blank placeholder option before any options
603 * in a dropdown.
604 *
605 * @since 4.04
606 * @return bool True if placeholder was added.
607 */
608 public static function add_placeholder_to_select( $field ) {
609 $placeholder = FrmField::get_option( $field, 'placeholder' );
610 if ( empty( $placeholder ) ) {
611 $placeholder = self::get_default_value_from_name( $field );
612 }
613
614 if ( $placeholder !== '' ) {
615 ?>
616 <option value="">
617 <?php echo esc_html( FrmField::get_option( $field, 'autocom' ) ? '' : $placeholder ); ?>
618 </option>
619 <?php
620 return true;
621 }
622
623 return false;
624 }
625
626 /**
627 * Use HMTL5 placeholder with js fallback
628 *
629 * @param array $field
630 * @param array $add_html
631 */
632 private static function add_placeholder_to_input( $field, &$add_html ) {
633 if ( FrmFieldsHelper::is_placeholder_field_type( $field['type'] ) ) {
634 $add_html['placeholder'] = 'placeholder="' . esc_attr( $field['placeholder'] ) . '"';
635 }
636 }
637
638 private static function add_frmval_to_input( $field, &$add_html ) {
639 if ( $field['placeholder'] != '' ) {
640 $add_html['data-frmval'] = 'data-frmval="' . esc_attr( $field['placeholder'] ) . '"';
641
642 if ( 'select' === $field['type'] ) {
643 $add_html['data-frmplaceholder'] = 'data-frmplaceholder="' . esc_attr( $field['placeholder'] ) . '"';
644 }
645 }
646
647 if ( $field['default_value'] != '' ) {
648 $add_html['data-frmval'] = 'data-frmval="' . esc_attr( $field['default_value'] ) . '"';
649 }
650 }
651
652 private static function add_validation_messages( $field, array &$add_html ) {
653 if ( FrmField::is_required( $field ) ) {
654 $required_message = FrmFieldsHelper::get_error_msg( $field, 'blank' );
655 $add_html['data-reqmsg'] = 'data-reqmsg="' . esc_attr( $required_message ) . '"';
656 self::maybe_add_html_required( $field, $add_html );
657 }
658
659 if ( ! FrmField::is_option_empty( $field, 'invalid' ) ) {
660 $invalid_message = FrmFieldsHelper::get_error_msg( $field, 'invalid' );
661 $add_html['data-invmsg'] = 'data-invmsg="' . esc_attr( $invalid_message ) . '"';
662 }
663
664 if ( ! empty( $add_html['data-reqmsg'] ) || ! empty( $add_html['data-invmsg'] ) ) {
665 self::maybe_add_error_html_for_js_validation( $field, $add_html );
666 }
667 }
668
669 /**
670 * @since 5.0.03
671 *
672 * @param array $field
673 * @param array $add_html
674 */
675 private static function maybe_add_error_html_for_js_validation( $field, array &$add_html ) {
676 $form = self::get_form_for_js_validation( $field );
677 if ( false === $form ) {
678 return;
679 }
680
681 $error_body = self::pull_custom_error_body_from_custom_html( $form, $field );
682 if ( false !== $error_body ) {
683 $error_body = urlencode( $error_body );
684 $add_html['data-error-html'] = 'data-error-html="' . esc_attr( $error_body ) . '"';
685 }
686 }
687
688 /**
689 * @since 5.0.03
690 *
691 * @param array $field
692 * @return stdClass|false false if there is no form object found with JS validation active.
693 */
694 private static function get_form_for_js_validation( $field ) {
695 global $frm_vars;
696 if ( ! empty( $frm_vars['js_validate_forms'] ) ) {
697 if ( isset( $frm_vars['js_validate_forms'][ $field['form_id'] ] ) ) {
698 return $frm_vars['js_validate_forms'][ $field['form_id'] ];
699 }
700 if ( ! empty( $field['parent_form_id'] ) && isset( $frm_vars['js_validate_forms'][ $field['parent_form_id'] ] ) ) {
701 return $frm_vars['js_validate_forms'][ $field['parent_form_id'] ];
702 }
703 }
704 return false;
705 }
706
707 /**
708 * @param stdClass $form
709 * @param array $field
710 * @param array $errors
711 * @return string|false
712 */
713 public static function pull_custom_error_body_from_custom_html( $form, $field, $errors = array() ) {
714 if ( empty( $field['custom_html'] ) ) {
715 return false;
716 }
717
718 $custom_html = $field['custom_html'];
719 $custom_html = apply_filters( 'frm_before_replace_shortcodes', $custom_html, $field, $errors, $form );
720
721 $start = strpos( $custom_html, '[if error]' );
722 if ( false === $start ) {
723 return false;
724 }
725
726 $end = strpos( $custom_html, '[/if error]' );
727 if ( false === $end || $end < $start ) {
728 return false;
729 }
730
731 $error_body = substr( $custom_html, $start + 10, $end - $start - 10 );
732 $default_html = array(
733 '<div class="frm_error" id="frm_error_field_[key]">[error]</div>',
734 '<div class="frm_error" role="alert" id="frm_error_field_[key]">[error]</div>',
735 '<div class="frm_error">[error]</div>',
736 '<div class="frm_error" role="alert">[error]</div>',
737 );
738
739 if ( in_array( $error_body, $default_html, true ) ) {
740 return false;
741 }
742
743 return $error_body;
744 }
745
746 /**
747 * If 'required' is added to a conditionally hidden field, the form won't
748 * submit in many browsers. Check to make sure the javascript to conditionally
749 * remove it is present if needed.
750 *
751 * @since 3.06.01
752 * @param array $field
753 * @param array $add_html
754 */
755 private static function maybe_add_html_required( $field, array &$add_html ) {
756 if ( in_array( $field['type'], array( 'file', 'data', 'lookup' ), true ) ) {
757 return;
758 }
759
760 $include_html = FrmAppHelper::meets_min_pro_version( '3.06.01' );
761 if ( $include_html ) {
762 $add_html['aria-required'] = 'aria-required="true"';
763 }
764 }
765
766 private static function add_shortcodes_to_html( $field, array &$add_html ) {
767 if ( FrmField::is_option_empty( $field, 'shortcodes' ) ) {
768 return;
769 }
770
771 foreach ( $field['shortcodes'] as $k => $v ) {
772 if ( 'opt' === $k ) {
773 continue;
774 }
775
776 if ( is_numeric( $k ) && strpos( $v, '=' ) ) {
777 $add_html[] = $v;
778 } elseif ( ! empty( $k ) && isset( $add_html[ $k ] ) ) {
779 $add_html[ $k ] = str_replace( $k . '="', $k . '="' . $v, $add_html[ $k ] );
780 } else {
781 $add_html[ $k ] = $k . '="' . esc_attr( $v ) . '"';
782 }
783
784 unset( $k, $v );
785 }
786 }
787
788 /**
789 * Add pattern attribute
790 *
791 * @since 3.0
792 *
793 * @param array $field
794 * @param array $add_html
795 */
796 private static function add_pattern_attribute( $field, array &$add_html ) {
797 $has_format = FrmField::is_option_true_in_array( $field, 'format' );
798 $format_field = FrmField::is_field_type( $field, 'text' );
799
800 if ( $field['type'] == 'phone' || ( $has_format && $format_field ) ) {
801 $frm_settings = FrmAppHelper::get_settings();
802
803 if ( $frm_settings->use_html ) {
804 $format = FrmEntryValidate::phone_format( $field );
805 $format = substr( $format, 2, - 1 );
806
807 $add_html['pattern'] = 'pattern="' . esc_attr( $format ) . '"';
808 }
809 }
810 }
811
812 public static function check_value( $opt, $opt_key, $field ) {
813 if ( is_array( $opt ) ) {
814 if ( FrmField::is_option_true( $field, 'separate_value' ) ) {
815 $opt = isset( $opt['value'] ) ? $opt['value'] : ( isset( $opt['label'] ) ? $opt['label'] : reset( $opt ) );
816 } else {
817 $opt = isset( $opt['label'] ) ? $opt['label'] : reset( $opt );
818 }
819 }
820
821 return $opt;
822 }
823
824 public static function check_label( $opt ) {
825 if ( is_array( $opt ) ) {
826 $opt = ( isset( $opt['label'] ) ? $opt['label'] : reset( $opt ) );
827 }
828
829 return $opt;
830 }
831
832 /**
833 * @deprecated 4.0
834 */
835 public static function update_ajax_option() {
836 _deprecated_function( __METHOD__, '4.0' );
837 FrmAppHelper::permission_check( 'frm_edit_forms' );
838 check_ajax_referer( 'frm_ajax', 'nonce' );
839
840 $field_id = FrmAppHelper::get_post_param( 'field', 0, 'absint' );
841 if ( ! $field_id ) {
842 wp_die();
843 }
844
845 $field = FrmField::getOne( $field_id );
846
847 if ( isset( $_POST['separate_value'] ) ) {
848 $new_val = FrmField::is_option_true( $field, 'separate_value' ) ? 0 : 1;
849
850 $field->field_options['separate_value'] = $new_val;
851 unset( $new_val );
852 }
853
854 FrmField::update(
855 $field_id,
856 array(
857 'field_options' => $field->field_options,
858 'form_id' => $field->form_id,
859 )
860 );
861 wp_die();
862 }
863
864 /**
865 * @deprecated 4.0
866 */
867 public static function import_choices() {
868 _deprecated_function( __METHOD__, '4.0' );
869 wp_die();
870 }
871
872 /**
873 * Add Single Option or Other Option.
874 *
875 * @deprecated 4.0 Moved to Pro for Other option only.
876 */
877 public static function add_option() {
878 _deprecated_function( __METHOD__, '4.0', 'FrmProFormsController::add_other_option' );
879 if ( is_callable( 'FrmProFormsController::add_other_option' ) ) {
880 FrmProFormsController::add_other_option();
881 }
882 }
883
884 /**
885 * @deprecated 4.0
886 */
887 public static function update_order() {
888 FrmDeprecated::update_order();
889 }
890
891 /**
892 * @deprecated 3.0
893 * @codeCoverageIgnore
894 */
895 public static function edit_name( $field = 'name', $id = '' ) {
896 FrmDeprecated::edit_name( $field, $id );
897 }
898
899 /**
900 * @deprecated 3.0
901 * @codeCoverageIgnore
902 *
903 * @param int $field_id
904 * @param array $values
905 * @param int $form_id
906 *
907 * @return array
908 */
909 public static function include_single_field( $field_id, $values, $form_id = 0 ) {
910 return FrmDeprecated::include_single_field( $field_id, $values, $form_id );
911 }
912
913 /**
914 * @deprecated 2.3
915 * @codeCoverageIgnore
916 */
917 public static function edit_option() {
918 FrmDeprecated::deprecated( __METHOD__, '2.3' );
919 }
920
921 /**
922 * @deprecated 2.3
923 * @codeCoverageIgnore
924 */
925 public static function delete_option() {
926 FrmDeprecated::deprecated( __METHOD__, '2.3' );
927 }
928 }
929