PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / trunk
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More vtrunk
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/models/FrmField.php +65 -9 6.29 → trunk View file →
@@ -79,8 +79,12 @@
79 79 'credit_card' => array(
80 80 'name' => __( 'Payment', 'formidable' ),
81 81 'icon' => 'frmfont frm_credit_card2_icon',
82 82 ),
83 + 'address' => array(
84 + 'name' => __( 'Address', 'formidable' ),
85 + 'icon' => 'frmfont frm_location2_icon',
86 + ),
83 87 FrmSubmitHelper::FIELD_TYPE => array(
84 88 'name' => __( 'Submit', 'formidable' ),
85 89 'hide' => true,
86 90 ),
@@ -88,8 +92,23 @@
88 92 'name' => __( 'GDPR', 'formidable' ),
89 93 'icon' => 'frmfont frm-gdpr-icon',
90 94 'hide' => FrmFieldGdprHelper::hide_gdpr_field(),
91 95 ),
96 + 'product' => array(
97 + 'name' => __( 'Product', 'formidable' ),
98 + 'icon' => 'frmfont frm_product2_icon',
99 + 'section' => 'pricing',
100 + ),
101 + 'quantity' => array(
102 + 'name' => __( 'Quantity', 'formidable' ),
103 + 'icon' => 'frmfont frm_quantity_icon',
104 + 'section' => 'pricing',
105 + ),
106 + 'total' => array(
107 + 'name' => __( 'Total', 'formidable' ),
108 + 'icon' => 'frmfont frm_total2_icon',
109 + 'section' => 'pricing',
110 + ),
92 111 );
93 112
94 113 /**
95 114 * @param array $fields
@@ -307,8 +326,9 @@
307 326 'icon' => 'frmfont frm-virtual-field-icon',
308 327 'message' => esc_html__( 'Protect sensitive data by storing field values server-side only, preventing users from viewing or manipulating them in their browser.', 'formidable' ), // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
309 328 'upsell_image' => $upsell_images_url . 'virtual-field-preview.webp',
310 329 'learn-more' => '/virtual',
330 + 'is_new' => self::field_is_new( 'virtual' ),
311 331 ),
312 332 'product' => array(
313 333 'name' => __( 'Product', 'formidable' ),
314 334 'icon' => 'frmfont frm_product2_icon',
@@ -370,8 +390,24 @@
370 390 return $fields;
371 391 }
372 392
373 393 /**
394 + * Gets field section labels in the form builder.
395 + *
396 + * @since 6.30
397 + *
398 + * @return array
399 + */
400 + public static function field_section_labels() {
401 + return apply_filters(
402 + 'frm_available_field_sections',
403 + array(
404 + 'pricing' => __( 'Pricing Fields', 'formidable' ),
405 + )
406 + );
407 + }
408 +
409 + /**
374 410 * Consider a field new for 90 days after the release date.
375 411 *
376 412 * @since 6.8.3
377 413 *
@@ -380,9 +416,9 @@
380 416 * @return bool
381 417 */
382 418 private static function field_is_new( $type ) {
383 419 $release_dates = array(
384 - 'coupon' => '2026-01-13',
420 + 'virtual' => '2026-03-10',
385 421 );
386 422
387 423 if ( ! isset( $release_dates[ $type ] ) ) {
388 424 return false;
@@ -393,15 +429,31 @@
393 429 return gmdate( 'Y-m-d' ) < $three_months_after_release;
394 430 }
395 431
396 432 /**
433 + * Remove field types that are moved from Pro to Lite.
434 + *
435 + * @since 6.30
436 + *
437 + * @param array $pro_fields
438 + *
439 + * @return void
440 + */
441 + public static function remove_moved_field_types_from_pro( &$pro_fields ) {
442 + unset( $pro_fields['credit_card'] );
443 + unset( $pro_fields['product'] );
444 + unset( $pro_fields['quantity'] );
445 + unset( $pro_fields['total'] );
446 + unset( $pro_fields['address'] );
447 + }
448 +
449 + /**
397 450 * @since 4.0
398 451 *
399 452 * @return array
400 453 */
401 454 public static function all_field_selection() {
402 - $pro_field_selection = self::pro_field_selection();
403 - return array_merge( $pro_field_selection, self::field_selection() );
455 + return array_merge( self::pro_field_selection(), self::field_selection() );
404 456 }
405 457
406 458 /**
407 459 * Create a field.
@@ -425,13 +477,19 @@
425 477 $new_values[ $col ] = $values[ $col ];
426 478 }
427 479 }
428 480
429 - $new_values['options'] = self::maybe_filter_options( $values['options'] );
481 + // Both option columns are stored serialized, but they do not accept the same shapes.
482 + // Choice fields pass options already serialized, as does FrmFieldsHelper::fill_field
483 + // when a field is duplicated, and fields with no choices pass an empty string, so a
484 + // missing key is the only thing worth defaulting. An is_array check here would throw
485 + // every one of those defaults away. field_options is always an array, so anything
486 + // else is invalid input, and replacing it stops consumers getting null.
487 + $new_values['options'] = self::maybe_filter_options( $values['options'] ?? array() );
430 488 $new_values['field_order'] = isset( $values['field_order'] ) ? (int) $values['field_order'] : null;
431 489 $new_values['required'] = isset( $values['required'] ) ? (int) $values['required'] : 0;
432 490 $new_values['form_id'] = isset( $values['form_id'] ) ? (int) $values['form_id'] : null;
433 - $new_values['field_options'] = $values['field_options'];
491 + $new_values['field_options'] = isset( $values['field_options'] ) && is_array( $values['field_options'] ) ? $values['field_options'] : array();
434 492 $new_values['created_at'] = current_time( 'mysql', 1 );
435 493
436 494 if ( isset( $values['id'] ) ) {
437 495 $frm_duplicate_ids[ $values['field_key'] ] = $new_values['field_key'];
@@ -474,9 +532,9 @@
474 532 * See FrmAppHelper::allow_unfiltered_html.
475 533 *
476 534 * @since 5.0.08
477 535 *
478 - * @param array $options
536 + * @param array|string $options Already serialized for choice fields, and an empty string for fields with no choices.
479 537 *
480 538 * @return array
481 539 */
482 540 private static function maybe_filter_options( $options ) {
@@ -1379,11 +1437,9 @@
1379 1437 *
1380 1438 * @return bool
1381 1439 */
1382 1440 public static function is_multiple_select( $field ) {
1383 - $field_type = self::get_field_type( $field );
1384 - $is_multiple = self::is_option_true( $field, 'multiple' ) && self::is_field_type( $field, 'select' ) && $field_type !== 'hidden';
1385 -
1441 + $is_multiple = self::is_option_true( $field, 'multiple' ) && self::is_field_type( $field, 'select' ) && self::get_field_type( $field ) !== 'hidden';
1386 1442 return apply_filters( 'frm_is_multiple_select', $is_multiple, $field );
1387 1443 }
1388 1444
1389 1445 /**