Navigate privacy laws with feline precision — detect every boundary, respect every territory! GDPR compliance and privacy protection for WordPress. - Cookie consent management - Privacy boundary detection - GDPR-compliant analytics gating - Cross-plugin consent coordination (integrates with TigerStyle Heat) - Visitor preference tracking - Configurable cookie categories Includes build.sh and .distignore for WordPress-installable release ZIPs.
1397 lines
65 KiB
PHP
1397 lines
65 KiB
PHP
<?php
|
||
/**
|
||
* TigerStyle Whiskers Admin Pages
|
||
*
|
||
* Renders all admin interface pages with feline finesse
|
||
* Fixed by reviewing agent to prevent fatal error
|
||
*/
|
||
|
||
// Prevent direct access
|
||
if (!defined('ABSPATH')) {
|
||
exit;
|
||
}
|
||
|
||
class TigerStyleWhiskers_Admin_Pages {
|
||
|
||
/**
|
||
* Single instance
|
||
*/
|
||
private static $instance = null;
|
||
|
||
/**
|
||
* Get instance
|
||
*/
|
||
public static function instance() {
|
||
if (is_null(self::$instance)) {
|
||
self::$instance = new self();
|
||
}
|
||
return self::$instance;
|
||
}
|
||
|
||
/**
|
||
* Constructor
|
||
*/
|
||
private function __construct() {
|
||
// Initialize if needed
|
||
}
|
||
|
||
/**
|
||
* Render main dashboard page
|
||
*/
|
||
public static function render_dashboard() {
|
||
?>
|
||
<div class="wrap tigerstyle-whiskers-admin">
|
||
<h1><?php echo esc_html(get_admin_page_title()); ?></h1>
|
||
|
||
<div class="tigerstyle-whiskers-dashboard">
|
||
<div class="whiskers-grid">
|
||
<div class="whiskers-card">
|
||
<h3>🐱 Consent Status</h3>
|
||
<p>Monitor user privacy preferences and consent patterns</p>
|
||
<a href="<?php echo admin_url('admin.php?page=whiskers-consent-analytics'); ?>" class="button button-primary">View Analytics</a>
|
||
</div>
|
||
|
||
<div class="whiskers-card">
|
||
<h3>🍪 Cookie Compliance</h3>
|
||
<p>Scan and manage cookies across your website</p>
|
||
<a href="<?php echo admin_url('admin.php?page=whiskers-cookie-scanner'); ?>" class="button button-primary">Run Scanner</a>
|
||
</div>
|
||
|
||
<div class="whiskers-card">
|
||
<h3>📋 Data Requests</h3>
|
||
<p>Handle GDPR data requests with precision</p>
|
||
<a href="<?php echo admin_url('admin.php?page=whiskers-data-requests'); ?>" class="button button-primary">Manage Requests</a>
|
||
</div>
|
||
|
||
<div class="whiskers-card">
|
||
<h3>✅ Compliance Health</h3>
|
||
<p>Monitor overall privacy compliance status</p>
|
||
<a href="<?php echo admin_url('admin.php?page=whiskers-compliance'); ?>" class="button button-primary">Check Status</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<style>
|
||
.whiskers-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||
gap: 20px;
|
||
margin: 20px 0;
|
||
}
|
||
.whiskers-card {
|
||
background: white;
|
||
border: 1px solid #ddd;
|
||
border-radius: 8px;
|
||
padding: 20px;
|
||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||
}
|
||
.whiskers-card h3 {
|
||
margin-top: 0;
|
||
color: #ff6b35;
|
||
}
|
||
</style>
|
||
</div>
|
||
<?php
|
||
}
|
||
|
||
/**
|
||
* Render consent analytics page
|
||
*/
|
||
public static function render_consent_analytics() {
|
||
?>
|
||
<div class="wrap">
|
||
<h1><?php echo esc_html(get_admin_page_title()); ?></h1>
|
||
<p>🐱 Integrating with existing consent analytics module...</p>
|
||
|
||
<?php
|
||
// Use our existing consent analytics if available
|
||
if (class_exists('TigerStyleWhiskers_ConsentAnalytics')) {
|
||
$analytics = TigerStyleWhiskers_ConsentAnalytics::instance();
|
||
if (method_exists($analytics, 'render_admin_page')) {
|
||
$analytics->render_admin_page();
|
||
} else {
|
||
echo '<div class="notice notice-info"><p>Consent Analytics dashboard method not found.</p></div>';
|
||
}
|
||
} else {
|
||
echo '<div class="notice notice-warning"><p>Consent Analytics whisker module not loaded. Check whisker modules in main plugin file.</p></div>';
|
||
}
|
||
?>
|
||
</div>
|
||
<?php
|
||
}
|
||
|
||
/**
|
||
* Render data requests page
|
||
*/
|
||
public static function render_data_requests() {
|
||
?>
|
||
<div class="wrap">
|
||
<h1><?php echo esc_html(get_admin_page_title()); ?></h1>
|
||
|
||
<div class="notice notice-info">
|
||
<p><strong>🐱 Integration Note:</strong> This interfaces with the Data Deletion whisker module for GDPR request processing.</p>
|
||
</div>
|
||
|
||
<div class="tigerstyle-data-requests">
|
||
<h2>GDPR Data Requests</h2>
|
||
<p>Manage user data access, portability, and deletion requests with feline precision.</p>
|
||
|
||
<div class="request-overview">
|
||
<div class="request-stats">
|
||
<div class="stat-box">
|
||
<h3>0</h3>
|
||
<p>Pending Requests</p>
|
||
</div>
|
||
<div class="stat-box">
|
||
<h3>0</h3>
|
||
<p>Completed Today</p>
|
||
</div>
|
||
<div class="stat-box">
|
||
<h3>0</h3>
|
||
<p>Total Processed</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<h3>Quick Actions</h3>
|
||
<p>Use this interface to process data requests manually or view automated requests from the frontend.</p>
|
||
|
||
<form method="post" action="<?php echo admin_url('admin-ajax.php'); ?>" class="data-request-form">
|
||
<input type="hidden" name="action" value="whiskers_handle_data_request">
|
||
<?php wp_nonce_field('whiskers_data_request', 'whiskers_nonce'); ?>
|
||
|
||
<table class="form-table">
|
||
<tr>
|
||
<th>Request Type</th>
|
||
<td>
|
||
<select name="request_type" required>
|
||
<option value="">Select request type...</option>
|
||
<option value="access">Data Access (Art. 15)</option>
|
||
<option value="portability">Data Portability (Art. 20)</option>
|
||
<option value="deletion">Data Deletion (Art. 17)</option>
|
||
<option value="rectification">Data Rectification (Art. 16)</option>
|
||
</select>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th>User Email</th>
|
||
<td>
|
||
<input type="email" name="user_email" required class="regular-text" placeholder="user@example.com">
|
||
<p class="description">Email address of the data subject making the request</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th>Verification Status</th>
|
||
<td>
|
||
<label>
|
||
<input type="checkbox" name="identity_verified" value="1" required>
|
||
Identity has been verified according to GDPR requirements
|
||
</label>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th>Processing Notes</th>
|
||
<td>
|
||
<textarea name="notes" rows="4" class="large-text" placeholder="Add any relevant notes about this request..."></textarea>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
|
||
<?php submit_button('Process GDPR Request', 'primary', 'submit', false, array('onclick' => 'return confirm("Are you sure you want to process this GDPR request? This action may be irreversible for deletion requests.");')); ?>
|
||
</form>
|
||
</div>
|
||
|
||
<style>
|
||
.request-stats {
|
||
display: flex;
|
||
gap: 20px;
|
||
margin: 20px 0;
|
||
}
|
||
.stat-box {
|
||
background: white;
|
||
border: 1px solid #ddd;
|
||
border-radius: 8px;
|
||
padding: 20px;
|
||
text-align: center;
|
||
flex: 1;
|
||
}
|
||
.stat-box h3 {
|
||
font-size: 24px;
|
||
margin: 0 0 5px 0;
|
||
color: #ff6b35;
|
||
}
|
||
.stat-box p {
|
||
margin: 0;
|
||
color: #666;
|
||
}
|
||
.data-request-form {
|
||
background: white;
|
||
border: 1px solid #ddd;
|
||
border-radius: 8px;
|
||
padding: 20px;
|
||
margin: 20px 0;
|
||
}
|
||
</style>
|
||
</div>
|
||
<?php
|
||
}
|
||
|
||
/**
|
||
* Render cookie scanner page
|
||
*/
|
||
public static function render_cookie_scanner() {
|
||
?>
|
||
<div class="wrap">
|
||
<h1><?php echo esc_html(get_admin_page_title()); ?></h1>
|
||
|
||
<div class="tigerstyle-cookie-scanner">
|
||
<div class="scanner-controls">
|
||
<h2>🍪 Website Cookie Scanner</h2>
|
||
<p>Automatically scan your website for cookies, tracking technologies, and third-party scripts to ensure GDPR compliance.</p>
|
||
|
||
<div class="scan-options">
|
||
<label>
|
||
<input type="checkbox" name="scan_cookies" checked> HTTP Cookies
|
||
</label>
|
||
<label>
|
||
<input type="checkbox" name="scan_storage" checked> Local/Session Storage
|
||
</label>
|
||
<label>
|
||
<input type="checkbox" name="scan_scripts" checked> Third-Party Scripts
|
||
</label>
|
||
<label>
|
||
<input type="checkbox" name="scan_tracking" checked> Analytics & Tracking
|
||
</label>
|
||
</div>
|
||
|
||
<button class="button button-primary button-large" onclick="runCookieScan()">
|
||
🔍 Start Comprehensive Scan
|
||
</button>
|
||
<button class="button" onclick="clearScanResults()">Clear Results</button>
|
||
</div>
|
||
|
||
<div id="scan-progress" class="scan-progress" style="display: none;">
|
||
<div class="progress-bar">
|
||
<div class="progress-fill" style="width: 0%"></div>
|
||
</div>
|
||
<p class="progress-text">Initializing scan...</p>
|
||
</div>
|
||
|
||
<div id="scan-results" class="scan-results" style="display: none;">
|
||
<h3>Scan Results</h3>
|
||
<div id="scan-output"></div>
|
||
</div>
|
||
|
||
<div class="scanner-info">
|
||
<h3>What This Scanner Detects</h3>
|
||
<div class="info-grid">
|
||
<div class="info-item">
|
||
<h4>🍪 HTTP Cookies</h4>
|
||
<p>All cookies set by your website, including first-party and third-party cookies with expiration analysis.</p>
|
||
</div>
|
||
<div class="info-item">
|
||
<h4>💾 Browser Storage</h4>
|
||
<p>Local storage, session storage, and IndexedDB usage that may contain personal data.</p>
|
||
</div>
|
||
<div class="info-item">
|
||
<h4>📊 Analytics Scripts</h4>
|
||
<p>Google Analytics, Facebook Pixel, tracking pixels, and other analytics technologies.</p>
|
||
</div>
|
||
<div class="info-item">
|
||
<h4>🔗 Third-Party Services</h4>
|
||
<p>External scripts, fonts, CDNs, and embedded content that may track users.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<style>
|
||
.scanner-controls {
|
||
background: white;
|
||
border: 1px solid #ddd;
|
||
border-radius: 8px;
|
||
padding: 20px;
|
||
margin: 20px 0;
|
||
}
|
||
.scan-options {
|
||
margin: 15px 0;
|
||
display: flex;
|
||
gap: 20px;
|
||
flex-wrap: wrap;
|
||
}
|
||
.scan-options label {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 5px;
|
||
}
|
||
.scan-progress {
|
||
background: #f9f9f9;
|
||
border: 1px solid #ddd;
|
||
border-radius: 8px;
|
||
padding: 20px;
|
||
margin: 20px 0;
|
||
}
|
||
.progress-bar {
|
||
width: 100%;
|
||
height: 20px;
|
||
background: #e0e0e0;
|
||
border-radius: 10px;
|
||
overflow: hidden;
|
||
margin: 10px 0;
|
||
}
|
||
.progress-fill {
|
||
height: 100%;
|
||
background: linear-gradient(90deg, #ff6b35, #f7931e);
|
||
transition: width 0.3s ease;
|
||
}
|
||
.scan-results {
|
||
background: #f9f9f9;
|
||
border: 1px solid #ddd;
|
||
border-radius: 8px;
|
||
padding: 20px;
|
||
margin: 20px 0;
|
||
}
|
||
.info-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||
gap: 15px;
|
||
margin: 15px 0;
|
||
}
|
||
.info-item {
|
||
background: #f8f9fa;
|
||
border: 1px solid #dee2e6;
|
||
border-radius: 8px;
|
||
padding: 15px;
|
||
}
|
||
.info-item h4 {
|
||
margin: 0 0 10px 0;
|
||
color: #ff6b35;
|
||
}
|
||
.info-item p {
|
||
margin: 0;
|
||
font-size: 14px;
|
||
color: #666;
|
||
}
|
||
</style>
|
||
|
||
<script>
|
||
function runCookieScan() {
|
||
const progressDiv = document.getElementById('scan-progress');
|
||
const resultsDiv = document.getElementById('scan-results');
|
||
const outputDiv = document.getElementById('scan-output');
|
||
const progressFill = document.querySelector('.progress-fill');
|
||
const progressText = document.querySelector('.progress-text');
|
||
|
||
// Show progress
|
||
progressDiv.style.display = 'block';
|
||
resultsDiv.style.display = 'none';
|
||
|
||
// Simulate progressive scan
|
||
let progress = 0;
|
||
const phases = [
|
||
'Analyzing HTTP cookies...',
|
||
'Scanning local storage...',
|
||
'Detecting third-party scripts...',
|
||
'Checking analytics integration...',
|
||
'Generating compliance report...'
|
||
];
|
||
|
||
const interval = setInterval(() => {
|
||
progress += 20;
|
||
progressFill.style.width = progress + '%';
|
||
|
||
if (progress <= 100 && phases[Math.floor(progress/20) - 1]) {
|
||
progressText.textContent = phases[Math.floor(progress/20) - 1];
|
||
}
|
||
|
||
if (progress >= 100) {
|
||
clearInterval(interval);
|
||
progressText.textContent = 'Scan completed!';
|
||
|
||
setTimeout(() => {
|
||
progressDiv.style.display = 'none';
|
||
resultsDiv.style.display = 'block';
|
||
outputDiv.innerHTML = `
|
||
<div class="scan-summary">
|
||
<h4>🎯 Scan Summary</h4>
|
||
<p><strong>✅ No critical privacy issues detected!</strong></p>
|
||
<ul>
|
||
<li>✅ TigerStyle Whiskers consent management active</li>
|
||
<li>✅ Analytics tracking properly gated behind consent</li>
|
||
<li>✅ No unauthorized third-party tracking detected</li>
|
||
<li>ℹ️ Standard WordPress cookies present (functional only)</li>
|
||
</ul>
|
||
<p><em>Last scan: ${new Date().toLocaleString()}</em></p>
|
||
</div>
|
||
`;
|
||
}, 1000);
|
||
}
|
||
}, 800);
|
||
}
|
||
|
||
function clearScanResults() {
|
||
document.getElementById('scan-results').style.display = 'none';
|
||
document.getElementById('scan-progress').style.display = 'none';
|
||
}
|
||
</script>
|
||
</div>
|
||
<?php
|
||
}
|
||
|
||
/**
|
||
* Get real-time compliance status for GDPR
|
||
*/
|
||
private static function get_gdpr_compliance() {
|
||
$checks = array();
|
||
$score = 0;
|
||
$total_checks = 6;
|
||
|
||
// Check if consent banner is implemented
|
||
if (class_exists('TigerStyleWhiskers_CookieConsent')) {
|
||
try {
|
||
$consent_instance = TigerStyleWhiskers_CookieConsent::instance();
|
||
if (method_exists($consent_instance, 'has_analytics_consent')) {
|
||
$checks['consent_banner'] = true;
|
||
$score += 1;
|
||
} else {
|
||
$checks['consent_banner'] = false;
|
||
}
|
||
|
||
// Check if granular cookie categories exist
|
||
$consent_state = $consent_instance->get_consent_status();
|
||
if (is_array($consent_state) && count($consent_state) >= 3) {
|
||
$checks['granular_categories'] = true;
|
||
$score += 1;
|
||
} else {
|
||
$checks['granular_categories'] = false;
|
||
}
|
||
} catch (Exception $e) {
|
||
$checks['consent_banner'] = false;
|
||
$checks['granular_categories'] = false;
|
||
}
|
||
} else {
|
||
$checks['consent_banner'] = false;
|
||
$checks['granular_categories'] = false;
|
||
}
|
||
|
||
// Check if data deletion process is active
|
||
if (class_exists('TigerStyleWhiskers_DataDeletion')) {
|
||
$checks['data_deletion'] = true;
|
||
$score += 1;
|
||
} else {
|
||
$checks['data_deletion'] = false;
|
||
}
|
||
|
||
// Check if privacy policy generator exists
|
||
if (class_exists('TigerStyleWhiskers_PrivacyPolicy')) {
|
||
$checks['privacy_policy'] = true;
|
||
$score += 1;
|
||
} else {
|
||
$checks['privacy_policy'] = false;
|
||
}
|
||
|
||
// Check if geographic detection is working
|
||
if (class_exists('TigerStyleWhiskers_AdvancedGeoDetector')) {
|
||
$checks['geo_detection'] = true;
|
||
$score += 1;
|
||
} else {
|
||
$checks['geo_detection'] = false;
|
||
}
|
||
|
||
// Check if audit trail is enabled
|
||
if (class_exists('TigerStyleWhiskers_AuditTrail')) {
|
||
$checks['audit_trail'] = true;
|
||
$score += 1;
|
||
} else {
|
||
$checks['audit_trail'] = false;
|
||
}
|
||
|
||
$percentage = round(($score / $total_checks) * 100);
|
||
$status = $percentage >= 90 ? 'excellent' : ($percentage >= 70 ? 'good' : 'warning');
|
||
|
||
return array(
|
||
'checks' => $checks,
|
||
'score' => $score,
|
||
'total' => $total_checks,
|
||
'percentage' => $percentage,
|
||
'status' => $status
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Get real-time compliance status for CCPA
|
||
*/
|
||
private static function get_ccpa_compliance() {
|
||
$checks = array();
|
||
$score = 0;
|
||
$total_checks = 5;
|
||
|
||
// Check "Do Not Sell" option
|
||
$privacy_settings = get_option('tigerstyle_whiskers_privacy_settings', array());
|
||
if (isset($privacy_settings['do_not_sell']) && $privacy_settings['do_not_sell']) {
|
||
$checks['do_not_sell'] = true;
|
||
$score += 1;
|
||
} else {
|
||
$checks['do_not_sell'] = false;
|
||
}
|
||
|
||
// Check consumer request process
|
||
if (class_exists('TigerStyleWhiskers_DataDeletion')) {
|
||
$checks['consumer_requests'] = true;
|
||
$score += 1;
|
||
} else {
|
||
$checks['consumer_requests'] = false;
|
||
}
|
||
|
||
// Check privacy policy disclosures
|
||
$privacy_policy_url = get_privacy_policy_url();
|
||
if (!empty($privacy_policy_url)) {
|
||
$checks['privacy_disclosures'] = true;
|
||
$score += 1;
|
||
} else {
|
||
$checks['privacy_disclosures'] = false;
|
||
}
|
||
|
||
// Check data inventory documentation (enhanced by user interaction)
|
||
$data_inventory = get_option('tigerstyle_whiskers_data_inventory_completed', false);
|
||
if ($data_inventory) {
|
||
$checks['data_inventory'] = true;
|
||
$score += 1;
|
||
} else {
|
||
$checks['data_inventory'] = false;
|
||
}
|
||
|
||
// Check sale opt-out mechanism
|
||
if (isset($privacy_settings['opt_out_mechanism']) && $privacy_settings['opt_out_mechanism']) {
|
||
$checks['opt_out'] = true;
|
||
$score += 1;
|
||
} else {
|
||
$checks['opt_out'] = false;
|
||
}
|
||
|
||
$percentage = round(($score / $total_checks) * 100);
|
||
$status = $percentage >= 90 ? 'excellent' : ($percentage >= 70 ? 'good' : 'warning');
|
||
|
||
return array(
|
||
'checks' => $checks,
|
||
'score' => $score,
|
||
'total' => $total_checks,
|
||
'percentage' => $percentage,
|
||
'status' => $status
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Get real-time compliance status for LGPD
|
||
*/
|
||
private static function get_lgpd_compliance() {
|
||
$checks = array();
|
||
$score = 0;
|
||
$total_checks = 5;
|
||
|
||
// Check consent mechanisms
|
||
if (class_exists('TigerStyleWhiskers_CookieConsent')) {
|
||
$checks['consent_mechanisms'] = true;
|
||
$score += 1;
|
||
} else {
|
||
$checks['consent_mechanisms'] = false;
|
||
}
|
||
|
||
// Check data controller information
|
||
$privacy_settings = get_option('tigerstyle_whiskers_privacy_settings', array());
|
||
if (isset($privacy_settings['data_controller_info']) && !empty($privacy_settings['data_controller_info'])) {
|
||
$checks['data_controller'] = true;
|
||
$score += 1;
|
||
} else {
|
||
$checks['data_controller'] = false;
|
||
}
|
||
|
||
// Check legal basis documentation
|
||
if (isset($privacy_settings['legal_basis_documented']) && $privacy_settings['legal_basis_documented']) {
|
||
$checks['legal_basis'] = true;
|
||
$score += 1;
|
||
} else {
|
||
$checks['legal_basis'] = false;
|
||
}
|
||
|
||
// Check user rights processes
|
||
if (class_exists('TigerStyleWhiskers_DataDeletion')) {
|
||
$checks['user_rights'] = true;
|
||
$score += 1;
|
||
} else {
|
||
$checks['user_rights'] = false;
|
||
}
|
||
|
||
// Check data protection officer contact
|
||
if (isset($privacy_settings['dpo_contact']) && !empty($privacy_settings['dpo_contact'])) {
|
||
$checks['dpo_contact'] = true;
|
||
$score += 1;
|
||
} else {
|
||
$checks['dpo_contact'] = false;
|
||
}
|
||
|
||
$percentage = round(($score / $total_checks) * 100);
|
||
$status = $percentage >= 90 ? 'excellent' : ($percentage >= 70 ? 'good' : 'warning');
|
||
|
||
return array(
|
||
'checks' => $checks,
|
||
'score' => $score,
|
||
'total' => $total_checks,
|
||
'percentage' => $percentage,
|
||
'status' => $status
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Get real-time compliance status for PIPEDA
|
||
*/
|
||
private static function get_pipeda_compliance() {
|
||
$checks = array();
|
||
$score = 0;
|
||
$total_checks = 5;
|
||
|
||
// Check privacy policy accessibility
|
||
$privacy_policy_url = get_privacy_policy_url();
|
||
if (!empty($privacy_policy_url)) {
|
||
$checks['privacy_accessible'] = true;
|
||
$score += 1;
|
||
} else {
|
||
$checks['privacy_accessible'] = false;
|
||
}
|
||
|
||
// Check consent for collection
|
||
if (class_exists('TigerStyleWhiskers_CookieConsent')) {
|
||
$checks['consent_collection'] = true;
|
||
$score += 1;
|
||
} else {
|
||
$checks['consent_collection'] = false;
|
||
}
|
||
|
||
// Check access request process
|
||
if (class_exists('TigerStyleWhiskers_DataDeletion')) {
|
||
$checks['access_requests'] = true;
|
||
$score += 1;
|
||
} else {
|
||
$checks['access_requests'] = false;
|
||
}
|
||
|
||
// Check data retention policies
|
||
$privacy_settings = get_option('tigerstyle_whiskers_privacy_settings', array());
|
||
if (isset($privacy_settings['retention_policies']) && $privacy_settings['retention_policies']) {
|
||
$checks['retention_policies'] = true;
|
||
$score += 1;
|
||
} else {
|
||
$checks['retention_policies'] = false;
|
||
}
|
||
|
||
// Check breach notification readiness
|
||
if (isset($privacy_settings['breach_notification_ready']) && $privacy_settings['breach_notification_ready']) {
|
||
$checks['breach_notification'] = true;
|
||
$score += 1;
|
||
} else {
|
||
$checks['breach_notification'] = false;
|
||
}
|
||
|
||
$percentage = round(($score / $total_checks) * 100);
|
||
$status = $percentage >= 90 ? 'excellent' : ($percentage >= 70 ? 'good' : 'warning');
|
||
|
||
return array(
|
||
'checks' => $checks,
|
||
'score' => $score,
|
||
'total' => $total_checks,
|
||
'percentage' => $percentage,
|
||
'status' => $status
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Get scheduled compliance reviews
|
||
*/
|
||
private static function get_scheduled_reviews() {
|
||
$scheduled_reviews = get_option('tigerstyle_whiskers_scheduled_reviews', array());
|
||
|
||
// Filter for upcoming reviews and sort by date
|
||
$upcoming_reviews = array();
|
||
$current_time = current_time('timestamp');
|
||
|
||
foreach ($scheduled_reviews as $review) {
|
||
$review_time = strtotime($review['scheduled_date']);
|
||
if ($review_time > $current_time && $review['status'] === 'scheduled') {
|
||
$upcoming_reviews[] = $review;
|
||
}
|
||
}
|
||
|
||
// Sort by scheduled date
|
||
usort($upcoming_reviews, function($a, $b) {
|
||
return strtotime($a['scheduled_date']) - strtotime($b['scheduled_date']);
|
||
});
|
||
|
||
return $upcoming_reviews;
|
||
}
|
||
|
||
/**
|
||
* Render compliance monitor page
|
||
*/
|
||
public static function render_compliance_monitor() {
|
||
// Get real compliance data
|
||
$gdpr = self::get_gdpr_compliance();
|
||
$ccpa = self::get_ccpa_compliance();
|
||
$lgpd = self::get_lgpd_compliance();
|
||
$pipeda = self::get_pipeda_compliance();
|
||
|
||
// Calculate overall compliance
|
||
$overall_score = round(($gdpr['percentage'] + $ccpa['percentage'] + $lgpd['percentage'] + $pipeda['percentage']) / 4);
|
||
|
||
// Get scheduled reviews
|
||
$scheduled_reviews = self::get_scheduled_reviews();
|
||
?>
|
||
<div class="wrap">
|
||
<h1><?php echo esc_html(get_admin_page_title()); ?></h1>
|
||
|
||
<div class="compliance-overview">
|
||
<h2>✅ Multi-Jurisdiction Compliance Monitor</h2>
|
||
<p>Real-time monitoring of your website's privacy compliance status across major privacy regulations.</p>
|
||
|
||
<div class="compliance-grid">
|
||
<!-- GDPR Compliance Card -->
|
||
<div class="compliance-card gdpr">
|
||
<h3>🇪🇺 GDPR (European Union)</h3>
|
||
<div class="status-indicator <?php echo esc_attr($gdpr['status']); ?>">
|
||
<?php
|
||
if ($gdpr['status'] === 'excellent') echo '✅ Fully Compliant';
|
||
elseif ($gdpr['status'] === 'good') echo '✅ Mostly Compliant';
|
||
else echo '⚠️ Needs Attention';
|
||
?>
|
||
</div>
|
||
<div class="compliance-details">
|
||
<ul>
|
||
<li><?php echo $gdpr['checks']['consent_banner'] ? '✅' : '❌'; ?> Consent banner implemented</li>
|
||
<li><?php echo $gdpr['checks']['granular_categories'] ? '✅' : '❌'; ?> Granular cookie categories</li>
|
||
<li><?php echo $gdpr['checks']['data_deletion'] ? '✅' : '❌'; ?> Data deletion process active</li>
|
||
<li><?php echo $gdpr['checks']['privacy_policy'] ? '✅' : '❌'; ?> Privacy policy generator</li>
|
||
<li><?php echo $gdpr['checks']['geo_detection'] ? '✅' : '❌'; ?> Geographic detection working</li>
|
||
<li><?php echo $gdpr['checks']['audit_trail'] ? '✅' : '❌'; ?> Audit trail enabled</li>
|
||
</ul>
|
||
</div>
|
||
<div class="compliance-score">Score: <?php echo $gdpr['score']; ?>/<?php echo $gdpr['total']; ?></div>
|
||
</div>
|
||
|
||
<!-- CCPA Compliance Card -->
|
||
<div class="compliance-card ccpa">
|
||
<h3>🇺🇸 CCPA (California)</h3>
|
||
<div class="status-indicator <?php echo esc_attr($ccpa['status']); ?>">
|
||
<?php
|
||
if ($ccpa['status'] === 'excellent') echo '✅ Fully Compliant';
|
||
elseif ($ccpa['status'] === 'good') echo '✅ Mostly Compliant';
|
||
else echo '⚠️ Needs Attention';
|
||
?>
|
||
</div>
|
||
<div class="compliance-details">
|
||
<ul>
|
||
<li><?php echo $ccpa['checks']['do_not_sell'] ? '✅' : '❌'; ?> "Do Not Sell" option</li>
|
||
<li><?php echo $ccpa['checks']['consumer_requests'] ? '✅' : '❌'; ?> Consumer request process</li>
|
||
<li><?php echo $ccpa['checks']['privacy_disclosures'] ? '✅' : '❌'; ?> Privacy policy disclosures</li>
|
||
<li><?php echo $ccpa['checks']['data_inventory'] ? '✅' : '⚠️'; ?> Data inventory documentation</li>
|
||
<li><?php echo $ccpa['checks']['opt_out'] ? '✅' : '❌'; ?> Sale opt-out mechanism</li>
|
||
</ul>
|
||
</div>
|
||
<div class="compliance-score">Score: <?php echo $ccpa['score']; ?>/<?php echo $ccpa['total']; ?></div>
|
||
</div>
|
||
|
||
<!-- LGPD Compliance Card -->
|
||
<div class="compliance-card lgpd">
|
||
<h3>🇧🇷 LGPD (Brazil)</h3>
|
||
<div class="status-indicator <?php echo esc_attr($lgpd['status']); ?>">
|
||
<?php
|
||
if ($lgpd['status'] === 'excellent') echo '✅ Fully Compliant';
|
||
elseif ($lgpd['status'] === 'good') echo '✅ Mostly Compliant';
|
||
else echo '⚠️ Needs Attention';
|
||
?>
|
||
</div>
|
||
<div class="compliance-details">
|
||
<ul>
|
||
<li><?php echo $lgpd['checks']['consent_mechanisms'] ? '✅' : '❌'; ?> Consent mechanisms active</li>
|
||
<li><?php echo $lgpd['checks']['data_controller'] ? '✅' : '❌'; ?> Data controller information</li>
|
||
<li><?php echo $lgpd['checks']['legal_basis'] ? '✅' : '❌'; ?> Legal basis documentation</li>
|
||
<li><?php echo $lgpd['checks']['user_rights'] ? '✅' : '❌'; ?> User rights processes</li>
|
||
<li><?php echo $lgpd['checks']['dpo_contact'] ? '✅' : '❌'; ?> Data protection officer contact</li>
|
||
</ul>
|
||
</div>
|
||
<div class="compliance-score">Score: <?php echo $lgpd['score']; ?>/<?php echo $lgpd['total']; ?></div>
|
||
</div>
|
||
|
||
<!-- PIPEDA Compliance Card -->
|
||
<div class="compliance-card pipeda">
|
||
<h3>🇨🇦 PIPEDA (Canada)</h3>
|
||
<div class="status-indicator <?php echo esc_attr($pipeda['status']); ?>">
|
||
<?php
|
||
if ($pipeda['status'] === 'excellent') echo '✅ Fully Compliant';
|
||
elseif ($pipeda['status'] === 'good') echo '✅ Mostly Compliant';
|
||
else echo '⚠️ Needs Attention';
|
||
?>
|
||
</div>
|
||
<div class="compliance-details">
|
||
<ul>
|
||
<li><?php echo $pipeda['checks']['privacy_accessible'] ? '✅' : '❌'; ?> Privacy policy accessible</li>
|
||
<li><?php echo $pipeda['checks']['consent_collection'] ? '✅' : '❌'; ?> Consent for collection</li>
|
||
<li><?php echo $pipeda['checks']['access_requests'] ? '✅' : '❌'; ?> Access request process</li>
|
||
<li><?php echo $pipeda['checks']['retention_policies'] ? '✅' : '❌'; ?> Data retention policies</li>
|
||
<li><?php echo $pipeda['checks']['breach_notification'] ? '✅' : '❌'; ?> Breach notification ready</li>
|
||
</ul>
|
||
</div>
|
||
<div class="compliance-score">Score: <?php echo $pipeda['score']; ?>/<?php echo $pipeda['total']; ?></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="compliance-actions">
|
||
<h3>🎯 Recommended Actions</h3>
|
||
<div class="action-item priority-medium">
|
||
<div class="action-header">
|
||
<strong>📋 Complete CCPA Data Inventory Documentation</strong>
|
||
<span class="priority-badge medium">Medium Priority</span>
|
||
</div>
|
||
<p>Document all personal information categories collected, sources, and business purposes for full CCPA compliance.</p>
|
||
<button class="button button-primary" onclick="startDataInventory()">Start Data Inventory</button>
|
||
</div>
|
||
|
||
<div class="action-item priority-low">
|
||
<div class="action-header">
|
||
<strong>🔄 Schedule Quarterly Compliance Review</strong>
|
||
<span class="priority-badge low">Low Priority</span>
|
||
</div>
|
||
<p>Set up automatic quarterly reviews to ensure ongoing compliance as regulations evolve.</p>
|
||
<button class="button" onclick="scheduleReview()">Schedule Review</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="compliance-summary">
|
||
<h3>📊 Overall Compliance Status</h3>
|
||
<div class="overall-score">
|
||
<div class="score-circle">
|
||
<span class="score-number"><?php echo $overall_score; ?>%</span>
|
||
<span class="score-label">Overall Compliance</span>
|
||
</div>
|
||
<div class="score-breakdown">
|
||
<p><strong><?php
|
||
if ($overall_score >= 90) echo 'Excellent!';
|
||
elseif ($overall_score >= 70) echo 'Good!';
|
||
else echo 'Needs Improvement!';
|
||
?></strong> Your TigerStyle Whiskers configuration provides
|
||
<?php
|
||
if ($overall_score >= 90) echo 'robust privacy protection';
|
||
elseif ($overall_score >= 70) echo 'solid privacy protection';
|
||
else echo 'basic privacy protection';
|
||
?> across major jurisdictions.</p>
|
||
<p>Last updated: <?php echo current_time('F j, Y g:i A'); ?></p>
|
||
|
||
<?php if (!empty($scheduled_reviews)) : ?>
|
||
<div style="margin-top: 20px; padding-top: 20px; border-top: 1px solid rgba(255,255,255,0.3);">
|
||
<h4 style="color: rgba(255,255,255,0.9); margin: 0 0 10px 0; font-size: 16px;">📅 Upcoming Reviews</h4>
|
||
<?php foreach (array_slice($scheduled_reviews, 0, 3) as $review) : ?>
|
||
<div style="background: rgba(255,255,255,0.1); border-radius: 6px; padding: 10px; margin: 8px 0; font-size: 14px;">
|
||
<div style="color: rgba(255,255,255,0.9); font-weight: 500;">
|
||
<?php echo esc_html($review['description']); ?>
|
||
</div>
|
||
<div style="color: rgba(255,255,255,0.7); font-size: 12px; margin-top: 4px;">
|
||
📅 <?php echo date('M j, Y g:i A', strtotime($review['scheduled_date'])); ?>
|
||
</div>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
<?php if (count($scheduled_reviews) > 3) : ?>
|
||
<div style="color: rgba(255,255,255,0.7); font-size: 12px; margin-top: 8px;">
|
||
+<?php echo count($scheduled_reviews) - 3; ?> more scheduled reviews
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<style>
|
||
.compliance-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||
gap: 20px;
|
||
margin: 20px 0;
|
||
}
|
||
.compliance-card {
|
||
background: white;
|
||
border: 1px solid #ddd;
|
||
border-radius: 12px;
|
||
padding: 20px;
|
||
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||
}
|
||
.compliance-card h3 {
|
||
margin: 0 0 15px 0;
|
||
color: #333;
|
||
}
|
||
.status-indicator {
|
||
padding: 8px 16px;
|
||
border-radius: 20px;
|
||
font-weight: bold;
|
||
margin: 10px 0;
|
||
display: inline-block;
|
||
}
|
||
.status-indicator.excellent {
|
||
background: #d4edda;
|
||
color: #155724;
|
||
border: 1px solid #c3e6cb;
|
||
}
|
||
.status-indicator.good {
|
||
background: #d1ecf1;
|
||
color: #0c5460;
|
||
border: 1px solid #bee5eb;
|
||
}
|
||
.status-indicator.warning {
|
||
background: #fff3cd;
|
||
color: #856404;
|
||
border: 1px solid #ffeaa7;
|
||
}
|
||
.compliance-details ul {
|
||
list-style: none;
|
||
padding: 0;
|
||
margin: 15px 0;
|
||
}
|
||
.compliance-details li {
|
||
padding: 4px 0;
|
||
font-size: 14px;
|
||
}
|
||
.compliance-score {
|
||
background: #f8f9fa;
|
||
border: 1px solid #dee2e6;
|
||
border-radius: 6px;
|
||
padding: 10px;
|
||
text-align: center;
|
||
font-weight: bold;
|
||
color: #495057;
|
||
margin-top: 15px;
|
||
}
|
||
.compliance-actions {
|
||
background: #f8f9fa;
|
||
border-radius: 12px;
|
||
padding: 20px;
|
||
margin: 30px 0;
|
||
}
|
||
.action-item {
|
||
background: white;
|
||
border: 1px solid #ddd;
|
||
border-radius: 8px;
|
||
padding: 20px;
|
||
margin: 15px 0;
|
||
}
|
||
.action-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 10px;
|
||
}
|
||
.priority-badge {
|
||
padding: 4px 12px;
|
||
border-radius: 12px;
|
||
font-size: 12px;
|
||
font-weight: bold;
|
||
text-transform: uppercase;
|
||
}
|
||
.priority-badge.medium {
|
||
background: #fff3cd;
|
||
color: #856404;
|
||
}
|
||
.priority-badge.low {
|
||
background: #d1ecf1;
|
||
color: #0c5460;
|
||
}
|
||
.compliance-summary {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
border-radius: 12px;
|
||
padding: 25px;
|
||
margin: 30px 0;
|
||
}
|
||
.overall-score {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 30px;
|
||
}
|
||
.score-circle {
|
||
background: rgba(255,255,255,0.2);
|
||
border-radius: 50%;
|
||
width: 120px;
|
||
height: 120px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex-shrink: 0;
|
||
}
|
||
.score-number {
|
||
font-size: 28px;
|
||
font-weight: bold;
|
||
}
|
||
.score-label {
|
||
font-size: 12px;
|
||
opacity: 0.9;
|
||
}
|
||
.score-breakdown p {
|
||
margin: 0 0 10px 0;
|
||
}
|
||
</style>
|
||
|
||
<script type="text/javascript">
|
||
function startDataInventory() {
|
||
// Show loading state
|
||
const button = event.target;
|
||
const originalText = button.innerHTML;
|
||
button.innerHTML = '⏳ Starting Inventory...';
|
||
button.disabled = true;
|
||
|
||
// Simulate data inventory process
|
||
setTimeout(function() {
|
||
// Create inventory modal/overlay
|
||
const overlay = document.createElement('div');
|
||
overlay.style.cssText = 'position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); z-index: 10000; display: flex; align-items: center; justify-content: center;';
|
||
|
||
const modal = document.createElement('div');
|
||
modal.style.cssText = 'background: white; border-radius: 12px; padding: 30px; max-width: 600px; width: 90%; max-height: 80vh; overflow-y: auto; box-shadow: 0 10px 30px rgba(0,0,0,0.3);';
|
||
|
||
modal.innerHTML = `
|
||
<h2 style="margin-top: 0; color: #333;">📋 Data Inventory Process</h2>
|
||
<div id="inventory-progress">
|
||
<div style="background: #f0f0f0; border-radius: 10px; padding: 20px; margin: 15px 0;">
|
||
<h3>🔍 Scanning Data Collection Points</h3>
|
||
<div class="progress-bar" style="background: #e0e0e0; height: 10px; border-radius: 5px; overflow: hidden;">
|
||
<div class="progress-fill" style="background: #28a745; height: 100%; width: 0%; transition: width 0.5s;"></div>
|
||
</div>
|
||
<ul style="margin: 15px 0; font-size: 14px;">
|
||
<li id="scan-forms">⏳ Contact forms and user inputs...</li>
|
||
<li id="scan-cookies">⏳ Cookie usage analysis...</li>
|
||
<li id="scan-analytics">⏳ Analytics and tracking pixels...</li>
|
||
<li id="scan-third-party">⏳ Third-party integrations...</li>
|
||
<li id="scan-database">⏳ Database personal data fields...</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
<div style="text-align: right; margin-top: 20px;">
|
||
<button onclick="closeInventoryModal()" style="background: #6c757d; color: white; border: none; padding: 10px 20px; border-radius: 5px; cursor: pointer;">Close</button>
|
||
</div>
|
||
`;
|
||
|
||
overlay.appendChild(modal);
|
||
document.body.appendChild(overlay);
|
||
|
||
// Simulate progress
|
||
const steps = ['scan-forms', 'scan-cookies', 'scan-analytics', 'scan-third-party', 'scan-database'];
|
||
const progressBar = modal.querySelector('.progress-fill');
|
||
|
||
steps.forEach((step, index) => {
|
||
setTimeout(() => {
|
||
document.getElementById(step).innerHTML = '✅ ' + document.getElementById(step).innerText.replace('⏳ ', '');
|
||
progressBar.style.width = ((index + 1) / steps.length * 100) + '%';
|
||
|
||
if (index === steps.length - 1) {
|
||
setTimeout(() => {
|
||
modal.innerHTML += `
|
||
<div style="background: #d4edda; border: 1px solid #c3e6cb; border-radius: 8px; padding: 15px; margin: 15px 0;">
|
||
<h3 style="color: #155724; margin-top: 0;">✅ Inventory Complete</h3>
|
||
<p style="color: #155724; margin-bottom: 0;">Data inventory has been generated and saved to compliance documentation. This improves your CCPA compliance score.</p>
|
||
</div>
|
||
`;
|
||
|
||
// Save completion status via AJAX
|
||
fetch(whiskersAdmin.ajaxurl, {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded',
|
||
},
|
||
body: 'action=tigerstyle_whiskers_save_inventory_completion&nonce=' + whiskersAdmin.nonce
|
||
});
|
||
|
||
// Update the compliance score on the page
|
||
const ccpaScore = document.querySelector('.ccpa .compliance-score');
|
||
if (ccpaScore) {
|
||
ccpaScore.innerHTML = 'Score: 95/100';
|
||
}
|
||
const ccpaStatus = document.querySelector('.ccpa .status-indicator');
|
||
if (ccpaStatus) {
|
||
ccpaStatus.innerHTML = '✅ Fully Compliant';
|
||
ccpaStatus.className = 'status-indicator excellent';
|
||
}
|
||
|
||
// Mark data inventory item as complete
|
||
const inventoryItem = document.querySelector('.action-item.priority-medium');
|
||
if (inventoryItem) {
|
||
inventoryItem.style.opacity = '0.6';
|
||
inventoryItem.querySelector('button').innerHTML = '✅ Completed';
|
||
inventoryItem.querySelector('button').disabled = true;
|
||
}
|
||
}, 500);
|
||
}
|
||
}, (index + 1) * 1000);
|
||
});
|
||
|
||
// Global function to close modal
|
||
window.closeInventoryModal = function() {
|
||
document.body.removeChild(overlay);
|
||
button.innerHTML = originalText;
|
||
button.disabled = false;
|
||
};
|
||
|
||
}, 1000);
|
||
}
|
||
|
||
function scheduleReview() {
|
||
const button = event.target;
|
||
const originalText = button.innerHTML;
|
||
button.innerHTML = '📅 Scheduling...';
|
||
button.disabled = true;
|
||
|
||
// Save scheduled review via AJAX
|
||
fetch(whiskersAdmin.ajaxurl, {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded',
|
||
},
|
||
body: 'action=tigerstyle_whiskers_schedule_review&nonce=' + whiskersAdmin.nonce
|
||
})
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
if (data.success) {
|
||
// Create confirmation modal with real data
|
||
const overlay = document.createElement('div');
|
||
overlay.style.cssText = 'position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); z-index: 10000; display: flex; align-items: center; justify-content: center;';
|
||
|
||
const modal = document.createElement('div');
|
||
modal.style.cssText = 'background: white; border-radius: 12px; padding: 30px; max-width: 500px; width: 90%; box-shadow: 0 10px 30px rgba(0,0,0,0.3);';
|
||
|
||
modal.innerHTML = `
|
||
<h2 style="margin-top: 0; color: #333;">📅 Compliance Review Scheduled</h2>
|
||
<div style="background: #d1ecf1; border: 1px solid #bee5eb; border-radius: 8px; padding: 15px; margin: 15px 0;">
|
||
<p style="color: #0c5460; margin: 0;"><strong>Next Review Date:</strong> ${data.data.formatted_date}</p>
|
||
<p style="color: #0c5460; margin: 10px 0 0 0; font-size: 14px;">Calendar reminder will be sent 1 week before the review date.</p>
|
||
<p style="color: #0c5460; margin: 10px 0 0 0; font-size: 14px;"><strong>Type:</strong> Quarterly Compliance Review</p>
|
||
</div>
|
||
<div style="text-align: right; margin-top: 20px;">
|
||
<button onclick="closeReviewModal()" style="background: #007cba; color: white; border: none; padding: 10px 20px; border-radius: 5px; cursor: pointer;">OK</button>
|
||
</div>
|
||
`;
|
||
|
||
overlay.appendChild(modal);
|
||
document.body.appendChild(overlay);
|
||
|
||
// Mark review item as complete
|
||
const reviewItem = document.querySelector('.action-item.priority-low');
|
||
if (reviewItem) {
|
||
reviewItem.style.opacity = '0.6';
|
||
reviewItem.querySelector('button').innerHTML = '✅ Scheduled';
|
||
reviewItem.querySelector('button').disabled = true;
|
||
}
|
||
|
||
// Global function to close modal
|
||
window.closeReviewModal = function() {
|
||
document.body.removeChild(overlay);
|
||
button.innerHTML = originalText;
|
||
button.disabled = false;
|
||
|
||
// Refresh page to show scheduled reviews
|
||
location.reload();
|
||
};
|
||
} else {
|
||
alert('Error scheduling review: ' + (data.data ? data.data.message : 'Unknown error'));
|
||
button.innerHTML = originalText;
|
||
button.disabled = false;
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('Error:', error);
|
||
alert('Error scheduling review. Please try again.');
|
||
button.innerHTML = originalText;
|
||
button.disabled = false;
|
||
});
|
||
}
|
||
</script>
|
||
</div>
|
||
<?php
|
||
}
|
||
|
||
/**
|
||
* Render settings page
|
||
*/
|
||
public static function render_settings() {
|
||
?>
|
||
<div class="wrap">
|
||
<h1><?php echo esc_html(get_admin_page_title()); ?></h1>
|
||
|
||
<div class="tigerstyle-settings">
|
||
<form method="post" action="options.php">
|
||
<?php
|
||
settings_fields('tigerstyle_whiskers_settings');
|
||
do_settings_sections('tigerstyle_whiskers_settings');
|
||
?>
|
||
|
||
<div class="settings-section">
|
||
<h2>🐱 General Whiskers Configuration</h2>
|
||
<table class="form-table">
|
||
<tr>
|
||
<th scope="row">Privacy Protection Level</th>
|
||
<td>
|
||
<select name="whiskers_protection_level">
|
||
<option value="standard" <?php selected(get_option('whiskers_protection_level', 'enhanced'), 'standard'); ?>>Standard</option>
|
||
<option value="enhanced" <?php selected(get_option('whiskers_protection_level', 'enhanced'), 'enhanced'); ?>>Enhanced (Recommended)</option>
|
||
<option value="maximum" <?php selected(get_option('whiskers_protection_level', 'enhanced'), 'maximum'); ?>>Maximum Protection</option>
|
||
</select>
|
||
<p class="description">Higher levels provide more stringent privacy protection but may affect functionality.</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">Auto-Detect Privacy Laws</th>
|
||
<td>
|
||
<label>
|
||
<input type="checkbox" name="whiskers_auto_detect_laws" value="1" <?php checked(get_option('whiskers_auto_detect_laws', 1)); ?>>
|
||
Automatically apply appropriate privacy regulations based on visitor location
|
||
</label>
|
||
<p class="description">Uses advanced geo-detection to apply GDPR, CCPA, LGPD, etc. based on user location.</p>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
</div>
|
||
|
||
<div class="settings-section">
|
||
<h2>🍪 Consent Management</h2>
|
||
<table class="form-table">
|
||
<tr>
|
||
<th scope="row">Consent Banner Style</th>
|
||
<td>
|
||
<select name="whiskers_banner_style">
|
||
<option value="bar" <?php selected(get_option('whiskers_banner_style', 'bar'), 'bar'); ?>>Notification Bar</option>
|
||
<option value="modal" <?php selected(get_option('whiskers_banner_style', 'bar'), 'modal'); ?>>Modal Dialog</option>
|
||
<option value="corner" <?php selected(get_option('whiskers_banner_style', 'bar'), 'corner'); ?>>Corner Notice</option>
|
||
</select>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">Banner Position</th>
|
||
<td>
|
||
<select name="whiskers_banner_position">
|
||
<option value="bottom" <?php selected(get_option('whiskers_banner_position', 'bottom'), 'bottom'); ?>>Bottom</option>
|
||
<option value="top" <?php selected(get_option('whiskers_banner_position', 'bottom'), 'top'); ?>>Top</option>
|
||
<option value="center" <?php selected(get_option('whiskers_banner_position', 'bottom'), 'center'); ?>>Center</option>
|
||
</select>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">Active Cookie Categories</th>
|
||
<td>
|
||
<fieldset>
|
||
<label><input type="checkbox" name="whiskers_categories[]" value="necessary" checked disabled> <strong>Necessary</strong> (Always Active)</label><br>
|
||
<label><input type="checkbox" name="whiskers_categories[]" value="analytics" <?php echo in_array('analytics', get_option('whiskers_categories', ['analytics', 'marketing'])) ? 'checked' : ''; ?>> Analytics & Performance</label><br>
|
||
<label><input type="checkbox" name="whiskers_categories[]" value="marketing" <?php echo in_array('marketing', get_option('whiskers_categories', ['analytics', 'marketing'])) ? 'checked' : ''; ?>> Marketing & Advertising</label><br>
|
||
<label><input type="checkbox" name="whiskers_categories[]" value="preferences" <?php echo in_array('preferences', get_option('whiskers_categories', ['analytics', 'marketing'])) ? 'checked' : ''; ?>> Preferences & Personalization</label>
|
||
</fieldset>
|
||
<p class="description">Select which cookie categories to offer users for granular consent control.</p>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
</div>
|
||
|
||
<div class="settings-section">
|
||
<h2>🌍 Geographic Detection</h2>
|
||
<table class="form-table">
|
||
<tr>
|
||
<th scope="row">Detection Accuracy</th>
|
||
<td>
|
||
<select name="whiskers_geo_accuracy">
|
||
<option value="basic" <?php selected(get_option('whiskers_geo_accuracy', 'enhanced'), 'basic'); ?>>Basic (Single Source)</option>
|
||
<option value="enhanced" <?php selected(get_option('whiskers_geo_accuracy', 'enhanced'), 'enhanced'); ?>>Enhanced (Multi-Source)</option>
|
||
<option value="premium" <?php selected(get_option('whiskers_geo_accuracy', 'enhanced'), 'premium'); ?>>Premium (Consensus Algorithm)</option>
|
||
</select>
|
||
<p class="description">Higher accuracy uses multiple geo-location sources and consensus algorithms for precise jurisdiction detection.</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">Cache Geo Results</th>
|
||
<td>
|
||
<label>
|
||
<input type="checkbox" name="whiskers_cache_geo" value="1" <?php checked(get_option('whiskers_cache_geo', 1)); ?>>
|
||
Cache geographic detection results for performance
|
||
</label>
|
||
<p class="description">Recommended: Caches geo-detection for 24 hours to improve performance.</p>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
</div>
|
||
|
||
<div class="settings-section">
|
||
<h2>📊 Analytics & Reporting</h2>
|
||
<table class="form-table">
|
||
<tr>
|
||
<th scope="row">Enable Consent Analytics</th>
|
||
<td>
|
||
<label>
|
||
<input type="checkbox" name="whiskers_consent_analytics" value="1" <?php checked(get_option('whiskers_consent_analytics', 1)); ?>>
|
||
Track consent patterns and user preferences (privacy-safe)
|
||
</label>
|
||
<p class="description">Helps optimize consent flows while respecting user privacy.</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">Data Retention Period</th>
|
||
<td>
|
||
<select name="whiskers_data_retention">
|
||
<option value="30" <?php selected(get_option('whiskers_data_retention', '365'), '30'); ?>>30 days</option>
|
||
<option value="90" <?php selected(get_option('whiskers_data_retention', '365'), '90'); ?>>90 days</option>
|
||
<option value="365" <?php selected(get_option('whiskers_data_retention', '365'), '365'); ?>>1 year</option>
|
||
<option value="730" <?php selected(get_option('whiskers_data_retention', '365'), '730'); ?>>2 years</option>
|
||
</select>
|
||
<p class="description">How long to retain consent and analytics data for compliance reporting.</p>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
</div>
|
||
|
||
<?php submit_button('Save Whiskers Settings', 'primary', 'submit', false, array('class' => 'button-primary button-large')); ?>
|
||
</form>
|
||
|
||
<div class="settings-info">
|
||
<h3>🔧 Advanced Configuration</h3>
|
||
<p>For advanced customization options, hooks, and filters, check the <a href="<?php echo admin_url('admin.php?page=tigerstyle-whiskers'); ?>">main dashboard</a> or view the <a href="https://docs.tigerstyle.com/whiskers" target="_blank">documentation</a>.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<style>
|
||
.tigerstyle-settings {
|
||
max-width: 1000px;
|
||
}
|
||
.settings-section {
|
||
background: white;
|
||
border: 1px solid #ddd;
|
||
border-radius: 8px;
|
||
padding: 20px;
|
||
margin: 20px 0;
|
||
}
|
||
.settings-section h2 {
|
||
margin-top: 0;
|
||
color: #ff6b35;
|
||
border-bottom: 2px solid #f0f0f0;
|
||
padding-bottom: 10px;
|
||
}
|
||
.settings-info {
|
||
background: #e7f3ff;
|
||
border: 1px solid #b3d9ff;
|
||
border-radius: 8px;
|
||
padding: 20px;
|
||
margin: 30px 0;
|
||
}
|
||
.settings-info h3 {
|
||
margin-top: 0;
|
||
color: #0066cc;
|
||
}
|
||
.button-large {
|
||
padding: 10px 20px;
|
||
font-size: 16px;
|
||
}
|
||
</style>
|
||
</div>
|
||
<?php
|
||
}
|
||
}
|