init_wp_recaptcha(); $this->hooks(); } } ); } private function hooks() { $template = WPF()->current_object['template']; ############################################################################### ############### X.com & Social Share API #################################### ############################################################################### if( is_wpforo_page() ) { if( apply_filters( 'wpforo_api_tw_load_wjs', true ) && wpforo_setting( 'social', 'sb', 'tw' ) ) { add_action( 'wpforo_top_hook', [ $this, 'tw_wjs' ], 11 ); } if( apply_filters( 'wpforo_api_vk_load_js', true ) && wpforo_setting( 'social', 'sb', 'vk' ) ) { add_action( 'wpforo_top_hook', [ $this, 'vk_js' ], 13 ); } } ############################################################################### ############### reCAPTCHA API ################################################# ############################################################################### $site_key = wpforo_setting( 'recaptcha', 'site_key' ); $secret_key = wpforo_setting( 'recaptcha', 'secret_key' ); if( ! is_user_logged_in() && $site_key && $secret_key ) { $wpf_reg_form = wpforo_setting( 'recaptcha', 'wpf_reg_form' ); $wpf_login_form = wpforo_setting( 'recaptcha', 'wpf_login_form' ); $wpf_lostpass_form = wpforo_setting( 'recaptcha', 'wpf_lostpass_form' ); add_filter( 'script_loader_tag', [ &$this, 'rc_enqueue_async' ], 10, 3 ); //Verification Hooks: Login / Register / Reset Pass if( $wpf_login_form ) add_filter( 'wp_authenticate_user', [ $this, 'rc_verify_wp_login' ], 15, 2 ); if( $wpf_reg_form ) add_filter( 'registration_errors', [ $this, 'rc_verify_wp_register' ], 10, 3 ); if( $wpf_lostpass_form ) add_action( 'lostpassword_post', [ $this, 'rc_verify_wp_lostpassword' ], 10 ); //Load reCAPTCHA API on wpForo pages: Login / Register / Reset Pass if( in_array( $template, [ 'login', 'register', 'lostpassword' ], true ) ) { if( $wpf_reg_form || $wpf_login_form || $wpf_lostpass_form ) { add_action( 'wp_enqueue_scripts', [ $this, 'rc_enqueue' ] ); } } //Load reCAPTCHA Widget wpForo forms: Login / Register / Reset Pass if( $wpf_login_form && $template === 'login' ) add_action( 'login_form', [ $this, 'rc_widget' ] ); if( $wpf_reg_form && $template === 'register' ) add_action( 'register_form', [ $this, 'rc_widget' ] ); if( $wpf_lostpass_form && $template === 'lostpassword' ) { add_action( 'lostpassword_form', [ $this, 'rc_widget' ] ); } //Load reCAPTCHA API and Widget for Topic and Post Editor if( in_array( $template, [ 'forum', 'topic', 'post', 'add-topic' ], true ) ) { if( wpforo_setting( 'recaptcha', 'topic_editor' ) || wpforo_setting( 'recaptcha', 'post_editor' ) ) { add_action( 'wp_enqueue_scripts', [ $this, 'rc_enqueue' ] ); add_action( 'wpforo_verify_form_end', [ $this, 'rc_verify' ] ); } if( wpforo_setting( 'recaptcha', 'topic_editor' ) ) { add_action( 'wpforo_topic_form_extra_fields_after', [ $this, 'rc_widget' ] ); } if( wpforo_setting( 'recaptcha', 'post_editor' ) ) { add_action( 'wpforo_reply_form_extra_fields_after', [ $this, 'rc_widget' ] ); add_action( 'wpforo_portable_form_extra_fields_after', [ $this, 'rc_widget' ] ); } } } ############################################################################### } private function init_wp_recaptcha() { $template = WPF()->current_object['template']; $site_key = wpforo_setting( 'recaptcha', 'site_key' ); $secret_key = wpforo_setting( 'recaptcha', 'secret_key' ); if( ! is_user_logged_in() && $site_key && $secret_key ) { $reg_form = wpforo_setting( 'recaptcha', 'reg_form' ); $login_form = wpforo_setting( 'recaptcha', 'login_form' ); $lostpass_form = wpforo_setting( 'recaptcha', 'lostpass_form' ); //Verification Hooks: Login / Register / Reset Pass if( $login_form ) add_filter( 'wp_authenticate_user', [ $this, 'rc_verify_wp_login' ], 15, 2 ); if( $reg_form ) add_filter( 'registration_errors', [ $this, 'rc_verify_wp_register' ], 10, 3 ); if( $lostpass_form ) add_action( 'lostpassword_post', [ $this, 'rc_verify_wp_lostpassword' ], 10 ); //Load reCAPTCHA API and Widget on wp-login.php if( $reg_form || $login_form || $lostpass_form ) { add_action( 'login_enqueue_scripts', [ $this, 'rc_enqueue' ] ); add_action( 'login_enqueue_scripts', [ $this, 'rc_enqueue_css' ] ); if( $login_form && $template !== 'login' ) add_action( 'login_form', [ $this, 'rc_widget' ] ); if( $reg_form && $template !== 'register' ) add_action( 'register_form', [ $this, 'rc_widget' ] ); if( $lostpass_form && $template !== 'lostpassword' ) { add_action( 'lostpassword_form', [ $this, 'rc_widget' ] ); } } } } public function local( $api ) { $wplocal = get_locale(); $wplocal_iso = substr( $wplocal, 0, 2 ); if( $api === 'fb' ) { if( in_array( $wplocal, $this->fb_local ) ) { return $wplocal; } else { return $this->locale; } } elseif( $api === 'tw' ) { if( in_array( $wplocal_iso, $this->tw_local ) ) { return $wplocal_iso; } else { return $this->locale_iso; } } elseif( $api === 'vk' ) { return $wplocal_iso; } elseif( $api === 'ok' ) { if( in_array( $wplocal_iso, $this->ok_local ) ) { return $wplocal_iso; } else { return $this->locale_iso; } } return $wplocal; } public function fb_share_button( $url = '', $type = 'custom', $text = '' ) { if( ! wpforo_setting( 'social', 'sb', 'fb' ) ) return; $url = $url ?: WPF()->current_url; // Facebook deprecated custom parameters (quote, title, etc.) // Content is now pulled from Open Graph meta tags on the shared URL $share_url = 'https://www.facebook.com/sharer/sharer.php?u=' . urlencode( (string) $url ); if( $type === 'custom' ) { ?>
current_url; $n_url = strlen( (string) $url ); $n_text = 280 - $n_url; $text = $text ?: wpfval( WPF()->current_object, 'og_text' ); $text = urlencode( wpforo_text( strip_shortcodes( strip_tags( (string) $text ) ), $n_text, false ) ); if( $type == 'custom' ) { ?>
current_url; $domain = wp_is_mobile() ? 'https://api.whatsapp.com' : 'https://web.whatsapp.com'; $text = $text ?: ( wpfval( WPF()->current_object, 'og_text' ) ? WPF()->current_object['og_text'] : WPF()->board->get_current( 'settings' )['title'] ); $text = urlencode( wpforo_text( strip_shortcodes( strip_tags( (string) $text ) ), 100, false ) ) . ' URL: ' . urlencode( (string) $url ); if( $type === 'custom' ) { ?>
current_url; $title = (string) wpfval( WPF()->current_object, 'topic', 'title' ); $text = $text ?: ( wpfval( WPF()->current_object, 'og_text' ) ? WPF()->current_object['og_text'] : WPF()->board->get_current( 'settings' )['title'] ); $text = urlencode( wpforo_text( strip_shortcodes( strip_tags( (string) $text ) ), 500, false ) ); if( $type == 'custom' ) { ?>
current_url; $text = $text ?: wpfval( WPF()->current_object, 'og_text' ); $text = urlencode( wpforo_text( strip_shortcodes( strip_tags( (string) $text ) ), 500, false ) ); if( $type === 'custom' ) { ?>
api->fb_share_button( $url, $type ); WPF()->api->tw_share_button( $url, $type, $text ); WPF()->api->wapp_share_button( $url, $type, $text ); WPF()->api->lin_share_button( $url, $type, $text ); WPF()->api->vk_share_button( $url, $type, $text ); } public function share_buttons( $url = '', $type = 'default', $text = '' ) { $template = wpfval( WPF()->current_object, 'template' ); $exclude = [ 'lostpassword', 'resetpassword' ]; if( $template && ! in_array( $template, $exclude ) ) { WPF()->api->fb_share_button( $url, $type ); WPF()->api->tw_share_button( $url, $type, $text ); WPF()->api->wapp_share_button( $url, $type, $text ); WPF()->api->lin_share_button( $url, $type, $text ); WPF()->api->vk_share_button( $url, $type, $text ); } } public function rc_enqueue() { $version = wpforo_setting( 'recaptcha', 'version' ); $theme = wpforo_setting( 'recaptcha', 'theme' ); $site_key = wpforo_setting( 'recaptcha', 'site_key' ); // reCAPTCHA v3 uses a different script URL and approach if( $version === 'v3' ) { wp_register_script( 'wpforo_recaptcha', 'https://www.google.com/recaptcha/api.js?render=' . $site_key ); wp_add_inline_script( 'wpforo_recaptcha', "var wpForoReCaptchaV3Execute = function(action){ return new Promise(function(resolve, reject){ if( typeof grecaptcha !== 'undefined' && typeof grecaptcha.execute === 'function' ){ grecaptcha.ready(function(){ grecaptcha.execute('" . esc_js( $site_key ) . "', {action: action}).then(function(token){ resolve(token); }).catch(function(error){ reject(error); }); }); } else { reject('reCAPTCHA not loaded'); } }); }; var wpForoReCaptchaV3Submit = function(form){ var btn = form.querySelector('input[type=\"submit\"], button[type=\"submit\"]'); if( btn && btn.name && !form.querySelector('input[type=\"hidden\"][name=\"' + btn.name + '\"]') ){ var h = document.createElement('input'); h.type = 'hidden'; h.name = btn.name; h.value = btn.value || '1'; form.appendChild(h); } form.submit(); }; var wpForoReCaptchaV3Init = function(){ var forms = document.querySelectorAll('form[data-wpforo-recaptcha-v3]'); forms.forEach(function(form){ form.addEventListener('submit', function(e){ var tokenInput = form.querySelector('input[name=\"g-recaptcha-response\"]'); if( tokenInput && !tokenInput.value ){ e.preventDefault(); var action = form.getAttribute('data-wpforo-recaptcha-action') || 'wpforo_form'; wpForoReCaptchaV3Execute(action).then(function(token){ tokenInput.value = token; wpForoReCaptchaV3Submit(form); }).catch(function(error){ console.error('reCAPTCHA error:', error); wpForoReCaptchaV3Submit(form); }); } }); }); }; if( document.readyState === 'loading' ){ document.addEventListener('DOMContentLoaded', wpForoReCaptchaV3Init); } else { wpForoReCaptchaV3Init(); }" ); } elseif( $version === 'v2_invisible' ) { // reCAPTCHA v2 Invisible wp_register_script( 'wpforo_recaptcha', 'https://www.google.com/recaptcha/api.js?onload=wpForoReCallback&render=explicit' ); wp_add_inline_script( 'wpforo_recaptcha', "var wpForoReWidgetIds = {}; var wpForoReCallback = function(){ setTimeout(function () { if( typeof grecaptcha !== 'undefined' && typeof grecaptcha.render === 'function' ){ var rc_widgets = document.getElementsByClassName('wpforo_recaptcha_widget'); if( rc_widgets.length ){ var i; for (i = 0; i < rc_widgets.length; i++) { if( rc_widgets[i].firstElementChild === null ){ rc_widgets[i].innerHTML = ''; var form = rc_widgets[i].closest('form'); var widgetId = grecaptcha.render( rc_widgets[i], { 'sitekey': '" . esc_js( $site_key ) . "', 'theme': '" . esc_js( $theme ) . "', 'size': 'invisible', 'callback': function(token){ if( form ){ var tokenInput = form.querySelector('input[name=\"g-recaptcha-response\"]'); if( !tokenInput ){ tokenInput = document.createElement('input'); tokenInput.type = 'hidden'; tokenInput.name = 'g-recaptcha-response'; form.appendChild(tokenInput); } tokenInput.value = token; form.submit(); } } } ); if( form ){ wpForoReWidgetIds[form.id || i] = widgetId; form.addEventListener('submit', function(e){ var formId = this.id || Array.prototype.indexOf.call(document.forms, this); if( wpForoReWidgetIds[formId] !== undefined ){ var tokenInput = this.querySelector('input[name=\"g-recaptcha-response\"]'); if( !tokenInput || !tokenInput.value ){ e.preventDefault(); grecaptcha.execute(wpForoReWidgetIds[formId]); } } }); } } } } } }, 800); }" ); } else { // reCAPTCHA v2 Checkbox (default) wp_register_script( 'wpforo_recaptcha', 'https://www.google.com/recaptcha/api.js?onload=wpForoReCallback&render=explicit' ); wp_add_inline_script( 'wpforo_recaptcha', "var wpForoReCallback = function(){ setTimeout(function () { if( typeof grecaptcha !== 'undefined' && typeof grecaptcha.render === 'function' ){ var rc_widgets = document.getElementsByClassName('wpforo_recaptcha_widget'); if( rc_widgets.length ){ var i; for (i = 0; i < rc_widgets.length; i++) { if( rc_widgets[i].firstElementChild === null ){ rc_widgets[i].innerHTML = ''; grecaptcha.render( rc_widgets[i], { 'sitekey': '" . esc_js( $site_key ) . "', 'theme': '" . esc_js( $theme ) . "' } ); } } } } }, 800); }" ); } wp_enqueue_script( 'wpforo_recaptcha' ); } public function rc_enqueue_async( $tag, $handle ) { if( $handle === 'wpforo_recaptcha' ) return str_replace( '