| 1 |
<?php |
| 2 |
|
| 3 |
namespace wpforo\classes; |
| 4 |
|
| 5 |
use WP_Error; |
| 6 |
|
| 7 |
// Exit if accessed directly |
| 8 |
if( ! defined( 'ABSPATH' ) ) exit; |
| 9 |
|
| 10 |
class API { |
| 11 |
public $locale = 'en_US'; |
| 12 |
public $locale_iso = 'en'; |
| 13 |
public $fb_local = [ |
| 14 |
'af_ZA', |
| 15 |
'ar_AR', |
| 16 |
'az_AZ', |
| 17 |
'be_BY', |
| 18 |
'bg_BG', |
| 19 |
'bn_IN', |
| 20 |
'bs_BA', |
| 21 |
'ca_ES', |
| 22 |
'cs_CZ', |
| 23 |
'cy_GB', |
| 24 |
'da_DK', |
| 25 |
'de_DE', |
| 26 |
'el_GR', |
| 27 |
'en_US', |
| 28 |
'en_GB', |
| 29 |
'eo_EO', |
| 30 |
'es_ES', |
| 31 |
'es_LA', |
| 32 |
'et_EE', |
| 33 |
'eu_ES', |
| 34 |
'fa_IR', |
| 35 |
'fb_LT', |
| 36 |
'fi_FI', |
| 37 |
'fo_FO', |
| 38 |
'fr_FR', |
| 39 |
'fr_CA', |
| 40 |
'fy_NL', |
| 41 |
'ga_IE', |
| 42 |
'gl_ES', |
| 43 |
'he_IL', |
| 44 |
'hi_IN', |
| 45 |
'hr_HR', |
| 46 |
'hu_HU', |
| 47 |
'hy_AM', |
| 48 |
'id_ID', |
| 49 |
'is_IS', |
| 50 |
'it_IT', |
| 51 |
'ja_JP', |
| 52 |
'ka_GE', |
| 53 |
'km_KH', |
| 54 |
'ko_KR', |
| 55 |
'ku_TR', |
| 56 |
'la_VA', |
| 57 |
'lt_LT', |
| 58 |
'lv_LV', |
| 59 |
'mk_MK', |
| 60 |
'ml_IN', |
| 61 |
'ms_MY', |
| 62 |
'nb_NO', |
| 63 |
'ne_NP', |
| 64 |
'nl_NL', |
| 65 |
'nn_NO', |
| 66 |
'pa_IN', |
| 67 |
'pl_PL', |
| 68 |
'ps_AF', |
| 69 |
'pt_PT', |
| 70 |
'pt_BR', |
| 71 |
'ro_RO', |
| 72 |
'ru_RU', |
| 73 |
'sk_SK', |
| 74 |
'sl_SI', |
| 75 |
'sq_AL', |
| 76 |
'sr_RS', |
| 77 |
'sv_SE', |
| 78 |
'sw_KE', |
| 79 |
'ta_IN', |
| 80 |
'te_IN', |
| 81 |
'th_TH', |
| 82 |
'tl_PH', |
| 83 |
'tr_TR', |
| 84 |
'uk_UA', |
| 85 |
'vi_VN', |
| 86 |
'zh_CN', |
| 87 |
'zh_HK', |
| 88 |
'zh_TW', |
| 89 |
]; |
| 90 |
public $tw_local = [ |
| 91 |
'en', |
| 92 |
'ar', |
| 93 |
'bn', |
| 94 |
'cs', |
| 95 |
'da', |
| 96 |
'de', |
| 97 |
'el', |
| 98 |
'es', |
| 99 |
'fa', |
| 100 |
'fi', |
| 101 |
'fil', |
| 102 |
'fr', |
| 103 |
'he', |
| 104 |
'hi', |
| 105 |
'hu', |
| 106 |
'id', |
| 107 |
'it', |
| 108 |
'ja', |
| 109 |
'ko', |
| 110 |
'msa', |
| 111 |
'nl', |
| 112 |
'no', |
| 113 |
'pl', |
| 114 |
'pt', |
| 115 |
'ro', |
| 116 |
'ru', |
| 117 |
'sv', |
| 118 |
'th', |
| 119 |
'tr', |
| 120 |
'uk', |
| 121 |
'ur', |
| 122 |
'vi', |
| 123 |
'zh-cn', |
| 124 |
'zh-tw', |
| 125 |
]; |
| 126 |
public $ok_local = [ "ru", "en", "uk", "hy", "mo", "ro", "kk", "uz", "az", "tr" ]; |
| 127 |
|
| 128 |
public function __construct() { |
| 129 |
add_action( 'wpforo_after_init', function() { |
| 130 |
if( ! wpforo_is_admin() ) { |
| 131 |
$this->init_wp_recaptcha(); |
| 132 |
$this->hooks(); |
| 133 |
} |
| 134 |
} ); |
| 135 |
} |
| 136 |
|
| 137 |
private function hooks() { |
| 138 |
$template = WPF()->current_object['template']; |
| 139 |
|
| 140 |
############################################################################### |
| 141 |
############### X.com & Social Share API #################################### |
| 142 |
############################################################################### |
| 143 |
|
| 144 |
if( is_wpforo_page() ) { |
| 145 |
if( apply_filters( 'wpforo_api_tw_load_wjs', true ) && wpforo_setting( 'social', 'sb', 'tw' ) ) { |
| 146 |
add_action( 'wpforo_top_hook', [ $this, 'tw_wjs' ], 11 ); |
| 147 |
} |
| 148 |
if( apply_filters( 'wpforo_api_vk_load_js', true ) && wpforo_setting( 'social', 'sb', 'vk' ) ) { |
| 149 |
add_action( 'wpforo_top_hook', [ $this, 'vk_js' ], 13 ); |
| 150 |
} |
| 151 |
} |
| 152 |
|
| 153 |
############################################################################### |
| 154 |
############### reCAPTCHA API ################################################# |
| 155 |
############################################################################### |
| 156 |
|
| 157 |
$site_key = wpforo_setting( 'recaptcha', 'site_key' ); |
| 158 |
$secret_key = wpforo_setting( 'recaptcha', 'secret_key' ); |
| 159 |
|
| 160 |
if( ! is_user_logged_in() && $site_key && $secret_key ) { |
| 161 |
|
| 162 |
$wpf_reg_form = wpforo_setting( 'recaptcha', 'wpf_reg_form' ); |
| 163 |
$wpf_login_form = wpforo_setting( 'recaptcha', 'wpf_login_form' ); |
| 164 |
$wpf_lostpass_form = wpforo_setting( 'recaptcha', 'wpf_lostpass_form' ); |
| 165 |
|
| 166 |
add_filter( 'script_loader_tag', [ &$this, 'rc_enqueue_async' ], 10, 3 ); |
| 167 |
|
| 168 |
//Verification Hooks: Login / Register / Reset Pass |
| 169 |
if( $wpf_login_form ) add_filter( 'wp_authenticate_user', [ $this, 'rc_verify_wp_login' ], 15, 2 ); |
| 170 |
if( $wpf_reg_form ) add_filter( 'registration_errors', [ $this, 'rc_verify_wp_register' ], 10, 3 ); |
| 171 |
if( $wpf_lostpass_form ) add_action( 'lostpassword_post', [ $this, 'rc_verify_wp_lostpassword' ], 10 ); |
| 172 |
|
| 173 |
//Load reCAPTCHA API on wpForo pages: Login / Register / Reset Pass |
| 174 |
if( in_array( $template, [ 'login', 'register', 'lostpassword' ], true ) ) { |
| 175 |
if( $wpf_reg_form || $wpf_login_form || $wpf_lostpass_form ) { |
| 176 |
add_action( 'wp_enqueue_scripts', [ $this, 'rc_enqueue' ] ); |
| 177 |
} |
| 178 |
} |
| 179 |
|
| 180 |
//Load reCAPTCHA Widget wpForo forms: Login / Register / Reset Pass |
| 181 |
if( $wpf_login_form && $template === 'login' ) add_action( 'login_form', [ $this, 'rc_widget' ] ); |
| 182 |
if( $wpf_reg_form && $template === 'register' ) add_action( 'register_form', [ $this, 'rc_widget' ] ); |
| 183 |
if( $wpf_lostpass_form && $template === 'lostpassword' ) { |
| 184 |
add_action( 'lostpassword_form', [ $this, 'rc_widget' ] ); |
| 185 |
} |
| 186 |
|
| 187 |
//Load reCAPTCHA API and Widget for Topic and Post Editor |
| 188 |
if( in_array( $template, [ 'forum', 'topic', 'post', 'add-topic' ], true ) ) { |
| 189 |
if( wpforo_setting( 'recaptcha', 'topic_editor' ) || wpforo_setting( 'recaptcha', 'post_editor' ) ) { |
| 190 |
add_action( 'wp_enqueue_scripts', [ $this, 'rc_enqueue' ] ); |
| 191 |
add_action( 'wpforo_verify_form_end', [ $this, 'rc_verify' ] ); |
| 192 |
} |
| 193 |
if( wpforo_setting( 'recaptcha', 'topic_editor' ) ) { |
| 194 |
add_action( 'wpforo_topic_form_extra_fields_after', [ $this, 'rc_widget' ] ); |
| 195 |
} |
| 196 |
if( wpforo_setting( 'recaptcha', 'post_editor' ) ) { |
| 197 |
add_action( 'wpforo_reply_form_extra_fields_after', [ $this, 'rc_widget' ] ); |
| 198 |
add_action( 'wpforo_portable_form_extra_fields_after', [ $this, 'rc_widget' ] ); |
| 199 |
} |
| 200 |
} |
| 201 |
} |
| 202 |
|
| 203 |
############################################################################### |
| 204 |
} |
| 205 |
|
| 206 |
private function init_wp_recaptcha() { |
| 207 |
$template = WPF()->current_object['template']; |
| 208 |
$site_key = wpforo_setting( 'recaptcha', 'site_key' ); |
| 209 |
$secret_key = wpforo_setting( 'recaptcha', 'secret_key' ); |
| 210 |
|
| 211 |
if( ! is_user_logged_in() && $site_key && $secret_key ) { |
| 212 |
$reg_form = wpforo_setting( 'recaptcha', 'reg_form' ); |
| 213 |
$login_form = wpforo_setting( 'recaptcha', 'login_form' ); |
| 214 |
$lostpass_form = wpforo_setting( 'recaptcha', 'lostpass_form' ); |
| 215 |
|
| 216 |
//Verification Hooks: Login / Register / Reset Pass |
| 217 |
if( $login_form ) add_filter( 'wp_authenticate_user', [ $this, 'rc_verify_wp_login' ], 15, 2 ); |
| 218 |
if( $reg_form ) add_filter( 'registration_errors', [ $this, 'rc_verify_wp_register' ], 10, 3 ); |
| 219 |
if( $lostpass_form ) add_action( 'lostpassword_post', [ $this, 'rc_verify_wp_lostpassword' ], 10 ); |
| 220 |
|
| 221 |
//Load reCAPTCHA API and Widget on wp-login.php |
| 222 |
if( $reg_form || $login_form || $lostpass_form ) { |
| 223 |
add_action( 'login_enqueue_scripts', [ $this, 'rc_enqueue' ] ); |
| 224 |
add_action( 'login_enqueue_scripts', [ $this, 'rc_enqueue_css' ] ); |
| 225 |
if( $login_form && $template !== 'login' ) add_action( 'login_form', [ $this, 'rc_widget' ] ); |
| 226 |
if( $reg_form && $template !== 'register' ) add_action( 'register_form', [ $this, 'rc_widget' ] ); |
| 227 |
if( $lostpass_form && $template !== 'lostpassword' ) { |
| 228 |
add_action( 'lostpassword_form', [ $this, 'rc_widget' ] ); |
| 229 |
} |
| 230 |
} |
| 231 |
} |
| 232 |
} |
| 233 |
|
| 234 |
public function local( $api ) { |
| 235 |
$wplocal = get_locale(); |
| 236 |
$wplocal_iso = substr( $wplocal, 0, 2 ); |
| 237 |
|
| 238 |
if( $api === 'fb' ) { |
| 239 |
if( in_array( $wplocal, $this->fb_local ) ) { |
| 240 |
return $wplocal; |
| 241 |
} else { |
| 242 |
return $this->locale; |
| 243 |
} |
| 244 |
} elseif( $api === 'tw' ) { |
| 245 |
if( in_array( $wplocal_iso, $this->tw_local ) ) { |
| 246 |
return $wplocal_iso; |
| 247 |
} else { |
| 248 |
return $this->locale_iso; |
| 249 |
} |
| 250 |
} elseif( $api === 'vk' ) { |
| 251 |
return $wplocal_iso; |
| 252 |
} elseif( $api === 'ok' ) { |
| 253 |
if( in_array( $wplocal_iso, $this->ok_local ) ) { |
| 254 |
return $wplocal_iso; |
| 255 |
} else { |
| 256 |
return $this->locale_iso; |
| 257 |
} |
| 258 |
} |
| 259 |
|
| 260 |
return $wplocal; |
| 261 |
} |
| 262 |
|
| 263 |
|
| 264 |
public function fb_share_button( $url = '', $type = 'custom', $text = '' ) { |
| 265 |
if( ! wpforo_setting( 'social', 'sb', 'fb' ) ) return; |
| 266 |
$url = $url ?: WPF()->current_url; |
| 267 |
// Facebook deprecated custom parameters (quote, title, etc.) |
| 268 |
// Content is now pulled from Open Graph meta tags on the shared URL |
| 269 |
$share_url = 'https://www.facebook.com/sharer/sharer.php?u=' . urlencode( (string) $url ); |
| 270 |
if( $type === 'custom' ) { ?> |
| 271 |
<span class="wpforo-share-button wpf-fb" data-wpfurl="<?php echo esc_attr( $url ) ?>" |
| 272 |
title="<?php wpforo_phrase( 'Share to Facebook' ); ?>"> |
| 273 |
<?php if( wpforo_setting( 'social', 'sb_icon' ) === 'figure' ): ?> |
| 274 |
<i class="fab fa-facebook-f" aria-hidden="true"></i> |
| 275 |
<?php elseif( wpforo_setting( 'social', 'sb_icon' ) === 'square' ): ?> |
| 276 |
<i class="fab fa-facebook-square" aria-hidden="true"></i> |
| 277 |
<?php else: ?> |
| 278 |
<i class="fab fa-facebook" aria-hidden="true"></i> |
| 279 |
<?php endif; ?> |
| 280 |
</span> |
| 281 |
<?php |
| 282 |
} else { |
| 283 |
?> |
| 284 |
<div class="wpf-sbw wpf-sbw-fb"> |
| 285 |
<?php if( wpforo_setting( 'social', 'sb_type' ) === 'button_count' ): ?> |
| 286 |
<a target="_blank" href="<?php echo esc_url( $share_url ) ?>" |
| 287 |
rel="nofollow"><?php wpforo_phrase( 'Share' ); ?></a> |
| 288 |
<?php elseif( wpforo_setting( 'social', 'sb_type' ) === 'button' ): ?> |
| 289 |
<a class="wpf-sb-button wpf-fb" href="<?php echo esc_url( $share_url ) ?>" target="_blank" rel="nofollow"> |
| 290 |
<i class="fab fa-facebook-f" aria-hidden="true"></i> <span><?php wpforo_phrase( 'Share' ) ?></span> |
| 291 |
</a> |
| 292 |
<?php else: ?> |
| 293 |
<a class="wpf-sb-button wpf-sb-icon wpf-fb" href="<?php echo esc_url( $share_url ) ?>" target="_blank" rel="nofollow"> |
| 294 |
<i class="fab fa-facebook-f" aria-hidden="true"></i> |
| 295 |
</a> |
| 296 |
<?php endif; ?> |
| 297 |
</div> |
| 298 |
<?php |
| 299 |
} |
| 300 |
} |
| 301 |
|
| 302 |
public function tw_wjs() { |
| 303 |
?> |
| 304 |
<script type="text/javascript">window.twttr = (function (d, s, id) { |
| 305 |
var js, fjs = d.getElementsByTagName(s)[0], t = window.twttr || {}; |
| 306 |
if (d.getElementById(id)) return t; |
| 307 |
js = d.createElement(s); |
| 308 |
js.id = id; |
| 309 |
js.src = 'https://platform.twitter.com/widgets.js'; |
| 310 |
fjs.parentNode.insertBefore(js, fjs); |
| 311 |
t._e = []; |
| 312 |
t.ready = function (f) { t._e.push(f); }; |
| 313 |
return t; |
| 314 |
}(document, 'script', 'twitter-wjs'));</script> |
| 315 |
<?php |
| 316 |
} |
| 317 |
|
| 318 |
public function tw_share_button( $url = '', $type = 'custom', $text = '' ) { |
| 319 |
if( ! wpforo_setting( 'social', 'sb', 'tw' ) ) return; |
| 320 |
$url = $url ?: WPF()->current_url; |
| 321 |
$n_url = strlen( (string) $url ); |
| 322 |
$n_text = 280 - $n_url; |
| 323 |
$text = $text ?: wpfval( WPF()->current_object, 'og_text' ); |
| 324 |
$text = urlencode( wpforo_text( strip_shortcodes( strip_tags( (string) $text ) ), $n_text, false ) ); |
| 325 |
if( $type == 'custom' ) { ?> |
| 326 |
<a class="wpforo-share-button wpf-tw" |
| 327 |
href="https://twitter.com/intent/tweet?text=<?php echo $text ?>&url=<?php echo urlencode( (string) $url ) ?>" |
| 328 |
title="<?php wpforo_phrase( 'Tweet this post' ); ?>" rel="nofollow"> |
| 329 |
<?php if( wpforo_setting( 'social', 'sb_icon' ) === 'figure' ): ?> |
| 330 |
<i class="fa-brands fa-x-twitter" aria-hidden="true"></i> |
| 331 |
<?php elseif( wpforo_setting( 'social', 'sb_icon' ) === 'square' ): ?> |
| 332 |
<i class="fa-brands fa-x-twitter-square" aria-hidden="true"></i> |
| 333 |
<?php else: ?> |
| 334 |
<i class="fa-brands fa-x-twitter" aria-hidden="true"></i> |
| 335 |
<?php endif; ?> |
| 336 |
</a> |
| 337 |
<?php |
| 338 |
} else { ?> |
| 339 |
<div class="wpf-sbw wpf-sbw-tw"> |
| 340 |
<?php if( wpforo_setting( 'social', 'sb_type' ) === 'button_count' ): ?> |
| 341 |
<a href="https://twitter.com/share?ref_src=twsrc%5Etfw" class="twitter-share-button" |
| 342 |
data-lang="<?php $this->local( 'tw' ) ?>" data-show-count="true" rel="nofollow"><?php wpforo_phrase( |
| 343 |
'Tweet' |
| 344 |
); ?></a> |
| 345 |
<?php elseif( wpforo_setting( 'social', 'sb_type' ) === 'button' ): ?> |
| 346 |
<a class="wpf-sb-button wpf-tw" |
| 347 |
href="https://twitter.com/intent/tweet?text=<?php echo $text ?>&url=<?php echo urlencode( |
| 348 |
(string) $url |
| 349 |
) ?>" rel="nofollow"> |
| 350 |
<i class="fa-brands fa-x-twitter" aria-hidden="true"></i> <span><?php wpforo_phrase( |
| 351 |
'Tweet' |
| 352 |
) ?></span> |
| 353 |
</a> |
| 354 |
<?php else: ?> |
| 355 |
<a class="wpf-sb-button wpf-sb-icon wpf-tw" |
| 356 |
href="https://twitter.com/intent/tweet?text=<?php echo $text ?>&url=<?php echo urlencode( |
| 357 |
(string) $url |
| 358 |
) ?>" rel="nofollow"> |
| 359 |
<i class="fa-brands fa-x-twitter" aria-hidden="true"></i> |
| 360 |
</a> |
| 361 |
<?php endif; ?> |
| 362 |
</div> |
| 363 |
<?php |
| 364 |
} |
| 365 |
} |
| 366 |
|
| 367 |
public function vk_js() { |
| 368 |
?> |
| 369 |
<script type="text/javascript" src="https://vk.com/js/api/share.js?95" charset="windows-1251"></script> |
| 370 |
<?php |
| 371 |
} |
| 372 |
|
| 373 |
public function wapp_share_button( $url = '', $type = 'custom', $text = '' ) { |
| 374 |
if( ! wpforo_setting( 'social', 'sb', 'wapp' ) ) return; |
| 375 |
$url = $url ?: WPF()->current_url; |
| 376 |
$domain = wp_is_mobile() ? 'https://api.whatsapp.com' : 'https://web.whatsapp.com'; |
| 377 |
$text = $text ?: ( wpfval( WPF()->current_object, 'og_text' ) ? WPF()->current_object['og_text'] : WPF()->board->get_current( 'settings' )['title'] ); |
| 378 |
$text = urlencode( wpforo_text( strip_shortcodes( strip_tags( (string) $text ) ), 100, false ) ) . ' URL: ' . urlencode( (string) $url ); |
| 379 |
if( $type === 'custom' ) { ?> |
| 380 |
<a class="wpforo-share-button wpf-wapp" href="<?php echo $domain ?>/send?text=<?php echo $text ?>" |
| 381 |
title="<?php wpforo_phrase( 'Share to WhatsApp' ); ?>" target="_blank" |
| 382 |
data-action="share/whatsapp/share" rel="nofollow"> |
| 383 |
<i class="fab fa-whatsapp" aria-hidden="true"></i> |
| 384 |
</a> |
| 385 |
<?php |
| 386 |
} else { ?> |
| 387 |
<div class="wpf-sbw wpf-sbw-wapp"> |
| 388 |
<?php if( wpforo_setting( 'social', 'sb_type' ) === 'button_count' ): ?> |
| 389 |
<!-- WhatsApp is not available --> |
| 390 |
<?php elseif( wpforo_setting( 'social', 'sb_type' ) === 'button' ): ?> |
| 391 |
<a class="wpf-sb-button wpf-wapp" href="<?php echo $domain ?>/send?text=<?php echo $text ?>" |
| 392 |
target="_blank" data-action="share/whatsapp/share" rel="nofollow"> |
| 393 |
<i class="fab fa-whatsapp" aria-hidden="true"></i> <span><?php wpforo_phrase( 'Share' ) ?></span> |
| 394 |
</a> |
| 395 |
<?php else: ?> |
| 396 |
<a class="wpf-sb-button wpf-sb-icon wpf-wapp" |
| 397 |
href="<?php echo $domain ?>/send?text=<?php echo $text ?>" target="_blank" |
| 398 |
data-action="share/whatsapp/share" rel="nofollow"> |
| 399 |
<i class="fab fa-whatsapp" aria-hidden="true"></i> |
| 400 |
</a> |
| 401 |
<?php endif; ?> |
| 402 |
</div> |
| 403 |
<?php |
| 404 |
} |
| 405 |
} |
| 406 |
|
| 407 |
public function lin_share_button( $url = '', $type = 'custom', $text = '' ) { |
| 408 |
if( ! wpforo_setting( 'social', 'sb', 'lin' ) ) return; |
| 409 |
$url = $url ?: WPF()->current_url; |
| 410 |
$title = (string) wpfval( WPF()->current_object, 'topic', 'title' ); |
| 411 |
$text = $text ?: ( wpfval( WPF()->current_object, 'og_text' ) ? WPF()->current_object['og_text'] : WPF()->board->get_current( |
| 412 |
'settings' |
| 413 |
)['title'] ); |
| 414 |
$text = urlencode( wpforo_text( strip_shortcodes( strip_tags( (string) $text ) ), 500, false ) ); |
| 415 |
if( $type == 'custom' ) { ?> |
| 416 |
<a class="wpforo-share-button wpf-lin" |
| 417 |
href="https://www.linkedin.com/shareArticle?mini=true&url=<?php echo urlencode( |
| 418 |
(string) $url |
| 419 |
) ?>&title=<?php echo urlencode( $title ) ?>&summary=<?php echo $text ?>" |
| 420 |
title="<?php wpforo_phrase( 'Share to LinkedIn' ); ?>" target="_blank" rel="nofollow"> |
| 421 |
<i class="fab fa-linkedin-in" aria-hidden="true"></i> |
| 422 |
</a> |
| 423 |
<?php |
| 424 |
} else { ?> |
| 425 |
<div class="wpf-sbw wpf-sbw-lin"> |
| 426 |
<?php if( wpforo_setting( 'social', 'sb_type' ) === 'button_count' ): ?> |
| 427 |
<!-- LinkedIn is not available --> |
| 428 |
<?php elseif( wpforo_setting( 'social', 'sb_type' ) === 'button' ): ?> |
| 429 |
<a class="wpf-sb-button wpf-lin" |
| 430 |
href="https://www.linkedin.com/shareArticle?mini=true&url=<?php echo urlencode( |
| 431 |
(string) $url |
| 432 |
) ?>&title=<?php echo urlencode( $title ) ?>&summary=<?php echo $text ?>" target="_blank" rel="nofollow"> |
| 433 |
<i class="fab fa-linkedin-in" aria-hidden="true"></i> <span><?php wpforo_phrase( |
| 434 |
'Share' |
| 435 |
) ?></span> |
| 436 |
</a> |
| 437 |
<?php else: ?> |
| 438 |
<a class="wpf-sb-button wpf-sb-icon wpf-lin" |
| 439 |
href="https://www.linkedin.com/shareArticle?mini=true&url=<?php echo urlencode( |
| 440 |
(string) $url |
| 441 |
) ?>&title=<?php echo urlencode( $title ) ?>&summary=<?php echo $text ?>" target="_blank" rel="nofollow"> |
| 442 |
<i class="fab fa-linkedin-in" aria-hidden="true"></i> |
| 443 |
</a> |
| 444 |
<?php endif; ?> |
| 445 |
</div> |
| 446 |
<?php |
| 447 |
} |
| 448 |
} |
| 449 |
|
| 450 |
public function vk_share_button( $url = '', $type = 'custom', $text = '' ) { |
| 451 |
if( ! wpforo_setting( 'social', 'sb', 'vk' ) ) return; |
| 452 |
$url = $url ?: WPF()->current_url; |
| 453 |
$text = $text ?: wpfval( WPF()->current_object, 'og_text' ); |
| 454 |
$text = urlencode( wpforo_text( strip_shortcodes( strip_tags( (string) $text ) ), 500, false ) ); |
| 455 |
if( $type === 'custom' ) { ?> |
| 456 |
<a class="wpforo-share-button wpf-vk" onclick="return VK.Share.click(0, this);" |
| 457 |
href="https://vk.com/share.php?url=<?php echo urlencode( (string) $url ) ?>&description=<?php echo $text ?>" |
| 458 |
title="<?php wpforo_phrase( 'Share to VK' ); ?>" target="_blank" rel="nofollow"> |
| 459 |
<i class="fab fa-vk" aria-hidden="true"></i> |
| 460 |
</a> |
| 461 |
<?php |
| 462 |
} else { ?> |
| 463 |
<div class="wpf-sbw wpf-sbw-vk"> |
| 464 |
<?php if( wpforo_setting( 'social', 'sb_type' ) === 'button_count' ): ?> |
| 465 |
<script type="text/javascript">document.write(VK.Share.button(false, { |
| 466 |
type: 'round', |
| 467 |
text: "<?php wpforo_phrase( 'Share' ); ?>", |
| 468 |
}));</script> |
| 469 |
<?php elseif( wpforo_setting( 'social', 'sb_type' ) === 'button' ): ?> |
| 470 |
<a class="wpf-sb-button wpf-vk" onclick="return VK.Share.click(0, this);" |
| 471 |
href="https://vk.com/share.php?url=<?php echo urlencode( |
| 472 |
(string) $url |
| 473 |
) ?>&description=<?php echo $text ?>" target="_blank" rel="nofollow"> |
| 474 |
<i class="fab fa-vk" aria-hidden="true"></i> <span><?php wpforo_phrase( 'Share' ) ?></span> |
| 475 |
</a> |
| 476 |
<?php else: ?> |
| 477 |
<a class="wpf-sb-button wpf-sb-icon wpf-vk" onclick="return VK.Share.click(0, this);" |
| 478 |
href="https://vk.com/share.php?url=<?php echo urlencode( |
| 479 |
(string) $url |
| 480 |
) ?>&description=<?php echo $text ?>" target="_blank" rel="nofollow"> |
| 481 |
<i class="fab fa-vk" aria-hidden="true"></i> |
| 482 |
</a> |
| 483 |
<?php endif; ?> |
| 484 |
</div> |
| 485 |
<?php |
| 486 |
} |
| 487 |
} |
| 488 |
|
| 489 |
|
| 490 |
public function share_toggle( $url = '', $text = '', $type = 'custom' ) { |
| 491 |
WPF()->api->fb_share_button( $url, $type ); |
| 492 |
WPF()->api->tw_share_button( $url, $type, $text ); |
| 493 |
WPF()->api->wapp_share_button( $url, $type, $text ); |
| 494 |
WPF()->api->lin_share_button( $url, $type, $text ); |
| 495 |
WPF()->api->vk_share_button( $url, $type, $text ); |
| 496 |
} |
| 497 |
|
| 498 |
public function share_buttons( $url = '', $type = 'default', $text = '' ) { |
| 499 |
$template = wpfval( WPF()->current_object, 'template' ); |
| 500 |
$exclude = [ 'lostpassword', 'resetpassword' ]; |
| 501 |
if( $template && ! in_array( $template, $exclude ) ) { |
| 502 |
WPF()->api->fb_share_button( $url, $type ); |
| 503 |
WPF()->api->tw_share_button( $url, $type, $text ); |
| 504 |
WPF()->api->wapp_share_button( $url, $type, $text ); |
| 505 |
WPF()->api->lin_share_button( $url, $type, $text ); |
| 506 |
WPF()->api->vk_share_button( $url, $type, $text ); |
| 507 |
} |
| 508 |
} |
| 509 |
|
| 510 |
public function rc_enqueue() { |
| 511 |
$version = wpforo_setting( 'recaptcha', 'version' ); |
| 512 |
$theme = wpforo_setting( 'recaptcha', 'theme' ); |
| 513 |
$site_key = wpforo_setting( 'recaptcha', 'site_key' ); |
| 514 |
|
| 515 |
// reCAPTCHA v3 uses a different script URL and approach |
| 516 |
if( $version === 'v3' ) { |
| 517 |
wp_register_script( |
| 518 |
'wpforo_recaptcha', |
| 519 |
'https://www.google.com/recaptcha/api.js?render=' . $site_key |
| 520 |
); |
| 521 |
wp_add_inline_script( |
| 522 |
'wpforo_recaptcha', |
| 523 |
"var wpForoReCaptchaV3Execute = function(action){ |
| 524 |
return new Promise(function(resolve, reject){ |
| 525 |
if( typeof grecaptcha !== 'undefined' && typeof grecaptcha.execute === 'function' ){ |
| 526 |
grecaptcha.ready(function(){ |
| 527 |
grecaptcha.execute('" . esc_js( $site_key ) . "', {action: action}).then(function(token){ |
| 528 |
resolve(token); |
| 529 |
}).catch(function(error){ |
| 530 |
reject(error); |
| 531 |
}); |
| 532 |
}); |
| 533 |
} else { |
| 534 |
reject('reCAPTCHA not loaded'); |
| 535 |
} |
| 536 |
}); |
| 537 |
}; |
| 538 |
var wpForoReCaptchaV3Submit = function(form){ |
| 539 |
var btn = form.querySelector('input[type=\"submit\"], button[type=\"submit\"]'); |
| 540 |
if( btn && btn.name && !form.querySelector('input[type=\"hidden\"][name=\"' + btn.name + '\"]') ){ |
| 541 |
var h = document.createElement('input'); |
| 542 |
h.type = 'hidden'; |
| 543 |
h.name = btn.name; |
| 544 |
h.value = btn.value || '1'; |
| 545 |
form.appendChild(h); |
| 546 |
} |
| 547 |
form.submit(); |
| 548 |
}; |
| 549 |
var wpForoReCaptchaV3Init = function(){ |
| 550 |
var forms = document.querySelectorAll('form[data-wpforo-recaptcha-v3]'); |
| 551 |
forms.forEach(function(form){ |
| 552 |
form.addEventListener('submit', function(e){ |
| 553 |
var tokenInput = form.querySelector('input[name=\"g-recaptcha-response\"]'); |
| 554 |
if( tokenInput && !tokenInput.value ){ |
| 555 |
e.preventDefault(); |
| 556 |
var action = form.getAttribute('data-wpforo-recaptcha-action') || 'wpforo_form'; |
| 557 |
wpForoReCaptchaV3Execute(action).then(function(token){ |
| 558 |
tokenInput.value = token; |
| 559 |
wpForoReCaptchaV3Submit(form); |
| 560 |
}).catch(function(error){ |
| 561 |
console.error('reCAPTCHA error:', error); |
| 562 |
wpForoReCaptchaV3Submit(form); |
| 563 |
}); |
| 564 |
} |
| 565 |
}); |
| 566 |
}); |
| 567 |
}; |
| 568 |
if( document.readyState === 'loading' ){ |
| 569 |
document.addEventListener('DOMContentLoaded', wpForoReCaptchaV3Init); |
| 570 |
} else { |
| 571 |
wpForoReCaptchaV3Init(); |
| 572 |
}" |
| 573 |
); |
| 574 |
} elseif( $version === 'v2_invisible' ) { |
| 575 |
// reCAPTCHA v2 Invisible |
| 576 |
wp_register_script( |
| 577 |
'wpforo_recaptcha', |
| 578 |
'https://www.google.com/recaptcha/api.js?onload=wpForoReCallback&render=explicit' |
| 579 |
); |
| 580 |
wp_add_inline_script( |
| 581 |
'wpforo_recaptcha', |
| 582 |
"var wpForoReWidgetIds = {}; |
| 583 |
var wpForoReCallback = function(){ |
| 584 |
setTimeout(function () { |
| 585 |
if( typeof grecaptcha !== 'undefined' && typeof grecaptcha.render === 'function' ){ |
| 586 |
var rc_widgets = document.getElementsByClassName('wpforo_recaptcha_widget'); |
| 587 |
if( rc_widgets.length ){ |
| 588 |
var i; |
| 589 |
for (i = 0; i < rc_widgets.length; i++) { |
| 590 |
if( rc_widgets[i].firstElementChild === null ){ |
| 591 |
rc_widgets[i].innerHTML = ''; |
| 592 |
var form = rc_widgets[i].closest('form'); |
| 593 |
var widgetId = grecaptcha.render( |
| 594 |
rc_widgets[i], { |
| 595 |
'sitekey': '" . esc_js( $site_key ) . "', |
| 596 |
'theme': '" . esc_js( $theme ) . "', |
| 597 |
'size': 'invisible', |
| 598 |
'callback': function(token){ |
| 599 |
if( form ){ |
| 600 |
var tokenInput = form.querySelector('input[name=\"g-recaptcha-response\"]'); |
| 601 |
if( !tokenInput ){ |
| 602 |
tokenInput = document.createElement('input'); |
| 603 |
tokenInput.type = 'hidden'; |
| 604 |
tokenInput.name = 'g-recaptcha-response'; |
| 605 |
form.appendChild(tokenInput); |
| 606 |
} |
| 607 |
tokenInput.value = token; |
| 608 |
form.submit(); |
| 609 |
} |
| 610 |
} |
| 611 |
} |
| 612 |
); |
| 613 |
if( form ){ |
| 614 |
wpForoReWidgetIds[form.id || i] = widgetId; |
| 615 |
form.addEventListener('submit', function(e){ |
| 616 |
var formId = this.id || Array.prototype.indexOf.call(document.forms, this); |
| 617 |
if( wpForoReWidgetIds[formId] !== undefined ){ |
| 618 |
var tokenInput = this.querySelector('input[name=\"g-recaptcha-response\"]'); |
| 619 |
if( !tokenInput || !tokenInput.value ){ |
| 620 |
e.preventDefault(); |
| 621 |
grecaptcha.execute(wpForoReWidgetIds[formId]); |
| 622 |
} |
| 623 |
} |
| 624 |
}); |
| 625 |
} |
| 626 |
} |
| 627 |
} |
| 628 |
} |
| 629 |
} |
| 630 |
}, 800); |
| 631 |
}" |
| 632 |
); |
| 633 |
} else { |
| 634 |
// reCAPTCHA v2 Checkbox (default) |
| 635 |
wp_register_script( |
| 636 |
'wpforo_recaptcha', |
| 637 |
'https://www.google.com/recaptcha/api.js?onload=wpForoReCallback&render=explicit' |
| 638 |
); |
| 639 |
wp_add_inline_script( |
| 640 |
'wpforo_recaptcha', |
| 641 |
"var wpForoReCallback = function(){ |
| 642 |
setTimeout(function () { |
| 643 |
if( typeof grecaptcha !== 'undefined' && typeof grecaptcha.render === 'function' ){ |
| 644 |
var rc_widgets = document.getElementsByClassName('wpforo_recaptcha_widget'); |
| 645 |
if( rc_widgets.length ){ |
| 646 |
var i; |
| 647 |
for (i = 0; i < rc_widgets.length; i++) { |
| 648 |
if( rc_widgets[i].firstElementChild === null ){ |
| 649 |
rc_widgets[i].innerHTML = ''; |
| 650 |
grecaptcha.render( |
| 651 |
rc_widgets[i], { 'sitekey': '" . esc_js( $site_key ) . "', 'theme': '" . esc_js( $theme ) . "' } |
| 652 |
); |
| 653 |
} |
| 654 |
} |
| 655 |
} |
| 656 |
} |
| 657 |
}, 800); |
| 658 |
}" |
| 659 |
); |
| 660 |
} |
| 661 |
wp_enqueue_script( 'wpforo_recaptcha' ); |
| 662 |
} |
| 663 |
|
| 664 |
public function rc_enqueue_async( $tag, $handle ) { |
| 665 |
if( $handle === 'wpforo_recaptcha' ) return str_replace( '<script', '<script async defer', $tag ); |
| 666 |
|
| 667 |
return $tag; |
| 668 |
} |
| 669 |
|
| 670 |
public function rc_enqueue_css() { |
| 671 |
$version = wpforo_setting( 'recaptcha', 'version' ); |
| 672 |
|
| 673 |
// Only add CSS for v2 checkbox (visible widget) |
| 674 |
// v2 invisible and v3 don't need widget styling |
| 675 |
if( $version !== 'v2_checkbox' ) { |
| 676 |
return; |
| 677 |
} |
| 678 |
|
| 679 |
wp_register_style( 'wpforo-rc-style', false ); |
| 680 |
wp_enqueue_style( 'wpforo-rc-style' ); |
| 681 |
$custom_css = ".wpforo_recaptcha_widget{ -webkit-transform:scale(0.9); transform:scale(0.9); -webkit-transform-origin:left 0; transform-origin:left 0; }"; |
| 682 |
wp_add_inline_style( 'wpforo-rc-style', $custom_css ); |
| 683 |
} |
| 684 |
|
| 685 |
public function rc_widget( $action = 'wpforo_form' ) { |
| 686 |
$site_key = wpforo_setting( 'recaptcha', 'site_key' ); |
| 687 |
$version = wpforo_setting( 'recaptcha', 'version' ); |
| 688 |
|
| 689 |
if( $site_key ) { |
| 690 |
if( $version === 'v3' ) { |
| 691 |
// reCAPTCHA v3 - hidden token input, form gets data attributes |
| 692 |
echo '<input type="hidden" name="g-recaptcha-response" value="" />'; |
| 693 |
echo '<input type="hidden" name="g-recaptcha-version" value="v3" />'; |
| 694 |
// Add JS to mark the parent form for v3 processing |
| 695 |
echo "\r\n<script>(function(){ |
| 696 |
var input = document.currentScript.previousElementSibling.previousElementSibling; |
| 697 |
var form = input.closest('form'); |
| 698 |
if(form){ |
| 699 |
form.setAttribute('data-wpforo-recaptcha-v3', '1'); |
| 700 |
form.setAttribute('data-wpforo-recaptcha-action', '" . esc_js( $action ) . "'); |
| 701 |
} |
| 702 |
})();</script>"; |
| 703 |
} else { |
| 704 |
// reCAPTCHA v2 (checkbox or invisible) - standard widget div |
| 705 |
echo '<div class="wpforo_recaptcha_widget"></div><div class="wpf-cl"></div>'; |
| 706 |
echo "\r\n<script>if(typeof wpForoReCallback === 'function') wpForoReCallback();</script>"; |
| 707 |
} |
| 708 |
} |
| 709 |
} |
| 710 |
|
| 711 |
public function _rc_check() { |
| 712 |
if( isset( $_POST['g-recaptcha-response'] ) && ! empty( $_POST['g-recaptcha-response'] ) ) { |
| 713 |
$secret_key = wpforo_setting( 'recaptcha', 'secret_key' ); |
| 714 |
$version = wpforo_setting( 'recaptcha', 'version' ); |
| 715 |
|
| 716 |
// Use POST method for verification (recommended by Google) |
| 717 |
$response = wp_remote_post( |
| 718 |
'https://www.google.com/recaptcha/api/siteverify', |
| 719 |
[ |
| 720 |
'body' => [ |
| 721 |
'secret' => $secret_key, |
| 722 |
'response' => sanitize_text_field( $_POST['g-recaptcha-response'] ), |
| 723 |
'remoteip' => WPF()->current_user_ip, |
| 724 |
], |
| 725 |
] |
| 726 |
); |
| 727 |
|
| 728 |
if( is_wp_error( $response ) || empty( $response['body'] ) ) { |
| 729 |
$error = wpforo_phrase( "ERROR: Can't connect to Google reCAPTCHA API", false ); |
| 730 |
if( wpforo_setting( 'general', 'debug_mode' ) && is_wp_error( $response ) ) { |
| 731 |
$error .= ' ( ' . $response->get_error_message() . ' )'; |
| 732 |
} |
| 733 |
|
| 734 |
return $error; |
| 735 |
} |
| 736 |
|
| 737 |
$response_data = json_decode( $response['body'], true ); |
| 738 |
|
| 739 |
if( ! empty( $response_data['success'] ) ) { |
| 740 |
// For reCAPTCHA v3, also check the score |
| 741 |
if( $version === 'v3' || ( isset( $_POST['g-recaptcha-version'] ) && $_POST['g-recaptcha-version'] === 'v3' ) ) { |
| 742 |
$score = isset( $response_data['score'] ) ? (float) $response_data['score'] : 0; |
| 743 |
$threshold = (float) wpforo_setting( 'recaptcha', 'v3_score_threshold' ); |
| 744 |
|
| 745 |
// Default threshold to 0.5 if not set |
| 746 |
if( $threshold <= 0 || $threshold > 1 ) { |
| 747 |
$threshold = 0.5; |
| 748 |
} |
| 749 |
|
| 750 |
if( $score < $threshold ) { |
| 751 |
// Score too low, likely a bot |
| 752 |
$error = wpforo_phrase( 'reCAPTCHA verification failed: suspicious activity detected', false ); |
| 753 |
if( wpforo_setting( 'general', 'debug_mode' ) ) { |
| 754 |
$error .= sprintf( ' (score: %.2f, threshold: %.2f)', $score, $threshold ); |
| 755 |
} |
| 756 |
|
| 757 |
return $error; |
| 758 |
} |
| 759 |
} |
| 760 |
|
| 761 |
return 'success'; |
| 762 |
} else { |
| 763 |
$error = wpforo_phrase( 'Google reCAPTCHA verification failed', false ); |
| 764 |
if( wpforo_setting( 'general', 'debug_mode' ) && ! empty( $response_data['error-codes'] ) ) { |
| 765 |
$error .= ' (' . implode( ', ', $response_data['error-codes'] ) . ')'; |
| 766 |
} |
| 767 |
|
| 768 |
return $error; |
| 769 |
} |
| 770 |
} else { |
| 771 |
return wpforo_phrase( 'Google reCAPTCHA data are not submitted', false ); |
| 772 |
} |
| 773 |
} |
| 774 |
|
| 775 |
public function rc_check() { |
| 776 |
return wpforo_ram_get( [ &$this, '_rc_check' ] ); |
| 777 |
} |
| 778 |
|
| 779 |
public function rc_verify() { |
| 780 |
if( ! wpforo_setting( 'recaptcha', 'post_editor' ) || ! wpforo_setting( 'recaptcha', 'topic_editor' ) ) { |
| 781 |
if( ! wpforo_setting( 'recaptcha', 'post_editor' ) && in_array( |
| 782 |
wpfval( $_POST, 'wpfaction' ), |
| 783 |
[ 'post_add', 'post_edit' ], |
| 784 |
true |
| 785 |
) ) { |
| 786 |
return true; |
| 787 |
} elseif( ! wpforo_setting( 'recaptcha', 'topic_editor' ) && in_array( |
| 788 |
wpfval( $_POST, 'wpfaction' ), |
| 789 |
[ 'topic_add', 'topic_edit' ], |
| 790 |
true |
| 791 |
) ) { |
| 792 |
return true; |
| 793 |
} |
| 794 |
} |
| 795 |
$result = $this->rc_check(); |
| 796 |
if( $result === 'success' ) { |
| 797 |
return true; |
| 798 |
} else { |
| 799 |
WPF()->notice->add( $result, 'error' ); |
| 800 |
wp_safe_redirect( wpforo_get_request_uri() ); |
| 801 |
exit(); |
| 802 |
} |
| 803 |
} |
| 804 |
|
| 805 |
public function rc_verify_wp_login( $user ) { |
| 806 |
if( ! isset( $_POST['log'] ) && ! isset( $_POST['pwd'] ) ) return $user; |
| 807 |
if( ! wpforo_setting( 'recaptcha', 'login_form' ) || ! wpforo_setting( 'recaptcha', 'wpf_login_form' ) ) { |
| 808 |
if( ! wpfval( $_POST, 'wpforologin' ) && ! wpforo_setting( 'recaptcha', 'login_form' ) ) { |
| 809 |
return $user; |
| 810 |
} elseif( wpfval( $_POST, 'wpforologin' ) && ! wpforo_setting( 'recaptcha', 'wpf_login_form' ) ) { |
| 811 |
return $user; |
| 812 |
} |
| 813 |
} |
| 814 |
$errors = is_wp_error( $user ) ? $user : new WP_Error(); |
| 815 |
$result = $this->rc_check(); |
| 816 |
if( $result !== 'success' ) { |
| 817 |
$errors->add( 'wpforo-recaptcha-error', $result ); |
| 818 |
$user = is_wp_error( $user ) ? $user : $errors; |
| 819 |
remove_filter( 'authenticate', 'wp_authenticate_username_password' ); |
| 820 |
remove_filter( 'authenticate', 'wp_authenticate_cookie' ); |
| 821 |
} |
| 822 |
|
| 823 |
return $user; |
| 824 |
} |
| 825 |
|
| 826 |
public function rc_verify_wp_register( $errors = '' ) { |
| 827 |
if( ! is_wp_error( $errors ) ) $errors = new WP_Error(); |
| 828 |
if( ! wpforo_setting( 'recaptcha', 'reg_form' ) || ! wpforo_setting( 'recaptcha', 'wpf_reg_form' ) ) { |
| 829 |
if( ! wpfval( $_POST, 'wpfreg' ) && ! wpforo_setting( 'recaptcha', 'reg_form' ) ) { |
| 830 |
return $errors; |
| 831 |
} elseif( wpfval( $_POST, 'wpfreg' ) && ! wpforo_setting( 'recaptcha', 'wpf_reg_form' ) ) { |
| 832 |
return $errors; |
| 833 |
} |
| 834 |
} |
| 835 |
$result = $this->rc_check(); |
| 836 |
if( $result !== 'success' ) { |
| 837 |
$errors->add( 'wpforo-recaptcha-error', $result ); |
| 838 |
} |
| 839 |
|
| 840 |
return $errors; |
| 841 |
} |
| 842 |
|
| 843 |
public function rc_verify_wp_lostpassword( $errors = '' ) { |
| 844 |
if( ! is_wp_error( $errors ) ) $errors = new WP_Error(); |
| 845 |
if( ! wpforo_setting( 'recaptcha', 'lostpass_form' ) || ! wpforo_setting( 'recaptcha', 'wpf_lostpass_form' ) ) { |
| 846 |
if( ! wpfval( $_POST, 'wpfororp' ) && ! wpforo_setting( 'recaptcha', 'lostpass_form' ) ) { |
| 847 |
return; |
| 848 |
} elseif( wpfval( $_POST, 'wpfororp' ) && ! wpforo_setting( 'recaptcha', 'wpf_lostpass_form' ) ) { |
| 849 |
return; |
| 850 |
} |
| 851 |
} |
| 852 |
$result = $this->rc_check(); |
| 853 |
if( $result !== 'success' ) { |
| 854 |
if( isset( $_POST['wc_reset_password'] ) && isset( $_POST['_wp_http_referer'] ) ) { |
| 855 |
//$errors->add('wpforo-recaptcha-error', $result); |
| 856 |
//return $errors; |
| 857 |
} else { |
| 858 |
wp_die( $result, 'reCAPTCHA ERROR', [ 'back_link' => true ] ); |
| 859 |
} |
| 860 |
} |
| 861 |
} |
| 862 |
} |
| 863 |
|