PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.20
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.20
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
← All changes | classes/controllers/FrmFieldsController.php +99 -383 6.356.20 View file →
@@ -11,55 +11,48 @@
11 11 * @var FrmFieldSelectionData|null
12 12 */
13 13 private static $field_selection_data;
14 14
15 - /**
16 - * Render the fields the form builder asked for over ajax.
17 - *
18 - * The browser sends field ids only. The fields themselves are read from the form, which is one
19 - * indexed query shared with the rest of the request through the field cache, and cheaper than
20 - * shipping every field's data down to the page and straight back up again.
21 - *
22 - * @return void
23 - */
24 15 public static function load_field() {
25 16 FrmAppHelper::permission_check( 'frm_edit_forms' );
26 17 check_ajax_referer( 'frm_ajax', 'nonce' );
27 18
28 - $field_ids = FrmAppHelper::get_post_param( 'field_ids', array(), 'absint' );
29 - $form_id = FrmAppHelper::get_post_param( 'form_id', 0, 'absint' );
30 -
31 - if ( ! $form_id || ! is_array( $field_ids ) || ! $field_ids ) {
19 + // Javascript may be included in some field settings.
20 + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
21 + $fields = isset( $_POST['field'] ) ? wp_unslash( $_POST['field'] ) : array();
22 + if ( empty( $fields ) ) {
32 23 wp_die();
33 24 }
34 25
35 26 $_GET['page'] = 'formidable';
36 - $fields = self::get_builder_fields_by_id( $form_id );
37 - $values = array(
38 - 'id' => $form_id,
27 +
28 + $values = array(
29 + 'id' => FrmAppHelper::get_post_param( 'form_id', '', 'absint' ),
39 30 'doing_ajax' => true,
40 31 );
41 - $field_html = array();
32 + $field_html = array();
42 33
43 - foreach ( $field_ids as $field_id ) {
44 - if ( ! isset( $fields[ $field_id ] ) ) {
45 - // This field may have already been loaded, or is no longer in the form.
34 + foreach ( $fields as $field ) {
35 + $field = htmlspecialchars_decode( nl2br( $field ) );
36 + $field = json_decode( $field );
37 + if ( ! isset( $field->id ) || ! is_numeric( $field->id ) ) {
38 + // this field may have already been loaded
46 39 continue;
47 40 }
48 41
49 - $field = $fields[ $field_id ];
42 + if ( ! isset( $field->value ) ) {
43 + $field->value = '';
44 + }
45 + $field->field_options = json_decode( json_encode( $field->field_options ), true );
46 + $field->options = json_decode( json_encode( $field->options ), true );
47 + $field->default_value = json_decode( json_encode( $field->default_value ), true );
50 48
51 49 ob_start();
52 50 self::load_single_field( $field, $values );
51 + $field_html[ absint( $field->id ) ] = ob_get_contents();
52 + ob_end_clean();
53 + }
53 54
54 - $field_html[ $field_id ] = array(
55 - // The type travels with the html so the js can report it to frm_ajax_loaded_field
56 - // listeners without a copy of the field.
57 - 'type' => $field->type,
58 - 'html' => ob_get_clean(),
59 - );
60 - }//end foreach
61 -
62 55 echo json_encode( $field_html );
63 56
64 57 wp_die();
65 58 }
@@ -64,40 +57,8 @@
64 57 wp_die();
65 58 }
66 59
67 60 /**
68 - * Get a form's fields, as the form builder sees them, indexed by field id.
69 - *
70 - * @since 6.35
71 - *
72 - * @param int $form_id
73 - *
74 - * @return array Field objects keyed by field id. Empty if the form is gone.
75 - */
76 - private static function get_builder_fields_by_id( $form_id ) {
77 - $form = FrmForm::getOne( $form_id );
78 -
79 - if ( ! $form ) {
80 - return array();
81 - }
82 -
83 - $fields = FrmField::get_all_for_form( $form_id );
84 -
85 - /** This filter is documented in classes/controllers/FrmFormsController.php */
86 - $fields = apply_filters( 'frm_fields_in_form_builder', $fields, compact( 'form' ) );
87 -
88 - $fields_by_id = array();
89 -
90 - foreach ( (array) $fields as $field ) {
91 - if ( is_object( $field ) && ! empty( $field->id ) ) {
92 - $fields_by_id[ (int) $field->id ] = $field;
93 - }
94 - }
95 -
96 - return $fields_by_id;
97 - }
98 -
99 - /**
100 61 * Create a new field with ajax
101 62 */
102 63 public static function create() {
103 64 FrmAppHelper::permission_check( 'frm_edit_forms' );
@@ -102,17 +63,16 @@
102 63 public static function create() {
103 64 FrmAppHelper::permission_check( 'frm_edit_forms' );
104 65 check_ajax_referer( 'frm_ajax', 'nonce' );
105 66
106 - $field_type = FrmAppHelper::get_post_param( 'field_type', '', 'sanitize_text_field' );
107 - $form_id = FrmAppHelper::get_post_param( 'form_id', 0, 'absint' );
108 - $field_options = FrmAppHelper::get_post_param( 'field_options', array(), 'wp_kses_post' );
67 + $field_type = FrmAppHelper::get_post_param( 'field_type', '', 'sanitize_text_field' );
68 + $form_id = FrmAppHelper::get_post_param( 'form_id', 0, 'absint' );
109 69
110 70 do_action( 'frm_before_create_field', $field_type, $form_id );
111 71
112 - $field = self::include_new_field( $field_type, $form_id, $field_options );
72 + $field = self::include_new_field( $field_type, $form_id );
113 73
114 - // This hook will allow for multiple fields to be added at once
74 + // this hook will allow for multiple fields to be added at once
115 75 do_action( 'frm_after_field_created', $field, $form_id );
116 76
117 77 wp_die();
118 78 }
@@ -121,19 +81,14 @@
121 81 * Set up and create a new field
122 82 *
123 83 * @param string $field_type
124 84 * @param int $form_id
125 - * @param array $field_options
126 85 *
127 86 * @return array|false
128 87 */
129 - public static function include_new_field( $field_type, $form_id, $field_options = array() ) {
88 + public static function include_new_field( $field_type, $form_id ) {
130 89 $field_values = FrmFieldsHelper::setup_new_vars( $field_type, $form_id );
131 90
132 - if ( $field_options ) {
133 - $field_values['field_options'] = array_merge( $field_values['field_options'], $field_options );
134 - }
135 -
136 91 // When a new field is added to the form, flag it as draft and hide it from the front-end.
137 92 $field_values['field_options']['draft'] = 1;
138 93
139 94 /**
@@ -145,15 +100,15 @@
145 100 if ( ! $field_id ) {
146 101 return false;
147 102 }
148 103
149 - $field = self::get_field_array_from_id( $field_id );
104 + $field = self::get_field_array_from_id( $field_id );
105 +
150 106 $values = array();
151 -
152 107 if ( FrmAppHelper::pro_is_installed() ) {
153 108 $values['post_type'] = FrmProFormsHelper::post_type( $form_id );
154 - $parent_form_id = FrmDb::get_var( 'frm_forms', array( 'id' => $form_id ), 'parent_form_id' );
155 109
110 + $parent_form_id = FrmDb::get_var( 'frm_forms', array( 'id' => $form_id ), 'parent_form_id' );
156 111 if ( $parent_form_id ) {
157 112 $field['parent_form_id'] = $parent_form_id;
158 113 }
159 114 }
@@ -166,14 +121,15 @@
166 121 public static function duplicate() {
167 122 FrmAppHelper::permission_check( 'frm_edit_forms' );
168 123 check_ajax_referer( 'frm_ajax', 'nonce' );
169 124
170 - $field_id = FrmAppHelper::get_post_param( 'field_id', 0, 'absint' );
171 - $form_id = FrmAppHelper::get_post_param( 'form_id', 0, 'absint' );
125 + $field_id = FrmAppHelper::get_post_param( 'field_id', 0, 'absint' );
126 + $form_id = FrmAppHelper::get_post_param( 'form_id', 0, 'absint' );
127 +
172 128 $new_field = FrmField::duplicate_single_field( $field_id, $form_id );
173 129
174 130 if ( is_array( $new_field ) && ! empty( $new_field['field_id'] ) ) {
175 - self::load_single_field( $new_field['field_id'], $new_field['values'], $form_id );
131 + self::load_single_field( $new_field['field_id'], $new_field['values'] );
176 132 }
177 133
178 134 wp_die();
179 135 }
@@ -186,8 +142,9 @@
186 142 * @return array
187 143 */
188 144 public static function get_field_array_from_id( $field_id ) {
189 145 $field = FrmField::getOne( $field_id );
146 +
190 147 return FrmFieldsHelper::setup_edit_vars( $field );
191 148 }
192 149
193 150 /**
@@ -192,13 +149,11 @@
192 149
193 150 /**
194 151 * @since 3.0
195 152 *
196 - * @param array|int|object|string $field_object
197 - * @param array $values
198 - * @param int $form_id
199 - *
200 - * @return void
153 + * @param array|int|object $field_object
154 + * @param array $values
155 + * @param int $form_id
201 156 */
202 157 public static function load_single_field( $field_object, $values, $form_id = 0 ) {
203 158 global $frm_vars;
204 159 $frm_vars['is_admin'] = true;
@@ -209,10 +164,11 @@
209 164 $field = $field_object;
210 165 $field_object = FrmField::getOne( $field['id'] );
211 166 }
212 167
213 - $field_obj = FrmFieldFactory::get_field_factory( $field_object );
214 - $display = self::display_field_options( array(), $field_obj );
168 + $field_obj = FrmFieldFactory::get_field_factory( $field_object );
169 + $display = self::display_field_options( array(), $field_obj );
170 +
215 171 $ajax_loading = ! empty( $values['ajax_load'] );
216 172 $ajax_this_field = isset( $values['count'] ) && $values['count'] > 10 && ! in_array( $field_object->type, array( 'divider', 'end_divider' ), true );
217 173
218 174 if ( $ajax_loading && $ajax_this_field ) {
@@ -221,26 +177,12 @@
221 177 return;
222 178 }
223 179
224 180 if ( ! isset( $field ) && is_object( $field_object ) ) {
225 - // Prefer the explicit form id. $values['id'] is not always a form id (for example when
226 - // duplicating a field it is the copied field's id), so trusting it would set parent_form_id
227 - // to a field id and break settings that resolve fields against the parent form.
228 - $field_object->parent_form_id = $form_id ? $form_id : ( $values['id'] ?? $field_object->form_id );
181 + $field_object->parent_form_id = isset( $values['id'] ) ? $values['id'] : $field_object->form_id;
229 182 $field = FrmFieldsHelper::setup_edit_vars( $field_object );
230 183 }
231 184
232 - /**
233 - * Filter for adding extra attributes to the field container.
234 - *
235 - * @since 6.23
236 - *
237 - * @param array $extra_field_attributes
238 - * @param array $field
239 - * @param array $display
240 - */
241 - $extra_field_attributes = apply_filters( 'frm_field_container_extra_attributes', array(), $field, $display );
242 -
243 185 $li_classes = self::get_classes_for_builder_field( $field, $display, $field_obj );
244 186 $li_classes .= ' ui-state-default widgets-holder-wrap';
245 187
246 188 require FrmAppHelper::plugin_path() . '/classes/views/frm-forms/add_field.php';
@@ -251,9 +193,8 @@
251 193 *
252 194 * @param array $field
253 195 * @param array $display
254 196 * @param FrmFieldType $field_info
255 - *
256 197 * @return string
257 198 */
258 199 private static function get_classes_for_builder_field( $field, $display, $field_info ) {
259 200 $li_classes = $field_info->form_builder_classes( $display['type'] );
@@ -258,14 +199,8 @@
258 199 private static function get_classes_for_builder_field( $field, $display, $field_info ) {
259 200 $li_classes = $field_info->form_builder_classes( $display['type'] );
260 201 $li_classes .= ' frm_form_field frmstart ';
261 202
262 - $style_align_class = self::get_builder_field_style_align_class( $field, $field_info );
263 -
264 - if ( $style_align_class ) {
265 - $li_classes .= $style_align_class . ' ';
266 - }
267 -
268 203 if ( isset( $field['classes'] ) ) {
269 204 $li_classes .= trim( $field['classes'] ) . ' ';
270 205 }
271 206
@@ -271,45 +206,14 @@
271 206
272 207 $li_classes .= 'frmend';
273 208
274 209 if ( $field ) {
275 - return apply_filters( 'frm_build_field_class', $li_classes, $field );
210 + $li_classes = apply_filters( 'frm_build_field_class', $li_classes, $field );
276 211 }
277 212
278 213 return $li_classes;
279 214 }
280 215
281 - /**
282 - * Apply the active style alignment to a radio or checkbox builder preview on load.
283 - *
284 - * The per-field alignment setting only exists in Pro, so on load the style setting is
285 - * used. When the field has an explicit alignment (Pro), the frm_build_field_class filter
286 - * applies it instead. When Pro is not installed, any saved alignment is treated as empty.
287 - *
288 - * @since 6.32
289 - *
290 - * @param array $field
291 - * @param FrmFieldType $field_info
292 - *
293 - * @return string
294 - */
295 - private static function get_builder_field_style_align_class( $field, $field_info ) {
296 - if ( ! $field || ! is_array( $field ) || ( ! FrmField::is_radio( $field ) && ! FrmField::is_checkbox( $field ) ) ) {
297 - return '';
298 - }
299 -
300 - $align = FrmAppHelper::pro_is_installed() ? FrmField::get_option( $field, 'align' ) : '';
301 -
302 - if ( $align ) {
303 - return '';
304 - }
305 -
306 - $align = FrmStylesHelper::get_align_from_active_style( $field );
307 - $field_info->prepare_align_class( $align );
308 -
309 - return $align;
310 - }
311 -
312 216 public static function destroy() {
313 217 FrmAppHelper::permission_check( 'frm_edit_forms' );
314 218 check_ajax_referer( 'frm_ajax', 'nonce' );
315 219
@@ -338,9 +242,8 @@
338 242 *
339 243 * @since 6.8.4
340 244 *
341 245 * @param array $bulk_edit_types
342 - *
343 246 * @return array
344 247 */
345 248 $bulk_edit_types = apply_filters( 'frm_bulk_edit_field_types', $bulk_edit_types );
346 249
@@ -348,19 +251,18 @@
348 251 return;
349 252 }
350 253
351 254 $field = FrmFieldsHelper::setup_edit_vars( $field );
255 + $opts = FrmAppHelper::get_param( 'opts', '', 'post', 'wp_kses_post' );
256 + $opts = explode( "\n", rtrim( $opts, "\n" ) );
257 + $opts = array_map( 'trim', $opts );
352 258
353 - $opts = FrmAppHelper::get_param( 'opts', '', 'post', 'wp_kses_post' );
354 - $opts = explode( "\n", rtrim( $opts, "\n" ) );
355 - $opts = array_map( 'trim', $opts );
356 -
357 259 $separate = FrmAppHelper::get_param( 'separate', '', 'post', 'sanitize_text_field' );
358 260 $field['separate_value'] = $separate === 'true';
359 261
360 262 if ( $field['separate_value'] ) {
361 263 foreach ( $opts as $opt_key => $opt ) {
362 - if ( str_contains( $opt, '|' ) ) {
264 + if ( strpos( $opt, '|' ) !== false ) {
363 265 $vals = explode( '|', $opt );
364 266 $opts[ $opt_key ] = array(
365 267 'label' => trim( $vals[0] ),
366 268 'value' => trim( $vals[1] ),
@@ -371,11 +273,10 @@
371 273 }
372 274 }
373 275
374 276 // Keep other options after bulk update.
375 - if ( ! empty( $field['field_options']['other'] ) ) {
277 + if ( isset( $field['field_options']['other'] ) && $field['field_options']['other'] == true ) {
376 278 $other_array = array();
377 -
378 279 foreach ( $field['options'] as $opt_key => $opt ) {
379 280 if ( FrmFieldsHelper::is_other_opt( $opt_key ) ) {
380 281 $other_array[ $opt_key ] = $opt;
381 282 }
@@ -380,10 +281,9 @@
380 281 $other_array[ $opt_key ] = $opt;
381 282 }
382 283 unset( $opt_key, $opt );
383 284 }
384 -
385 - if ( $other_array ) {
285 + if ( ! empty( $other_array ) ) {
386 286 $opts = array_merge( $opts, $other_array );
387 287 }
388 288 }
389 289
@@ -397,9 +297,8 @@
397 297 /**
398 298 * @since 4.0
399 299 *
400 300 * @param array $atts - Includes field array, field_obj, display array, values array.
401 - *
402 301 * @return void
403 302 */
404 303 public static function load_single_field_settings( $atts ) {
405 304 $field = $atts['field'];
@@ -425,9 +324,9 @@
425 324 if ( ! isset( $all_field_types[ $field['type'] ] ) ) {
426 325 // Add fallback for an add-on field type that has been deactivated.
427 326 $all_field_types[ $field['type'] ] = array(
428 327 'name' => ucfirst( $field['type'] ),
429 - 'icon' => 'frmfont frm_pencil_icon',
328 + 'icon' => 'frm_icon_font frm_pencil_icon',
430 329 );
431 330 } elseif ( ! is_array( $all_field_types[ $field['type'] ] ) ) {
432 331 // Fallback for fields added in a more basic way.
433 332 FrmFormsHelper::prepare_field_type( $all_field_types[ $field['type'] ] );
@@ -433,9 +332,8 @@
433 332 FrmFormsHelper::prepare_field_type( $all_field_types[ $field['type'] ] );
434 333 }
435 334
436 335 $type_name = $all_field_types[ $field['type'] ]['name'];
437 -
438 336 if ( $field['type'] === 'divider' && FrmField::is_option_true( $field, 'repeat' ) ) {
439 337 $type_name = $all_field_types['divider|repeat']['name'];
440 338 }
441 339
@@ -446,79 +344,8 @@
446 344 if ( $display['clear_on_focus'] && is_array( $field['placeholder'] ) ) {
447 345 $field['placeholder'] = implode( ', ', $field['placeholder'] );
448 346 }
449 347
450 - $pro_is_installed = FrmAppHelper::pro_is_installed();
451 -
452 - $unique_values_label_atts = array(
453 - 'for' => 'frm_uniq_field_' . $field['id'],
454 - 'class' => 'frm_help frm-mb-0',
455 - 'title' => __(
456 - 'Unique: Do not allow the same response multiple times. For example, if one user enters \'Joe\', then no one else will be allowed to enter the same name.',
457 - 'formidable'
458 - ),
459 - 'data-trigger' => 'hover',
460 - );
461 -
462 - $read_only_label_atts = array(
463 - 'for' => 'frm_read_only_field_' . $field['id'],
464 - 'class' => 'frm_help frm-mb-0',
465 - 'title' => __( 'Read Only: Show this field but do not allow the field value to be edited from the front-end.', 'formidable' ),
466 - 'data-trigger' => 'hover',
467 - );
468 -
469 - if ( ! $pro_is_installed ) {
470 - $visibility_upsell_atts = FrmSettingsUpsellHelper::add_upgrade_modal_atts(
471 - array(
472 - 'id' => 'field_options_admin_only_' . $field['id'],
473 - 'readonly' => '1',
474 - ),
475 - 'field_visibility',
476 - __( 'Visibility options', 'formidable' ),
477 - '/field-options/#kb-visibility'
478 - );
479 -
480 - $autocomplete_upsell_atts = FrmSettingsUpsellHelper::add_upgrade_modal_atts(
481 - array( 'id' => 'field_options_autocomplete_' . $field['id'] ),
482 - 'autocomplete',
483 - __( 'Autocomplete options', 'formidable' ),
484 - '/email-address/#kb-autocomplete-attribute'
485 - );
486 -
487 - $before_after_content_upsell_atts = FrmSettingsUpsellHelper::add_upgrade_modal_atts(
488 - array(
489 - 'type' => 'text',
490 - 'readonly' => '1',
491 - ),
492 - 'before_after_contents',
493 - __( 'Before and after field contents', 'formidable' ),
494 - '/field-options/#kb-before-after-input'
495 - );
496 -
497 - $show_upsell_for_unique_value = in_array(
498 - $field['type'],
499 - array( 'checkbox', 'email', 'name', 'number', 'phone', 'radio', 'text', 'textarea', 'url' ),
500 - true
501 - );
502 - $show_upsell_for_read_only = in_array( $field['type'], array( 'address', 'email', 'hidden', 'number', 'phone', 'radio', 'text', 'textarea', 'url' ), true );
503 - $show_upsell_for_before_after_contents = in_array( $field['type'], array( 'email', 'number', 'phone', 'quantity', 'select', 'tag', 'text', 'total', 'url' ), true );
504 - $show_upsell_for_autocomplete = in_array( $field['type'], array( 'text', 'email', 'number' ), true );
505 - $show_upsell_for_visibility = $field['type'] !== 'hidden';
506 -
507 - $unique_values_label_atts = FrmSettingsUpsellHelper::add_upgrade_modal_atts(
508 - $unique_values_label_atts,
509 - 'unique_values',
510 - __( 'Unique Values', 'formidable' ),
511 - '/field-options/#kb-unique'
512 - );
513 - $read_only_label_atts = FrmSettingsUpsellHelper::add_upgrade_modal_atts(
514 - $read_only_label_atts,
515 - 'read_only',
516 - __( 'Read Only Values', 'formidable' ),
517 - '/field-options/#kb-read-only'
518 - );
519 - }//end if
520 -
521 348 include FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/settings.php';
522 349 }
523 350
524 351 /**
@@ -539,9 +366,8 @@
539 366 * @since 4.0
540 367 *
541 368 * @param array $field
542 369 * @param array $atts
543 - *
544 370 * @return array
545 371 */
546 372 private static function default_value_types( $field, $atts ) {
547 373 $types = array(
@@ -546,33 +372,31 @@
546 372 private static function default_value_types( $field, $atts ) {
547 373 $types = array(
548 374 'default_value' => array(
549 375 'class' => '',
550 - 'icon' => 'frmfont frm_text2_icon',
551 - 'title' => __( 'Default Value', 'formidable' ),
376 + 'icon' => 'frm_icon_font frm_text2_icon',
377 + 'title' => __( 'Default Value (Text)', 'formidable' ),
552 378 'data' => array(
553 379 'frmshow' => '#default-value-for-',
554 380 ),
555 381 ),
556 382 'calc' => array(
557 - 'class' => 'frm_show_upgrade frm_noallow',
558 - 'title' => __( 'Calculate Value', 'formidable' ),
559 - 'icon' => 'frmfont frm_calculator_icon',
560 - 'data' => array(
383 + 'class' => 'frm_show_upgrade frm_noallow',
384 + 'title' => __( 'Default Value (Calculation)', 'formidable' ),
385 + 'icon' => 'frm_icon_font frm_calculator_icon',
386 + 'data' => array(
561 387 'medium' => 'calculations',
562 388 'upgrade' => __( 'Calculator forms', 'formidable' ),
563 389 ),
564 - 'tooltip' => __( 'Automatically calculate the value of this field based on values from other fields.', 'formidable' ),
565 390 ),
566 391 'get_values_field' => array(
567 - 'class' => 'frm_show_upgrade frm_noallow',
568 - 'title' => __( 'Lookup', 'formidable' ),
569 - 'icon' => 'frmfont frm_search_icon',
570 - 'data' => array(
392 + 'class' => 'frm_show_upgrade frm_noallow',
393 + 'title' => __( 'Default Value (Lookup)', 'formidable' ),
394 + 'icon' => 'frm_icon_font frm_search_icon',
395 + 'data' => array(
571 396 'medium' => 'lookup',
572 397 'upgrade' => __( 'Lookup fields', 'formidable' ),
573 398 ),
574 - 'tooltip' => __( 'Dynamically retrieve the value of this field from a lookup field.', 'formidable' ),
575 399 ),
576 400 );
577 401
578 402 $types = apply_filters( 'frm_default_value_types', $types, $atts );
@@ -580,13 +404,11 @@
580 404 // Set active class.
581 405 $settings = array_keys( $types );
582 406 $active = 'default_value';
583 407
584 - if ( FrmAppHelper::pro_is_connected() ) {
585 - foreach ( $settings as $type ) {
586 - if ( ! empty( $field[ $type ] ) ) {
587 - $active = $type;
588 - }
408 + foreach ( $settings as $type ) {
409 + if ( ! empty( $field[ $type ] ) ) {
410 + $active = $type;
589 411 }
590 412 }
591 413
592 414 $types[ $active ]['class'] .= ' current';
@@ -596,9 +418,8 @@
596 418 }
597 419
598 420 /**
599 421 * @param string $type
600 - *
601 422 * @return string
602 423 */
603 424 public static function change_type( $type ) {
604 425 $type_switch = array(
@@ -608,9 +429,8 @@
608 429 'rte' => 'textarea',
609 430 'website' => 'url',
610 431 'image' => 'url',
611 432 );
612 -
613 433 if ( isset( $type_switch[ $type ] ) ) {
614 434 $type = $type_switch[ $type ];
615 435 }
616 436
@@ -616,11 +436,15 @@
616 436
617 437 $pro_fields = FrmField::pro_field_selection();
618 438 // We want to keep credit_card types as credit card types for Stripe Lite.
619 439 // The credit_card key is set for backward compatibility.
620 - FrmField::remove_moved_field_types_from_pro( $pro_fields );
440 + unset( $pro_fields['credit_card'] );
621 441
622 - return array_key_exists( $type, $pro_fields ) ? 'text' : $type;
442 + if ( array_key_exists( $type, $pro_fields ) ) {
443 + $type = 'text';
444 + }
445 +
446 + return $type;
623 447 }
624 448
625 449 /**
626 450 * @param array $settings
@@ -645,9 +469,8 @@
645 469 * @since 3.0
646 470 *
647 471 * @param array $field Field data.
648 472 * @param bool $is_hidden Whether the format option should be hidden.
649 - *
650 473 * @return void
651 474 */
652 475 public static function show_format_option( $field, $is_hidden = false ) {
653 476 $attributes = array(
@@ -661,14 +484,8 @@
661 484
662 485 include FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/value-format.php';
663 486 }
664 487
665 - /**
666 - * @param array $field
667 - * @param bool $echo
668 - *
669 - * @return string
670 - */
671 488 public static function input_html( $field, $echo = true ) {
672 489 $class = array();
673 490 self::add_input_classes( $field, $class );
674 491
@@ -683,9 +500,8 @@
683 500 FrmFormsHelper::add_html_attr( $class, 'class', $add_html );
684 501
685 502 self::add_shortcodes_to_html( $field, $add_html );
686 503 self::add_pattern_attribute( $field, $add_html );
687 - self::add_currency_field_attributes( $field, $add_html );
688 504
689 505 $add_html = apply_filters( 'frm_field_extra_html', $add_html, $field );
690 506 $add_html = ' ' . implode( ' ', $add_html ) . ' ';
691 507
@@ -698,9 +514,8 @@
698 514
699 515 /**
700 516 * @param array $field
701 517 * @param array $class
702 - *
703 518 * @return void
704 519 */
705 520 private static function add_input_classes( $field, array &$class ) {
706 521 if ( ! empty( $field['input_class'] ) ) {
@@ -718,9 +533,8 @@
718 533
719 534 /**
720 535 * @param array $field
721 536 * @param array $add_html
722 - *
723 537 * @return void
724 538 */
725 539 private static function add_html_size( $field, array &$add_html ) {
726 540 $size_fields = array(
@@ -753,9 +567,8 @@
753 567
754 568 /**
755 569 * @param array $field
756 570 * @param array $add_html
757 - *
758 571 * @return void
759 572 */
760 573 private static function add_html_cols( $field, array &$add_html ) {
761 574 if ( ! in_array( $field['type'], array( 'textarea', 'rte' ), true ) ) {
@@ -769,9 +582,9 @@
769 582 'rem' => 0.444,
770 583 'em' => 0.544,
771 584 );
772 585
773 - // Include "col" for valid html
586 + // include "col" for valid html
774 587 $unit = trim( preg_replace( '/[0-9]+/', '', $field['size'] ) );
775 588
776 589 if ( ! isset( $calc[ $unit ] ) ) {
777 590 return;
@@ -776,9 +589,10 @@
776 589 if ( ! isset( $calc[ $unit ] ) ) {
777 590 return;
778 591 }
779 592
780 - $size = (float) str_replace( $unit, '', $field['size'] ) / $calc[ $unit ];
593 + $size = (float) str_replace( $unit, '', $field['size'] ) / $calc[ $unit ];
594 +
781 595 $add_html['cols'] = 'cols="' . absint( $size ) . '"';
782 596 }
783 597
784 598 /**
@@ -783,9 +597,8 @@
783 597
784 598 /**
785 599 * @param array $field
786 600 * @param array $add_html
787 - *
788 601 * @return void
789 602 */
790 603 private static function add_html_length( $field, array &$add_html ) {
791 604 // Check for max setting and if this field accepts maxlength.
@@ -811,13 +624,11 @@
811 624 /**
812 625 * @param array $field
813 626 * @param array $add_html
814 627 * @param array $class
815 - *
816 628 * @return void
817 629 */
818 630 private static function add_html_placeholder( $field, array &$add_html, array &$class ) {
819 - // phpcs:ignore Universal.Operators.StrictComparisons
820 631 if ( $field['default_value'] != '' ) {
821 632 if ( is_array( $field['default_value'] ) ) {
822 633 $add_html['data-frmval'] = 'data-frmval="' . esc_attr( json_encode( $field['default_value'] ) ) . '"';
823 634 } else {
@@ -825,12 +636,10 @@
825 636 }
826 637 }
827 638
828 639 $field['placeholder'] = self::prepare_placeholder( $field );
829 -
830 - // phpcs:ignore Universal.Operators.StrictComparisons
831 640 if ( $field['placeholder'] == '' || is_array( $field['placeholder'] ) ) {
832 - // Don't include a json placeholder
641 + // don't include a json placeholder
833 642 return;
834 643 }
835 644
836 645 self::add_placeholder_to_input( $field, $add_html );
@@ -841,13 +650,14 @@
841 650 *
842 651 * @since 5.4 This doesn't call `FrmFieldsController::get_default_value_from_name()` anymore.
843 652 *
844 653 * @param array $field Field array.
845 - *
846 654 * @return string
847 655 */
848 656 private static function prepare_placeholder( $field ) {
849 - return $field['placeholder'] ?? '';
657 + $placeholder = isset( $field['placeholder'] ) ? $field['placeholder'] : '';
658 +
659 + return $placeholder;
850 660 }
851 661
852 662 /**
853 663 * If the label position is "inside",
@@ -868,17 +678,13 @@
868 678 * Maybe add a blank placeholder option before any options
869 679 * in a dropdown.
870 680 *
871 681 * @since 4.04
872 - *
873 - * @param array|object $field
874 - *
875 682 * @return bool True if placeholder was added.
876 683 */
877 684 public static function add_placeholder_to_select( $field ) {
878 685 $placeholder = FrmField::get_option( $field, 'placeholder' );
879 -
880 - if ( ! $placeholder ) {
686 + if ( empty( $placeholder ) ) {
881 687 $placeholder = self::get_default_value_from_name( $field );
882 688 }
883 689
884 690 $use_placeholder = $placeholder;
@@ -885,9 +691,8 @@
885 691 $autocomplete = FrmField::get_option( $field, 'autocom' );
886 692
887 693 if ( $autocomplete ) {
888 694 $use_chosen = ! is_callable( 'FrmProAppHelper::use_chosen_js' ) || FrmProAppHelper::use_chosen_js();
889 -
890 695 if ( $use_chosen ) {
891 696 $use_placeholder = '';
892 697 }
893 698 }
@@ -910,9 +715,8 @@
910 715 * Use HTML5 placeholder with js fallback.
911 716 *
912 717 * @param array $field
913 718 * @param array $add_html
914 - *
915 719 * @return void
916 720 */
917 721 private static function add_placeholder_to_input( $field, &$add_html ) {
918 722 if ( FrmFieldsHelper::is_placeholder_field_type( $field['type'] ) ) {
@@ -922,13 +726,11 @@
922 726
923 727 /**
924 728 * @param array $field
925 729 * @param array $add_html
926 - *
927 730 * @return void
928 731 */
929 732 private static function add_frmval_to_input( $field, &$add_html ) {
930 - // phpcs:ignore Universal.Operators.StrictComparisons
931 733 if ( $field['placeholder'] != '' ) {
932 734 $add_html['data-frmval'] = 'data-frmval="' . esc_attr( $field['placeholder'] ) . '"';
933 735
934 736 if ( 'select' === $field['type'] ) {
@@ -935,20 +737,13 @@
935 737 $add_html['data-frmplaceholder'] = 'data-frmplaceholder="' . esc_attr( $field['placeholder'] ) . '"';
936 738 }
937 739 }
938 740
939 - // phpcs:ignore Universal.Operators.StrictComparisons
940 741 if ( $field['default_value'] != '' ) {
941 742 $add_html['data-frmval'] = 'data-frmval="' . esc_attr( $field['default_value'] ) . '"';
942 743 }
943 744 }
944 745
945 - /**
946 - * @param array $field
947 - * @param array $add_html
948 - *
949 - * @return void
950 - */
951 746 private static function add_validation_messages( $field, array &$add_html ) {
952 747 $field_validation_messages_status = self::get_validation_data_attribute_visibility_info( $field );
953 748
954 749 if ( FrmField::is_required( $field ) && ! empty( $field_validation_messages_status['data-reqmsg'] ) ) {
@@ -972,9 +767,8 @@
972 767 *
973 768 * @since 6.9
974 769 *
975 770 * @param array|object $field
976 - *
977 771 * @return array
978 772 */
979 773 private static function get_validation_data_attribute_visibility_info( $field ) {
980 774 if ( FrmField::get_field_type( $field ) === 'hidden' ) {
@@ -1004,26 +798,21 @@
1004 798 * @since 5.0.03
1005 799 *
1006 800 * @param array $field
1007 801 * @param array $add_html
1008 - *
1009 802 * @return void
1010 803 */
1011 804 private static function maybe_add_error_html_for_js_validation( $field, array &$add_html ) {
1012 805 $form = self::get_form_for_js_validation( $field );
1013 -
1014 806 if ( false === $form ) {
1015 807 return;
1016 808 }
1017 809
1018 810 $error_body = self::pull_custom_error_body_from_custom_html( $form, $field );
1019 -
1020 - if ( false === $error_body ) {
1021 - return;
811 + if ( false !== $error_body ) {
812 + $error_body = urlencode( $error_body );
813 + $add_html['data-error-html'] = 'data-error-html="' . esc_attr( $error_body ) . '"';
1022 814 }
1023 -
1024 - $error_body = urlencode( $error_body );
1025 - $add_html['data-error-html'] = 'data-error-html="' . esc_attr( $error_body ) . '"';
1026 815 }
1027 816
1028 817 /**
1029 818 * @since 5.0.03
@@ -1028,24 +817,20 @@
1028 817 /**
1029 818 * @since 5.0.03
1030 819 *
1031 820 * @param array $field
1032 - *
1033 821 * @return false|stdClass false if there is no form object found with JS validation active.
1034 822 */
1035 823 private static function get_form_for_js_validation( $field ) {
1036 824 global $frm_vars;
1037 -
1038 825 if ( ! empty( $frm_vars['js_validate_forms'] ) ) {
1039 826 if ( isset( $frm_vars['js_validate_forms'][ $field['form_id'] ] ) ) {
1040 827 return $frm_vars['js_validate_forms'][ $field['form_id'] ];
1041 828 }
1042 -
1043 829 if ( ! empty( $field['parent_form_id'] ) && isset( $frm_vars['js_validate_forms'][ $field['parent_form_id'] ] ) ) {
1044 830 return $frm_vars['js_validate_forms'][ $field['parent_form_id'] ];
1045 831 }
1046 832 }
1047 -
1048 833 return false;
1049 834 }
1050 835
1051 836 /**
@@ -1051,9 +836,8 @@
1051 836 /**
1052 837 * @param stdClass $form
1053 838 * @param array $field
1054 839 * @param array $errors
1055 - *
1056 840 * @return false|string
1057 841 */
1058 842 public static function pull_custom_error_body_from_custom_html( $form, $field, $errors = array() ) {
1059 843 if ( empty( $field['custom_html'] ) ) {
@@ -1061,16 +845,15 @@
1061 845 }
1062 846
1063 847 $custom_html = $field['custom_html'];
1064 848 $custom_html = apply_filters( 'frm_before_replace_shortcodes', $custom_html, $field, $errors, $form );
1065 - $start = strpos( $custom_html, '[if error]' );
1066 849
850 + $start = strpos( $custom_html, '[if error]' );
1067 851 if ( false === $start ) {
1068 852 return false;
1069 853 }
1070 854
1071 855 $end = strpos( $custom_html, '[/if error]' );
1072 -
1073 856 if ( false === $end || $end < $start ) {
1074 857 return false;
1075 858 }
1076 859
@@ -1081,9 +864,13 @@
1081 864 '<div class="frm_error">[error]</div>',
1082 865 '<div class="frm_error" role="alert">[error]</div>',
1083 866 );
1084 867
1085 - return in_array( $error_body, $default_html, true ) ? false : $error_body;
868 + if ( in_array( $error_body, $default_html, true ) ) {
869 + return false;
870 + }
871 +
872 + return $error_body;
1086 873 }
1087 874
1088 875 /**
1089 876 * If 'required' is added to a conditionally hidden field, the form won't
@@ -1090,16 +877,13 @@
1090 877 * submit in many browsers. Check to make sure the javascript to conditionally
1091 878 * remove it is present if needed.
1092 879 *
1093 880 * @since 3.06.01
1094 - *
1095 881 * @param array $field
1096 882 * @param array $add_html
1097 - *
1098 883 * @return void
1099 884 */
1100 885 private static function maybe_add_html_required( $field, array &$add_html ) {
1101 - // phpcs:disable Generic.WhiteSpace.ScopeIndent
1102 886 $excluded_field_types =
1103 887 FrmField::is_radio( $field ) ||
1104 888 FrmField::is_checkbox( $field ) ||
1105 889 FrmField::is_field_type( $field, 'file' ) ||
@@ -1104,9 +888,8 @@
1104 888 FrmField::is_checkbox( $field ) ||
1105 889 FrmField::is_field_type( $field, 'file' ) ||
1106 890 FrmField::is_field_type( $field, 'nps' ) ||
1107 891 FrmField::is_field_type( $field, 'scale' );
1108 - // phpcs:enable Generic.WhiteSpace.ScopeIndent
1109 892
1110 893 if ( $excluded_field_types ) {
1111 894 return;
1112 895 }
@@ -1116,9 +899,8 @@
1116 899
1117 900 /**
1118 901 * @param array $field
1119 902 * @param array $add_html
1120 - *
1121 903 * @return void
1122 904 */
1123 905 private static function add_shortcodes_to_html( $field, array &$add_html ) {
1124 906 if ( FrmField::is_option_empty( $field, 'shortcodes' ) ) {
@@ -1129,11 +911,10 @@
1129 911 unset( $field['shortcodes']['autocomplete'] );
1130 912 }
1131 913
1132 914 foreach ( $field['shortcodes'] as $k => $v ) {
1133 - if ( isset( $field['subfield_name'] ) && str_starts_with( $k, 'aria-invalid' ) ) {
915 + if ( isset( $field['subfield_name'] ) && 0 === strpos( $k, 'aria-invalid' ) ) {
1134 916 $subfield_name = $field['subfield_name'];
1135 -
1136 917 if ( ! isset( $field['shortcodes'][ 'aria-invalid-' . $subfield_name ] ) ) {
1137 918 continue;
1138 919 }
1139 920 // Change the key to the correct aria-invalid value so that $add_html is set correctly for the current subfield of a combo field.
@@ -1140,14 +921,13 @@
1140 921 $k = 'aria-invalid';
1141 922 $v = $field['shortcodes'][ 'aria-invalid-' . $subfield_name ];
1142 923 unset( $field['shortcodes'][ 'aria-invalid-' . $subfield_name ] );
1143 924 }
1144 -
1145 925 if ( 'opt' === $k || ! self::should_allow_input_attribute( $k ) ) {
1146 926 continue;
1147 927 }
1148 928
1149 - if ( is_numeric( $k ) && str_contains( $v, '=' ) ) {
929 + if ( is_numeric( $k ) && strpos( $v, '=' ) ) {
1150 930 $add_html[] = $v;
1151 931 } elseif ( ! empty( $k ) && isset( $add_html[ $k ] ) ) {
1152 932 $add_html[ $k ] = str_replace( $k . '="', $k . '="' . $v, $add_html[ $k ] );
1153 933 } else {
@@ -1163,9 +943,8 @@
1163 943 *
1164 944 * @since 6.11.2
1165 945 *
1166 946 * @param string $key The option key.
1167 - *
1168 947 * @return bool
1169 948 */
1170 949 private static function should_allow_input_attribute( $key ) {
1171 950 if ( ! FrmAppHelper::should_never_allow_unfiltered_html() ) {
@@ -1180,9 +959,8 @@
1180 959 * @since 3.0
1181 960 *
1182 961 * @param array $field
1183 962 * @param array $add_html
1184 - *
1185 963 * @return void
1186 964 */
1187 965 private static function add_pattern_attribute( $field, array &$add_html ) {
1188 966 $format_value = FrmField::get_option( $field, 'format' );
@@ -1188,83 +966,22 @@
1188 966 $format_value = FrmField::get_option( $field, 'format' );
1189 967 $has_format = $format_value && ! FrmCurrencyHelper::is_currency_format( $format_value );
1190 968 $format_field = FrmField::is_field_type( $field, 'text' );
1191 969
1192 - if ( $field['type'] !== 'phone' && ( ! $has_format || ! $format_field ) ) {
1193 - return;
1194 - }
970 + if ( $field['type'] === 'phone' || ( $has_format && $format_field ) ) {
971 + $format = FrmEntryValidate::phone_format( $field );
972 + $format = substr( $format, 2, - 1 );
1195 973
1196 - $format = FrmEntryValidate::phone_format( $field );
1197 - $format = substr( $format, 2, - 1 );
1198 -
1199 - $add_html['pattern'] = 'pattern="' . esc_attr( $format ) . '"';
1200 - }
1201 -
1202 - /**
1203 - * Add product attributes to fields in multi-paged forms.
1204 - *
1205 - * @param array $field
1206 - * @param array $add_html
1207 - *
1208 - * @return void
1209 - */
1210 - private static function add_currency_field_attributes( $field, &$add_html ) {
1211 - $type = $field['original_type'] ?? $field['type'];
1212 - $is_product_field = in_array( $type, array( 'total', 'quantity', 'product' ), true );
1213 -
1214 - if ( ! $is_product_field ) {
1215 - return;
974 + $add_html['pattern'] = 'pattern="' . esc_attr( $format ) . '"';
1216 975 }
1217 -
1218 - if ( $type === 'total' ) {
1219 - $add_html['data-frmtotal'] = 'data-frmtotal';
1220 - } elseif ( $type === 'quantity' ) {
1221 - $product_field = FrmField::get_option( $field, 'product_field' );
1222 - $add_html['data-frmproduct'] = 'data-frmproduct="' . esc_attr( json_encode( $product_field ) ) . '"';
1223 - } elseif ( $type === 'product' && 'hidden' === $field['type'] ) {
1224 - // We want to do this only for fields that are hidden because it's
1225 - // not their page, hence the check : 'hidden' === $field['type'].
1226 - $price = empty( $field['value'] ) ? 0 : self::get_product_price( $field );
1227 -
1228 - $add_html['data-frmprice'] = 'data-frmprice="' . esc_attr( $price ) . '"';
1229 - }
1230 976 }
1231 977
1232 - /**
1233 - * @param array $field
1234 - */
1235 - private static function get_product_price( $field ) {
1236 - if ( is_array( $field['value'] ) ) {
1237 - // '' is unlikely though, let's just do it to prevent warnings
1238 - $value = isset( $field['opt_key'] ) && isset( $field['value'][ $field['opt_key'] ] )
1239 - ? $field['value'][ $field['opt_key'] ]
1240 - : '';
1241 - } else {
1242 - $value = $field['value'];
1243 - }
1244 -
1245 - $field_obj = FrmFieldFactory::get_field_object( $field['id'] );
1246 -
1247 - if ( method_exists( $field_obj, 'get_posted_price' ) ) {
1248 - return $field_obj->get_posted_price( $value );
1249 - }
1250 -
1251 - return $value;
1252 - }
1253 -
1254 - /**
1255 - * @param mixed $opt
1256 - * @param mixed $opt_key
1257 - * @param array|object $field
1258 - *
1259 - * @return mixed
1260 - */
1261 978 public static function check_value( $opt, $opt_key, $field ) {
1262 979 if ( is_array( $opt ) ) {
1263 980 if ( FrmField::is_option_true( $field, 'separate_value' ) ) {
1264 - $opt = $opt['value'] ?? $opt['label'] ?? reset( $opt );
981 + $opt = isset( $opt['value'] ) ? $opt['value'] : ( isset( $opt['label'] ) ? $opt['label'] : reset( $opt ) );
1265 982 } else {
1266 - $opt = $opt['label'] ?? reset( $opt );
983 + $opt = isset( $opt['label'] ) ? $opt['label'] : reset( $opt );
1267 984 }
1268 985 }
1269 986
1270 987 return $opt;
@@ -1269,13 +986,12 @@
1269 986
1270 987 return $opt;
1271 988 }
1272 989
1273 - /**
1274 - * @param mixed $opt
1275 - *
1276 - * @return mixed
1277 - */
1278 990 public static function check_label( $opt ) {
1279 - return is_array( $opt ) ? ( $opt['label'] ?? reset( $opt ) ) : $opt;
991 + if ( is_array( $opt ) ) {
992 + $opt = isset( $opt['label'] ) ? $opt['label'] : reset( $opt );
993 + }
994 +
995 + return $opt;
1280 996 }
1281 997 }