, %2$s - characters limit. */ esc_html__( '%1$s of %2$s max characters.', 'wpforms-lite' ), '{count}', '{limit}' ) ), 'val_limit_words' => wpforms_setting( 'validation-word-limit', sprintf( /* translators: %1$s - words count, %2$s - words limit. */ esc_html__( '%1$s of %2$s max words.', 'wpforms-lite' ), '{count}', '{limit}' ) ), 'val_recaptcha_fail_msg' => wpforms_setting( 'recaptcha-fail-msg', esc_html__( 'Google reCAPTCHA verification failed, please try again later.', 'wpforms-lite' ) ), 'val_turnstile_fail_msg' => wpforms_setting( 'turnstile-fail-msg', esc_html__( 'Cloudflare Turnstile verification failed, please try again later.', 'wpforms-lite' ) ), 'val_inputmask_incomplete' => wpforms_setting( 'validation-inputmask-incomplete', esc_html__( 'Please fill out the field in required format.', 'wpforms-lite' ) ), 'uuid_cookie' => false, 'locale' => wpforms_get_language_code(), /** * Filters the user's country code. * * Leave empty for most cases, it will be auto-detected. * If set it will make country recognition in wpforms.js frontend skipped. * Allows to test Phone Smart field with different countries. * * @since 1.9.0 * * @param string|false $country Country code. */ 'country' => apply_filters( 'wpforms_frontend_get_user_country_code', false ), 'country_list_label' => esc_html__( 'Country list', 'wpforms-lite' ), 'wpforms_plugin_url' => WPFORMS_PLUGIN_URL, 'gdpr' => wpforms_setting( 'gdpr' ), 'ajaxurl' => admin_url( 'admin-ajax.php' ), /** * Filters mail check enabled flag. * * @since 1.5.4.2 * * @param bool $flag Enabled flag. */ 'mailcheck_enabled' => (bool) apply_filters( 'wpforms_mailcheck_enabled', true ), // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName /** * Filters mail check domains. * * @since 1.5.4.2 * * @param array $domains Domains to check. */ 'mailcheck_domains' => array_map( 'sanitize_text_field', (array) apply_filters( 'wpforms_mailcheck_domains', [] ) ), // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName /** * Filters toplevel domains for mail check. * * @since 1.5.4.2 * * @param array $toplevel_domains Toplevel domains to check. */ 'mailcheck_toplevel_domains' => array_map( 'sanitize_text_field', (array) apply_filters( 'wpforms_mailcheck_toplevel_domains', [ 'dev' ] ) ), // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName 'is_ssl' => is_ssl(), ]; // Include payment related strings if needed. $strings = $this->get_payment_strings( $strings ); // Include CSS variables list. $strings = $this->get_css_vars_strings( $strings ); /** * Filters frontend strings. * * @since 1.3.7.3 * * @param array $strings Frontend strings. */ $strings = (array) apply_filters( 'wpforms_frontend_strings', $strings ); foreach ( $strings as $key => $value ) { if ( ! is_scalar( $value ) ) { continue; } $strings[ $key ] = esc_html( html_entity_decode( (string) $value, ENT_QUOTES, 'UTF-8' ) ); } return $strings; } /** * Get payment strings. * * @since 1.8.1 * * @param array $strings Strings. * * @return array */ private function get_payment_strings( array $strings ): array { if ( function_exists( 'wpforms_get_currencies' ) ) { $currency = wpforms_get_currency(); $currencies = wpforms_get_currencies(); $strings['currency_code'] = $currency; $strings['currency_thousands'] = $currencies[ $currency ]['thousands_separator'] ?? ','; $strings['currency_decimals'] = wpforms_get_currency_decimals( $currencies[ $currency ] ); $strings['currency_decimal'] = $currencies[ $currency ]['decimal_separator'] ?? '.'; $strings['currency_symbol'] = $currencies[ $currency ]['symbol'] ?? '$'; $strings['currency_symbol_pos'] = $currencies[ $currency ]['symbol_pos'] ?? 'left'; } $strings['val_requiredpayment'] = wpforms_setting( 'validation-requiredpayment', esc_html__( 'Payment is required.', 'wpforms-lite' ) ); $strings['val_creditcard'] = wpforms_setting( 'validation-creditcard', esc_html__( 'Please enter a valid credit card number.', 'wpforms-lite' ) ); return $strings; } /** * Get CSS variables data. * * @since 1.8.1 * * @param array $strings Strings. * * @return array */ private function get_css_vars_strings( array $strings ): array { if ( wpforms_get_render_engine() !== 'modern' ) { return $strings; } $css_vars_obj = wpforms()->obj( 'css_vars' ); if ( empty( $css_vars_obj ) ) { return $strings; } $strings['css_vars'] = array_keys( $css_vars_obj->get_vars( ':root' ) ); return $strings; } /** * Hook at fires at a later priority in wp_footer. * * @since 1.0.5 * @since 1.7.0 Load wpforms_settings on the confirmation page for a non-ajax form. */ public function footer_end() { if ( ( empty( $this->forms ) && empty( $_POST['wpforms'] ) && ! $this->assets_global() ) || // phpcs:ignore WordPress.Security.NonceVerification.Missing $this->amp_obj->is_amp() ) { return; } $strings = $this->get_strings(); /* * Below we do our own implementation of wp_localize_script in an effort * to be better compatible with caching plugins which were causing * conflicts. */ echo "\n"; /** * Fires after the end of the footer. * * @since 1.0.6 * * @param array $forms Forms being shown. */ do_action( 'wpforms_wp_footer_end', $this->forms ); // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName } /** * Shortcode wrapper for the outputting a form. * * @since 1.0.0 * * @param array|mixed $atts Shortcode attributes provided by a user. * * @return string */ public function shortcode( $atts ): string { $atts = (array) $atts; $defaults = [ 'id' => false, 'title' => false, 'description' => false, ]; $atts = shortcode_atts( $defaults, shortcode_atts( $defaults, $atts, 'output' ), 'wpforms' ); ob_start(); $this->output( $atts['id'], $atts['title'], $atts['description'] ); return (string) ob_get_clean(); } /** * Inline a script to check if our main js is loaded and display a warning message otherwise. * * @since 1.6.4.1 */ public function missing_assets_error_js() { /** * Disable missing assets error js checking. * * @since 1.6.6 * * @param bool $skip False by default, set to True to disable checking. */ $skip = (bool) apply_filters( 'wpforms_frontend_missing_assets_error_js_disable', false ); if ( $skip || ! wpforms_current_user_can() ) { return; } if ( empty( $this->forms ) && ! $this->assets_global() ) { return; } if ( $this->amp_obj->is_amp() ) { return; } // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped printf( $this->get_missing_assets_error_script(), $this->get_missing_assets_error_message() ); } /** * Get missing assets error script. * * @since 1.6.4.1 * * @return string */ private function get_missing_assets_error_script(): string { return ""; } /** * Get a missing assets error message. * * @since 1.6.4.1 * * @return string * @noinspection HtmlUnknownTarget */ private function get_missing_assets_error_message(): string { $message = sprintf( wp_kses( /* translators: %s - URL to the troubleshooting guide. */ __( 'Heads up! WPForms has detected an issue with JavaScript on this page. JavaScript is required for this form to work properly, so this form may not work as expected. See our troubleshooting guide to learn more or contact support.', 'wpforms-lite' ), [ 'a' => [ 'href' => [], 'target' => [], 'rel' => [], ], ] ), 'https://wpforms.com/docs/getting-support-wpforms/' ); $message .= '

'; $message .= esc_html__( 'This message is only displayed to site administrators.', 'wpforms-lite' ); $message .= '

'; return $message; } /** * Render the single field. * * @since 1.7.7 * * @param array $form_data Form data. * @param array $field Field data. */ public function render_field( $form_data, $field ) { if ( ! has_action( "wpforms_display_field_{$field['type']}" ) ) { return; } /** * Modify Field before render. * * @since 1.4.0 * * @param array $field Current field. * @param array $form_data Form data and settings. */ $field = (array) apply_filters( 'wpforms_field_data', $field, $form_data ); // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName if ( empty( $field ) ) { return; } // Get field attributes. Deprecated; Customizations should use // field properties instead. $attributes = $this->get_field_attributes( $field, $form_data ); // Add properties to the field, so it's available everywhere. $field['properties'] = $this->get_field_properties( $field, $form_data, $attributes ); /** * Core actions on this hook: * Priority / Description * 5 Field opening container markup. * 15 Field label. * 20 Field description (depending on position). * * @since 1.3.7 * * @param array $field Field. * @param array $form_data Form data. */ do_action( 'wpforms_display_field_before', $field, $form_data ); // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName /** * Individual field classes use this hook to display the actual * field form elements. * See `field_display` methods in /includes/fields. * * @since 1.3.7 * * @param array $field Field. * @param array $attributes Field attributes. * @param array $form_data Form data. */ do_action( "wpforms_display_field_{$field['type']}", $field, $attributes, $form_data ); // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName /** * Core actions on this hook: * Priority / Description * 3 Field error messages. * 5 Field description (depending on position). * 15 Field closing container markup. * 20 Pagebreak markups (close previous page, open next). * * @since 1.3.7 * * @param array $field Field. * @param array $form_data Form data. */ do_action( 'wpforms_display_field_after', $field, $form_data ); // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName } /** * Whether to print the script in the footer. * * @since 1.9.0 * * @return bool */ protected function load_script_in_footer(): bool { return ! wpforms_is_frontend_js_header_force_load(); } }