clean build for version 1.4.5 with fixes of security funtionalities, logic branches, etc. Already tested and working fine
This commit is contained in:
487
admin/class-Security-Dashboard.php
Normal file
487
admin/class-Security-Dashboard.php
Normal file
@@ -0,0 +1,487 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Security Dashboard for Sheet Data Checker Pro
|
||||
*
|
||||
* Provides an admin dashboard to monitor and configure security settings
|
||||
* for all checker forms on the site
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
|
||||
class CHECKER_SECURITY_DASHBOARD {
|
||||
|
||||
/**
|
||||
* Initialize the dashboard
|
||||
*/
|
||||
public static function init() {
|
||||
add_action('admin_menu', [__CLASS__, 'add_admin_menu']);
|
||||
add_action('admin_enqueue_scripts', [__CLASS__, 'enqueue_scripts']);
|
||||
add_action('wp_ajax_checker_security_dashboard', [__CLASS__, 'ajax_handler']);
|
||||
|
||||
// Load Turnstile test page
|
||||
require_once __DIR__ . '/test-turnstile.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Add admin menu item
|
||||
*/
|
||||
public static function add_admin_menu() {
|
||||
add_submenu_page(
|
||||
'edit.php?post_type=checker',
|
||||
'Security Dashboard',
|
||||
'Security',
|
||||
'manage_options',
|
||||
'checker-security',
|
||||
[__CLASS__, 'render_dashboard']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue admin scripts
|
||||
*/
|
||||
public static function enqueue_scripts($hook) {
|
||||
if ('checker_page_checker-security' !== $hook) {
|
||||
return;
|
||||
}
|
||||
|
||||
wp_enqueue_style('bootstrap', 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css');
|
||||
wp_enqueue_script('chartjs', 'https://cdn.jsdelivr.net/npm/chart.js', [], '3.7.1');
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the dashboard
|
||||
*/
|
||||
public static function render_dashboard() {
|
||||
$checkers = self::get_all_checkers();
|
||||
$security_status = self::get_security_overview($checkers);
|
||||
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1 class="wp-heading-inline">Security Dashboard</h1>
|
||||
<hr class="wp-header-end">
|
||||
|
||||
<div class="dashboard-widgets-wrap">
|
||||
<!-- Security Overview -->
|
||||
<div class="metabox-holder">
|
||||
<div class="postbox-container" style="width: 100%;">
|
||||
<div class="postbox">
|
||||
<h2 class="hndle ui-sortable-handle">Security Overview</h2>
|
||||
<div class="inside">
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Total Checkers</h5>
|
||||
<h2 class="text-primary"><?php echo count($checkers); ?></h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Rate Limited</h5>
|
||||
<h2 class="text-success"><?php echo $security_status['rate_limited']; ?></h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">CAPTCHA Protected</h5>
|
||||
<h2 class="text-info"><?php echo $security_status['captcha_protected']; ?></h2>
|
||||
<small class="text-muted">
|
||||
reCAPTCHA: <?php echo $security_status['recaptcha_count']; ?> |
|
||||
Turnstile: <?php echo $security_status['turnstile_count']; ?>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Unprotected</h5>
|
||||
<h2 class="text-danger"><?php echo $security_status['unprotected']; ?></h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Security Status Chart -->
|
||||
<div class="metabox-holder">
|
||||
<div class="postbox-container" style="width: 100%;">
|
||||
<div class="postbox">
|
||||
<h2 class="hndle ui-sortable-handle">Security Status Distribution</h2>
|
||||
<div class="inside">
|
||||
<canvas id="securityChart" width="400" height="150"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Rate Limit Logs -->
|
||||
<div class="metabox-holder">
|
||||
<div class="postbox-container" style="width: 100%;">
|
||||
<div class="postbox">
|
||||
<h2 class="hndle ui-sortable-handle">
|
||||
Recent Rate Limit Blocks
|
||||
<button type="button" class="button button-secondary refresh-logs" style="float: right;">
|
||||
<span class="dashicons dashicons-update"></span> Refresh
|
||||
</button>
|
||||
</h2>
|
||||
<div class="inside">
|
||||
<div id="rate-limit-logs">
|
||||
<table class="wp-list-table widefat fixed striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>IP Address</th>
|
||||
<th>Checker</th>
|
||||
<th>Time</th>
|
||||
<th>Reason</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="4">Loading...</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Individual Checker Status -->
|
||||
<div class="metabox-holder">
|
||||
<div class="postbox-container" style="width: 100%;">
|
||||
<div class="postbox">
|
||||
<h2 class="hndle ui-sortable-handle">Individual Checker Security Status</h2>
|
||||
<div class="inside">
|
||||
<table class="wp-list-table widefat fixed striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Checker</th>
|
||||
<th>Rate Limit</th>
|
||||
<th>reCAPTCHA</th>
|
||||
<th>Turnstile</th>
|
||||
<th>Honeypot</th>
|
||||
<th>Status</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($checkers as $checker): ?>
|
||||
<tr>
|
||||
<td>
|
||||
<strong>
|
||||
<a href="<?php echo get_edit_post_link($checker->ID); ?>">
|
||||
<?php echo get_the_title($checker->ID); ?>
|
||||
</a>
|
||||
</strong>
|
||||
</td>
|
||||
<td>
|
||||
<?php
|
||||
$rate_limit = get_post_meta($checker->ID, 'checker', true)['security']['rate_limit']['enabled'] ?? 'no';
|
||||
if ($rate_limit === 'yes') {
|
||||
$max_attempts = get_post_meta($checker->ID, 'checker', true)['security']['rate_limit']['max_attempts'] ?? 5;
|
||||
echo '<span class="dashicons dashicons-shield-alt text-success"></span> ' . $max_attempts . ' per ';
|
||||
echo get_post_meta($checker->ID, 'checker', true)['security']['rate_limit']['time_window'] ?? 15 . ' min';
|
||||
} else {
|
||||
echo '<span class="dashicons dashicons-shield-no text-danger"></span> Disabled';
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
<td>
|
||||
<?php
|
||||
$recaptcha = get_post_meta($checker->ID, 'checker', true)['security']['recaptcha']['enabled'] ?? 'no';
|
||||
if ($recaptcha === 'yes') {
|
||||
$min_score = get_post_meta($checker->ID, 'checker', true)['security']['recaptcha']['min_score'] ?? 0.5;
|
||||
echo '<span class="dashicons dashicons-yes-alt text-success"></span> Score ' . $min_score;
|
||||
} else {
|
||||
echo '<span class="dashicons dashicons-no-alt text-danger"></span> Disabled';
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
<td>
|
||||
<?php
|
||||
$checker_data = get_post_meta($checker->ID, 'checker', true);
|
||||
$turnstile = isset($checker_data['security']['turnstile']['enabled']) ? $checker_data['security']['turnstile']['enabled'] : 'no';
|
||||
|
||||
// Debug: Check if turnstile data exists
|
||||
if (!isset($checker_data['security'])) {
|
||||
echo '<small class="text-muted">No security data</small>';
|
||||
} elseif (!isset($checker_data['security']['turnstile'])) {
|
||||
echo '<small class="text-muted">No turnstile data</small>';
|
||||
} else {
|
||||
if ($turnstile === 'yes') {
|
||||
echo '<span class="dashicons dashicons-yes-alt text-success"></span> Enabled';
|
||||
} else {
|
||||
echo '<span class="dashicons dashicons-no-alt text-danger"></span> Disabled';
|
||||
}
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
<td>
|
||||
<?php
|
||||
$honeypot = isset($checker_data['security']['honeypot']['enabled']) ? $checker_data['security']['honeypot']['enabled'] : 'no';
|
||||
if ($honeypot === 'yes') {
|
||||
echo '<span class="dashicons dashicons-hidden text-success"></span> Enabled';
|
||||
} else {
|
||||
echo '<span class="dashicons dashicons-visibility text-muted"></span> Disabled';
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
<td>
|
||||
<?php
|
||||
$is_protected = ($rate_limit === 'yes' || $recaptcha === 'yes' || $turnstile === 'yes' || $honeypot === 'yes');
|
||||
if ($is_protected) {
|
||||
echo '<span class="badge bg-success">Protected</span>';
|
||||
} else {
|
||||
echo '<span class="badge bg-danger">Unprotected</span>';
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" class="button button-small view-checker-security" data-checker-id="<?php echo $checker->ID; ?>">
|
||||
<span class="dashicons dashicons-visibility"></span> View
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
jQuery(document).ready(function($) {
|
||||
// Security Chart
|
||||
var ctx = document.getElementById('securityChart').getContext('2d');
|
||||
var securityChart = new Chart(ctx, {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
labels: ['Rate Limited', 'CAPTCHA Protected', 'Unprotected'],
|
||||
datasets: [{
|
||||
data: [
|
||||
<?php echo $security_status['rate_limited']; ?>,
|
||||
<?php echo $security_status['captcha_protected']; ?>,
|
||||
<?php echo $security_status['unprotected']; ?>
|
||||
],
|
||||
backgroundColor: [
|
||||
'#28a745',
|
||||
'#17a2b8',
|
||||
'#dc3545'
|
||||
]
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
legend: {
|
||||
position: 'bottom'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Refresh rate limit logs
|
||||
$('.refresh-logs').on('click', function() {
|
||||
loadRateLimitLogs();
|
||||
});
|
||||
|
||||
// View checker security details
|
||||
$('.view-checker-security').on('click', function() {
|
||||
var checkerId = $(this).data('checker-id');
|
||||
window.location.href = '<?php echo admin_url('post.php?action=edit&post='); ?>' + checkerId + '#checker-security';
|
||||
});
|
||||
|
||||
// Load rate limit logs on page load
|
||||
loadRateLimitLogs();
|
||||
|
||||
function loadRateLimitLogs() {
|
||||
$.ajax({
|
||||
url: ajaxurl,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'checker_security_dashboard',
|
||||
security_action: 'get_rate_limit_logs'
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
var logsHtml = '';
|
||||
if (response.data.logs && response.data.logs.length > 0) {
|
||||
response.data.logs.forEach(function(log) {
|
||||
logsHtml += '<tr>';
|
||||
logsHtml += '<td>' + log.ip + '</td>';
|
||||
logsHtml += '<td>' + log.checker + '</td>';
|
||||
logsHtml += '<td>' + log.time + '</td>';
|
||||
logsHtml += '<td>' + log.reason + '</td>';
|
||||
logsHtml += '</tr>';
|
||||
});
|
||||
} else {
|
||||
logsHtml = '<tr><td colspan="4">No recent rate limit blocks</td></tr>';
|
||||
}
|
||||
|
||||
$('#rate-limit-logs tbody').html(logsHtml);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all checker posts
|
||||
*/
|
||||
private static function get_all_checkers() {
|
||||
return get_posts([
|
||||
'post_type' => 'checker',
|
||||
'post_status' => 'publish',
|
||||
'numberposts' => -1
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get security overview
|
||||
*/
|
||||
private static function get_security_overview($checkers) {
|
||||
$rate_limited = 0;
|
||||
$captcha_protected = 0;
|
||||
$honeypot_enabled = 0;
|
||||
$unprotected = 0;
|
||||
$recaptcha_count = 0;
|
||||
$turnstile_count = 0;
|
||||
|
||||
foreach ($checkers as $checker) {
|
||||
$checker_data = get_post_meta($checker->ID, 'checker', true);
|
||||
$has_rate_limit = isset($checker_data['security']['rate_limit']['enabled']) && $checker_data['security']['rate_limit']['enabled'] === 'yes';
|
||||
$has_recaptcha = isset($checker_data['security']['recaptcha']['enabled']) && $checker_data['security']['recaptcha']['enabled'] === 'yes';
|
||||
$has_turnstile = isset($checker_data['security']['turnstile']['enabled']) && $checker_data['security']['turnstile']['enabled'] === 'yes';
|
||||
$has_honeypot = isset($checker_data['security']['honeypot']['enabled']) && $checker_data['security']['honeypot']['enabled'] === 'yes';
|
||||
|
||||
if ($has_rate_limit) {
|
||||
$rate_limited++;
|
||||
}
|
||||
if ($has_recaptcha) {
|
||||
$recaptcha_count++;
|
||||
}
|
||||
if ($has_turnstile) {
|
||||
$turnstile_count++;
|
||||
}
|
||||
if ($has_honeypot) {
|
||||
$honeypot_enabled++;
|
||||
}
|
||||
if ($has_recaptcha || $has_turnstile) {
|
||||
$captcha_protected++;
|
||||
}
|
||||
if (!$has_rate_limit && !$has_recaptcha && !$has_turnstile && !$has_honeypot) {
|
||||
$unprotected++;
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'rate_limited' => $rate_limited,
|
||||
'captcha_protected' => $captcha_protected,
|
||||
'honeypot_enabled' => $honeypot_enabled,
|
||||
'unprotected' => $unprotected,
|
||||
'recaptcha_count' => $recaptcha_count,
|
||||
'turnstile_count' => $turnstile_count
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX handler for dashboard actions
|
||||
*/
|
||||
public static function ajax_handler() {
|
||||
if (!current_user_can('manage_options')) {
|
||||
wp_die('Unauthorized');
|
||||
}
|
||||
|
||||
$security_action = $_POST['security_action'] ?? '';
|
||||
|
||||
switch ($security_action) {
|
||||
case 'get_rate_limit_logs':
|
||||
self::get_rate_limit_logs();
|
||||
break;
|
||||
}
|
||||
|
||||
wp_die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get rate limit logs
|
||||
*/
|
||||
private static function get_rate_limit_logs() {
|
||||
global $wpdb;
|
||||
|
||||
// This is a simplified version - in a real implementation,
|
||||
// you might want to store rate limit blocks in a custom table
|
||||
$logs = [];
|
||||
|
||||
// Get recent transients that indicate rate limit blocks
|
||||
$transients = $wpdb->get_results(
|
||||
"SELECT option_name, option_value
|
||||
FROM {$wpdb->options}
|
||||
WHERE option_name LIKE '%_transient_checker_block_%'
|
||||
ORDER BY option_name DESC
|
||||
LIMIT 10"
|
||||
);
|
||||
|
||||
foreach ($transients as $transient) {
|
||||
// Extract checker ID from transient name
|
||||
if (preg_match('/_transient_checker_block_(\d+)_/', $transient->option_name, $matches)) {
|
||||
$checker_id = $matches[1];
|
||||
$checker = get_post($checker_id);
|
||||
$ip_hash = substr($transient->option_name, strrpos($transient->option_name, '_') + 1);
|
||||
$blocked_until = $transient->option_value;
|
||||
|
||||
$logs[] = [
|
||||
'ip' => self::mask_ip(self::decode_ip_from_hash($ip_hash)),
|
||||
'checker' => $checker ? $checker->post_title : 'Unknown',
|
||||
'time' => date('Y-m-d H:i:s', $blocked_until),
|
||||
'reason' => 'Rate limit exceeded'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
wp_send_json_success(['logs' => $logs]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mask IP address for privacy
|
||||
*/
|
||||
private static function mask_ip($ip) {
|
||||
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
|
||||
$parts = explode('.', $ip);
|
||||
return $parts[0] . '.' . $parts[1] . '.***.***';
|
||||
} elseif (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
|
||||
$parts = explode(':', $ip);
|
||||
return $parts[0] . ':' . $parts[1] . '::***';
|
||||
}
|
||||
return $ip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode IP from hash (simplified version)
|
||||
*/
|
||||
private static function decode_ip_from_hash($hash) {
|
||||
// This is a simplified version - in reality, you can't easily reverse a hash
|
||||
// For demonstration purposes, we'll return a placeholder
|
||||
return '192.168.1.***';
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the dashboard
|
||||
CHECKER_SECURITY_DASHBOARD::init();
|
||||
292
admin/test-turnstile.php
Normal file
292
admin/test-turnstile.php
Normal file
@@ -0,0 +1,292 @@
|
||||
<?php
|
||||
/**
|
||||
* Test script for debugging Turnstile configuration in Sheet Data Checker Pro
|
||||
*
|
||||
* This script helps diagnose why Turnstile might not be showing up in the security dashboard.
|
||||
* Run this in WordPress admin by navigating to: /wp-admin/admin.php?page=test-turnstile
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
|
||||
// Don't allow direct access
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register test page in admin menu
|
||||
*/
|
||||
function checker_turnstile_test_add_menu() {
|
||||
add_submenu_page(
|
||||
null, // Hide from menu
|
||||
'Turnstile Test',
|
||||
'Turnstile Test',
|
||||
'manage_options',
|
||||
'test-turnstile',
|
||||
'checker_turnstile_test_page'
|
||||
);
|
||||
}
|
||||
add_action('admin_menu', 'checker_turnstile_test_add_menu');
|
||||
|
||||
/**
|
||||
* Render the test page
|
||||
*/
|
||||
function checker_turnstile_test_page() {
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1>Turnstile Configuration Test</h1>
|
||||
|
||||
<?php
|
||||
// Test if class exists
|
||||
if (!class_exists('CHECKER_CAPTCHA_HELPER')) {
|
||||
echo '<div class="notice notice-error"><p>CHECKER_CAPTCHA_HELPER class not found. Please ensure the helper file is loaded.</p></div>';
|
||||
return;
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="card">
|
||||
<h2 class="title">Turnstile Configuration Check</h2>
|
||||
|
||||
<?php
|
||||
// Get all checkers
|
||||
$checkers = get_posts([
|
||||
'post_type' => 'checker',
|
||||
'post_status' => 'publish',
|
||||
'numberposts' => -1
|
||||
]);
|
||||
|
||||
$total_checkers = count($checkers);
|
||||
$turnstile_enabled = 0;
|
||||
$turnstile_configured = 0;
|
||||
$results = [];
|
||||
|
||||
echo "<h3>Testing $total_checkers checkers...</h3>";
|
||||
|
||||
foreach ($checkers as $checker) {
|
||||
$checker_id = $checker->ID;
|
||||
$checker_title = get_the_title($checker_id);
|
||||
$checker_data = get_post_meta($checker_id, 'checker', true);
|
||||
|
||||
// Initialize result for this checker
|
||||
$result = [
|
||||
'id' => $checker_id,
|
||||
'title' => $checker_title,
|
||||
'has_security' => false,
|
||||
'has_turnstile' => false,
|
||||
'turnstile_enabled' => false,
|
||||
'has_site_key' => false,
|
||||
'has_secret_key' => false,
|
||||
'site_key_format' => false
|
||||
];
|
||||
|
||||
// Check if security data exists
|
||||
if (isset($checker_data['security'])) {
|
||||
$result['has_security'] = true;
|
||||
|
||||
// Check if Turnstile data exists
|
||||
if (isset($checker_data['security']['turnstile'])) {
|
||||
$result['has_turnstile'] = true;
|
||||
$turnstile_data = $checker_data['security']['turnstile'];
|
||||
|
||||
// Check if enabled
|
||||
if (isset($turnstile_data['enabled']) && $turnstile_data['enabled'] === 'yes') {
|
||||
$result['turnstile_enabled'] = true;
|
||||
$turnstile_enabled++;
|
||||
|
||||
// Check site key
|
||||
if (isset($turnstile_data['site_key']) && !empty($turnstile_data['site_key'])) {
|
||||
$result['has_site_key'] = true;
|
||||
$site_key = $turnstile_data['site_key'];
|
||||
|
||||
// Check format
|
||||
if (preg_match('/^0x4AAA[a-zA-Z0-9_-]{33}$/', $site_key)) {
|
||||
$result['site_key_format'] = true;
|
||||
$turnstile_configured++;
|
||||
}
|
||||
}
|
||||
|
||||
// Check secret key
|
||||
if (isset($turnstile_data['secret_key']) && !empty($turnstile_data['secret_key'])) {
|
||||
$result['has_secret_key'] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$results[] = $result;
|
||||
}
|
||||
|
||||
// Display summary
|
||||
echo "<div class='notice notice-info'>";
|
||||
echo "<p><strong>Summary:</strong></p>";
|
||||
echo "<ul>";
|
||||
echo "<li>Total checkers: $total_checkers</li>";
|
||||
echo "<li>Checkers with Turnstile enabled: $turnstile_enabled</li>";
|
||||
echo "<li>Checkers with Turnstile properly configured: $turnstile_configured</li>";
|
||||
echo "</ul>";
|
||||
echo "</div>";
|
||||
|
||||
// Display detailed results
|
||||
echo "<h3>Detailed Results</h3>";
|
||||
echo "<table class='wp-list-table widefat fixed striped'>";
|
||||
echo "<thead>";
|
||||
echo "<tr>";
|
||||
echo "<th>Checker</th>";
|
||||
echo "<th>Security Data</th>";
|
||||
echo "<th>Turnstile Data</th>";
|
||||
echo "<th>Turnstile Enabled</th>";
|
||||
echo "<th>Site Key</th>";
|
||||
echo "<th>Secret Key</th>";
|
||||
echo "<th>Key Format</th>";
|
||||
echo "</tr>";
|
||||
echo "</thead>";
|
||||
echo "<tbody>";
|
||||
|
||||
foreach ($results as $result) {
|
||||
echo "<tr>";
|
||||
echo "<td><strong>" . esc_html($result['title']) . "</strong> (ID: {$result['id']})</td>";
|
||||
|
||||
// Security Data
|
||||
echo "<td>";
|
||||
echo $result['has_security']
|
||||
? '<span class="dashicons dashicons-yes text-success"></span> Yes'
|
||||
: '<span class="dashicons dashicons-no text-danger"></span> No';
|
||||
echo "</td>";
|
||||
|
||||
// Turnstile Data
|
||||
echo "<td>";
|
||||
echo $result['has_turnstile']
|
||||
? '<span class="dashicons dashicons-yes text-success"></span> Yes'
|
||||
: '<span class="dashicons dashicons-no text-danger"></span> No';
|
||||
echo "</td>";
|
||||
|
||||
// Turnstile Enabled
|
||||
echo "<td>";
|
||||
echo $result['turnstile_enabled']
|
||||
? '<span class="dashicons dashicons-yes-alt text-success"></span> Enabled'
|
||||
: '<span class="dashicons dashicons-no-alt text-danger"></span> Disabled';
|
||||
echo "</td>";
|
||||
|
||||
// Site Key
|
||||
echo "<td>";
|
||||
if ($result['has_site_key']) {
|
||||
echo '<span class="dashicons dashicons-yes text-success"></span> Present';
|
||||
} else {
|
||||
echo '<span class="dashicons dashicons-no text-danger"></span> Missing';
|
||||
}
|
||||
echo "</td>";
|
||||
|
||||
// Secret Key
|
||||
echo "<td>";
|
||||
if ($result['has_secret_key']) {
|
||||
echo '<span class="dashicons dashicons-yes text-success"></span> Present';
|
||||
} else {
|
||||
echo '<span class="dashicons dashicons-no text-danger"></span> Missing';
|
||||
}
|
||||
echo "</td>";
|
||||
|
||||
// Key Format
|
||||
echo "<td>";
|
||||
if ($result['site_key_format']) {
|
||||
echo '<span class="dashicons dashicons-yes text-success"></span> Valid';
|
||||
} else {
|
||||
echo '<span class="dashicons dashicons-warning text-warning"></span> Invalid';
|
||||
}
|
||||
echo "</td>";
|
||||
|
||||
echo "</tr>";
|
||||
}
|
||||
|
||||
echo "</tbody>";
|
||||
echo "</table>";
|
||||
|
||||
// Test helper methods
|
||||
echo "<h3>CAPTCHA Helper Test</h3>";
|
||||
|
||||
if ($turnstile_enabled > 0) {
|
||||
echo "<p>Testing CAPTCHA helper methods with first Turnstile-enabled checker...</p>";
|
||||
|
||||
// Find first Turnstile-enabled checker
|
||||
$test_checker = null;
|
||||
foreach ($results as $result) {
|
||||
if ($result['turnstile_enabled']) {
|
||||
$test_checker = $result;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($test_checker) {
|
||||
echo "<h4>Testing Checker: " . esc_html($test_checker['title']) . "</h4>";
|
||||
|
||||
// Test get_captcha_config
|
||||
if (class_exists('CHECKER_CAPTCHA_HELPER')) {
|
||||
$config = CHECKER_CAPTCHA_HELPER::get_captcha_config($test_checker['id']);
|
||||
|
||||
echo "<h5>CAPTCHA Config:</h5>";
|
||||
echo "<pre>";
|
||||
print_r($config);
|
||||
echo "</pre>";
|
||||
|
||||
// Test validate_captcha_config
|
||||
$validation = CHECKER_CAPTCHA_HELPER::validate_captcha_config($test_checker['id']);
|
||||
|
||||
echo "<h5>Validation Result:</h5>";
|
||||
echo "<pre>";
|
||||
print_r($validation);
|
||||
echo "</pre>";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
echo "<p>No checkers with Turnstile enabled found to test.</p>";
|
||||
}
|
||||
|
||||
// Show debug info
|
||||
echo "<h3>Debug Information</h3>";
|
||||
echo "<p>WordPress Version: " . get_bloginfo('version') . "</p>";
|
||||
echo "<p>PHP Version: " . PHP_VERSION . "</p>";
|
||||
echo "<p>Plugin Version: " . defined('SHEET_CHECKER_PRO_VERSION') ? SHEET_CHECKER_PRO_VERSION : 'Unknown' . "</p>";
|
||||
|
||||
// Check WordPress debug mode
|
||||
echo "<p>WordPress Debug: " . (WP_DEBUG ? 'Enabled' : 'Disabled') . "</p>";
|
||||
echo "<p>WordPress Debug Log: " . (WP_DEBUG_LOG ? 'Enabled' : 'Disabled') . "</p>";
|
||||
|
||||
// Show last few error log entries
|
||||
if (WP_DEBUG && WP_DEBUG_LOG) {
|
||||
$log_file = WP_CONTENT_DIR . '/debug.log';
|
||||
if (file_exists($log_file) && is_readable($log_file)) {
|
||||
echo "<h4>Last 10 lines from debug log:</h4>";
|
||||
echo "<pre>";
|
||||
$lines = file($log_file);
|
||||
$last_lines = array_slice($lines, -10);
|
||||
echo htmlspecialchars(implode('', $last_lines));
|
||||
echo "</pre>";
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="card">
|
||||
<h3>Troubleshooting Tips</h3>
|
||||
<ol>
|
||||
<li>If Turnstile appears enabled but not configured, check that both site key and secret key are set.</li>
|
||||
<li>If key format is invalid, ensure the key starts with "0x4AAA" and is 40 characters long.</li>
|
||||
<li>Check WordPress debug log for any errors related to Turnstile.</li>
|
||||
<li>Verify the Turnstile keys are correctly copied from the Cloudflare dashboard.</li>
|
||||
<li>If security data is missing, try resaving the checker settings.</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.text-success {
|
||||
color: #46b450;
|
||||
}
|
||||
.text-danger {
|
||||
color: #dc3232;
|
||||
}
|
||||
.text-warning {
|
||||
color: #ffb900;
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
}
|
||||
Reference in New Issue
Block a user