| @@ -9,9 +9,9 @@ | ||
| 9 | 9 | * Version of the database we are moving to. |
| 10 | 10 | * |
| 11 | 11 | * @var int |
| 12 | 12 | */ |
| 13 | - public static $db_version = 104; | |
| 13 | + public static $db_version = 106; | |
| 14 | 14 | |
| 15 | 15 | /** |
| 16 | 16 | * Used by the API add-on. |
| 17 | 17 | * |
| @@ -28,9 +28,9 @@ | ||
| 28 | 28 | * @since 2.0 |
| 29 | 29 | * |
| 30 | 30 | * @var string |
| 31 | 31 | */ |
| 32 | - public static $plug_version = '6.28'; | |
| 32 | + public static $plug_version = '6.35'; | |
| 33 | 33 | |
| 34 | 34 | /** |
| 35 | 35 | * @var bool |
| 36 | 36 | */ |
| @@ -309,10 +309,9 @@ | ||
| 309 | 309 | if ( ! self::pro_is_installed() ) { |
| 310 | 310 | return true; |
| 311 | 311 | } |
| 312 | 312 | |
| 313 | - $menu_icon = self::get_menu_icon_class(); | |
| 314 | - return str_contains( $menu_icon, 'frm_logo_icon' ); | |
| 313 | + return str_contains( self::get_menu_icon_class(), 'frm_logo_icon' ); | |
| 315 | 314 | } |
| 316 | 315 | |
| 317 | 316 | /** |
| 318 | 317 | * @since 3.05 |
| @@ -938,8 +937,9 @@ | ||
| 938 | 937 | } else { |
| 939 | 938 | self::sanitize_value( self::class . '::strip_most_html', $value ); |
| 940 | 939 | } |
| 941 | 940 | self::decode_specialchars( $value ); |
| 941 | + self::sanitize_value( 'FrmHtmlSanitizer::sanitize_url_attributes', $value ); | |
| 942 | 942 | } |
| 943 | 943 | |
| 944 | 944 | /** |
| 945 | 945 | * Allow only a small set of very basic HTML for unprivileged users. |
| @@ -948,8 +948,12 @@ | ||
| 948 | 948 | * |
| 949 | 949 | * @param string $value |
| 950 | 950 | */ |
| 951 | 951 | public static function strip_most_html( $value ) { |
| 952 | + if ( '' === $value ) { | |
| 953 | + return $value; | |
| 954 | + } | |
| 955 | + | |
| 952 | 956 | $allowed_html = array( |
| 953 | 957 | 'b' => array(), |
| 954 | 958 | 'br' => array(), |
| 955 | 959 | 'strong' => array(), |
| @@ -1046,10 +1050,9 @@ | ||
| 1046 | 1050 | * |
| 1047 | 1051 | * @return string |
| 1048 | 1052 | */ |
| 1049 | 1053 | public static function kses( $value, $allowed = array() ) { |
| 1050 | - $allowed_html = self::allowed_html( $allowed ); | |
| 1051 | - return wp_kses( $value, $allowed_html ); | |
| 1054 | + return wp_kses( $value, self::allowed_html( $allowed ) ); | |
| 1052 | 1055 | } |
| 1053 | 1056 | |
| 1054 | 1057 | /** |
| 1055 | 1058 | * Sanitizes and echoes a given value. |
| @@ -1366,10 +1369,9 @@ | ||
| 1366 | 1369 | if ( isset( $atts['echo'] ) ) { |
| 1367 | 1370 | unset( $atts['echo'] ); |
| 1368 | 1371 | } |
| 1369 | 1372 | |
| 1370 | - $html_atts = self::array_to_html_params( $atts ); | |
| 1371 | - $icon = trim( str_replace( array( 'frm_icon_font', 'frmfont ' ), '', $class ) ); | |
| 1373 | + $icon = trim( str_replace( array( 'frm_icon_font', 'frmfont ' ), '', $class ) ); | |
| 1372 | 1374 | |
| 1373 | 1375 | // Replace icons that have been removed or renamed. |
| 1374 | 1376 | $deprecated = array( |
| 1375 | 1377 | 'frm_clone_solid_icon' => 'frm_clone_icon', |
| @@ -1381,11 +1383,11 @@ | ||
| 1381 | 1383 | $icon = $deprecated[ $icon ]; |
| 1382 | 1384 | $class = str_replace( $icon, $deprecated[ $icon ], $class ); |
| 1383 | 1385 | } |
| 1384 | 1386 | |
| 1385 | - if ( $icon === $class ) { | |
| 1386 | - $icon = '<i class="' . esc_attr( $class ) . '"' . $html_atts . '></i>'; | |
| 1387 | - } else { | |
| 1387 | + $is_font_icon = $icon === $class; | |
| 1388 | + | |
| 1389 | + if ( ! $is_font_icon ) { | |
| 1388 | 1390 | $class = str_contains( $icon, ' ' ) ? ' ' . $icon : ''; |
| 1389 | 1391 | |
| 1390 | 1392 | if ( str_contains( $icon, ' ' ) ) { |
| 1391 | 1393 | $icon = explode( ' ', $icon ); |
| @@ -1390,18 +1392,46 @@ | ||
| 1390 | 1392 | if ( str_contains( $icon, ' ' ) ) { |
| 1391 | 1393 | $icon = explode( ' ', $icon ); |
| 1392 | 1394 | $icon = reset( $icon ); |
| 1393 | 1395 | } |
| 1396 | + } | |
| 1394 | 1397 | |
| 1395 | - $icon = '<svg class="frmsvg' . esc_attr( $class ) . '"' . $html_atts . '><use href="#' . esc_attr( $icon ) . '" /></svg>'; | |
| 1396 | - } | |
| 1398 | + if ( $atts ) { | |
| 1399 | + // A caller passed attributes, so kses still has to decide which of them survive. Its | |
| 1400 | + // allowlist comes from safe_html() through the frm_striphtml_allowed_tags filter, and | |
| 1401 | + // add-ons widen it around their own icons, so there is no fixed list to check against. | |
| 1402 | + $html_atts = self::array_to_html_params( $atts ); | |
| 1403 | + $markup = $is_font_icon | |
| 1404 | + ? '<i class="' . esc_attr( $class ) . '"' . $html_atts . '></i>' | |
| 1405 | + : '<svg class="frmsvg' . esc_attr( $class ) . '"' . $html_atts . '><use href="#' . esc_attr( $icon ) . '" /></svg>'; | |
| 1397 | 1406 | |
| 1398 | - if ( $echo ) { | |
| 1399 | - echo self::kses_icon( $icon ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped | |
| 1407 | + if ( ! $echo ) { | |
| 1408 | + return $markup; | |
| 1409 | + } | |
| 1410 | + | |
| 1411 | + echo self::kses_icon( $markup ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped | |
| 1400 | 1412 | return null; |
| 1401 | 1413 | } |
| 1402 | 1414 | |
| 1403 | - return $icon; | |
| 1415 | + /** | |
| 1416 | + * With no attributes from the caller, the tag is nothing but this method's own markup | |
| 1417 | + * around an escaped class and icon id, so there is nothing left for kses to decide and it | |
| 1418 | + * can be skipped. Echoing the pieces rather than a finished string keeps that safe to the | |
| 1419 | + * escaping sniff without an annotation. | |
| 1420 | + * | |
| 1421 | + * This is the path the form builder takes for most of the tens of thousands of icons it | |
| 1422 | + * renders on a large form, and the kses pass was most of what each one cost. | |
| 1423 | + */ | |
| 1424 | + $callback = function () use ( $is_font_icon, $class, $icon ) { | |
| 1425 | + if ( $is_font_icon ) { | |
| 1426 | + echo '<i class="' . esc_attr( $class ) . '"></i>'; | |
| 1427 | + return; | |
| 1428 | + } | |
| 1429 | + | |
| 1430 | + echo '<svg class="frmsvg' . esc_attr( $class ) . '"><use href="#' . esc_attr( $icon ) . '" /></svg>'; | |
| 1431 | + }; | |
| 1432 | + | |
| 1433 | + return self::clip( $callback, $echo ); | |
| 1404 | 1434 | } |
| 1405 | 1435 | |
| 1406 | 1436 | /** |
| 1407 | 1437 | * Run kses for icons. It needs to add a few filters first in order to preserve some custom style values. |
| @@ -1513,13 +1543,15 @@ | ||
| 1513 | 1543 | * @return string|void |
| 1514 | 1544 | */ |
| 1515 | 1545 | public static function array_to_html_params( $atts, $echo = false ) { |
| 1516 | 1546 | $callback = function () use ( $atts ) { |
| 1517 | - if ( $atts ) { | |
| 1518 | - foreach ( $atts as $key => $value ) { | |
| 1519 | - echo ' ' . esc_attr( $key ) . '="' . esc_attr( $value ) . '"'; | |
| 1520 | - } | |
| 1547 | + if ( ! $atts ) { | |
| 1548 | + return; | |
| 1521 | 1549 | } |
| 1550 | + | |
| 1551 | + foreach ( $atts as $key => $value ) { | |
| 1552 | + echo ' ' . esc_attr( $key ) . '="' . esc_attr( $value ) . '"'; | |
| 1553 | + } | |
| 1522 | 1554 | }; |
| 1523 | 1555 | return self::clip( $callback, $echo ); |
| 1524 | 1556 | } |
| 1525 | 1557 | |
| @@ -1531,8 +1563,10 @@ | ||
| 1531 | 1563 | * @param Closure $echo_function |
| 1532 | 1564 | * @param bool $echo |
| 1533 | 1565 | * |
| 1534 | 1566 | * @return string|null |
| 1567 | + * | |
| 1568 | + * @psalm-return ($echo is true ? null : string) | |
| 1535 | 1569 | */ |
| 1536 | 1570 | public static function clip( $echo_function, $echo = false ) { |
| 1537 | 1571 | if ( ! $echo ) { |
| 1538 | 1572 | ob_start(); |
| @@ -1624,9 +1658,9 @@ | ||
| 1624 | 1658 | |
| 1625 | 1659 | printf( |
| 1626 | 1660 | /* translators: %1$s: Start link HTML, %2$s: CTA text ("upgrading to PRO" by default), %3$s: End link HTML */ |
| 1627 | 1661 | esc_html__( 'You\'re using Formidable Forms Lite. To unlock more features consider %1$s%2$s%3$s.', 'formidable' ), |
| 1628 | - '<a href="' . esc_url( $upgrade_link ) . '">', | |
| 1662 | + '<a href="' . esc_url( $upgrade_link ) . '" target="_blank" rel="noopener">', | |
| 1629 | 1663 | esc_html( $cta_text ), |
| 1630 | 1664 | '</a>' |
| 1631 | 1665 | ); |
| 1632 | 1666 | ?> |
| @@ -2334,10 +2368,9 @@ | ||
| 2334 | 2368 | if ( ! current_user_can( 'administrator' ) || current_user_can( 'frm_view_forms' ) ) { |
| 2335 | 2369 | return; |
| 2336 | 2370 | } |
| 2337 | 2371 | |
| 2338 | - $user_id = get_current_user_id(); | |
| 2339 | - $user = new WP_User( $user_id ); | |
| 2372 | + $user = new WP_User( get_current_user_id() ); | |
| 2340 | 2373 | $frm_roles = self::frm_capabilities(); |
| 2341 | 2374 | |
| 2342 | 2375 | foreach ( $frm_roles as $frm_role => $frm_role_description ) { |
| 2343 | 2376 | $user->add_cap( $frm_role ); |
| @@ -2354,15 +2387,17 @@ | ||
| 2354 | 2387 | * |
| 2355 | 2388 | * @return void |
| 2356 | 2389 | */ |
| 2357 | 2390 | public static function force_capability( $cap = 'frm_change_settings' ) { |
| 2358 | - if ( current_user_can( 'administrator' ) && ! current_user_can( $cap ) ) { | |
| 2359 | - $role = get_role( 'administrator' ); | |
| 2360 | - $frm_roles = self::frm_capabilities(); | |
| 2391 | + if ( ! current_user_can( 'administrator' ) || current_user_can( $cap ) ) { | |
| 2392 | + return; | |
| 2393 | + } | |
| 2361 | 2394 | |
| 2362 | - foreach ( $frm_roles as $frm_role => $frm_role_description ) { | |
| 2363 | - $role->add_cap( $frm_role ); | |
| 2364 | - } | |
| 2395 | + $role = get_role( 'administrator' ); | |
| 2396 | + $frm_roles = self::frm_capabilities(); | |
| 2397 | + | |
| 2398 | + foreach ( $frm_roles as $frm_role => $frm_role_description ) { | |
| 2399 | + $role->add_cap( $frm_role ); | |
| 2365 | 2400 | } |
| 2366 | 2401 | } |
| 2367 | 2402 | |
| 2368 | 2403 | /** |
| @@ -2458,16 +2493,16 @@ | ||
| 2458 | 2493 | if ( is_array( $value ) ) { |
| 2459 | 2494 | $original_function = $function; |
| 2460 | 2495 | $function = count( $value ) ? explode( ', ', FrmDb::prepare_array_values( $value, $function ) ) : array( $function ); |
| 2461 | 2496 | |
| 2462 | - if ( ! self::is_assoc( $value ) ) { | |
| 2463 | - $value = array_map( array( 'FrmAppHelper', 'recursive_function_map' ), $value, $function ); | |
| 2464 | - } else { | |
| 2497 | + if ( self::is_assoc( $value ) ) { | |
| 2465 | 2498 | foreach ( $value as $k => $v ) { |
| 2466 | 2499 | if ( ! is_array( $v ) ) { |
| 2467 | 2500 | $value[ $k ] = call_user_func( $original_function, $v ); |
| 2468 | 2501 | } |
| 2469 | 2502 | } |
| 2503 | + } else { | |
| 2504 | + $value = array_map( array( 'FrmAppHelper', 'recursive_function_map' ), $value, $function ); | |
| 2470 | 2505 | } |
| 2471 | 2506 | } else { |
| 2472 | 2507 | $value = self::maybe_update_value_if_null( $value, $function ); |
| 2473 | 2508 | $value = call_user_func( $function, $value ); |
| @@ -3059,16 +3094,23 @@ | ||
| 3059 | 3094 | return $frm_settings->load_style !== 'none'; |
| 3060 | 3095 | } |
| 3061 | 3096 | |
| 3062 | 3097 | /** |
| 3098 | + * Truncate a string. | |
| 3099 | + * | |
| 3100 | + * Note: By default, this function will allow for a few additional characters more than $length. | |
| 3101 | + * If a string has no spaces, it allows up to 50 additional characters. To force a true length limit, | |
| 3102 | + * use $force_length_limit = true. | |
| 3103 | + * | |
| 3063 | 3104 | * @param mixed $original_string |
| 3064 | 3105 | * @param int|string $length |
| 3065 | 3106 | * @param int $minword |
| 3066 | 3107 | * @param string $continue |
| 3108 | + * @param bool $force_length_limit Force the final string to never exceed the length limit. | |
| 3067 | 3109 | * |
| 3068 | 3110 | * @return string |
| 3069 | 3111 | */ |
| 3070 | - public static function truncate( $original_string, $length, $minword = 3, $continue = '...' ) { | |
| 3112 | + public static function truncate( $original_string, $length, $minword = 3, $continue = '...', $force_length_limit = false ) { | |
| 3071 | 3113 | if ( ! is_string( $original_string ) && ! is_int( $original_string ) ) { |
| 3072 | 3114 | return ''; |
| 3073 | 3115 | } |
| 3074 | 3116 | |
| @@ -3082,8 +3124,13 @@ | ||
| 3082 | 3124 | $original_len = self::mb_function( array( 'mb_strlen', 'strlen' ), array( $str ) ); |
| 3083 | 3125 | |
| 3084 | 3126 | if ( $length <= 10 ) { |
| 3085 | 3127 | $sub = self::mb_function( array( 'mb_substr', 'substr' ), array( $str, 0, $length ) ); |
| 3128 | + | |
| 3129 | + if ( $force_length_limit ) { | |
| 3130 | + return $sub; | |
| 3131 | + } | |
| 3132 | + | |
| 3086 | 3133 | return $sub . ( $length < $original_len ? $continue : '' ); |
| 3087 | 3134 | } |
| 3088 | 3135 | |
| 3089 | 3136 | $sub = ''; |
| @@ -3111,10 +3158,21 @@ | ||
| 3111 | 3158 | |
| 3112 | 3159 | unset( $total_len, $word ); |
| 3113 | 3160 | } |
| 3114 | 3161 | |
| 3115 | - $sub = self::maybe_force_truncate_on_string_with_no_spaces( $sub, $length ); | |
| 3162 | + $sub = self::maybe_force_truncate_on_string_with_no_spaces( $sub, $length, $force_length_limit ); | |
| 3116 | 3163 | |
| 3164 | + if ( $force_length_limit ) { | |
| 3165 | + // Ensure the final string doesn't exceed the length limit. | |
| 3166 | + $final_len = self::mb_function( array( 'mb_strlen', 'strlen' ), array( $sub ) ); | |
| 3167 | + | |
| 3168 | + if ( $final_len > $length ) { | |
| 3169 | + return self::mb_function( array( 'mb_substr', 'substr' ), array( $sub, 0, $length ) ); | |
| 3170 | + } | |
| 3171 | + | |
| 3172 | + return $sub; | |
| 3173 | + } | |
| 3174 | + | |
| 3117 | 3175 | return $sub . ( $len < $original_len ? $continue : '' ); |
| 3118 | 3176 | } |
| 3119 | 3177 | |
| 3120 | 3178 | /** |
| @@ -3121,27 +3179,39 @@ | ||
| 3121 | 3179 | * If the string is still too long because there may not have been any spaces, force truncate. |
| 3122 | 3180 | * |
| 3123 | 3181 | * @since 6.5.4 |
| 3124 | 3182 | * |
| 3125 | - * @param string $sub Current substring. | |
| 3126 | - * @param int $length The length limit. | |
| 3183 | + * @param string $sub Current substring. | |
| 3184 | + * @param int $length The length limit. | |
| 3185 | + * @param bool $force_length_limit Force the string to not exceed the length limit. | |
| 3127 | 3186 | * |
| 3128 | 3187 | * @return string |
| 3129 | 3188 | */ |
| 3130 | - private static function maybe_force_truncate_on_string_with_no_spaces( $sub, $length ) { | |
| 3131 | - if ( strlen( $sub ) < $length + 50 ) { | |
| 3132 | - // If the string isn't way over the limit, leave it. | |
| 3133 | - return $sub; | |
| 3189 | + private static function maybe_force_truncate_on_string_with_no_spaces( $sub, $length, $force_length_limit = false ) { | |
| 3190 | + if ( ! $force_length_limit ) { | |
| 3191 | + if ( strlen( $sub ) < $length + 50 ) { | |
| 3192 | + // If the string isn't way over the limit, leave it. | |
| 3193 | + return $sub; | |
| 3194 | + } | |
| 3195 | + | |
| 3196 | + $first_space = strpos( $sub, ' ', $length ); | |
| 3197 | + | |
| 3198 | + if ( false !== $first_space ) { | |
| 3199 | + // Ignore anything with spaces. | |
| 3200 | + return $sub; | |
| 3201 | + } | |
| 3202 | + | |
| 3203 | + return substr( $sub, 0, $length + 10 ); | |
| 3134 | 3204 | } |
| 3135 | 3205 | |
| 3136 | - $first_space = strpos( $sub, ' ', $length ); | |
| 3206 | + // When force_length_limit is true, ensure the string doesn't exceed the length. | |
| 3207 | + $final_len = self::mb_function( array( 'mb_strlen', 'strlen' ), array( $sub ) ); | |
| 3137 | 3208 | |
| 3138 | - if ( false !== $first_space ) { | |
| 3139 | - // Ignore anything with spaces. | |
| 3140 | - return $sub; | |
| 3209 | + if ( $final_len > $length ) { | |
| 3210 | + return self::mb_function( array( 'mb_substr', 'substr' ), array( $sub, 0, $length ) ); | |
| 3141 | 3211 | } |
| 3142 | 3212 | |
| 3143 | - return substr( $sub, 0, $length + 10 ); | |
| 3213 | + return $sub; | |
| 3144 | 3214 | } |
| 3145 | 3215 | |
| 3146 | 3216 | /** |
| 3147 | 3217 | * @param array $function_names |
| @@ -3811,10 +3881,9 @@ | ||
| 3811 | 3881 | * |
| 3812 | 3882 | * @return void |
| 3813 | 3883 | */ |
| 3814 | 3884 | public static function load_admin_wide_js( $load = true ) { |
| 3815 | - $version = self::plugin_version(); | |
| 3816 | - wp_register_script( 'formidable_admin_global', self::plugin_url() . '/js/formidable_admin_global.js', array( 'jquery' ), $version ); | |
| 3885 | + wp_register_script( 'formidable_admin_global', self::plugin_url() . '/js/formidable_admin_global.js', array( 'jquery' ), self::plugin_version() ); | |
| 3817 | 3886 | |
| 3818 | 3887 | $global_strings = array( |
| 3819 | 3888 | 'updating_msg' => __( 'Please wait while your site updates.', 'formidable' ), |
| 3820 | 3889 | 'deauthorize' => __( 'Are you sure you want to deauthorize Formidable Forms on this site?', 'formidable' ), |
| @@ -3912,8 +3981,10 @@ | ||
| 3912 | 3981 | 'text_shortcodes' => __( 'This calculation may have shortcodes that work in text calculations but not numeric calculations.', 'formidable' ), |
| 3913 | 3982 | /* translators: %d is the number of allowed actions per form */ |
| 3914 | 3983 | 'only_one_action' => sprintf( __( 'This form action is limited to %d per form.', 'formidable' ), 1 ), |
| 3915 | 3984 | 'edit_action_text' => __( 'Please edit the existing form action.', 'formidable' ), |
| 3985 | + 'only_one_payment_action' => __( 'This form already has a payment action, and is currently limited to a single payment action.', 'formidable' ), | |
| 3986 | + 'only_one_stripe_action' => __( 'This form already has a payment action. Multiple Stripe actions are available when using the Stripe add-on, available for Formidable Business licenses and higher.', 'formidable' ), // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong | |
| 3916 | 3987 | 'unsafe_params' => FrmFormsHelper::reserved_words(), |
| 3917 | 3988 | /* Translators: %s is the name of a Detail Page Slug that is a reserved word.*/ |
| 3918 | 3989 | 'slug_is_reserved' => sprintf( __( 'The Detail Page Slug "%s" is reserved by WordPress. This may cause problems. Is this intentional?', 'formidable' ), '****' ), // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong |
| 3919 | 3990 | /* Translators: %s is the name of a parameter that is a reserved word. More than one word could be listed here, though that would not be common. */ |
| @@ -3942,8 +4013,11 @@ | ||
| 3942 | 4013 | // In older versions this event listener causes the section to immediately close again |
| 3943 | 4014 | // When the h3 element is clicked. It's only required in WP 6.7+. |
| 3944 | 4015 | 'requireAccordionTitleClickListener' => version_compare( $wp_version, '6.7', '>=' ), |
| 3945 | 4016 | ); |
| 4017 | + | |
| 4018 | + self::add_form_builder_modal_data( $admin_script_strings ); | |
| 4019 | + | |
| 3946 | 4020 | /** |
| 3947 | 4021 | * @param array $admin_script_strings |
| 3948 | 4022 | */ |
| 3949 | 4023 | $admin_script_strings = apply_filters( 'frm_admin_script_strings', $admin_script_strings ); |
| @@ -3956,8 +4030,80 @@ | ||
| 3956 | 4030 | }//end if |
| 3957 | 4031 | } |
| 3958 | 4032 | |
| 3959 | 4033 | /** |
| 4034 | + * @param array $admin_script_strings | |
| 4035 | + * | |
| 4036 | + * @return void | |
| 4037 | + */ | |
| 4038 | + private static function add_form_builder_modal_data( &$admin_script_strings ) { | |
| 4039 | + if ( ! self::is_form_builder_page() || self::pro_is_installed() ) { | |
| 4040 | + return; | |
| 4041 | + } | |
| 4042 | + | |
| 4043 | + $stripe_connected = FrmStrpLiteConnectHelper::at_least_one_mode_is_setup(); | |
| 4044 | + $square_connected = FrmSquareLiteConnectHelper::at_least_one_mode_is_setup(); | |
| 4045 | + $paypal_connected = FrmPayPalLiteConnectHelper::at_least_one_mode_is_setup(); | |
| 4046 | + $gateway_connected = $stripe_connected || $square_connected || $paypal_connected; | |
| 4047 | + $payments_settings_url = FrmStrpLiteAppController::get_payments_settings_url(); | |
| 4048 | + | |
| 4049 | + if ( ! $gateway_connected ) { | |
| 4050 | + // This modal shows when user clicks on one of the pricing fields and no payment gateways configured. | |
| 4051 | + $admin_script_strings['paymentsSettingsModal'] = array( | |
| 4052 | + 'title' => __( 'Setup a Payment Gateway first', 'formidable' ), | |
| 4053 | + 'msg' => __( 'To use the payment fields, please install and configure a payment gateway in your account settings.', 'formidable' ), | |
| 4054 | + 'closeText' => __( 'Close', 'formidable' ), | |
| 4055 | + 'actionUrl' => $payments_settings_url, | |
| 4056 | + 'actionText' => __( 'Go to Payment Settings', 'formidable' ), | |
| 4057 | + 'noCenter' => true, | |
| 4058 | + ); | |
| 4059 | + } | |
| 4060 | + | |
| 4061 | + // This modal shows on load once after upgrading the plugin. | |
| 4062 | + $show_pricing_fields_modal = get_option( 'frm_show_pricing_fields_modal' ); | |
| 4063 | + | |
| 4064 | + if ( ! $show_pricing_fields_modal ) { | |
| 4065 | + return; | |
| 4066 | + } | |
| 4067 | + | |
| 4068 | + $admin_script_strings['pricingFieldsModal'] = array( | |
| 4069 | + 'title' => esc_html__( 'Start Accepting Payments Today!', 'formidable' ), | |
| 4070 | + 'img' => esc_url( self::plugin_url() . '/images/upsell/pricing-fields.png' ), | |
| 4071 | + 'noCenter' => true, | |
| 4072 | + ); | |
| 4073 | + | |
| 4074 | + if ( $gateway_connected ) { | |
| 4075 | + $gateway_texts = array(); | |
| 4076 | + | |
| 4077 | + if ( $stripe_connected ) { | |
| 4078 | + $gateway_texts['stripe'] = esc_html__( 'Stripe', 'formidable' ); | |
| 4079 | + } | |
| 4080 | + | |
| 4081 | + if ( $square_connected ) { | |
| 4082 | + $gateway_texts['square'] = esc_html__( 'Square', 'formidable' ); | |
| 4083 | + } | |
| 4084 | + | |
| 4085 | + if ( $paypal_connected ) { | |
| 4086 | + $gateway_texts['paypal'] = esc_html__( 'PayPal', 'formidable' ); | |
| 4087 | + } | |
| 4088 | + | |
| 4089 | + $admin_script_strings['pricingFieldsModal']['msg'] = sprintf( | |
| 4090 | + // translators: %s: Stripe, Square, or PayPal. | |
| 4091 | + esc_html__( 'You already have %s connected, so these have already been unlocked.', 'formidable' ), | |
| 4092 | + esc_html( implode( ' ' . esc_html__( 'and', 'formidable' ) . ' ', $gateway_texts ) ) | |
| 4093 | + ); | |
| 4094 | + } else { | |
| 4095 | + $admin_script_strings['pricingFieldsModal']['closeText'] = __( 'I\'ll do it later!', 'formidable' ); | |
| 4096 | + $admin_script_strings['pricingFieldsModal']['actionText'] = __( 'Setup Payments Now', 'formidable' ); | |
| 4097 | + $admin_script_strings['pricingFieldsModal']['actionUrl'] = $payments_settings_url; | |
| 4098 | + // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong | |
| 4099 | + $admin_script_strings['pricingFieldsModal']['msg'] = __( 'We\'ve unlocked Product, Quantity, and Total fields for Lite users! You can now transform your forms into checkout pages. To start collecting revenue, simply connect your preferred payment gateway (Stripe, Square, or PayPal) in your settings.', 'formidable' ); | |
| 4100 | + }//end if | |
| 4101 | + | |
| 4102 | + delete_option( 'frm_show_pricing_fields_modal' ); | |
| 4103 | + } | |
| 4104 | + | |
| 4105 | + /** | |
| 3960 | 4106 | * Get the no label text. |
| 3961 | 4107 | * |
| 3962 | 4108 | * @since 6.25.1 |
| 3963 | 4109 | * |
| @@ -4480,11 +4626,9 @@ | ||
| 4480 | 4626 | * |
| 4481 | 4627 | * @return array |
| 4482 | 4628 | */ |
| 4483 | 4629 | public static function maybe_filter_array( $values, $keys ) { |
| 4484 | - $allow_unfiltered_html = self::allow_unfiltered_html(); | |
| 4485 | - | |
| 4486 | - if ( $allow_unfiltered_html ) { | |
| 4630 | + if ( self::allow_unfiltered_html() ) { | |
| 4487 | 4631 | return $values; |
| 4488 | 4632 | } |
| 4489 | 4633 | |
| 4490 | 4634 | foreach ( $keys as $key ) { |
| @@ -4597,14 +4741,9 @@ | ||
| 4597 | 4741 | * @return bool |
| 4598 | 4742 | */ |
| 4599 | 4743 | public static function show_new_feature( $feature ) { |
| 4600 | 4744 | $link = FrmAddonsController::install_link( $feature ); |
| 4601 | - | |
| 4602 | - if ( array_key_exists( 'status', $link ) || array_key_exists( 'class', $link ) ) { | |
| 4603 | - return true; | |
| 4604 | - } | |
| 4605 | - | |
| 4606 | - return 'coupons' === $feature && class_exists( 'FrmCouponsAppController' ); | |
| 4745 | + return array_key_exists( 'status', $link ) || array_key_exists( 'class', $link ); | |
| 4607 | 4746 | } |
| 4608 | 4747 | |
| 4609 | 4748 | /** |
| 4610 | 4749 | * Enhances upgrade data parameters with installation link and plan requirement information. |
| @@ -4998,13 +5137,18 @@ | ||
| 4998 | 5137 | * Check if a string is valid UTF-8. |
| 4999 | 5138 | * |
| 5000 | 5139 | * @since 6.24 |
| 5001 | 5140 | * |
| 5002 | - * @param string $string The string to check. | |
| 5141 | + * @param string|null $string The string to check. | |
| 5003 | 5142 | * |
| 5004 | 5143 | * @return bool |
| 5005 | 5144 | */ |
| 5006 | 5145 | public static function is_valid_utf8( $string ) { |
| 5146 | + if ( is_null( $string ) ) { | |
| 5147 | + // Return true so we do not attempt to change encoding on a null value. | |
| 5148 | + return true; | |
| 5149 | + } | |
| 5150 | + | |
| 5007 | 5151 | // wp_is_valid_utf8 is added in WP 6.9. |
| 5008 | 5152 | if ( function_exists( 'wp_is_valid_utf8' ) ) { |
| 5009 | 5153 | return wp_is_valid_utf8( $string ); |
| 5010 | 5154 | } |