PluginProbe
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor / 3.16.1
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor v3.16.1
4.0.3 4.0.2 4.0.1 4.0.0 3.16.6 3.16.5 3.16.4 3.16.3 3.16.2 3.16.1 3.16.0 3.15.9 3.9.9 3.9.5 3.9.6 3.9.7 3.9.8 1.1.7 1.1.8 1.1.9 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 All 341 releases
profile-builder / front-end / default-fields / recaptcha / recaptcha.php

recaptcha.php in User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor 3.16.1, at front-end/default-fields/recaptcha/recaptcha.php

1,029 lines 49.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
3
4 /**
5 * Encodes the given data into a query string format
6 * @param $data - array of string elements to be encoded
7 * @return string - encoded request
8 */
9 function _wppb_encodeQS($data)
10 {
11 $req = "";
12 foreach ($data as $key => $value) {
13 $req .= $key . '=' . urlencode(stripslashes($value)) . '&';
14 }
15 // Cut the last '&'
16 $req=substr($req, 0, strlen($req)-1);
17 return $req;
18 }
19
20
21
22 /**
23 * Submits an HTTP GET to a reCAPTCHA server
24 * @param string $path
25 * @param array $data
26 */
27 function _wppb_submitHTTPGet($path, $data)
28 {
29 $req = _wppb_encodeQS($data);
30 $response = wp_remote_get($path . $req);
31
32 if ( ! is_wp_error( $response ))
33 return $response["body"];
34 }
35
36 /**
37 * Gets the challenge HTML (javascript and non-javascript version).
38 * This is called from the browser, and the resulting reCAPTCHA HTML widget
39 * is embedded within the HTML form it was called from.
40 * @param string $pubkey A public key for reCAPTCHA
41 * @param string $error The error given by reCAPTCHA (optional, default is null)
42 * @param boolean $use_ssl Should the request be made over ssl? (optional, default is false)
43
44 * @return string - The HTML to be embedded in the user's form.
45 */
46 function wppb_recaptcha_get_html ( $pubkey, $form_name='' ){
47 global $wppb_recaptcha_forms; // is the counter for the number of forms that have recaptcha so we always have unique ids on the element
48 if( is_null( $wppb_recaptcha_forms ) )
49 $wppb_recaptcha_forms = 0;
50 $wppb_recaptcha_forms++;
51
52 $field = wppb_get_recaptcha_field();
53
54 if ( empty($pubkey) )
55 echo '<span class="error">'. esc_html__("To use reCAPTCHA you must get an API key from", "profile-builder"). " <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a></span><br/><br/>";
56
57 // extra class needed for Invisible reCAPTCHA html
58 $invisible_class = '';
59 $v3_field_html = '';
60 if ( isset($field['recaptcha-type']) && ($field['recaptcha-type'] == 'invisible') ) {
61 $invisible_class = 'wppb-invisible-recaptcha';
62 } elseif ( isset($field['recaptcha-type']) && ($field['recaptcha-type'] == 'v3') ) {
63 $invisible_class = 'wppb-v3-recaptcha';
64 $v3_field_html = '<input type="hidden" name="g-recaptcha-response" class="g-recaptcha-response wppb-v3-recaptcha">';
65 }
66
67 $output = '<div id="wppb-recaptcha-element-'.$form_name.$wppb_recaptcha_forms.'" class="wppb-recaptcha-element '.$invisible_class.'">'.$v3_field_html.'</div>';
68
69 if ( isset($field['recaptcha-type']) && ($field['recaptcha-type'] == 'v3') ) {
70 $output .= '<input type="hidden" name="wppb-recaptcha-v3" value="1">';
71
72 if( $form_name == 'pb_login' ) {
73 add_filter( 'wppb_login_submit_button_extra_attributes', 'wppb_recaptcha_login_submit_button_extra_attributes' );
74 }
75
76 }
77
78 // reCAPTCHA html for all forms and we make sure we have a unique id for v2
79 return $output;
80 }
81
82 /**
83 * Add disabled attribute to login form submit button when reCaptcha v3 is used
84 * This is used to prevent form submission before the reCaptcha script is loaded and a token is received
85 *
86 * @param string $attributes
87 * @return string
88 */
89 function wppb_recaptcha_login_submit_button_extra_attributes( $attributes ) {
90 return $attributes . ' disabled="disabled"';
91 }
92
93 /**
94 * Add reCAPTCHA scripts to both front-end PB forms (with support for multiple forms) as well as Default WP forms
95 */
96 function wppb_recaptcha_script_footer(){
97 $field = wppb_get_recaptcha_field();
98 /* if we do not have a recaptcha field do nothing */
99 if( empty( $field ) )
100 return;
101
102 //do not add script if there is no shortcode
103 global $wppb_shortcode_on_front;
104 if( current_filter() == 'wp_footer' && ( !isset( $wppb_shortcode_on_front ) || $wppb_shortcode_on_front === false ) )
105 return;
106
107 //do not add script if the html for the field has not been added
108 global $wppb_recaptcha_present;
109 if( !isset( $wppb_recaptcha_present ) || $wppb_recaptcha_present === false )
110 return;
111
112 //we don't have jquery on the backend
113 if( current_filter() != 'wp_footer' ) {
114 wp_print_scripts('jquery');
115 }else if(!wp_script_is('jquery')){
116 wp_print_scripts('jquery');
117 }
118
119 //get site key
120 $pubkey = '';
121 if( isset( $field['public-key'] ) ) {
122 $pubkey = sanitize_text_field( $field['public-key'] );
123 }
124
125 // Check if we have a reCAPTCHA type
126 if ( !isset($field['recaptcha-type']) )
127 $field['recaptcha-type'] = 'v2' ;
128
129 /*for invisible recaptcha we have extra parameters and the selector is different. v2 is initialized on the id of the div
130 that must be unique and invisible is on the submit button of the forms that have the div */
131 if ( $field['recaptcha-type'] === 'invisible' ) {
132 $callback_conditions = 'jQuery("input[type=\'submit\']", jQuery( ".wppb-recaptcha-element" ).closest("form") )';
133 $invisible_parameters = '"callback" : wppbInvisibleRecaptchaOnSubmit,"size": "invisible"';
134 } elseif ( $field['recaptcha-type'] === 'v3' ) {
135 $callback_conditions = 'jQuery( jQuery( ".wppb-recaptcha-element" ).closest("form") )';
136 $invisible_parameters = '';
137 } else {
138 $callback_conditions = 'jQuery(".wppb-recaptcha-element")';
139 $invisible_parameters = '';
140 }
141
142 if( $field['recaptcha-type'] === 'v3' ) {
143
144 //the section below is properly escaped or the variables contain static strings
145 // phpcs:disable
146 echo '
147 <script>
148 window.wppbRecaptchaCallbackExecuted = false;
149 window.wppbRecaptchaV3 = true;
150 var wppbRecaptchaCallback = function() {
151 if( !window.wppbRecaptchaCallbackExecuted ){
152 '.$callback_conditions.'.each(function() {
153 let wppbElement = jQuery(this),
154 form = wppbElement.is("form") ? wppbElement : wppbElement.find("form"),
155 currentForm = form[0];
156
157 // Ensure we have a PB Form
158 if (form.length === 0) {
159 return;
160 }
161
162 // Listen for PB-Form submission
163 jQuery(currentForm).on("submit.wppbRecaptchaV3", wppbInitializeRecaptchaV3);
164 });
165 window.wppbRecaptchaCallbackExecuted = true;//we use this to make sure we only run the callback once
166
167 // Enable login form submit button
168 if( jQuery("#wppb-loginform input[type=submit]").length > 0 ) {
169 jQuery("#wppb-loginform input[type=submit]").attr("disabled", false);
170 }
171 }
172 };
173
174 function wppbInitializeRecaptchaV3( event = null, current_form = null ){
175
176 if( event ){
177 event.preventDefault();
178 event.stopPropagation();
179 }
180
181 let currentForm = this
182
183 if( current_form != null && current_form && current_form[0] ){
184 currentForm = current_form[0]
185 }
186
187 return new Promise((resolve) => {
188
189 grecaptcha.ready(function() {
190 grecaptcha.execute("' . $pubkey . '", {action: "submit"}).then(function(token) {
191
192 let recaptchaResponse = jQuery(currentForm).find(".wppb-v3-recaptcha.g-recaptcha-response");
193 jQuery(recaptchaResponse).val(token); // Set the recaptcha response
194
195 if( token === false ){
196 return wppbRecaptchaInitializationError();
197 }
198
199 var submitForm = true
200
201 /* dont submit form if PMS gateway is Stripe */
202 if( jQuery(".pms_pay_gate[type=radio]").length > 0 ){
203 jQuery(".pms_pay_gate").each( function(){
204 if( jQuery(this).is(":checked") && !jQuery(this).is(":disabled") && ( jQuery(this).val() == "stripe_connect" || jQuery(this).val() == "stripe_intents" || jQuery(this).val() == "stripe" || jQuery(this).val() == "paypal_connect" ) )
205 submitForm = false
206 })
207 } else if( jQuery(".pms_pay_gate[type=hidden]").length > 0 ) {
208
209 if( !jQuery(".pms_pay_gate[type=hidden]").is(":disabled") && ( jQuery(".pms_pay_gate[type=hidden]").val() == "stripe_connect" || jQuery(".pms_pay_gate[type=hidden]").val() == "stripe_intents" || jQuery(".pms_pay_gate[type=hidden]").val() == "stripe" || jQuery(".pms_pay_gate[type=hidden]").val() == "paypal_connect" ) )
210 submitForm = false
211 } else if( currentForm.classList.contains("wppb-ajax-form") ) {
212 submitForm = false;
213 } else if( currentForm.classList.contains("wppb-2fa-form") ) {
214 submitForm = false;
215 }
216
217 if( currentForm.classList.contains("wppb-2fa-authentication-requested" ) ){
218 submitForm = true;
219 }
220
221 if( submitForm ){
222 jQuery(currentForm).off("submit.wppbRecaptchaV3");
223 currentForm.submit();
224 } else {
225 jQuery(document).trigger( "wppb_v3_recaptcha_success", jQuery( "input[type=\'submit\']", jQuery( currentForm ) ) )
226 }
227
228 resolve( token );
229
230 });
231 });
232
233 });
234 }
235
236 /* the callback function for when the captcha does not load propperly, maybe network problem or wrong keys */
237 function wppbRecaptchaInitializationError(){
238 window.wppbRecaptchaInitError = true;
239 ';
240
241 } else {
242 //the section below is properly escaped or the variables contain static strings
243 // phpcs:disable
244 echo '
245 <script>
246 window.wppbRecaptchaCallbackExecuted = false;
247 window.wppbRecaptcha = true;
248 var wppbRecaptchaCallback = function() {
249 if( !window.wppbRecaptchaCallbackExecuted ){//see if we executed this before
250 ' . $callback_conditions . '.each(function(){
251 var $recaptchaElement = jQuery(this);
252 var existingRecaptchaId = $recaptchaElement.data("wppb-recaptcha-id");
253
254 if ( typeof existingRecaptchaId !== "undefined" ) {
255 grecaptcha.reset( existingRecaptchaId );
256 return;
257 }
258
259 var recID = grecaptcha.render(
260 $recaptchaElement.attr("id"),
261 {
262 "sitekey" : "' . $pubkey . '",
263 "error-callback": wppbRecaptchaInitializationError,
264 ' . $invisible_parameters . '
265 }
266 )
267
268 $recaptchaElement.data("wppb-recaptcha-id", recID);
269 });
270 window.wppbRecaptchaCallbackExecuted = true;//we use this to make sure we only run the callback once
271 }
272 };
273
274 /* the callback function for when the captcha does not load propperly, maybe network problem or wrong keys */
275 function wppbRecaptchaInitializationError(){
276 window.wppbRecaptchaInitError = true;
277 ';
278 }
279
280 if ( $field['recaptcha-type'] === 'invisible' ) {
281 echo '
282 /* make sure that if the invisible recaptcha did not load properly ( network error or wrong keys ) we can still submit the form */
283 jQuery("input[type=\'submit\']", jQuery( ".wppb-recaptcha-element" ).closest("form") ).on("click", function(e){
284 jQuery(this).closest("form").submit();
285 });
286 ';
287 }
288
289 echo '
290 //add a captcha field so we do not just let the form submit if we do not have a captcha response
291 jQuery( ".wppb-recaptcha-element" ).after(\'' . wp_nonce_field( 'wppb_recaptcha_init_error', 'wppb_recaptcha_load_error', false, false ) . '\');
292 }
293
294 /* compatibility with other plugins that may include recaptcha with an onload callback. if their script loads first then our callback will not execute so call it explicitly */
295 jQuery( window ).on( "load", function() {
296 wppbRecaptchaCallback();
297 });
298 </script>';
299 // phpcs:enable
300 if ( $field['recaptcha-type'] === 'invisible' ) {
301 echo '<script>
302 /* success callback for invisible recaptcha. it submits the form that contains the right token response */
303 function wppbInvisibleRecaptchaOnSubmit(token){
304
305 var elem = jQuery(".g-recaptcha-response").filter(function(){
306 return jQuery(this).val() === token;
307 });
308
309 var form = elem.closest("form");
310
311 var submitForm = true
312
313 /* dont submit form if PMS gateway is Stripe */
314 if( jQuery(".pms_pay_gate[type=radio]").length > 0 ){
315 jQuery(".pms_pay_gate").each( function(){
316 if( jQuery(this).is(":checked") && !jQuery(this).is(":disabled") && ( jQuery(this).val() == "stripe_connect" || jQuery(this).val() == "stripe_intents" || jQuery(this).val() == "stripe" || jQuery(this).val() == "paypal_connect" ) )
317 submitForm = false
318 })
319 } else if( jQuery(".pms_pay_gate[type=hidden]").length > 0 ) {
320
321 if( !jQuery(".pms_pay_gate[type=hidden]").is(":disabled") && ( jQuery(".pms_pay_gate[type=hidden]").val() == "stripe_connect" || jQuery(".pms_pay_gate[type=hidden]").val() == "stripe_intents" || jQuery(".pms_pay_gate[type=hidden]").val() == "stripe" || jQuery(".pms_pay_gate[type=hidden]").val() == "paypal_connect" ) )
322 submitForm = false
323
324 } else if( form.hasClass("wppb-ajax-form") ) {
325 submitForm = false;
326 } else if( form.hasClass("wppb-2fa-form") ) {
327 submitForm = false;
328 }
329
330 if( form.hasClass("wppb-2fa-authentication-requested" ) ){
331 submitForm = true;
332 }
333
334 if( submitForm ){
335 form.submit();
336 } else {
337 jQuery(document).trigger( "wppb_invisible_recaptcha_success", jQuery( ".form-submit input[type=\'submit\']", elem.closest("form") ) )
338 return true;
339 }
340 }
341 </script>';
342 }
343
344 $lang = '&hl=en';
345 $locale = get_locale();
346 if(!empty($locale)) {
347 $locale_parts = explode('_',$locale);
348 $lang = '&hl='.urlencode($locale_parts[0]);
349 }
350
351 $source = apply_filters( 'wppb_recaptcha_custom_field_source', 'www.google.com' );
352
353 if( $field['recaptcha-type'] === 'v3' ) {
354 echo '<script src="https://'. esc_attr( $source ) .'/recaptcha/api.js?render='.esc_attr( $pubkey ).'" async defer></script>';
355 } else {
356 echo '<script src="https://'. esc_attr( $source ) .'/recaptcha/api.js?onload=wppbRecaptchaCallback&render=explicit'.esc_attr( $lang ).'" async defer></script>';
357 }
358
359 }
360 add_action('wp_footer', 'wppb_recaptcha_script_footer', 9999);
361 add_action('login_footer', 'wppb_recaptcha_script_footer');
362 add_action('register_form', 'wppb_recaptcha_script_footer');
363 add_action('lost_password', 'wppb_recaptcha_script_footer');
364
365
366 /**
367 * Print style
368 *
369 */
370 function wppb_recaptcha_print_style() {
371 echo '<style type="text/css">
372 /* Hide reCAPTCHA V3 badge */
373 .grecaptcha-badge {
374
375 visibility: hidden !important;
376
377 }
378 </style>';
379 }
380
381 add_action( 'wp_footer', 'wppb_recaptcha_print_style' );
382 add_action( 'login_footer', 'wppb_recaptcha_print_style' );
383
384
385 /**
386 * A wppb_ReCaptchaResponse is returned from wppb_recaptcha_check_answer()
387 */
388 class wppb_ReCaptchaResponse {
389 var $is_valid;
390 }
391
392
393 /**
394 * Calls an HTTP POST function to verify if the user's answer was correct
395 * @param string $privkey
396 * @param string $remoteip
397 * @param string $response
398 * @return wppb_ReCaptchaResponse
399 */
400 function wppb_recaptcha_check_answer ( $privkey, $remoteip, $response, $score_threshold = 0.5 ) {
401
402 if ( $remoteip == null || $remoteip == '' )
403 echo '<span class="error">'. esc_html__("For security reasons, you must pass the remote ip to reCAPTCHA!", "profile-builder") .'</span><br/><br/>';
404
405 // Discard empty solution submissions
406 if ($response == null || strlen($response) == 0) {
407 $recaptchaResponse = new wppb_ReCaptchaResponse();
408
409 if( isset( $_POST['wppb_recaptcha_load_error'] ) && wp_verify_nonce( sanitize_text_field( $_POST['wppb_recaptcha_load_error'] ), 'wppb_recaptcha_init_error' ) )
410 $recaptchaResponse->is_valid = true;
411 else
412 $recaptchaResponse->is_valid = false;
413
414 return $recaptchaResponse;
415 }
416
417 $source = apply_filters( 'wppb_recaptcha_custom_field_source', 'www.google.com' );
418
419 $getResponse = _wppb_submitHTTPGet(
420 "https://".$source."/recaptcha/api/siteverify?",
421 array (
422 'secret' => $privkey,
423 'remoteip' => $remoteip,
424 'response' => $response
425 )
426 );
427
428 $answers = json_decode($getResponse, true);
429 $recaptchaResponse = new wppb_ReCaptchaResponse();
430
431 if (trim($answers ['success']) == true) {
432 if ( array_key_exists( 'score', $answers ) ) {
433 $recaptchaResponse->is_valid = ($answers['score'] >= $score_threshold);
434 } else {
435 $recaptchaResponse->is_valid = true;
436 }
437 } else {
438 $recaptchaResponse->is_valid = false;
439 }
440
441 return $recaptchaResponse;
442
443 }
444
445 /* the function to display error message on the registration page */
446 function wppb_validate_captcha_response( $publickey, $privatekey, $score_threshold = 0.5 ){
447 if (isset($_POST['g-recaptcha-response'])){
448 $recaptcha_response_field = sanitize_textarea_field( $_POST['g-recaptcha-response'] );
449 } else {
450 $recaptcha_response_field = '';
451 }
452
453 $already_validated = false;
454 $saved = get_option( 'wppb_recaptcha_validations', array() );
455
456 if( isset( $saved[ $recaptcha_response_field ] ) && $saved[ $recaptcha_response_field ] == true ){
457 $already_validated = true;
458
459 if( !wp_doing_ajax() ){
460 unset( $saved[ $recaptcha_response_field ] );
461
462 update_option( 'wppb_recaptcha_validations', $saved, false );
463 }
464 }
465
466 if( !$already_validated ){
467
468 if( isset( $_SERVER["REMOTE_ADDR"] ) ){
469 $resp = wppb_recaptcha_check_answer($privatekey, sanitize_text_field( $_SERVER["REMOTE_ADDR"] ), $recaptcha_response_field, $score_threshold );
470
471 if( isset( $resp ) ){
472 $already_validated = ( ( !$resp->is_valid ) ? false : true );
473 }
474 }
475
476 }
477
478 // Save valid results when they are being triggered from an ajax request
479 if( wp_doing_ajax() && isset( $_POST['action'] ) && $_POST['action'] == 'pms_validate_checkout' ){
480
481 $saved = get_option( 'wppb_recaptcha_validations', array() );
482
483 if( $already_validated === true )
484 $saved[ $recaptcha_response_field ] = true;
485
486 update_option( 'wppb_recaptcha_validations', $saved, false );
487
488 }
489
490 return $already_validated;
491
492 }
493
494 /* the function to add reCAPTCHA to the registration form of PB */
495 function wppb_recaptcha_handler ( $output, $form_location, $field, $user_id, $field_check_errors, $request_data ){
496 if ( $field['field'] == 'reCAPTCHA' ){
497 $item_title = apply_filters( 'wppb_'.$form_location.'_recaptcha_custom_field_'.$field['id'].'_item_title', wppb_icl_t( 'plugin profile-builder-pro', 'custom_field_'.$field['id'].'_title_translation', $field['field-title'], true ) );
498 $item_description = wppb_icl_t( 'plugin profile-builder-pro', 'custom_field_'.$field['id'].'_description_translation', $field['description'], true );
499
500 wppb_recaptcha_set_default_values();
501
502 if ( ($form_location == 'register') && ( isset($field['captcha-pb-forms']) ) && ( strpos($field['captcha-pb-forms'],'pb_register') !== false || ( $field['recaptcha-type'] == 'v3' && wppb_maybe_enable_recaptcha_v3_on_form( $field ) ) ) ) {
503 $error_mark = ( ( $field['required'] == 'Yes' ) ? '<span class="wppb-required" title="'.wppb_required_field_error($field["field-title"]).'">*</span>' : '' );
504
505 global $wppb_recaptcha_present;
506 $wppb_recaptcha_present = true;
507
508 if ( array_key_exists( $field['id'], $field_check_errors ) )
509 $error_mark = '<img src="'.WPPB_PLUGIN_URL.'assets/images/pencil_delete.png" title="'.wppb_required_field_error($field["field-title"]).'"/>';
510
511 $publickey = trim( $field['public-key'] );
512 $privatekey = trim( $field['private-key'] );
513
514 if ( empty( $publickey ) || empty( $privatekey ) )
515 return '<span class="custom_field_recaptcha_error_message" id="'.$field['meta-name'].'_error_message">'.apply_filters( 'wppb_'.$form_location.'_recaptcha_custom_field_'.$field['id'].'_error_message', __("To use reCAPTCHA you must get an API public key from:", "profile-builder"). '<a href="https://www.google.com/recaptcha/admin/create">https://www.google.com/recaptcha/admin/create</a>' ).'</span>';
516
517 if ( empty($field['recaptcha-type']) || ($field['recaptcha-type'] == 'v2') ) {
518 $output = '<label for="recaptcha_response_field">' . $item_title . $error_mark . '</label>' . wppb_recaptcha_get_html($publickey, 'pb_register');
519 if (!empty($item_description))
520 $output .= '<span class="wppb-description-delimiter">' . $item_description . '</span>';
521 }
522 else {
523 // html for Invisible reCAPTCHA
524 $output = wppb_recaptcha_get_html($publickey, 'pb_register');
525 }
526
527
528 return $output;
529
530 }
531 }
532 }
533 add_filter( 'wppb_output_form_field_recaptcha', 'wppb_recaptcha_handler', 10, 6 );
534
535
536 /* handle reCAPTCHA field validation on PB Register form */
537 function wppb_check_recaptcha_value( $message, $field, $request_data, $form_location ){
538 if( $field['field'] == 'reCAPTCHA' ){
539 if ( ( $form_location == 'register' ) && ( isset($field['captcha-pb-forms']) ) && ( strpos($field['captcha-pb-forms'],'pb_register') !== false || ( $field['recaptcha-type'] == 'v3' && wppb_maybe_enable_recaptcha_v3_on_form( $field ) ) ) ) {
540 /* theme my login plugin executes the register_errors hook on the frontend on all pages so on our register forms we might have already a recaptcha response
541 so do not verify it again or it will fail */
542 global $wppb_recaptcha_response;
543 if (!isset($wppb_recaptcha_response)){
544 $wppb_recaptcha_response = wppb_validate_captcha_response( trim( $field['public-key'] ), trim( $field['private-key'] ), isset( $field['score-threshold'] ) ? trim( $field['score-threshold'] ) : 0.5 );
545 }
546 if ( ( $wppb_recaptcha_response == false ) && ( $field['required'] == 'Yes' ) ){
547 return wppb_required_field_error($field["field-title"]);
548 }
549 }
550 }
551 return $message;
552 }
553 add_filter( 'wppb_check_form_field_recaptcha', 'wppb_check_recaptcha_value', 10, 4 );
554
555 // Get the reCAPTCHA field information
556 function wppb_get_recaptcha_field(){
557 $wppb_manage_fields = get_option( 'wppb_manage_fields', 'not_found' );
558 $field = array();
559 if ( $wppb_manage_fields != 'not_found' ) {
560 foreach ($wppb_manage_fields as $value) {
561 if ($value['field'] == 'reCAPTCHA'){
562 $field = $value;
563 break;
564 }
565 }
566 }
567 return $field;
568 }
569
570 /* Display reCAPTCHA on PB Recover Password form */
571 function wppb_display_recaptcha_recover_password( $output ){
572 $field = wppb_get_recaptcha_field();
573
574 if ( !empty($field) ) {
575 $publickey = trim($field['public-key']);
576 $item_title = apply_filters('wppb_recover_password_recaptcha_custom_field_' . $field['id'] . '_item_title', wppb_icl_t('plugin profile-builder-pro', 'custom_field_' . $field['id'] . '_title_translation', $field['field-title'], true));
577 $item_description = wppb_icl_t('plugin profile-builder-pro', 'custom_field_' . $field['id'] . '_description_translation', $field['description'], true);
578
579 // check where reCAPTCHA should display and add reCAPTCHA html
580 if ( isset($field['captcha-pb-forms']) && ( strpos( $field['captcha-pb-forms'],'pb_recover_password' ) !== false || ( $field['recaptcha-type'] == 'v3' && wppb_maybe_enable_recaptcha_v3_on_form( $field ) ) ) ) {
581
582 global $wppb_recaptcha_present;
583 $wppb_recaptcha_present = true;
584
585 if ( empty($field['recaptcha-type']) || ($field['recaptcha-type'] == 'v2') ) {
586 $recaptcha_output = '<label for="recaptcha_response_field">' . $item_title . '</label>' . wppb_recaptcha_get_html($publickey, 'pb_recover_password');
587 if (!empty($item_description))
588 $recaptcha_output .= '<span class="wppb-description-delimiter">' . $item_description . '</span>';
589
590 $output = str_replace('</ul>', '<li class="wppb-form-field wppb-recaptcha wppb-recaptcha-'. $field['recaptcha-type'] .'">' . $recaptcha_output . '</li>' . '</ul>', $output);
591 }
592 else {
593 // output Invisible reCAPTCHA html
594 $output = str_replace('</ul>', '<li class="wppb-form-field wppb-recaptcha wppb-recaptcha-'. $field['recaptcha-type'] .'">' . wppb_recaptcha_get_html($publickey, 'pb_recover_password') . '</li>' . '</ul>', $output);
595 }
596 }
597 }
598 return $output;
599 }
600 add_filter('wppb_recover_password_generate_password_input','wppb_display_recaptcha_recover_password');
601
602 /* Function that changes the messageNo from the Recover Password form */
603 function wppb_recaptcha_change_recover_password_message_no($messageNo) {
604
605 if (isset($_REQUEST['action']) && $_REQUEST['action'] === 'recover_password') {
606 $field = wppb_get_recaptcha_field();
607 if (!empty($field)) {
608
609 global $wppb_recaptcha_response;
610 if (!isset($wppb_recaptcha_response)) $wppb_recaptcha_response = wppb_validate_captcha_response( trim( $field['public-key'] ), trim( $field['private-key'] ), isset( $field['score-threshold'] ) ? trim( $field['score-threshold'] ) : 0.5 );
611
612 if ( isset($field['captcha-pb-forms']) && (strpos($field['captcha-pb-forms'], 'pb_recover_password') !== false) ) {
613
614 if ( ($wppb_recaptcha_response == false ) && ( $field['required'] == 'Yes' ) )
615 $messageNo = '';
616 }
617 }
618 }
619
620 return $messageNo;
621 }
622 add_filter('wppb_recover_password_message_no', 'wppb_recaptcha_change_recover_password_message_no');
623
624 /* Function that adds the reCAPTCHA error message on the Recover Password form */
625 function wppb_recaptcha_recover_password_displayed_message1( $message ) {
626 $field = wppb_get_recaptcha_field();
627
628 if ( !empty($field) ){
629 global $wppb_recaptcha_response;
630 if (!isset($wppb_recaptcha_response)) $wppb_recaptcha_response = wppb_validate_captcha_response( trim( $field['public-key'] ), trim( $field['private-key'] ), isset( $field['score-threshold'] ) ? trim( $field['score-threshold'] ) : 0.5 );
631
632 if ( isset($field['captcha-pb-forms']) && ( strpos( $field['captcha-pb-forms'],'pb_recover_password' ) !== false ) && ( $wppb_recaptcha_response == false )) {
633
634 // This message is also altered by the plugin-compatibilities.php file, in regards to Captcha plugin ( function wppb_captcha_recover_password_displayed_message1 )
635 if (($message == '<p class="wppb-warning">wppb_recaptcha_error</p>') || ($message == '<p class="wppb-warning">wppb_captcha_error</p>'))
636 $message = '<p class="wppb-warning">' . wppb_recaptcha_field_error($field["field-title"]) . '</p>';
637 else
638 $message = $message . '<p class="wppb-warning">' . wppb_recaptcha_field_error($field["field-title"]) . '</p>';
639
640 }
641 }
642
643 return $message;
644 }
645 add_filter('wppb_recover_password_displayed_message1', 'wppb_recaptcha_recover_password_displayed_message1');
646
647 /* Function that changes the default success message to wppb_recaptcha_error if the reCAPTCHA doesn't validate
648 so that we can change the message displayed with the wppb_recover_password_displayed_message1 filter */
649 function wppb_recaptcha_recover_password_sent_message_1($message) {
650
651 if (isset($_REQUEST['action']) && $_REQUEST['action'] === 'recover_password') {
652 $field = wppb_get_recaptcha_field();
653
654 if (!empty($field)) {
655 global $wppb_recaptcha_response;
656 if (!isset($wppb_recaptcha_response)) $wppb_recaptcha_response = wppb_validate_captcha_response( trim( $field['public-key'] ), trim( $field['private-key'] ), isset( $field['score-threshold'] ) ? trim( $field['score-threshold'] ) : 0.5 );
657
658 if ( isset($field['captcha-pb-forms']) && ( strpos($field['captcha-pb-forms'], 'pb_recover_password') !== false ) && ( $wppb_recaptcha_response == false ) ){
659 $message = 'wppb_recaptcha_error';
660 }
661 }
662
663 }
664
665 return $message;
666 }
667 add_filter('wppb_recover_password_sent_message1', 'wppb_recaptcha_recover_password_sent_message_1');
668
669 /* Display reCAPTCHA html on PB Login form */
670 function wppb_display_recaptcha_login_form($form_part, $args) {
671
672 if( !isset( $args['form_id'] ) || $args['form_id'] != 'wppb-loginform' )
673 return $form_part;
674
675 $field = wppb_get_recaptcha_field();
676
677 if ( !empty($field) ) {
678 $item_title = apply_filters('wppb_login_recaptcha_custom_field_' . $field['id'] . '_item_title', wppb_icl_t('plugin profile-builder-pro', 'custom_field_' . $field['id'] . '_title_translation', $field['field-title'], true));
679 $item_description = wppb_icl_t('plugin profile-builder-pro', 'custom_field_' . $field['id'] . '_description_translation', $field['description'], true);
680
681 if ( isset($field['captcha-pb-forms']) && ( strpos( $field['captcha-pb-forms'],'pb_login' ) !== false || ( $field['recaptcha-type'] == 'v3' && wppb_maybe_enable_recaptcha_v3_on_form( $field ) ) ) ) { // check where reCAPTCHA should display and add reCAPTCHA html
682
683 global $wppb_recaptcha_present;
684 $wppb_recaptcha_present = true;
685
686 if ( empty($field['recaptcha-type']) || ($field['recaptcha-type'] == 'v2') ) {
687 $recaptcha_output = '<label for="recaptcha_response_field">' . $item_title . '</label>' . wppb_recaptcha_get_html(trim($field['public-key']), 'pb_login');
688 if (!empty($item_description))
689 $recaptcha_output .= '<span class="wppb-description-delimiter">' . $item_description . '</span>';
690
691 $form_part .= '<div class="wppb-form-field wppb-recaptcha wppb-recaptcha-'. $field['recaptcha-type'] .'">' . $recaptcha_output . '</div>';
692 }
693 else {
694 //output Invisible reCAPTCHA html
695 // $form_part .= wppb_recaptcha_get_html(trim($field['public-key']), 'pb_login');
696 $form_part .= '<div class="wppb-form-field wppb-recaptcha wppb-recaptcha-'. $field['recaptcha-type'] .'">' . wppb_recaptcha_get_html(trim($field['public-key']), 'pb_login') . '</div>';
697 }
698 }
699 }
700
701 return $form_part;
702 }
703 add_filter('login_form_middle', 'wppb_display_recaptcha_login_form', 10, 2);
704
705 /* Display reCAPTCHA html on default WP Login form */
706 function wppb_display_recaptcha_wp_login_form(){
707 $field = wppb_get_recaptcha_field();
708
709 if ( !empty($field) ) {
710 $item_title = apply_filters('wppb_login_recaptcha_custom_field_' . $field['id'] . '_item_title', wppb_icl_t('plugin profile-builder-pro', 'custom_field_' . $field['id'] . '_title_translation', $field['field-title'], true));
711 $item_description = wppb_icl_t('plugin profile-builder-pro', 'custom_field_' . $field['id'] . '_description_translation', $field['description'], true);
712
713 if ( isset($field['captcha-wp-forms']) && (strpos( $field['captcha-wp-forms'],'default_wp_login' ) !== false) ) { // check where reCAPTCHA should display and add reCAPTCHA html
714
715 global $wppb_recaptcha_present;
716 $wppb_recaptcha_present = true;
717
718 if ( empty($field['recaptcha-type']) || ($field['recaptcha-type'] == 'v2') ) {
719 $recaptcha_output = '<label for="recaptcha_response_field" style="padding-left:15px; padding-bottom:7px;">' . $item_title . '</label>' . wppb_recaptcha_get_html(trim($field['public-key']));
720 if (!empty($item_description))
721 $recaptcha_output .= '<span class="wppb-description-delimiter">' . $item_description . '</span>';
722
723 echo '<div class="wppb-form-field wppb-recaptcha" style="margin-left:-14px; margin-bottom: 15px;">' . $recaptcha_output . '</div>'; /* phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped */ /* properly escaped when constructing the var */
724 }
725 else {
726 // output Invisible reCAPTCHA html
727 echo wppb_recaptcha_get_html( trim($field['public-key'])); /* phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped */ /* properly escaped when constructing the var */
728 }
729 }
730 }
731 }
732 add_action( 'login_form', 'wppb_display_recaptcha_wp_login_form' );
733
734 //Show reCAPTCHA error on Login form (both default and PB one)
735 function wppb_recaptcha_login_wp_error_message($user){
736 //make sure you're on a Login form (WP or PB)
737 if ( isset( $_POST['log'] ) && !is_wp_error($user) && !isset( $_POST['pms_login'] ) ) {
738
739 $field = wppb_get_recaptcha_field();
740 if ( !empty($field) ){
741 global $wppb_recaptcha_response;
742
743 if (!isset($wppb_recaptcha_response)) $wppb_recaptcha_response = wppb_validate_captcha_response( trim( $field['public-key'] ), trim( $field['private-key'] ), isset( $field['score-threshold'] ) ? trim( $field['score-threshold'] ) : 0.5 );
744
745 $recaptcha_error_message = __('reCaptcha could not be verified. Please try again.','profile-builder');
746
747 if( isset( $field['recaptcha-type'] ) && $field['recaptcha-type'] === 'v2' ) {
748 $recaptcha_error_message = __('Please enter a (valid) reCAPTCHA value','profile-builder');
749 }
750
751 //reCAPTCHA error for displaying on the PB login form
752 if ( isset($_POST['wppb_login']) && ($_POST['wppb_login'] == true) ) {
753
754 // it's a PB login form, check if we have a reCAPTCHA on it and display error if not valid
755 if ((isset($field['captcha-pb-forms'])) && (strpos($field['captcha-pb-forms'], 'pb_login') !== false || ( $field['recaptcha-type'] == 'v3' && wppb_maybe_enable_recaptcha_v3_on_form( $field ) ) ) && ($wppb_recaptcha_response == false)) {
756 $user = new WP_Error('wppb_recaptcha_error', $recaptcha_error_message);
757 remove_filter( 'authenticate', 'wp_authenticate_username_password', 20, 3 );
758 remove_filter( 'authenticate', 'wp_authenticate_email_password', 20, 3 );
759 }
760
761 }
762 else {
763 //reCAPTCHA error for displaying on the default WP login form
764 if (isset($field['captcha-wp-forms']) && (strpos($field['captcha-wp-forms'], 'default_wp_login') !== false) && ($wppb_recaptcha_response == false)) {
765 $user = new WP_Error('wppb_recaptcha_error', $recaptcha_error_message);
766 remove_filter( 'authenticate', 'wp_authenticate_username_password', 20, 3 );
767 remove_filter( 'authenticate', 'wp_authenticate_email_password', 20, 3 );
768 }
769
770 }
771 }
772 }
773 return $user;
774 }
775 add_filter('authenticate','wppb_recaptcha_login_wp_error_message', 9);
776
777 /**
778 * Add a reCAPTCHA type–specific CSS class to the Register form field
779 *
780 * @param $classes - existing field classes
781 * @param $field - field data
782 * @return mixed|string
783 */
784 function wppb_register_form_recaptcha_type_class( $classes, $field ){
785
786 if ( isset( $field['field'] ) && $field['field'] == 'reCAPTCHA' && ! empty( $field['recaptcha-type'] ) )
787 $classes .= ' wppb-recaptcha-' . $field['recaptcha-type'];
788
789 return $classes;
790 }
791 add_filter( 'wppb_field_css_class', 'wppb_register_form_recaptcha_type_class', 20, 2);
792
793 // Display reCAPTCHA html on default WP Recover Password form
794 function wppb_display_recaptcha_default_wp_recover_password() {
795 $field = wppb_get_recaptcha_field();
796
797 if (!empty($field)) {
798 $publickey = trim($field['public-key']);
799 $item_title = apply_filters('wppb_recover_password_recaptcha_custom_field_' . $field['id'] . '_item_title', wppb_icl_t('plugin profile-builder-pro', 'custom_field_' . $field['id'] . '_title_translation', $field['field-title'], true));
800 $item_description = wppb_icl_t('plugin profile-builder-pro', 'custom_field_' . $field['id'] . '_description_translation', $field['description'], true);
801
802 if ( isset($field['captcha-wp-forms']) && (strpos( $field['captcha-wp-forms'], 'default_wp_recover_password') !== false) ) { // check where reCAPTCHA should display and add reCAPTCHA html
803
804 global $wppb_recaptcha_present;
805 $wppb_recaptcha_present = true;
806
807 if ( empty($field['recaptcha-type']) || ($field['recaptcha-type'] == 'v2') ){
808 $recaptcha_output = '<label for="recaptcha_response_field" style="padding-left:15px; padding-bottom:7px;">' . $item_title . '</label>' . wppb_recaptcha_get_html($publickey);
809 if (!empty($item_description))
810 $recaptcha_output .= '<span class="wppb-description-delimiter">' . $item_description . '</span>';
811
812 echo '<div class="wppb-form-field wppb-recaptcha" style="margin-left:-14px; margin-bottom: 15px;">' . $recaptcha_output . '</div>'; /* phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped */ /* properly escaped when constructing the var */
813 }
814 else {
815 // output Invisible reCAPTCHA html
816 echo wppb_recaptcha_get_html($publickey); /* phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped */ /* properly escaped when constructing the var */
817 }
818 }
819 }
820 }
821 add_action('lostpassword_form','wppb_display_recaptcha_default_wp_recover_password');
822
823 // Verify and show reCAPTCHA errors for default WP Recover Password
824 function wppb_verify_recaptcha_default_wp_recover_password(){
825
826 // If field 'username or email' is empty - return
827 if( isset( $_REQUEST['user_login'] ) && "" === $_REQUEST['user_login'] )
828 return;
829
830 $field = wppb_get_recaptcha_field();
831 if ( !empty($field) ){
832 global $wppb_recaptcha_response;
833 if (!isset($wppb_recaptcha_response)) $wppb_recaptcha_response = wppb_validate_captcha_response( trim( $field['public-key'] ), trim( $field['private-key'] ), isset( $field['score-threshold'] ) ? trim( $field['score-threshold'] ) : 0.5 );
834
835 $recaptcha_error_message = esc_html__('reCaptcha could not be verified. Please try again.','profile-builder');
836
837 if( isset( $field['recaptcha-type'] ) && $field['recaptcha-type'] === 'v2' ) {
838 $recaptcha_error_message = esc_html__('Please enter a (valid) reCAPTCHA value','profile-builder');
839 }
840
841 // If reCAPTCHA not entered or incorrect reCAPTCHA answer
842 if ( isset( $_REQUEST['g-recaptcha-response'] ) && ( ( "" === $_REQUEST['g-recaptcha-response'] ) || ( $wppb_recaptcha_response == false ) ) ) {
843 wp_die( esc_html( $recaptcha_error_message ) . '<br />' . esc_html__( "Click the BACK button on your browser, and try again.", 'profile-builder' ) ) ;
844 }
845 }
846 }
847 add_action('lostpassword_post','wppb_verify_recaptcha_default_wp_recover_password');
848
849 /* Display reCAPTCHA html on default WP Register form */
850 function wppb_display_recaptcha_default_wp_register(){
851 $field = wppb_get_recaptcha_field();
852
853 if (!empty($field)) {
854
855 $publickey = trim($field['public-key']);
856 $item_title = apply_filters('wppb_register_recaptcha_custom_field_' . $field['id'] . '_item_title', wppb_icl_t('plugin profile-builder-pro', 'custom_field_' . $field['id'] . '_title_translation', $field['field-title'], true));
857 $item_description = wppb_icl_t('plugin profile-builder-pro', 'custom_field_' . $field['id'] . '_description_translation', $field['description'], true);
858
859 wppb_recaptcha_set_default_values();
860 if (isset($field['captcha-wp-forms']) && (strpos($field['captcha-wp-forms'], 'default_wp_register') !== false)) { // check where reCAPTCHA should display and add reCAPTCHA html
861
862 global $wppb_recaptcha_present;
863 $wppb_recaptcha_present = true;
864
865 if ( empty($field['recaptcha-type']) || ($field['recaptcha-type'] == 'v2') ) {
866 $recaptcha_output = '<label for="recaptcha_response_field" style="padding-left:15px; padding-bottom:7px;">' . $item_title . '</label>' . wppb_recaptcha_get_html($publickey);
867 if (!empty($item_description))
868 $recaptcha_output .= '<span class="wppb-description-delimiter">' . $item_description . '</span>';
869
870 echo '<div class="wppb-form-field wppb-recaptcha" style="margin-left:-14px; margin-bottom: 15px;">' . $recaptcha_output . '</div>'; /* phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped */ /* properly escaped when constructing the var */
871 }
872 else {
873 // output reCAPTCHA html
874 echo wppb_recaptcha_get_html($publickey); /* phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped */ /* properly escaped when constructing the var */
875 }
876 }
877 }
878 }
879 add_action( 'register_form', 'wppb_display_recaptcha_default_wp_register' );
880
881 // Verify and show reCAPTCHA errors for default WP Register form
882 function wppb_verify_recaptcha_default_wp_register( $errors ){
883
884 $field = wppb_get_recaptcha_field();
885 if ( !empty($field) ){
886 global $wppb_recaptcha_response;
887 if (!isset($wppb_recaptcha_response)) $wppb_recaptcha_response = wppb_validate_captcha_response( trim( $field['public-key'] ), trim( $field['private-key'] ), isset( $field['score-threshold'] ) ? trim( $field['score-threshold'] ) : 0.5 );
888
889 $recaptcha_error_message = esc_html__('reCaptcha could not be verified. Please try again.','profile-builder');
890
891 if( isset( $field['recaptcha-type'] ) && $field['recaptcha-type'] === 'v2' ) {
892 $recaptcha_error_message = esc_html__('Please enter a (valid) reCAPTCHA value','profile-builder');
893 }
894
895 // If reCAPTCHA not entered or incorrect reCAPTCHA answer
896 if ( isset( $_REQUEST['g-recaptcha-response'] ) && ( ( "" === $_REQUEST['g-recaptcha-response'] ) || ( $wppb_recaptcha_response == false ) ) ) {
897 $errors->add( 'wppb_recaptcha_error', $recaptcha_error_message );
898 }
899 }
900
901 return $errors;
902 }
903 add_filter('registration_errors','wppb_verify_recaptcha_default_wp_register');
904
905 // set default values in case there's already an existing reCAPTCHA field in Manage fields (when upgrading)
906 function wppb_recaptcha_set_default_values() {
907 $manage_fields = get_option('wppb_manage_fields', 'not_set');
908 if ($manage_fields != 'not_set') {
909 foreach ($manage_fields as $key => $value) {
910 if ($value['field'] == 'reCAPTCHA') {
911 if ( !isset($value['captcha-pb-forms']) ) $manage_fields[$key]['captcha-pb-forms'] = 'pb_register';
912 if ( !isset($value['captcha-wp-forms']) ) $manage_fields[$key]['captcha-wp-forms'] = 'default_wp_register';
913 if ( !isset($value['recaptcha-type']) ) $manage_fields[$key]['recaptcha-type'] = 'v2';
914 }
915 }
916 update_option('wppb_manage_fields', $manage_fields);
917 }
918 }
919
920 if ( function_exists( 'is_plugin_active' ) && is_plugin_active( 'paid-member-subscriptions/index.php' ) && defined( 'PMS_VERSION' ) && version_compare( PMS_VERSION, '2.12.9', '<' ) ) {
921
922 $notifications = WPPB_Plugin_Notifications::get_instance();
923
924 // this must be unique
925 $notification_id = 'wppb_pms_recaptcha_compatibility';
926
927 $notification_message = '<p>' . __( 'reCAPTCHA v3 is not compatible with Paid Member Subscriptions versions that are older than <strong>2.12.7</strong>. <br>Please update Paid Member Subscriptions to a newer version to avoid any issues.', 'profile-builder' ) . '</p>';
928 $notification_message .= '<a href="' . wp_nonce_url( add_query_arg( array( 'wppb_dismiss_admin_notification' => $notification_id ) ), 'wppb_plugin_notice_dismiss' ) . '" type="button" class="notice-dismiss"><span class="screen-reader-text">' . __( 'Dismiss this notice.', 'profile-builder' ) . '</span></a>';
929
930 // add the notification (we need to add the "notice is-dismissible" classes for the dismiss button to be correctly positioned)
931 $notifications->add_notification( $notification_id, $notification_message, 'wppb-notice notice notice-warning is-dismissible', false );
932
933 }
934
935 // Make sure the reCAPTCHA field score threshold is set correctly
936 function wppb_check_recaptcha_fields_settings( $values ) {
937 if( isset( $values['field'] ) && $values['field'] == 'reCAPTCHA' ) {
938 if ( empty( $values['score-threshold'] ) || $values['score-threshold'] < 0 || $values['score-threshold'] > 1 ) {
939 $values['score-threshold'] = 0.5;
940 }
941 }
942
943 return $values;
944 }
945 add_action( 'wck_update_meta_filter_values_wppb_manage_fields', 'wppb_check_recaptcha_fields_settings' );
946
947 function wppb_maybe_enable_recaptcha_v3_on_form( $recaptcha_field ){
948
949 // Static cache to avoid repeated calculations
950 static $cache = array();
951
952 // Early validation checks
953 if( empty( $recaptcha_field ) || empty( $recaptcha_field['captcha-pb-forms'] ) )
954 return false;
955
956 $post_id = get_the_ID();
957 $post = get_post( $post_id );
958
959 // Check if post is set, if not return false
960 if( empty( $post ) || empty( $post->post_content ) )
961 return false;
962
963 // Create cache key based on post ID and captcha forms configuration
964 $cache_key = md5( $post_id . serialize( $recaptcha_field['captcha-pb-forms'] ) );
965
966 // Return cached result if available
967 if( isset( $cache[ $cache_key ] ) )
968 return $cache[ $cache_key ];
969
970 $wppb_recaptcha_v3 = false;
971
972 // Define form configurations for loop processing
973 $form_configs = array(
974 'pb_register' => array(
975 'shortcode_pattern' => '[wppb-register',
976 'block_name' => 'wppb/register',
977 'other_forms' => array(
978 array( 'shortcode' => '[wppb-login', 'block' => 'wppb/login', 'form_type' => 'pb_login' ),
979 array( 'shortcode' => '[wppb-recover-password', 'block' => 'wppb/recover-password', 'form_type' => 'pb_recover_password' )
980 )
981 ),
982 'pb_login' => array(
983 'shortcode_pattern' => '[wppb-login',
984 'block_name' => 'wppb/login',
985 'other_forms' => array(
986 array( 'shortcode' => '[wppb-register', 'block' => 'wppb/register', 'form_type' => 'pb_register' ),
987 array( 'shortcode' => '[wppb-recover-password', 'block' => 'wppb/recover-password', 'form_type' => 'pb_recover_password' )
988 )
989 ),
990 'pb_recover_password' => array(
991 'shortcode_pattern' => '[wppb-recover-password',
992 'block_name' => 'wppb/recover-password',
993 'other_forms' => array(
994 array( 'shortcode' => '[wppb-register', 'block' => 'wppb/register', 'form_type' => 'pb_register' ),
995 array( 'shortcode' => '[wppb-login', 'block' => 'wppb/login', 'form_type' => 'pb_login' )
996 )
997 )
998 );
999
1000 // Process each form type using loop
1001 foreach( $form_configs as $form_type => $config ) {
1002 // Skip if this form type is already enabled in captcha-pb-forms
1003 if( strpos( $recaptcha_field['captcha-pb-forms'], $form_type ) !== false )
1004 continue;
1005
1006 // Check if current form type exists on the page
1007 $current_form_exists = ( strpos( $post->post_content, $config['shortcode_pattern'] ) !== false || has_block( $config['block_name'] ) );
1008
1009 if( $current_form_exists ) {
1010 // Check if any other enabled form types also exist on the page
1011 foreach( $config['other_forms'] as $other_form ) {
1012 $other_form_exists = ( strpos( $post->post_content, $other_form['shortcode'] ) !== false || has_block( $other_form['block'] ) );
1013 $other_form_enabled = ( strpos( $recaptcha_field['captcha-pb-forms'], $other_form['form_type'] ) !== false );
1014
1015 if( $other_form_exists && $other_form_enabled ) {
1016 $wppb_recaptcha_v3 = true;
1017 break 2; // Break out of both loops since we found a match
1018 }
1019 }
1020 }
1021 }
1022
1023 // Cache the result
1024 $cache[ $cache_key ] = $wppb_recaptcha_v3;
1025
1026 return $wppb_recaptcha_v3;
1027
1028 }
1029