File: /var/www/html/wp-content/mu-plugins/ethnic-recaptcha.php
<?php
/**
* Shared Google reCAPTCHA v2 checkbox support for public forms.
*
* @package EthnicInfotech
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! function_exists( 'ethnic_recaptcha_option_name' ) ) {
function ethnic_recaptcha_option_name() {
return 'ethnic_recaptcha_settings';
}
}
if ( ! function_exists( 'ethnic_recaptcha_default_settings' ) ) {
function ethnic_recaptcha_default_settings() {
return array(
'enabled' => 1,
'site_key' => '',
'secret_key' => '',
'contact_form_7_enabled' => 1,
'proposal_request_enabled' => 1,
'resource_download_enabled' => 1,
'wordpress_comments_enabled'=> 1,
);
}
}
if ( ! function_exists( 'ethnic_recaptcha_settings' ) ) {
function ethnic_recaptcha_settings() {
$defaults = ethnic_recaptcha_default_settings();
$stored = get_option( ethnic_recaptcha_option_name(), array() );
$stored = is_array( $stored ) ? $stored : array();
$settings = wp_parse_args( $stored, $defaults );
$settings['enabled'] = ! empty( $settings['enabled'] ) ? 1 : 0;
$settings['contact_form_7_enabled'] = ! empty( $settings['contact_form_7_enabled'] ) ? 1 : 0;
$settings['proposal_request_enabled'] = ! empty( $settings['proposal_request_enabled'] ) ? 1 : 0;
$settings['resource_download_enabled'] = ! empty( $settings['resource_download_enabled'] ) ? 1 : 0;
$settings['wordpress_comments_enabled']= ! empty( $settings['wordpress_comments_enabled'] ) ? 1 : 0;
$settings['site_key'] = trim( sanitize_text_field( (string) $settings['site_key'] ) );
$settings['secret_key'] = trim( sanitize_text_field( (string) $settings['secret_key'] ) );
return $settings;
}
}
if ( ! function_exists( 'ethnic_recaptcha_context_map' ) ) {
function ethnic_recaptcha_context_map() {
return array(
'contact_form_7' => 'contact_form_7_enabled',
'proposal_request' => 'proposal_request_enabled',
'resource_download' => 'resource_download_enabled',
'wordpress_comments'=> 'wordpress_comments_enabled',
);
}
}
if ( ! function_exists( 'ethnic_recaptcha_source_labels' ) ) {
function ethnic_recaptcha_source_labels() {
return array(
'admin' => 'Admin settings',
'ethnic_constants' => 'ETHNIC constants',
);
}
}
if ( ! function_exists( 'ethnic_recaptcha_configuration_source_label' ) ) {
function ethnic_recaptcha_configuration_source_label( $source ) {
$labels = ethnic_recaptcha_source_labels();
return isset( $labels[ $source ] ) ? $labels[ $source ] : 'Not configured';
}
}
if ( ! function_exists( 'ethnic_recaptcha_page_url' ) ) {
function ethnic_recaptcha_page_url( $args = array() ) {
$url = admin_url( 'options-general.php?page=ethnic-shared-recaptcha' );
if ( empty( $args ) ) {
return $url;
}
return add_query_arg( $args, $url );
}
}
if ( ! function_exists( 'ethnic_recaptcha_configuration' ) ) {
function ethnic_recaptcha_configuration() {
static $configuration = null;
if ( null !== $configuration ) {
return $configuration;
}
$settings = ethnic_recaptcha_settings();
$configuration = array(
'site_key' => '',
'secret_key' => '',
'source' => '',
);
$candidates = array(
array(
'site_key' => $settings['site_key'],
'secret_key' => $settings['secret_key'],
'source' => 'admin',
),
array(
'site_key' => defined( 'ETHNIC_RECAPTCHA_SITE_KEY' ) ? (string) ETHNIC_RECAPTCHA_SITE_KEY : '',
'secret_key' => defined( 'ETHNIC_RECAPTCHA_SECRET_KEY' ) ? (string) ETHNIC_RECAPTCHA_SECRET_KEY : '',
'source' => 'ethnic_constants',
),
);
foreach ( $candidates as $candidate ) {
$site_key = trim( sanitize_text_field( (string) $candidate['site_key'] ) );
$secret_key = trim( sanitize_text_field( (string) $candidate['secret_key'] ) );
if ( '' === $site_key || '' === $secret_key ) {
continue;
}
$configuration = array(
'site_key' => $site_key,
'secret_key' => $secret_key,
'source' => (string) $candidate['source'],
);
break;
}
return $configuration;
}
}
if ( ! function_exists( 'ethnic_recaptcha_is_context_enabled' ) ) {
function ethnic_recaptcha_is_context_enabled( $context = '' ) {
$settings = ethnic_recaptcha_settings();
if ( empty( $settings['enabled'] ) ) {
return false;
}
if ( '' === $context ) {
return true;
}
$map = ethnic_recaptcha_context_map();
if ( ! isset( $map[ $context ] ) ) {
return true;
}
return ! empty( $settings[ $map[ $context ] ] );
}
}
if ( ! function_exists( 'ethnic_recaptcha_is_enabled' ) ) {
function ethnic_recaptcha_is_enabled( $context = '' ) {
$configuration = ethnic_recaptcha_configuration();
return ethnic_recaptcha_is_context_enabled( $context )
&& '' !== $configuration['site_key']
&& '' !== $configuration['secret_key'];
}
}
if ( ! function_exists( 'ethnic_recaptcha_site_key' ) ) {
function ethnic_recaptcha_site_key() {
$configuration = ethnic_recaptcha_configuration();
return $configuration['site_key'];
}
}
if ( ! function_exists( 'ethnic_recaptcha_secret_key' ) ) {
function ethnic_recaptcha_secret_key() {
$configuration = ethnic_recaptcha_configuration();
return $configuration['secret_key'];
}
}
if ( ! function_exists( 'ethnic_recaptcha_has_enabled_forms' ) ) {
function ethnic_recaptcha_has_enabled_forms() {
return ethnic_recaptcha_is_enabled( 'contact_form_7' )
|| ethnic_recaptcha_is_enabled( 'proposal_request' )
|| ethnic_recaptcha_is_enabled( 'resource_download' )
|| ethnic_recaptcha_is_enabled( 'wordpress_comments' );
}
}
if ( ! function_exists( 'ethnic_recaptcha_mask_value' ) ) {
function ethnic_recaptcha_mask_value( $value, $visible_chars = 6 ) {
$value = trim( (string) $value );
if ( '' === $value ) {
return 'Not set';
}
$length = strlen( $value );
if ( $length <= $visible_chars ) {
return $value;
}
return str_repeat( '•', max( 0, $length - $visible_chars ) ) . substr( $value, -1 * $visible_chars );
}
}
if ( ! function_exists( 'ethnic_recaptcha_widget_markup' ) ) {
function ethnic_recaptcha_widget_markup( $context, $args = array() ) {
$context = sanitize_key( $context );
if ( ! ethnic_recaptcha_is_enabled( $context ) ) {
return '';
}
$args = wp_parse_args(
$args,
array(
'wrapper_class' => '',
'widget_class' => '',
'message_class' => 'ethnic-recaptcha-message',
'include_message' => false,
'theme' => 'light',
'size' => 'normal',
)
);
$wrapper_classes = trim( 'ethnic-recaptcha-field ' . $args['wrapper_class'] );
$widget_classes = trim( 'ethnic-recaptcha-widget ' . $args['widget_class'] );
$theme = in_array( $args['theme'], array( 'light', 'dark' ), true ) ? $args['theme'] : 'light';
$size = in_array( $args['size'], array( 'normal', 'compact' ), true ) ? $args['size'] : 'normal';
ob_start();
?>
<div class="<?php echo esc_attr( $wrapper_classes ); ?>">
<div
class="<?php echo esc_attr( $widget_classes ); ?>"
data-ethnic-recaptcha-widget="true"
data-sitekey="<?php echo esc_attr( ethnic_recaptcha_site_key() ); ?>"
data-theme="<?php echo esc_attr( $theme ); ?>"
data-size="<?php echo esc_attr( $size ); ?>"
></div>
<?php if ( ! empty( $args['include_message'] ) ) : ?>
<div class="<?php echo esc_attr( $args['message_class'] ); ?>" data-ethnic-recaptcha-message hidden></div>
<?php endif; ?>
</div>
<?php
return trim( (string) ob_get_clean() );
}
}
if ( ! function_exists( 'ethnic_recaptcha_render_widget' ) ) {
function ethnic_recaptcha_render_widget( $context, $args = array() ) {
echo ethnic_recaptcha_widget_markup( $context, $args ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
}
if ( ! function_exists( 'ethnic_recaptcha_verify_submission' ) ) {
function ethnic_recaptcha_verify_submission( $expected_action = '' ) {
$expected_action = sanitize_key( $expected_action );
if ( ! ethnic_recaptcha_is_enabled( $expected_action ) ) {
return true;
}
$token = isset( $_POST['g-recaptcha-response'] ) ? sanitize_text_field( wp_unslash( $_POST['g-recaptcha-response'] ) ) : '';
if ( '' === $token ) {
return new WP_Error( 'ethnic_recaptcha_missing_token', 'The reCAPTCHA token is missing.' );
}
$response = wp_remote_post(
'https://www.google.com/recaptcha/api/siteverify',
array(
'timeout' => 15,
'body' => array(
'secret' => ethnic_recaptcha_secret_key(),
'response' => $token,
'remoteip' => isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : '',
),
)
);
if ( is_wp_error( $response ) ) {
return new WP_Error( 'ethnic_recaptcha_request_failed', 'The reCAPTCHA request failed.', $response );
}
if ( 200 !== (int) wp_remote_retrieve_response_code( $response ) ) {
return new WP_Error( 'ethnic_recaptcha_bad_response', 'The reCAPTCHA verification response was invalid.', $response );
}
$body = json_decode( wp_remote_retrieve_body( $response ), true );
if ( ! is_array( $body ) || empty( $body['success'] ) ) {
return new WP_Error( 'ethnic_recaptcha_failed', 'The reCAPTCHA verification did not succeed.', $body );
}
return $body;
}
}
if ( ! function_exists( 'ethnic_recaptcha_disable_cf7_builtin_recaptcha' ) ) {
function ethnic_recaptcha_disable_cf7_builtin_recaptcha() {
if ( ! ethnic_recaptcha_is_context_enabled( 'contact_form_7' ) ) {
return;
}
if ( function_exists( 'wpcf7_recaptcha_enqueue_scripts' ) ) {
remove_action( 'wp_enqueue_scripts', 'wpcf7_recaptcha_enqueue_scripts', 20 );
}
if ( function_exists( 'wpcf7_recaptcha_add_hidden_fields' ) ) {
remove_filter( 'wpcf7_form_hidden_fields', 'wpcf7_recaptcha_add_hidden_fields', 100 );
}
if ( function_exists( 'wpcf7_recaptcha_verify_response' ) ) {
remove_filter( 'wpcf7_spam', 'wpcf7_recaptcha_verify_response', 9 );
}
}
add_action( 'plugins_loaded', 'ethnic_recaptcha_disable_cf7_builtin_recaptcha', 50 );
}
if ( ! function_exists( 'ethnic_recaptcha_append_cf7_widget' ) ) {
function ethnic_recaptcha_append_cf7_widget( $content ) {
if ( ! ethnic_recaptcha_is_enabled( 'contact_form_7' ) ) {
return $content;
}
if ( false !== strpos( $content, 'data-ethnic-recaptcha-widget="true"' ) || false !== strpos( $content, 'g-recaptcha' ) ) {
return $content;
}
$widget = ethnic_recaptcha_widget_markup(
'contact_form_7',
array(
'wrapper_class' => 'ethnic-shared-contact-form__recaptcha',
'message_class' => 'wpcf7-not-valid-tip ethnic-recaptcha-inline-message',
'include_message' => true,
)
);
if ( '' === $widget ) {
return $content;
}
return $content . "\n\n" . $widget;
}
add_filter( 'wpcf7_form_elements', 'ethnic_recaptcha_append_cf7_widget', 20 );
}
if ( ! function_exists( 'ethnic_recaptcha_verify_cf7_submission' ) ) {
function ethnic_recaptcha_verify_cf7_submission( $spam, $submission ) {
if ( $spam || ! ethnic_recaptcha_is_enabled( 'contact_form_7' ) ) {
return $spam;
}
$result = ethnic_recaptcha_verify_submission( 'contact_form_7' );
if ( is_wp_error( $result ) ) {
$submission->add_spam_log(
array(
'agent' => 'ethnic_recaptcha',
'reason' => 'Google reCAPTCHA v2 checkbox validation failed.',
)
);
return true;
}
return false;
}
add_filter( 'wpcf7_spam', 'ethnic_recaptcha_verify_cf7_submission', 8, 2 );
}
if ( ! function_exists( 'ethnic_recaptcha_append_comment_widget' ) ) {
function ethnic_recaptcha_append_comment_widget( $submit_field, $args = array() ) {
if ( is_user_logged_in() || ! ethnic_recaptcha_is_enabled( 'wordpress_comments' ) ) {
return $submit_field;
}
$widget = ethnic_recaptcha_widget_markup(
'wordpress_comments',
array(
'wrapper_class' => 'ethnic-comments-recaptcha',
'message_class' => 'ethnic-comments-recaptcha__message ethnic-recaptcha-message',
'include_message' => true,
)
);
if ( '' === $widget ) {
return $submit_field;
}
return $widget . $submit_field;
}
add_filter( 'comment_form_submit_field', 'ethnic_recaptcha_append_comment_widget', 20, 2 );
}
if ( ! function_exists( 'ethnic_recaptcha_verify_comment_submission' ) ) {
function ethnic_recaptcha_verify_comment_submission( $comment_data ) {
if ( is_user_logged_in() || ! ethnic_recaptcha_is_enabled( 'wordpress_comments' ) ) {
return $comment_data;
}
$result = ethnic_recaptcha_verify_submission( 'wordpress_comments' );
if ( is_wp_error( $result ) ) {
wp_die(
esc_html__( 'Please complete the reCAPTCHA checkbox before submitting your comment.', 'thegem' ),
esc_html__( 'Comment security check failed', 'thegem' ),
array(
'back_link' => true,
'response' => 403,
)
);
}
return $comment_data;
}
add_filter( 'preprocess_comment', 'ethnic_recaptcha_verify_comment_submission', 9 );
}
if ( ! function_exists( 'ethnic_recaptcha_enqueue_assets' ) ) {
function ethnic_recaptcha_enqueue_assets() {
if ( is_admin() || ! ethnic_recaptcha_has_enabled_forms() ) {
return;
}
wp_register_style( 'ethnic-recaptcha', false, array(), null );
wp_enqueue_style( 'ethnic-recaptcha' );
wp_add_inline_style(
'ethnic-recaptcha',
<<<'CSS'
.ethnic-recaptcha-field {
margin-top: 18px;
}
.ethnic-recaptcha-inline-message,
.ethnic-recaptcha-message {
margin-top: 10px;
}
.ethnic-proposal-submit__recaptcha,
.ethnic-resources-capture__recaptcha,
.ethnic-comments-recaptcha {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 10px;
}
.ethnic-proposal-submit__recaptcha {
margin-top: 18px;
}
.ethnic-resources-capture__recaptcha {
margin-top: 18px;
}
.ethnic-comments-recaptcha {
margin: 16px 0 8px;
}
.ethnic-comments-recaptcha__message {
width: 100%;
max-width: 620px;
padding: 12px 14px;
border: 1px solid rgba(185, 28, 28, 0.18);
border-radius: 10px;
background: #fff1f2;
color: #b42318;
font-size: 15px;
font-weight: 700;
line-height: 1.45;
}
.ethnic-comments-recaptcha__message p {
margin: 0;
color: inherit;
}
.ethnic-shared-contact-form__recaptcha .g-recaptcha,
.ethnic-proposal-submit__recaptcha .g-recaptcha,
.ethnic-resources-capture__recaptcha .g-recaptcha,
.ethnic-comments-recaptcha .g-recaptcha {
transform-origin: left top;
}
@media (max-width: 480px) {
.ethnic-shared-contact-form__recaptcha .g-recaptcha,
.ethnic-proposal-submit__recaptcha .g-recaptcha,
.ethnic-resources-capture__recaptcha .g-recaptcha,
.ethnic-comments-recaptcha .g-recaptcha {
transform: scale(0.92);
}
}
CSS
);
wp_register_script( 'ethnic-recaptcha-core', false, array(), null, true );
wp_enqueue_script( 'ethnic-recaptcha-core' );
wp_add_inline_script(
'ethnic-recaptcha-core',
sprintf(
'window.ethnicRecaptchaConfig = %s;',
wp_json_encode(
array(
'enabled' => true,
'siteKey' => ethnic_recaptcha_site_key(),
'emptyMessage' => 'Please complete the reCAPTCHA checkbox before submitting this form.',
'verificationErrorMessage' => 'We could not verify the security check. Please try again.',
),
JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE
)
),
'before'
);
wp_add_inline_script(
'ethnic-recaptcha-core',
<<<'JS'
(function (window, document) {
var config = window.ethnicRecaptchaConfig || {};
function messageNode(form) {
return form.querySelector('[data-ethnic-recaptcha-message]');
}
function clearMessage(form) {
var node = messageNode(form);
if (!node) {
return;
}
node.hidden = true;
node.innerHTML = '';
}
function showMessage(form, message) {
var node = messageNode(form);
if (!node) {
return;
}
node.innerHTML = '<p>' + message + '</p>';
node.hidden = false;
}
function widgetContainer(form) {
return form.querySelector('[data-ethnic-recaptcha-widget="true"]');
}
function widgetId(form) {
var container = widgetContainer(form);
if (!container) {
return null;
}
if (!container.dataset.ethnicRecaptchaWidgetId) {
return null;
}
return Number(container.dataset.ethnicRecaptchaWidgetId);
}
function responseForForm(form) {
var id = widgetId(form);
if (id === null || Number.isNaN(id) || typeof window.grecaptcha === 'undefined') {
return '';
}
return String(window.grecaptcha.getResponse(id) || '').trim();
}
function renderWidgets(root) {
if (typeof window.grecaptcha === 'undefined' || typeof window.grecaptcha.render !== 'function') {
return;
}
(root || document).querySelectorAll('[data-ethnic-recaptcha-widget="true"]').forEach(function (container) {
if (container.dataset.ethnicRecaptchaWidgetId) {
return;
}
var siteKey = container.getAttribute('data-sitekey') || config.siteKey;
var theme = container.getAttribute('data-theme') || 'light';
var size = container.getAttribute('data-size') || 'normal';
var id = window.grecaptcha.render(container, {
sitekey: siteKey,
theme: theme,
size: size,
callback: function () {
var form = container.closest('form');
if (form) {
clearMessage(form);
}
},
'expired-callback': function () {
var form = container.closest('form');
if (form) {
showMessage(form, config.emptyMessage || 'Please complete the reCAPTCHA checkbox before submitting this form.');
}
}
});
container.dataset.ethnicRecaptchaWidgetId = String(id);
});
}
function validateForm(form) {
if (!widgetContainer(form)) {
return true;
}
clearMessage(form);
if (responseForForm(form)) {
return true;
}
showMessage(form, config.emptyMessage || 'Please complete the reCAPTCHA checkbox before submitting this form.');
return false;
}
function resetForm(form) {
var id = widgetId(form);
if (id === null || Number.isNaN(id) || typeof window.grecaptcha === 'undefined') {
return;
}
window.grecaptcha.reset(id);
clearMessage(form);
}
window.ethnicRecaptchaInit = function () {
renderWidgets(document);
};
window.ethnicRecaptcha = {
enabled: !!config.enabled,
validateForm: validateForm,
resetForm: resetForm,
getErrorMessage: function () {
return config.verificationErrorMessage || 'We could not verify the security check. Please try again.';
}
};
document.addEventListener('DOMContentLoaded', function () {
if (typeof window.grecaptcha !== 'undefined' && typeof window.grecaptcha.render === 'function') {
renderWidgets(document);
}
});
document.addEventListener('submit', function (event) {
var form = event.target;
if (!(form instanceof HTMLFormElement) || !widgetContainer(form)) {
return;
}
if (!validateForm(form)) {
event.preventDefault();
}
}, true);
document.addEventListener('wpcf7submit', function (event) {
resetForm(event.target);
});
document.addEventListener('wpcf7reset', function (event) {
window.requestAnimationFrame(function () {
resetForm(event.target);
});
});
})(window, document);
JS
);
wp_enqueue_script(
'google-recaptcha-checkbox',
'https://www.google.com/recaptcha/api.js?onload=ethnicRecaptchaInit&render=explicit',
array( 'ethnic-recaptcha-core' ),
null,
array(
'in_footer' => true,
'strategy' => 'defer',
)
);
}
add_action( 'wp_enqueue_scripts', 'ethnic_recaptcha_enqueue_assets', 30 );
}
if ( ! function_exists( 'ethnic_recaptcha_register_settings_page' ) ) {
function ethnic_recaptcha_register_settings_page() {
add_options_page(
'Shared reCAPTCHA',
'Shared reCAPTCHA',
'manage_options',
'ethnic-shared-recaptcha',
'ethnic_recaptcha_render_settings_page'
);
}
add_action( 'admin_menu', 'ethnic_recaptcha_register_settings_page', 40 );
}
if ( ! function_exists( 'ethnic_recaptcha_handle_settings_save' ) ) {
function ethnic_recaptcha_handle_settings_save() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
if ( empty( $_POST['ethnic_recaptcha_settings_nonce'] ) ) {
return;
}
if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['ethnic_recaptcha_settings_nonce'] ) ), 'ethnic_recaptcha_settings' ) ) {
wp_die( 'Invalid reCAPTCHA settings request.', 403 );
}
$current_settings = ethnic_recaptcha_settings();
$raw_settings = isset( $_POST['ethnic_recaptcha'] ) && is_array( $_POST['ethnic_recaptcha'] ) ? wp_unslash( $_POST['ethnic_recaptcha'] ) : array();
$site_key = isset( $raw_settings['site_key'] ) ? trim( sanitize_text_field( (string) $raw_settings['site_key'] ) ) : '';
$secret_key = $current_settings['secret_key'];
if ( ! empty( $raw_settings['clear_secret_key'] ) ) {
$secret_key = '';
} elseif ( isset( $raw_settings['secret_key'] ) && '' !== trim( (string) $raw_settings['secret_key'] ) ) {
$secret_key = trim( sanitize_text_field( (string) $raw_settings['secret_key'] ) );
}
update_option(
ethnic_recaptcha_option_name(),
array(
'enabled' => ! empty( $raw_settings['enabled'] ) ? 1 : 0,
'site_key' => $site_key,
'secret_key' => $secret_key,
'contact_form_7_enabled' => ! empty( $raw_settings['contact_form_7_enabled'] ) ? 1 : 0,
'proposal_request_enabled' => ! empty( $raw_settings['proposal_request_enabled'] ) ? 1 : 0,
'resource_download_enabled' => ! empty( $raw_settings['resource_download_enabled'] ) ? 1 : 0,
'wordpress_comments_enabled'=> ! empty( $raw_settings['wordpress_comments_enabled'] ) ? 1 : 0,
),
false
);
wp_safe_redirect(
ethnic_recaptcha_page_url(
array(
'ethnic_recaptcha_notice' => 'saved',
)
)
);
exit;
}
add_action( 'admin_init', 'ethnic_recaptcha_handle_settings_save' );
}
if ( ! function_exists( 'ethnic_recaptcha_render_settings_page' ) ) {
function ethnic_recaptcha_render_settings_page() {
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( 'You do not have permission to manage reCAPTCHA settings.', 403 );
}
$settings = ethnic_recaptcha_settings();
$configuration = ethnic_recaptcha_configuration();
$notice = isset( $_GET['ethnic_recaptcha_notice'] ) ? sanitize_key( wp_unslash( $_GET['ethnic_recaptcha_notice'] ) ) : '';
$active_source = ! empty( $configuration['source'] ) ? ethnic_recaptcha_configuration_source_label( $configuration['source'] ) : 'No active key source';
$status_cards = array(
'Shared protection' => ! empty( $settings['enabled'] ) ? 'Enabled' : 'Disabled',
'Contact Form 7' => ! empty( $settings['contact_form_7_enabled'] ) ? 'Enabled' : 'Disabled',
'Proposal request form' => ! empty( $settings['proposal_request_enabled'] ) ? 'Enabled' : 'Disabled',
'Resource download form' => ! empty( $settings['resource_download_enabled'] ) ? 'Enabled' : 'Disabled',
'WordPress comments' => ! empty( $settings['wordpress_comments_enabled'] ) ? 'Enabled' : 'Disabled',
);
?>
<div class="wrap">
<h1>Shared reCAPTCHA</h1>
<p>Manage one shared Google reCAPTCHA v2 checkbox setup for the public proposal form, resource download forms, and Contact Form 7.</p>
<?php if ( 'saved' === $notice ) : ?>
<div class="notice notice-success is-dismissible">
<p>Shared reCAPTCHA settings saved.</p>
</div>
<?php endif; ?>
<div style="display:grid;gap:12px;margin-top:18px;">
<div style="display:flex;flex-wrap:wrap;gap:18px;color:#5f6f8b;font-size:13px;">
<span><strong>Active key source:</strong> <?php echo esc_html( $active_source ); ?></span>
<span><strong>Resolved site key:</strong> <?php echo esc_html( ethnic_recaptcha_mask_value( $configuration['site_key'] ) ); ?></span>
</div>
</div>
<form method="post" action="<?php echo esc_url( ethnic_recaptcha_page_url() ); ?>" style="margin-top:20px;">
<?php wp_nonce_field( 'ethnic_recaptcha_settings', 'ethnic_recaptcha_settings_nonce' ); ?>
<div style="background:#fff;border:1px solid #d9e1ef;border-radius:16px;padding:24px;margin-bottom:18px;">
<h2 style="margin-top:0;">General</h2>
<p style="margin-top:0;color:#5f6f8b;">Turn shared Google reCAPTCHA v2 checkbox protection on or off for supported public forms.</p>
<label style="display:block;">
<span style="display:block;font-weight:600;margin-bottom:6px;">Enable shared reCAPTCHA protection</span>
<span style="display:flex;align-items:center;gap:10px;">
<input type="checkbox" name="ethnic_recaptcha[enabled]" value="1" <?php checked( ! empty( $settings['enabled'] ) ); ?> />
<span>Allow shared Google reCAPTCHA v2 checkbox protection on supported public forms.</span>
</span>
</label>
</div>
<div style="background:#fff;border:1px solid #d9e1ef;border-radius:16px;padding:24px;margin-bottom:18px;">
<h2 style="margin-top:0;">Keys</h2>
<p style="margin-top:0;color:#5f6f8b;">Use Google reCAPTCHA <strong>v2 checkbox</strong> keys here. Existing v3 keys will not render a visible checkbox widget.</p>
<div style="display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px 18px;">
<label style="grid-column:1 / -1;">
<span style="display:block;font-weight:600;margin-bottom:6px;">v2 checkbox site key</span>
<input type="text" name="ethnic_recaptcha[site_key]" value="<?php echo esc_attr( $settings['site_key'] ); ?>" placeholder="Enter your Google reCAPTCHA v2 checkbox site key" style="width:100%;" />
</label>
<label style="grid-column:1 / -1;">
<span style="display:block;font-weight:600;margin-bottom:6px;">v2 checkbox secret key</span>
<input type="password" name="ethnic_recaptcha[secret_key]" value="" placeholder="<?php echo esc_attr( '' !== $settings['secret_key'] ? 'Stored already — leave blank to keep the current secret' : 'Enter your Google reCAPTCHA v2 checkbox secret key' ); ?>" style="width:100%;" />
</label>
<label style="grid-column:1 / -1;">
<span style="display:flex;align-items:center;gap:10px;">
<input type="checkbox" name="ethnic_recaptcha[clear_secret_key]" value="1" />
<span>Clear the currently stored secret key</span>
</span>
</label>
</div>
</div>
<div style="background:#fff;border:1px solid #d9e1ef;border-radius:16px;padding:24px;margin-bottom:18px;">
<h2 style="margin-top:0;">Form Coverage</h2>
<p style="margin-top:0;color:#5f6f8b;">Choose where the visible checkbox widget should appear and be enforced.</p>
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:18px;">
<?php foreach ( $status_cards as $label => $status ) : ?>
<div style="border:1px solid #d9e1ef;border-radius:16px;padding:18px;background:#f8fbff;">
<h3 style="margin-top:0;margin-bottom:8px;"><?php echo esc_html( $label ); ?></h3>
<p style="margin:0;color:#5f6f8b;"><?php echo esc_html( $status ); ?></p>
</div>
<?php endforeach; ?>
</div>
<div style="display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px 18px;margin-top:18px;">
<label style="grid-column:1 / -1;">
<span style="display:flex;align-items:center;gap:10px;">
<input type="checkbox" name="ethnic_recaptcha[contact_form_7_enabled]" value="1" <?php checked( ! empty( $settings['contact_form_7_enabled'] ) ); ?> />
<span>Show and verify the Google v2 checkbox on Contact Form 7 forms.</span>
</span>
</label>
<label style="grid-column:1 / -1;">
<span style="display:flex;align-items:center;gap:10px;">
<input type="checkbox" name="ethnic_recaptcha[proposal_request_enabled]" value="1" <?php checked( ! empty( $settings['proposal_request_enabled'] ) ); ?> />
<span>Show and verify the Google v2 checkbox on the Request a Proposal form.</span>
</span>
</label>
<label style="grid-column:1 / -1;">
<span style="display:flex;align-items:center;gap:10px;">
<input type="checkbox" name="ethnic_recaptcha[resource_download_enabled]" value="1" <?php checked( ! empty( $settings['resource_download_enabled'] ) ); ?> />
<span>Show and verify the Google v2 checkbox on public resource download forms.</span>
</span>
</label>
<label style="grid-column:1 / -1;">
<span style="display:flex;align-items:center;gap:10px;">
<input type="checkbox" name="ethnic_recaptcha[wordpress_comments_enabled]" value="1" <?php checked( ! empty( $settings['wordpress_comments_enabled'] ) ); ?> />
<span>Show and verify the Google v2 checkbox on WordPress blog comment forms for logged-out visitors.</span>
</span>
</label>
</div>
</div>
<div style="background:#fff;border:1px solid #d9e1ef;border-radius:16px;padding:24px;margin-bottom:18px;">
<h2 style="margin-top:0;">Notes</h2>
<ul style="margin:0;padding-left:18px;display:grid;gap:8px;color:#334155;">
<li>This setup is for Google reCAPTCHA v2 checkbox only.</li>
<li>If you previously saved v3 keys, replace them with v2 checkbox keys before expecting a visible widget.</li>
<li>Contact Form 7 built-in v3 integration is bypassed when this shared Contact Form 7 option is enabled.</li>
</ul>
</div>
<?php submit_button( 'Save reCAPTCHA Settings' ); ?>
</form>
</div>
<?php
}
}