PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.22
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.22
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/helpers/FrmFieldsHelper.php +430 -197 6.3.26.22 View file →
@@ -4,8 +4,15 @@
4 4 }
5 5
6 6 class FrmFieldsHelper {
7 7
8 + /**
9 + * The context is memoized for re-use as the context is checked for each field.
10 + *
11 + * @var bool|null
12 + */
13 + private static $context_is_safe_to_load_field_options_from_request_data;
14 +
8 15 public static function setup_new_vars( $type = '', $form_id = '' ) {
9 16
10 17 if ( strpos( $type, '|' ) ) {
11 18 list( $type, $setting ) = explode( '|', $type );
@@ -13,9 +20,14 @@
13 20
14 21 $values = self::get_default_field( $type );
15 22
16 23 global $wpdb;
17 - $field_count = FrmDb::get_var( 'frm_fields', array( 'form_id' => $form_id ), 'field_order', array( 'order_by' => 'field_order DESC' ) );
24 + $field_count = FrmDb::get_var(
25 + 'frm_fields',
26 + array( 'form_id' => $form_id ),
27 + 'field_order',
28 + array( 'order_by' => 'field_order DESC' )
29 + );
18 30
19 31 $values['field_key'] = FrmAppHelper::get_unique_key( '', $wpdb->prefix . 'frm_fields', 'field_key' );
20 32 $values['form_id'] = $form_id;
21 33 $values['field_order'] = $field_count + 1;
@@ -21,10 +33,10 @@
21 33 $values['field_order'] = $field_count + 1;
22 34
23 35 $values['field_options']['custom_html'] = self::get_default_html( $type );
24 36
25 - if ( isset( $setting ) && ! empty( $setting ) ) {
26 - if ( in_array( $type, array( 'data', 'lookup' ) ) ) {
37 + if ( ! empty( $setting ) ) {
38 + if ( in_array( $type, array( 'data', 'lookup' ), true ) ) {
27 39 $values['field_options']['data_type'] = $setting;
28 40 } else {
29 41 $values['field_options'][ $setting ] = 1;
30 42 }
@@ -29,8 +41,19 @@
29 41 $values['field_options'][ $setting ] = 1;
30 42 }
31 43 }
32 44
45 + // Increase the field order of submit field and fields in the same row.
46 + $last_row_field_ids = FrmAppHelper::get_post_param( 'last_row_field_ids', array() );
47 + if ( $last_row_field_ids ) {
48 + foreach ( $last_row_field_ids as $index => $last_row_field_id ) {
49 + FrmField::update(
50 + $last_row_field_id,
51 + array( 'field_order' => $field_count + $index + 2 )
52 + );
53 + }
54 + }
55 +
33 56 return $values;
34 57 }
35 58
36 59 public static function get_html_id( $field, $plus = '' ) {
@@ -47,9 +70,9 @@
47 70 $values = (array) $field;
48 71
49 72 self::fill_field_array( $field, $values );
50 73
51 - $values['custom_html'] = ( isset( $field->field_options['custom_html'] ) ) ? $field->field_options['custom_html'] : self::get_default_html( $field->type );
74 + $values['custom_html'] = isset( $field->field_options['custom_html'] ) ? $field->field_options['custom_html'] : self::get_default_html( $field->type );
52 75
53 76 return $values;
54 77 }
55 78
@@ -86,8 +109,13 @@
86 109 /**
87 110 * Prepare field while creating a new entry
88 111 *
89 112 * @since 3.0
113 + *
114 + * @param array $field_array
115 + * @param stdClass $field
116 + * @param array $args
117 + * @return void
90 118 */
91 119 private static function prepare_front_field( &$field_array, $field, $args ) {
92 120 self::fill_default_field_opts( $field, $field_array );
93 121 self::fill_cleared_strings( $field, $field_array );
@@ -96,11 +124,22 @@
96 124 $field_array['original_type'] = isset( $field->field_options['original_type'] ) ? $field->field_options['original_type'] : $field->type;
97 125
98 126 self::prepare_field_options_for_display( $field_array, $field, $args );
99 127
100 - if ( $args['action'] == 'edit' ) {
128 + if ( $args['action'] === 'edit' ) {
129 + /**
130 + * @param array $field_array
131 + * @param stdClass $field
132 + * @param int|string $entry_id
133 + * @param array $args
134 + */
101 135 $field_array = apply_filters( 'frm_setup_edit_fields_vars', $field_array, $field, $args['entry_id'], $args );
102 136 } else {
137 + /**
138 + * @param array $field_array
139 + * @param stdClass $field
140 + * @param array $args
141 + */
103 142 $field_array = apply_filters( 'frm_setup_new_fields_vars', $field_array, $field, $args );
104 143 }
105 144 }
106 145
@@ -120,14 +159,14 @@
120 159 /**
121 160 * @since 3.0
122 161 *
123 162 * @param object $field
124 - * @param array $values
163 + * @param array $values
125 164 */
126 165 private static function fill_default_field_opts( $field, array &$values ) {
127 - $check_post = FrmAppHelper::is_admin_page() && $_POST && isset( $_POST['field_options'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
166 + $check_post = self::context_is_safe_to_load_field_options_from_request_data();
167 + $defaults = self::get_default_field_options_from_field( $field, $values );
128 168
129 - $defaults = self::get_default_field_options_from_field( $field, $values );
130 169 if ( ! $check_post ) {
131 170 $defaults['required_indicator'] = '';
132 171 $defaults['original_type'] = $field->type;
133 172 }
@@ -137,11 +176,58 @@
137 176
138 177 if ( $check_post ) {
139 178 self::get_posted_field_setting( $opt . '_' . $field->id, $values[ $opt ] );
140 179 }
180 + }
181 + }
141 182
142 - unset( $opt, $default );
183 + /**
184 + * The fill_default_field_opts method is called when loading a field.
185 + * This is used to preserve the $_POST data after updating settings for a field.
186 + * To prevent this from happening when creating an entry, we need to check the context.
187 + *
188 + * @return bool
189 + */
190 + private static function context_is_safe_to_load_field_options_from_request_data() {
191 + if ( isset( self::$context_is_safe_to_load_field_options_from_request_data ) ) {
192 + return self::$context_is_safe_to_load_field_options_from_request_data;
143 193 }
194 +
195 + $function = function () {
196 + if ( ! FrmAppHelper::is_admin_page() ) {
197 + return false;
198 + }
199 +
200 + if ( ! $_POST || ! isset( $_POST['field_options'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
201 + return false;
202 + }
203 +
204 + if ( ! current_user_can( 'frm_edit_forms' ) ) {
205 + return false;
206 + }
207 +
208 + $action = FrmAppHelper::get_post_param( 'action', '', 'sanitize_title' );
209 + if ( 'frm_forms_preview' === $action ) {
210 + // Never trigger when previewing.
211 + return false;
212 + }
213 +
214 + // Confirm an allowed action is being used, and that the correct nonce is being used.
215 + if ( 'update' === $action ) {
216 + $nonce = FrmAppHelper::get_post_param( 'frm_save_form', '', 'sanitize_text_field' );
217 + return wp_verify_nonce( $nonce, 'frm_save_form_nonce' );
218 + }
219 +
220 + $action = FrmAppHelper::get_post_param( 'frm_action', '', 'sanitize_title' );
221 + if ( 'update_settings' === $action ) {
222 + $nonce = FrmAppHelper::get_post_param( 'process_form', '', 'sanitize_text_field' );
223 + return wp_verify_nonce( $nonce, 'process_form_nonce' );
224 + }
225 + };
226 +
227 + self::$context_is_safe_to_load_field_options_from_request_data = $function();
228 +
229 + return self::$context_is_safe_to_load_field_options_from_request_data;
144 230 }
145 231
146 232 /**
147 233 * Fill the required message, invalid message,
@@ -149,23 +235,21 @@
149 235 *
150 236 * @since 3.0
151 237 *
152 238 * @param object $field
153 - * @param array $field_array
239 + * @param array $field_array
154 240 */
155 241 private static function fill_cleared_strings( $field, array &$field_array ) {
156 - $frm_settings = FrmAppHelper::get_settings();
157 -
158 242 if ( '' == $field_array['blank'] && '1' === $field_array['required'] ) {
159 - $field_array['blank'] = $frm_settings->blank_msg;
243 + $field_array['blank'] = self::default_blank_msg();
160 244 }
161 245
162 246 if ( '' === $field_array['invalid'] ) {
163 247 if ( 'captcha' === $field->type ) {
248 + $frm_settings = FrmAppHelper::get_settings();
164 249 $field_array['invalid'] = $frm_settings->re_msg;
165 250 } else {
166 - /* translators: %s: Field name */
167 - $field_array['invalid'] = sprintf( __( '%s is invalid', 'formidable' ), $field_array['name'] );
251 + $field_array['invalid'] = self::default_invalid_msg();
168 252 }
169 253 }
170 254
171 255 if ( '' == $field_array['custom_html'] ) {
@@ -173,12 +257,48 @@
173 257 }
174 258 }
175 259
176 260 /**
261 + * @since 6.8.3
262 + *
263 + * @return string
264 + */
265 + public static function default_invalid_msg() {
266 + /* translators: %s: [field_name] shortcode (Which gets replaced by a Field Name) */
267 + return sprintf( __( '%s is invalid', 'formidable' ), '[field_name]' );
268 + }
269 +
270 + /**
271 + * @since 6.8.3
272 + *
273 + * @return string
274 + */
275 + public static function default_unique_msg() {
276 + $frm_settings = FrmAppHelper::get_settings();
277 + $unique_message = $frm_settings->unique_msg;
278 + $unique_message = str_replace( 'This value', '[field_name]', $unique_message );
279 + return $unique_message;
280 + }
281 +
282 + /**
283 + * @since 6.8.3
284 + *
285 + * @return string
286 + */
287 + public static function default_blank_msg() {
288 + $frm_settings = FrmAppHelper::get_settings();
289 + $blank_message = $frm_settings->blank_msg;
290 + $blank_message = str_replace( 'This field', '[field_name]', $blank_message );
291 + return $blank_message;
292 + }
293 +
294 + /**
295 + * When loading settings for a field, check the $_POST data and possibly use that instead of the DB value.
296 + *
177 297 * @since 3.0
178 298 *
179 299 * @param string $setting
180 - * @param mixed $value
300 + * @param mixed $value
181 301 */
182 302 private static function get_posted_field_setting( $setting, &$value ) {
183 303 if ( ! isset( $_POST['field_options'][ $setting ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
184 304 return;
@@ -184,10 +304,14 @@
184 304 return;
185 305 }
186 306
187 307 if ( strpos( $setting, 'html' ) !== false ) {
188 - // Strip slashes from HTML but not regex or script tags.
189 308 $value = wp_unslash( $_POST['field_options'][ $setting ] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing
309 +
310 + // Conditionally strip script tags if the user sending $_POST data is not allowed to use unfiltered HTML.
311 + if ( ! FrmAppHelper::allow_unfiltered_html() ) {
312 + $value = FrmAppHelper::kses( $value, 'all' );
313 + }
190 314 } elseif ( strpos( $setting, 'format_' ) === 0 ) {
191 315 // TODO: Remove stripslashes on output, and use on input only.
192 316 $value = sanitize_text_field( $_POST['field_options'][ $setting ] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.NonceVerification.Missing
193 317 } else {
@@ -199,9 +323,9 @@
199 323 /**
200 324 * @since 3.0
201 325 *
202 326 * @param object $field
203 - * @param array $values The field array is needed for hooks
327 + * @param array $values The field array is needed for hooks.
204 328 *
205 329 * @return array
206 330 */
207 331 public static function get_default_field_options_from_field( $field, $values = array() ) {
@@ -218,9 +342,9 @@
218 342 * @since 3.0
219 343 *
220 344 * @param object $field
221 345 *
222 - * @return array
346 + * @return FrmFieldType
223 347 */
224 348 private static function get_original_field( $field ) {
225 349 $original_type = FrmField::get_option( $field, 'original_type' );
226 350 if ( ! empty( $original_type ) && $field->type != $original_type ) {
@@ -232,11 +356,11 @@
232 356
233 357 /**
234 358 * @since 3.0
235 359 *
236 - * @param array $field_array
360 + * @param array $field_array
237 361 * @param object $field
238 - * @param array $atts
362 + * @param array $atts
239 363 */
240 364 private static function prepare_field_options_for_display( &$field_array, $field, $atts ) {
241 365 $field_obj = FrmFieldFactory::get_field_object( $field );
242 366 $field_array = $field_obj->prepare_front_field( $field_array, $atts );
@@ -270,29 +394,27 @@
270 394
271 395 /**
272 396 * @since 2.0
273 397 *
274 - * @param $field
275 - * @param $error
398 + * @param array|object $field
399 + * @param string $error
276 400 *
277 401 * @return string
278 402 */
279 403 public static function get_error_msg( $field, $error ) {
280 - $frm_settings = FrmAppHelper::get_settings();
281 - $default_settings = $frm_settings->default_options();
282 - $field_name = is_array( $field ) ? $field['name'] : $field->name;
404 + $frm_settings = FrmAppHelper::get_settings();
283 405
284 406 $conf_msg = __( 'The entered values do not match', 'formidable' );
285 407 $defaults = array(
286 408 'unique_msg' => array(
287 - 'full' => $default_settings['unique_msg'],
409 + 'full' => self::default_unique_msg(),
288 410 /* translators: %s: Field name */
289 - 'part' => sprintf( __( '%s must be unique', 'formidable' ), $field_name ),
411 + 'part' => sprintf( __( '%s must be unique', 'formidable' ), '[field_name]' ),
290 412 ),
291 413 'invalid' => array(
292 414 'full' => __( 'This field is invalid', 'formidable' ),
293 415 /* translators: %s: Field name */
294 - 'part' => sprintf( __( '%s is invalid', 'formidable' ), $field_name ),
416 + 'part' => sprintf( __( '%s is invalid', 'formidable' ), '[field_name]' ),
295 417 ),
296 418 'blank' => array(
297 419 'full' => $frm_settings->blank_msg,
298 420 'part' => $frm_settings->blank_msg,
@@ -306,11 +428,74 @@
306 428 $msg = FrmField::get_option( $field, $error );
307 429 $msg = empty( $msg ) ? $defaults[ $error ]['part'] : $msg;
308 430 $msg = do_shortcode( $msg );
309 431
432 + $msg = self::maybe_replace_substrings_with_field_name( $msg, $error, $field );
433 +
310 434 return $msg;
311 435 }
312 436
437 + /**
438 + * @since 6.8.3
439 + *
440 + * @param string $msg
441 + * @param string $error
442 + * @param array|object $field
443 + */
444 + private static function maybe_replace_substrings_with_field_name( $msg, $error, $field ) {
445 + $field_name = is_array( $field ) ? $field['name'] : $field->name;
446 + $field_name = FrmAppHelper::maybe_kses( $field_name );
447 + $substrings = self::get_substrings_to_replace_with_field_name( $field_name, compact( 'msg', 'error', 'field' ) );
448 +
449 + // Use the "This value"/"This field" placeholder strings if field name is empty.
450 + if ( ! $field_name ) {
451 + if ( 'unique_msg' === $error ) {
452 + $field_name = __( 'This value', 'formidable' );
453 + } else {
454 + $field_name = __( 'This field', 'formidable' );
455 + }
456 + }
457 +
458 + $msg = str_replace( $substrings, $field_name, $msg );
459 + return $msg;
460 + }
461 +
462 + /**
463 + * @since 6.8.3
464 + *
465 + * @param string $field_name
466 + * @param array $filter_args {
467 + * Filter arguments.
468 + *
469 + * @type string $msg The current error message before the substrings are replaced.
470 + * @type string $error A key including 'unique_msg', 'invalid', 'blank', or 'conf_msg'.
471 + * @type array|object $field The field with the error.
472 + * }
473 + * @return array
474 + */
475 + private static function get_substrings_to_replace_with_field_name( $field_name, $filter_args ) {
476 + $substrings = array( '[field_name]' );
477 + if ( $field_name ) {
478 + array_push( $substrings, 'This value', 'This field' );
479 + }
480 +
481 + /**
482 + * @since 6.8.3
483 + *
484 + * @param array<string> $substrings
485 + * @param array $filter_args
486 + */
487 + $filtered_substrings = apply_filters( 'frm_error_substrings_to_replace_with_field_name', $substrings, $filter_args );
488 +
489 + if ( is_array( $filtered_substrings ) ) {
490 + $substrings = $filtered_substrings;
491 + } else {
492 + _doing_it_wrong( __METHOD__, 'Only arrays should be returned when using the frm_error_substrings_to_replace_with_field_name filter.', '6.8.3' );
493 + }
494 +
495 + return $substrings;
496 + }
497 +
313 498 public static function get_form_fields( $form_id, $error = array() ) {
314 499 $fields = FrmField::get_all_for_form( $form_id );
315 500
316 501 return apply_filters( 'frm_get_paged_fields', $fields, $form_id, $error );
@@ -328,12 +513,12 @@
328 513 return apply_filters( 'frm_custom_html', $default_html, $type );
329 514 }
330 515
331 516 /**
332 - * @param array $fields
333 - * @param array $errors
517 + * @param array $fields
518 + * @param array $errors
334 519 * @param object $form
335 - * @param $form_action
520 + * @param object $form_action
336 521 */
337 522 public static function show_fields( $fields, $errors, $form, $form_action ) {
338 523 foreach ( $fields as $field ) {
339 524 $field_obj = FrmFieldFactory::get_field_type( $field['type'], $field );
@@ -343,10 +528,10 @@
343 528
344 529 /**
345 530 * @since 3.0
346 531 *
347 - * @param array $atts
348 - * @param string|array $value
532 + * @param array $atts
533 + * @param array|string $value
349 534 */
350 535 public static function run_wpautop( $atts, &$value ) {
351 536 $autop = isset( $atts['wpautop'] ) ? $atts['wpautop'] : true;
352 537 if ( apply_filters( 'frm_use_wpautop', $autop ) ) {
@@ -363,9 +548,9 @@
363 548 * @since 2.05
364 549 */
365 550 public static function &label_position( $position, $field, $form ) {
366 551 if ( $position && $position != '' ) {
367 - if ( $position == 'inside' && ! self::is_placeholder_field_type( $field['type'] ) ) {
552 + if ( $position === 'inside' && ! self::is_placeholder_field_type( $field['type'] ) ) {
368 553 $position = 'top';
369 554 }
370 555
371 556 return $position;
@@ -371,18 +556,18 @@
371 556 return $position;
372 557 }
373 558
374 559 $position = FrmStylesController::get_style_val( 'position', $form );
375 - if ( $position == 'none' ) {
560 + if ( $position === 'none' ) {
376 561 $position = 'top';
377 - } elseif ( $position == 'no_label' ) {
562 + } elseif ( $position === 'no_label' ) {
378 563 $position = 'none';
379 - } elseif ( $position == 'inside' && ! self::is_placeholder_field_type( $field['type'] ) ) {
564 + } elseif ( $position === 'inside' && ! self::is_placeholder_field_type( $field['type'] ) ) {
380 565 $position = 'top';
381 566 }
382 567
383 568 $position = apply_filters( 'frm_html_label_position', $position, $field, $form );
384 - $position = ( ! empty( $position ) ) ? $position : 'top';
569 + $position = ! empty( $position ) ? $position : 'top';
385 570
386 571 return $position;
387 572 }
388 573
@@ -413,9 +598,9 @@
413 598 return;
414 599 }
415 600
416 601 $base_name = 'default_value_' . $field['id'];
417 - $html_id = isset( $field['html_id'] ) ? $field['html_id'] : self::get_html_id( $field );
602 + $html_id = isset( $field['html_id'] ) ? $field['html_id'] : self::get_html_id( $field );
418 603
419 604 $default_type = self::get_default_value_type( $field );
420 605
421 606 foreach ( $field['options'] as $opt_key => $opt ) {
@@ -428,12 +613,12 @@
428 613
429 614 // If this is an "Other" option, get the HTML for it.
430 615 if ( self::is_other_opt( $opt_key ) ) {
431 616 if ( FrmAppHelper::pro_is_installed() ) {
432 - require( FrmProAppHelper::plugin_path() . '/classes/views/frmpro-fields/other-option.php' );
617 + require FrmProAppHelper::plugin_path() . '/classes/views/frmpro-fields/other-option.php';
433 618 }
434 619 } else {
435 - require( FrmAppHelper::plugin_path() . '/classes/views/frm-fields/single-option.php' );
620 + require FrmAppHelper::plugin_path() . '/classes/views/frm-fields/single-option.php';
436 621 }
437 622
438 623 unset( $checked );
439 624 }
@@ -461,9 +646,9 @@
461 646
462 647 $default_type = self::get_default_value_type( $field );
463 648 $field_name .= ( $default_type === 'checkbox' ? '[' . $opt_key . ']' : '' );
464 649
465 - require( FrmAppHelper::plugin_path() . '/classes/views/frm-fields/single-option.php' );
650 + require FrmAppHelper::plugin_path() . '/classes/views/frm-fields/single-option.php';
466 651 }
467 652
468 653 /**
469 654 * @since 4.0
@@ -491,22 +676,28 @@
491 676 return FrmFieldsController::check_label( $opt );
492 677 }
493 678
494 679 /**
680 + * Shows the inline modal.
681 + *
495 682 * @since 4.0
683 + * @since 6.4.1 Added `inside_class` in the arguments.
684 + *
685 + * @param array $args The arguments.
496 686 */
497 687 public static function inline_modal( $args ) {
498 688 $defaults = array(
499 - 'id' => '',
500 - 'class' => '',
501 - 'show' => 0,
502 - 'callback' => array(),
503 - 'args' => array(),
504 - 'title' => '',
689 + 'id' => '',
690 + 'class' => '',
691 + 'show' => 0,
692 + 'callback' => array(),
693 + 'args' => array(),
694 + 'title' => '',
695 + 'inside_class' => 'inside',
505 696 );
506 - $args = array_merge( $defaults, $args );
697 + $args = array_merge( $defaults, $args );
507 698
508 - include( FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/inline-modal.php' );
699 + include FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/inline-modal.php';
509 700 }
510 701
511 702 /**
512 703 * @since 4.0
@@ -517,9 +708,9 @@
517 708 $upgrade_link = array(
518 709 'medium' => 'builder',
519 710 'content' => 'smart-tags',
520 711 );
521 - include( FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/smart-values.php' );
712 + include FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/smart-values.php';
522 713 }
523 714 }
524 715
525 716 /**
@@ -525,9 +716,9 @@
525 716 /**
526 717 * @since 4.0
527 718 */
528 719 public static function input_mask() {
529 - include( FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/input-mask-info.php' );
720 + include FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/input-mask-info.php';
530 721 }
531 722
532 723 /**
533 724 * @since 4.0
@@ -532,9 +723,9 @@
532 723 /**
533 724 * @since 4.0
534 725 */
535 726 public static function layout_classes() {
536 - include( FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/layout-classes.php' );
727 + include FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/layout-classes.php';
537 728 }
538 729
539 730 /**
540 731 * @param int $tax_id
@@ -560,10 +751,10 @@
560 751 return $link;
561 752 }
562 753
563 754 public static function value_meets_condition( $observed_value, $cond, $hide_opt ) {
564 - $hide_opt = self::get_value_for_comparision( $hide_opt );
565 - $observed_value = self::get_value_for_comparision( $observed_value );
755 + $hide_opt = self::get_value_for_comparison( $hide_opt );
756 + $observed_value = self::get_value_for_comparison( $observed_value );
566 757
567 758 if ( is_array( $observed_value ) ) {
568 759 return self::array_value_condition( $observed_value, $cond, $hide_opt );
569 760 }
@@ -583,11 +774,11 @@
583 774 $m = $observed_value <= $hide_opt;
584 775 } elseif ( $cond === 'LIKE' || $cond === 'not LIKE' ) {
585 776 $m = stripos( $observed_value, $hide_opt );
586 777 if ( $cond === 'not LIKE' ) {
587 - $m = ( $m === false ) ? true : false;
778 + $m = $m === false;
588 779 } else {
589 - $m = ( $m === false ) ? false : true;
780 + $m = $m !== false;
590 781 }
591 782 } elseif ( $cond === '%LIKE' ) {
592 783 // ends with
593 784 $length = strlen( $hide_opt );
@@ -597,9 +788,9 @@
597 788 // starts with
598 789 $length = strlen( $hide_opt );
599 790 $substr = substr( $observed_value, 0, $length );
600 791 $m = 0 === strcasecmp( $substr, $hide_opt );
601 - }
792 + }//end if
602 793
603 794 return $m;
604 795 }
605 796
@@ -607,9 +798,9 @@
607 798 * Trim and sanitize the values
608 799 *
609 800 * @since 2.05
610 801 */
611 - private static function get_value_for_comparision( $value ) {
802 + private static function get_value_for_comparison( $value ) {
612 803 // Remove white space from hide_opt
613 804 if ( ! is_array( $value ) ) {
614 805 $value = trim( $value );
615 806 }
@@ -623,9 +814,9 @@
623 814 $m = false;
624 815 if ( $cond === '==' ) {
625 816 if ( is_array( $hide_opt ) ) {
626 817 $m = array_intersect( $hide_opt, $observed_value );
627 - $m = empty( $m ) ? false : true;
818 + $m = ! empty( $m );
628 819 } else {
629 820 $m = in_array( $hide_opt, $observed_value );
630 821 }
631 822 } elseif ( $cond === '!=' ) {
@@ -645,9 +836,9 @@
645 836 }
646 837 }
647 838
648 839 if ( $cond === 'not LIKE' ) {
649 - $m = ( $m === false ) ? true : false;
840 + $m = $m === false;
650 841 }
651 842 } elseif ( $cond === '%LIKE' ) {
652 843 // ends with
653 844 foreach ( $observed_value as $ob ) {
@@ -663,9 +854,9 @@
663 854 $m = true;
664 855 break;
665 856 }
666 857 }
667 - }
858 + }//end if
668 859
669 860 return $m;
670 861 }
671 862
@@ -714,13 +905,16 @@
714 905 'ip',
715 906 'siteurl',
716 907 'sitename',
717 908 'admin_email',
909 + 'default-email',
910 + 'default-from-email',
718 911 'post[-|_]id',
719 912 'created[-|_]at',
720 913 'updated[-|_]at',
721 914 'updated[-|_]by',
722 915 'parent[-|_]id',
916 + 'form_name',
723 917 );
724 918
725 919 foreach ( $fields as $field ) {
726 920 $tagregexp[] = $field->id;
@@ -809,12 +1003,17 @@
809 1003 * Prevent shortcodes in fields from being processed
810 1004 *
811 1005 * @since 3.01.02
812 1006 *
813 - * @param array $atts - includes entry object
814 - * @param string $value
1007 + * @param array $atts Includes entry object.
1008 + * @param string|null $value
1009 + * @return void
815 1010 */
816 1011 public static function sanitize_embedded_shortcodes( $atts, &$value ) {
1012 + if ( is_null( $value ) ) {
1013 + return;
1014 + }
1015 +
817 1016 $atts['value'] = $value;
818 1017 $should_sanitize = apply_filters( 'frm_sanitize_shortcodes', true, $atts );
819 1018 if ( $should_sanitize ) {
820 1019 $value = str_replace( '[', '&#91;', $value );
@@ -823,9 +1022,9 @@
823 1022
824 1023 /**
825 1024 * @since 3.0
826 1025 *
827 - * @param $atts
1026 + * @param array $atts
828 1027 *
829 1028 * @return string
830 1029 */
831 1030 private static function get_value_for_shortcode( $atts ) {
@@ -836,21 +1035,21 @@
836 1035 'key' => $atts['entry']->item_key,
837 1036 'ip' => $atts['entry']->ip,
838 1037 );
839 1038
840 - $dynamic_default = array( 'admin_email', 'siteurl', 'frmurl', 'sitename', 'get' );
1039 + $dynamic_default = array( 'admin_email', 'siteurl', 'frmurl', 'sitename', 'get', 'default-email', 'default-from-email' );
841 1040
842 1041 if ( isset( $shortcode_values[ $atts['tag'] ] ) ) {
843 1042 $replace_with = $shortcode_values[ $atts['tag'] ];
844 - } elseif ( in_array( $atts['tag'], $dynamic_default ) ) {
1043 + } elseif ( in_array( $atts['tag'], $dynamic_default, true ) ) {
845 1044 $replace_with = self::dynamic_default_values( $atts['tag'], $atts );
846 - } elseif ( $clean_tag == 'user_agent' ) {
1045 + } elseif ( $clean_tag === 'user_agent' ) {
847 1046 $description = $atts['entry']->description;
848 1047 $replace_with = FrmEntriesHelper::get_browser( $description['browser'] );
849 - } elseif ( $clean_tag == 'created_at' || $clean_tag == 'updated_at' ) {
1048 + } elseif ( $clean_tag === 'created_at' || $clean_tag === 'updated_at' ) {
850 1049 $atts['tag'] = $clean_tag;
851 1050 $replace_with = self::get_entry_timestamp( $atts );
852 - } elseif ( $clean_tag == 'created_by' || $clean_tag == 'updated_by' ) {
1051 + } elseif ( $clean_tag === 'created_by' || $clean_tag === 'updated_by' ) {
853 1052 $replace_with = self::get_display_value( $atts['entry']->{$clean_tag}, (object) array( 'type' => 'user_id' ), $atts );
854 1053 } else {
855 1054 $replace_with = self::get_field_shortcode_value( $atts );
856 1055 }
@@ -860,9 +1059,9 @@
860 1059
861 1060 /**
862 1061 * @since 3.0
863 1062 *
864 - * @param $atts
1063 + * @param array $atts
865 1064 *
866 1065 * @return string
867 1066 */
868 1067 private static function get_entry_timestamp( $atts ) {
@@ -878,11 +1077,11 @@
878 1077
879 1078 /**
880 1079 * @since 3.0
881 1080 *
882 - * @param $atts
1081 + * @param array $atts
883 1082 *
884 - * @return null|string
1083 + * @return string|null
885 1084 */
886 1085 private static function get_field_shortcode_value( $atts ) {
887 1086 $field = FrmField::getOne( $atts['tag'] );
888 1087 if ( empty( $field ) ) {
@@ -897,9 +1096,9 @@
897 1096 $replace_with = FrmEntryMeta::get_meta_value( $atts['entry'], $field->id );
898 1097 $string_value = $replace_with;
899 1098 if ( is_array( $replace_with ) ) {
900 1099 $sep = isset( $atts['sep'] ) ? $atts['sep'] : ', ';
901 - $string_value = implode( $sep, $replace_with );
1100 + $string_value = FrmAppHelper::safe_implode( $sep, $replace_with );
902 1101 }
903 1102
904 1103 if ( empty( $string_value ) && $string_value != '0' ) {
905 1104 $replace_with = '';
@@ -924,8 +1123,16 @@
924 1123 switch ( $tag ) {
925 1124 case 'admin_email':
926 1125 $new_value = get_option( 'admin_email' );
927 1126 break;
1127 + case 'default-email':
1128 + $frm_settings = FrmAppHelper::get_settings();
1129 + $new_value = ! empty( $frm_settings->default_email ) && is_email( $frm_settings->default_email ) ? $frm_settings->default_email : get_option( 'admin_email' );
1130 + break;
1131 + case 'default-from-email':
1132 + $frm_settings = FrmAppHelper::get_settings();
1133 + $new_value = ! empty( $frm_settings->from_email ) && is_email( $frm_settings->from_email ) ? $frm_settings->from_email : get_option( 'admin_email' );
1134 + break;
928 1135 case 'siteurl':
929 1136 $new_value = FrmAppHelper::site_url();
930 1137 break;
931 1138 case 'frmurl':
@@ -935,9 +1142,9 @@
935 1142 $new_value = FrmAppHelper::site_name();
936 1143 break;
937 1144 case 'get':
938 1145 $new_value = self::process_get_shortcode( $atts, $return_array );
939 - }
1146 + }//end switch
940 1147
941 1148 return $new_value;
942 1149 }
943 1150
@@ -944,9 +1151,9 @@
944 1151 /**
945 1152 * Process the [get] shortcode
946 1153 *
947 1154 * @since 2.0
948 - * @return string|array
1155 + * @return array|string
949 1156 */
950 1157 public static function process_get_shortcode( $atts, $return_array = false ) {
951 1158 if ( ! isset( $atts['param'] ) ) {
952 1159 return '';
@@ -985,9 +1192,9 @@
985 1192 return apply_filters( 'frm_display_value', $value, $field, $atts );
986 1193 }
987 1194
988 1195 /**
989 - * @param $atts array Includes value, field, and atts
1196 + * @param array $atts Includes value, field, and atts.
990 1197 */
991 1198 public static function get_unfiltered_display_value( $atts ) {
992 1199 $value = $atts['value'];
993 1200 $field = $atts['field'];
@@ -1005,8 +1212,10 @@
1005 1212 /**
1006 1213 * Get a value from the user profile from the user ID
1007 1214 *
1008 1215 * @since 3.0
1216 + *
1217 + * @return string
1009 1218 */
1010 1219 public static function get_user_display_name( $user_id, $user_info = 'display_name', $args = array() ) {
1011 1220 $defaults = array(
1012 1221 'blank' => false,
@@ -1019,11 +1228,11 @@
1019 1228 $user = get_userdata( $user_id );
1020 1229 $info = '';
1021 1230
1022 1231 if ( $user ) {
1023 - if ( $user_info == 'avatar' ) {
1232 + if ( $user_info === 'avatar' ) {
1024 1233 $info = get_avatar( $user_id, $args['size'] );
1025 - } elseif ( $user_info == 'author_link' ) {
1234 + } elseif ( $user_info === 'author_link' ) {
1026 1235 $info = get_author_posts_url( $user_id );
1027 1236 } else {
1028 1237 $info = isset( $user->$user_info ) ? $user->$user_info : '';
1029 1238 }
@@ -1039,18 +1248,21 @@
1039 1248
1040 1249 return $info;
1041 1250 }
1042 1251
1252 + /**
1253 + * @param string $type
1254 + * @return array
1255 + */
1043 1256 public static function get_field_types( $type ) {
1044 - $single_input = self::single_input_fields();
1045 - $multiple_input = array( 'radio', 'checkbox', 'select', 'scale', 'star', 'lookup' );
1046 -
1257 + $single_input = self::single_input_fields();
1258 + $multiple_input = array( 'radio', 'checkbox', 'select', 'scale', 'star', 'lookup' );
1047 1259 $field_selection = FrmField::all_field_selection();
1260 + $field_types = array();
1048 1261
1049 - $field_types = array();
1050 - if ( in_array( $type, $single_input ) ) {
1262 + if ( in_array( $type, $single_input, true ) ) {
1051 1263 self::field_types_for_input( $single_input, $field_selection, $field_types );
1052 - } elseif ( in_array( $type, $multiple_input ) ) {
1264 + } elseif ( in_array( $type, $multiple_input, true ) ) {
1053 1265 self::field_types_for_input( $multiple_input, $field_selection, $field_types );
1054 1266 } elseif ( isset( $field_selection[ $type ] ) ) {
1055 1267 $field_types[ $type ] = $field_selection[ $type ];
1056 1268 }
@@ -1078,15 +1290,25 @@
1078 1290 'hidden',
1079 1291 'time',
1080 1292 'tag',
1081 1293 'password',
1294 + 'gdpr',
1082 1295 );
1083 1296 return apply_filters( 'frm_single_input_fields', $fields );
1084 1297 }
1085 1298
1299 + /**
1300 + * @param string[] $inputs
1301 + * @param array $fields
1302 + * @param array $field_types
1303 + * @return void
1304 + */
1086 1305 private static function field_types_for_input( $inputs, $fields, &$field_types ) {
1087 1306 foreach ( $inputs as $input ) {
1088 - $field_types[ $input ] = $fields[ $input ];
1307 + // This may not be set if a field type was removed using the frm_available_fields or frm_pro_available_fields filters.
1308 + if ( array_key_exists( $input, $fields ) ) {
1309 + $field_types[ $input ] = $fields[ $input ];
1310 + }
1089 1311 unset( $input );
1090 1312 }
1091 1313 }
1092 1314
@@ -1096,9 +1318,9 @@
1096 1318 * @since 2.0.6
1097 1319 *
1098 1320 * @param string $opt_key
1099 1321 *
1100 - * @return boolean Returns true if current field option is an "Other" option
1322 + * @return bool Returns true if current field option is an "Other" option
1101 1323 */
1102 1324 public static function is_other_opt( $opt_key ) {
1103 1325 return $opt_key && strpos( $opt_key, 'other_' ) === 0;
1104 1326 }
@@ -1141,10 +1363,11 @@
1141 1363 $other_val = sanitize_text_field( wp_unslash( $_POST['item_meta'][ $parent ][ $pointer ]['other'][ $field['id'] ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
1142 1364 }
1143 1365
1144 1366 return $other_val;
1367 + }
1145 1368
1146 - } elseif ( isset( $field['id'] ) && isset( $_POST['item_meta']['other'][ $field['id'] ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
1369 + if ( isset( $field['id'] ) && isset( $_POST['item_meta']['other'][ $field['id'] ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
1147 1370 // For normal fields
1148 1371
1149 1372 if ( FrmField::is_field_with_multiple_values( $field ) ) {
1150 1373 // phpcs:ignore WordPress.Security.NonceVerification.Missing
@@ -1153,9 +1376,9 @@
1153 1376 $other_val = sanitize_text_field( wp_unslash( $_POST['item_meta']['other'][ $field['id'] ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
1154 1377 }
1155 1378
1156 1379 return $other_val;
1157 - }
1380 + }//end if
1158 1381
1159 1382 // For checkboxes
1160 1383 if ( $field['type'] === 'checkbox' && is_array( $field['value'] ) ) {
1161 1384 // Check if there is an "other" val in saved value and make sure the
@@ -1167,9 +1390,9 @@
1167 1390 /**
1168 1391 * For radio buttons and dropdowns
1169 1392 * Check if saved value equals any of the options. If not, set it as the other value.
1170 1393 */
1171 - foreach ( $field['options'] as $opt_key => $opt_val ) {
1394 + foreach ( $field['options'] as $opt_val ) {
1172 1395 $temp_val = is_array( $opt_val ) ? $opt_val['value'] : $opt_val;
1173 1396 // Multi-select dropdowns - key is not preserved
1174 1397 if ( is_array( $field['value'] ) ) {
1175 1398 $o_key = array_search( $temp_val, $field['value'] );
@@ -1181,15 +1404,15 @@
1181 1404 return '';
1182 1405 } else {
1183 1406 $other_val = $field['value'];
1184 1407 }
1185 - unset( $opt_key, $opt_val, $temp_val );
1408 + unset( $opt_val, $temp_val );
1186 1409 }
1187 1410 // For multi-select dropdowns only
1188 1411 if ( is_array( $field['value'] ) && ! empty( $field['value'] ) ) {
1189 1412 $other_val = reset( $field['value'] );
1190 1413 }
1191 - }
1414 + }//end if
1192 1415
1193 1416 return $other_val;
1194 1417 }
1195 1418
@@ -1198,10 +1421,10 @@
1198 1421 * Intended for front-end use
1199 1422 *
1200 1423 * @since 2.0.6
1201 1424 *
1202 - * @param array $args should include field, opt_key and field name
1203 - * @param boolean $other_opt
1425 + * @param array $args Should include field, opt_key and field name.
1426 + * @param bool $other_opt
1204 1427 * @param string $checked
1205 1428 *
1206 1429 * @return array $other_args
1207 1430 */
@@ -1210,14 +1433,14 @@
1210 1433 'name' => '',
1211 1434 'value' => '',
1212 1435 );
1213 1436
1214 - //Check if this is an "Other" option
1437 + // Check if this is an "Other" option.
1215 1438 if ( ! self::is_other_opt( $args['opt_key'] ) ) {
1216 1439 return $other_args;
1217 1440 }
1218 1441
1219 - $other_opt = true;
1442 + $other_opt = true;
1220 1443
1221 1444 self::set_other_name( $args, $other_args );
1222 1445 self::set_other_value( $args, $other_args );
1223 1446
@@ -1224,25 +1447,34 @@
1224 1447 if ( '' !== $other_args['value'] ) {
1225 1448 $checked = 'checked="checked" ';
1226 1449 }
1227 1450
1451 + // If 'other' is selected as one of the default values for a checkbox field, 'checked' attribute should be on.
1452 + if ( ! $checked &&
1453 + $args['field']['type'] === 'checkbox' &&
1454 + is_array( $args['field']['value'] ) &&
1455 + isset( $args['field_val'] ) &&
1456 + in_array( $args['field_val'], $args['field']['value'], true )
1457 + ) {
1458 + $checked = 'checked="checked" ';
1459 + }
1460 +
1228 1461 return $other_args;
1229 1462 }
1230 1463
1231 1464 /**
1465 + * @since 2.0.6
1232 1466 * @param array $args
1233 1467 * @param array $other_args
1234 - *
1235 - * @since 2.0.6
1236 1468 */
1237 1469 private static function set_other_name( $args, &$other_args ) {
1238 - //Set up name for other field
1470 + // Set up name for other field
1239 1471 $other_args['name'] = str_replace( '[]', '', $args['field_name'] );
1240 1472 $other_args['name'] = preg_replace( '/\[' . $args['field']['id'] . '\]$/', '', $other_args['name'] );
1241 1473 $other_args['name'] = $other_args['name'] . '[other][' . $args['field']['id'] . ']';
1242 1474
1243 - //Converts item_meta[field_id] => item_meta[other][field_id] and
1244 - //item_meta[parent][0][field_id] => item_meta[parent][0][other][field_id]
1475 + // Converts item_meta[field_id] => item_meta[other][field_id] and
1476 + // item_meta[parent][0][field_id] => item_meta[parent][0][other][field_id]
1245 1477 if ( FrmField::is_field_with_multiple_values( $args['field'] ) ) {
1246 1478 $other_args['name'] .= '[' . $args['opt_key'] . ']';
1247 1479 }
1248 1480 }
@@ -1249,12 +1481,11 @@
1249 1481
1250 1482 /**
1251 1483 * Find the parent and pointer, and get text for "other" text field
1252 1484 *
1485 + * @since 2.0.6
1253 1486 * @param array $args
1254 1487 * @param array $other_args
1255 - *
1256 - * @since 2.0.6
1257 1488 */
1258 1489 private static function set_other_value( $args, &$other_args ) {
1259 1490 $parent = '';
1260 1491 $pointer = '';
@@ -1281,11 +1512,10 @@
1281 1512
1282 1513 /**
1283 1514 * If this field includes an other option, show it
1284 1515 *
1285 - * @param $args array
1286 - *
1287 1516 * @since 2.0.6
1517 + * @param array $args
1288 1518 */
1289 1519 public static function include_other_input( $args ) {
1290 1520 if ( ! $args['other_opt'] ) {
1291 1521 return;
@@ -1295,9 +1525,9 @@
1295 1525 if ( ! $args['checked'] || trim( $args['checked'] ) == '' ) {
1296 1526 // hide the field if the other option is not selected
1297 1527 $classes[] = 'frm_pos_none';
1298 1528 }
1299 - if ( $args['field']['type'] == 'select' && $args['field']['multiple'] ) {
1529 + if ( $args['field']['type'] === 'select' && ! empty( $args['field']['multiple'] ) ) {
1300 1530 $classes[] = 'frm_other_full';
1301 1531 }
1302 1532
1303 1533 // Set up HTML ID for Other field
@@ -1318,11 +1548,11 @@
1318 1548 * Note: This does not affect fields in repeating sections
1319 1549 *
1320 1550 * @since 2.0.08
1321 1551 *
1322 - * @param string $type - field type
1323 - * @param string $html_id
1324 - * @param string|boolean $opt_key
1552 + * @param string $type Field type.
1553 + * @param string $html_id
1554 + * @param bool|string $opt_key
1325 1555 *
1326 1556 * @return string $other_id
1327 1557 */
1328 1558 public static function get_other_field_html_id( $type, $html_id, $opt_key = false ) {
@@ -1328,9 +1558,9 @@
1328 1558 public static function get_other_field_html_id( $type, $html_id, $opt_key = false ) {
1329 1559 $other_id = $html_id;
1330 1560
1331 1561 // If hidden radio field, add an opt key of 0
1332 - if ( $type == 'radio' && $opt_key === false ) {
1562 + if ( $type === 'radio' && $opt_key === false ) {
1333 1563 $opt_key = 0;
1334 1564 }
1335 1565
1336 1566 if ( $opt_key !== false ) {
@@ -1369,12 +1599,17 @@
1369 1599 $replace_with[] = 'field_id="' . $new . '"';
1370 1600 $replace[] = 'field_id=\"' . $old . '\"';
1371 1601 $replace_with[] = 'field_id=\"' . $new . '\"';
1372 1602 unset( $old, $new );
1373 - }
1603 + }//end foreach
1374 1604 if ( is_array( $val ) ) {
1375 1605 foreach ( $val as $k => $v ) {
1376 1606 if ( is_string( $v ) ) {
1607 + if ( 'custom_html' === $k ) {
1608 + $val[ $k ] = self::switch_ids_except_strings( $replace, $replace_with, array( '[if description]', '[description]', '[/if description]' ), $v );
1609 + unset( $k, $v );
1610 + continue;
1611 + }
1377 1612 $val[ $k ] = str_replace( $replace, $replace_with, $v );
1378 1613 unset( $k, $v );
1379 1614 }
1380 1615 }
@@ -1385,8 +1620,33 @@
1385 1620 return $val;
1386 1621 }
1387 1622
1388 1623 /**
1624 + * Removes exception strings from replacement arrays and replaces the rest in the provided value string.
1625 + *
1626 + * @since 6.14
1627 + *
1628 + * @param array $replace Values to be replaced.
1629 + * @param array $replace_with Replacement values.
1630 + * @param array $exceptions Array of strings to skip.
1631 + * @param string $value Value to be updated.
1632 + *
1633 + * @return string
1634 + */
1635 + private static function switch_ids_except_strings( $replace, $replace_with, $exceptions, $value ) {
1636 + foreach ( $exceptions as $exception ) {
1637 + $index = array_search( $exception, $replace, true );
1638 + if ( false === $index ) {
1639 + continue;
1640 + }
1641 + unset( $replace[ $index ] );
1642 + unset( $replace_with[ $index ] );
1643 + }
1644 + $value = str_replace( $replace, $replace_with, $value );
1645 + return $value;
1646 + }
1647 +
1648 + /**
1389 1649 * @since 4.0
1390 1650 */
1391 1651 public static function bulk_options_overlay() {
1392 1652 $prepop = array();
@@ -1391,9 +1651,9 @@
1391 1651 public static function bulk_options_overlay() {
1392 1652 $prepop = array();
1393 1653 self::get_bulk_prefilled_opts( $prepop, true );
1394 1654
1395 - include( FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/bulk-options-overlay.php' );
1655 + include FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/bulk-options-overlay.php';
1396 1656 }
1397 1657
1398 1658 public static function get_us_states() {
1399 1659 $states = array(
@@ -1833,9 +2093,9 @@
1833 2093 * Display a field value selector
1834 2094 *
1835 2095 * @since 2.03.05
1836 2096 *
1837 - * @param int $selector_field_id
2097 + * @param int $selector_field_id
1838 2098 * @param array $selector_args
1839 2099 */
1840 2100 public static function display_field_value_selector( $selector_field_id, $selector_args ) {
1841 2101 $field_value_selector = FrmFieldFactory::create_field_value_selector( $selector_field_id, $selector_args );
@@ -1851,9 +2111,9 @@
1851 2111 *
1852 2112 * @return array
1853 2113 */
1854 2114 public static function convert_field_object_to_flat_array( $field ) {
1855 - $field_options = $field->field_options;
2115 + $field_options = is_array( $field->field_options ) ? $field->field_options : array();
1856 2116 $field_array = get_object_vars( $field );
1857 2117 unset( $field_array['field_options'] );
1858 2118
1859 2119 return $field_array + $field_options;
@@ -1871,8 +2131,14 @@
1871 2131 $field_label = FrmAppHelper::icon_by_class( FrmFormsHelper::get_field_link_icon( $field_type ), array( 'echo' => false ) );
1872 2132 $field_name = FrmFormsHelper::get_field_link_name( $field_type );
1873 2133 $field_label .= ' <span>' . $field_name . '</span>';
1874 2134
2135 + if ( ! empty( $field_type['is_new'] ) ) {
2136 + ob_start();
2137 + FrmAppHelper::show_pill_text();
2138 + $field_label .= ob_get_clean();
2139 + }
2140 +
1875 2141 // If the individual field isn't allowed, disable it.
1876 2142 $run_filter = true;
1877 2143 $single_no_allow = ' ';
1878 2144 $install_data = '';
@@ -1877,9 +2143,9 @@
1877 2143 $single_no_allow = ' ';
1878 2144 $install_data = '';
1879 2145 $requires = '';
1880 2146 $link = isset( $field_type['link'] ) ? esc_url_raw( $field_type['link'] ) : '';
1881 - $has_show_upgrade_class = strpos( $field_type['icon'], ' frm_show_upgrade' );
2147 + $has_show_upgrade_class = isset( $field_type['icon'] ) && strpos( $field_type['icon'], ' frm_show_upgrade' );
1882 2148 $show_upgrade = $has_show_upgrade_class || false !== strpos( $args['no_allow_class'], 'frm_show_upgrade' );
1883 2149
1884 2150 if ( $has_show_upgrade_class ) {
1885 2151 $single_no_allow .= 'frm_show_upgrade';
@@ -1917,8 +2183,16 @@
1917 2183 'data-content' => $field_key,
1918 2184 'data-requires' => $requires,
1919 2185 );
1920 2186
2187 + if ( ! empty( $field_type['hide'] ) ) {
2188 + $li_params['class'] .= ' frm_hidden';
2189 + }
2190 +
2191 + if ( ! empty( $field_type['upsell_image'] ) ) {
2192 + $li_params['data-upsell-image'] = $field_type['upsell_image'];
2193 + }
2194 +
1921 2195 if ( $upgrade_message ) {
1922 2196 $li_params['data-message'] = $upgrade_message;
1923 2197 }
1924 2198 ?>
@@ -1926,9 +2200,9 @@
1926 2200 <?php
1927 2201 if ( $run_filter ) {
1928 2202 $field_label = apply_filters( 'frmpro_field_links', $field_label, $args['id'], $field_key );
1929 2203 }
1930 - echo FrmAppHelper::kses( $field_label, array( 'a', 'i', 'span', 'use', 'svg' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
2204 + FrmAppHelper::kses_echo( $field_label, array( 'a', 'i', 'span', 'use', 'svg' ) );
1931 2205 ?>
1932 2206 </li>
1933 2207 <?php
1934 2208 }
@@ -1959,10 +2233,10 @@
1959 2233 */
1960 2234 public static function get_display_format_options( $field ) {
1961 2235 $options = array(
1962 2236 '0' => array(
1963 - 'text' => __( 'Simple', 'formidable' ),
1964 - 'svg' => 'frm_simple_radio',
2237 + 'text' => __( 'Simple', 'formidable' ),
2238 + 'svg' => 'frm_simple_radio',
1965 2239 ),
1966 2240 '1' => array(
1967 2241 'text' => __( 'Images', 'formidable' ),
1968 2242 'svg' => 'frm_image_as_option',
@@ -2084,9 +2358,10 @@
2084 2358 }
2085 2359
2086 2360 /**
2087 2361 * Maybe adjust a field value based on type.
2088 - * Some types require unserializing an array (@see self::field_type_requires_unserialize).
2362 + * Some types require unserializing an array.
2363 + * These types are defined by a array_allowed property on their field model class.
2089 2364 *
2090 2365 * @since 6.2
2091 2366 *
2092 2367 * @param mixed $value
@@ -2098,95 +2373,53 @@
2098 2373 $value = $field_object->maybe_decode_value( $value );
2099 2374 }
2100 2375
2101 2376 /**
2102 - * @deprecated 4.0
2377 + * @since 6.8
2378 + *
2379 + * @param int|string $form_id
2380 + * @param array $field_ids If this is not empty, the results will be filtered by field id.
2381 + * @return array
2103 2382 */
2104 - public static function show_icon_link_js( $atts ) {
2105 - _deprecated_function( __METHOD__, '4.0' );
2106 - $atts['icon'] .= $atts['is_selected'] ? ' ' : ' frm_inactive_icon ';
2107 - if ( isset( $atts['has_default'] ) && ! $atts['has_default'] ) {
2108 - $atts['icon'] .= 'frm_hidden ';
2383 + public static function get_draft_field_results( $form_id, $field_ids = array() ) {
2384 + if ( FrmAppHelper::pro_is_installed() ) {
2385 + $child_form_ids = FrmDb::get_col( 'frm_forms', array( 'parent_form_id' => $form_id ) );
2386 + $form_ids = array_merge( array( $form_id ), $child_form_ids );
2387 + } else {
2388 + $form_ids = array( $form_id );
2109 2389 }
2110 - echo '<a href="javascript:void(0)" class="frm_bstooltip ' . esc_attr( $atts['icon'] ) . 'frm_default_val_icons frm_action_icon frm_icon_font" title="' . esc_attr( $atts['message'] ) . '"></a>';
2111 - }
2112 2390
2113 - /**
2114 - * @deprecated 4.0
2115 - */
2116 - public static function show_default_blank_js( $is_selected, $has_default_value = true ) {
2117 - _deprecated_function( __METHOD__, '4.0' );
2118 - }
2391 + $where = array(
2392 + 'form_id' => $form_ids,
2393 + // Do a soft check for fields that look like drafts only.
2394 + 'field_options LIKE' => 's:5:"draft";i:1;',
2395 + );
2119 2396
2120 - /**
2121 - * @deprecated 4.0
2122 - */
2123 - public static function clear_on_focus_html( $field, $display, $id = '' ) {
2124 - _deprecated_function( __METHOD__, '4.0' );
2125 - }
2397 + if ( $field_ids ) {
2398 + $where['id'] = $field_ids;
2399 + }
2126 2400
2127 - /**
2128 - * @deprecated 4.0
2129 - */
2130 - public static function show_onfocus_js( $is_selected, $has_default_value = true ) {
2131 - _deprecated_function( __METHOD__, '4.0' );
2132 - }
2401 + $rows = FrmDb::get_results( 'frm_fields', $where, 'id, field_options' );
2133 2402
2134 - /**
2135 - * @deprecated 3.0
2136 - * @codeCoverageIgnore
2137 - */
2138 - public static function display_recaptcha() {
2139 - _deprecated_function( __FUNCTION__, '3.0', 'FrmFieldCaptcha::field_input' );
2403 + return array_filter(
2404 + $rows,
2405 + function ( $row ) {
2406 + FrmAppHelper::unserialize_or_decode( $row->field_options );
2407 + return is_array( $row->field_options ) && ! empty( $row->field_options['draft'] );
2408 + }
2409 + );
2140 2410 }
2141 2411
2142 2412 /**
2143 - * @deprecated 3.0
2144 - * @codeCoverageIgnore
2145 - */
2146 - public static function remove_inline_conditions( $no_vars, $code, $replace_with, &$html ) {
2147 - FrmDeprecated::remove_inline_conditions( $no_vars, $code, $replace_with, $html );
2148 - }
2149 -
2150 - /**
2151 - * @deprecated 3.0
2152 - * @codeCoverageIgnore
2153 - */
2154 - public static function get_shortcode_tag( $shortcodes, $short_key, $args ) {
2155 - return FrmDeprecated::get_shortcode_tag( $shortcodes, $short_key, $args );
2156 - }
2157 -
2158 - /**
2159 - * @deprecated 3.0
2160 - * @codeCoverageIgnore
2413 + * This is called when loading the form builder.
2414 + * Any unsaved draft fields get added to a hidden draft_fields input on load.
2161 2415 *
2162 - * @param string $html
2163 - * @param array $field
2164 - * @param array $errors
2165 - * @param object|false $form
2166 - * @param array $args
2416 + * @since 6.8
2167 2417 *
2168 - * @return string
2418 + * @param int|string $form_id
2419 + * @return array
2169 2420 */
2170 - public static function replace_shortcodes( $html, $field, $errors = array(), $form = false, $args = array() ) {
2171 - return FrmDeprecated::replace_shortcodes( $html, $field, $errors, $form, $args );
2172 - }
2173 -
2174 - /**
2175 - * @deprecated 3.0
2176 - * @codeCoverageIgnore
2177 - */
2178 - public static function get_default_field_opts( $type, $field = null, $limit = false ) {
2179 - return FrmDeprecated::get_default_field_opts( $type, $field, $limit );
2180 - }
2181 -
2182 - /**
2183 - * @deprecated 2.02.07 This is still referenced in the Highrise add on as of v1.06.
2184 - * @codeCoverageIgnore
2185 - *
2186 - * @param array $args
2187 - * @return string
2188 - */
2189 - public static function dropdown_categories( $args ) {
2190 - return FrmDeprecated::dropdown_categories( $args );
2421 + public static function get_all_draft_field_ids( $form_id ) {
2422 + $draft_field_rows = self::get_draft_field_results( $form_id );
2423 + return wp_list_pluck( $draft_field_rows, 'id' );
2191 2424 }
2192 2425 }