tigerstyle-whiskers/admin/class-admin-pages.php
Ryan Malloy adbdae19c8 Initial commit: TigerStyle Whiskers v1.0.0
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.
2026-05-27 14:31:51 -06:00

1397 lines
65 KiB
PHP
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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
}
}