init_compliance_scanner(); } /** * Initialize compliance scanner */ private function init_compliance_scanner() { // Define compliance checks $this->define_compliance_checks(); // Schedule periodic scans add_action('wp_loaded', array($this, 'schedule_periodic_scan')); // Admin hooks if (is_admin()) { add_action('wp_ajax_whiskers_run_compliance_scan', array($this, 'ajax_run_compliance_scan')); } } /** * Define compliance checks */ private function define_compliance_checks() { $this->compliance_checks = array( 'cookie_consent' => array( 'name' => __('Cookie Consent Banner', 'tigerstyle-whiskers'), 'description' => __('Ensure cookie consent banner is active and compliant', 'tigerstyle-whiskers'), 'priority' => 'high', 'callback' => array($this, 'check_cookie_consent') ), 'privacy_policy' => array( 'name' => __('Privacy Policy', 'tigerstyle-whiskers'), 'description' => __('Verify privacy policy exists and is up-to-date', 'tigerstyle-whiskers'), 'priority' => 'high', 'callback' => array($this, 'check_privacy_policy') ), 'data_processing' => array( 'name' => __('Data Processing Records', 'tigerstyle-whiskers'), 'description' => __('Check data processing documentation', 'tigerstyle-whiskers'), 'priority' => 'medium', 'callback' => array($this, 'check_data_processing') ), 'user_rights' => array( 'name' => __('User Rights Implementation', 'tigerstyle-whiskers'), 'description' => __('Verify GDPR user rights are implemented', 'tigerstyle-whiskers'), 'priority' => 'high', 'callback' => array($this, 'check_user_rights') ), 'data_security' => array( 'name' => __('Data Security Measures', 'tigerstyle-whiskers'), 'description' => __('Check basic data security implementations', 'tigerstyle-whiskers'), 'priority' => 'medium', 'callback' => array($this, 'check_data_security') ), 'third_party_scripts' => array( 'name' => __('Third-party Script Compliance', 'tigerstyle-whiskers'), 'description' => __('Verify third-party scripts respect consent', 'tigerstyle-whiskers'), 'priority' => 'high', 'callback' => array($this, 'check_third_party_scripts') ) ); } /** * Run full compliance scan */ public function run_full_scan() { $results = array(); $total_score = 0; $max_score = 0; foreach ($this->compliance_checks as $check_id => $check) { $result = call_user_func($check['callback']); $results[$check_id] = array_merge($check, $result); // Calculate weighted score $weight = ($check['priority'] === 'high') ? 3 : ($check['priority'] === 'medium' ? 2 : 1); $total_score += $result['score'] * $weight; $max_score += 10 * $weight; } $overall_score = ($max_score > 0) ? round(($total_score / $max_score) * 10, 1) : 0; $this->last_scan_results = array( 'overall_score' => $overall_score, 'scan_date' => current_time('mysql'), 'checks' => $results, 'recommendations' => $this->generate_recommendations($results) ); // Store results update_option('whiskers_compliance_scan_results', $this->last_scan_results); return $this->last_scan_results; } /** * Check cookie consent implementation */ private function check_cookie_consent() { $score = 0; $issues = array(); $recommendations = array(); // Check if consent banner is active $consent_module = tigerstyle_whiskers()->get_whisker('cookie_consent'); if ($consent_module) { $score += 3; } else { $issues[] = __('Cookie consent banner not active', 'tigerstyle-whiskers'); $recommendations[] = __('Activate cookie consent banner', 'tigerstyle-whiskers'); } // Check for granular consent options if ($consent_module && method_exists($consent_module, 'get_consent_categories')) { $categories = $consent_module->get_consent_categories(); if (count($categories) >= 3) { $score += 3; } else { $issues[] = __('Limited consent categories available', 'tigerstyle-whiskers'); $recommendations[] = __('Implement granular consent categories', 'tigerstyle-whiskers'); } } // Check for consent withdrawal mechanism if ($consent_module && method_exists($consent_module, 'withdraw_consent')) { $score += 2; } else { $issues[] = __('Consent withdrawal mechanism missing', 'tigerstyle-whiskers'); $recommendations[] = __('Implement consent withdrawal functionality', 'tigerstyle-whiskers'); } // Check for proper cookie blocking if ($this->check_cookie_blocking()) { $score += 2; } else { $issues[] = __('Cookies may load before consent', 'tigerstyle-whiskers'); $recommendations[] = __('Ensure cookies are blocked until consent is given', 'tigerstyle-whiskers'); } return array( 'score' => min($score, 10), 'status' => ($score >= 8) ? 'excellent' : (($score >= 6) ? 'good' : (($score >= 4) ? 'fair' : 'poor')), 'issues' => $issues, 'recommendations' => $recommendations ); } /** * Check privacy policy */ private function check_privacy_policy() { $score = 0; $issues = array(); $recommendations = array(); // Check if privacy policy page exists $policy_page = get_option('wp_page_for_privacy_policy'); if ($policy_page && get_post_status($policy_page) === 'publish') { $score += 4; // Check if policy is recent (updated within last year) $policy_post = get_post($policy_page); if ($policy_post && strtotime($policy_post->post_modified) > (time() - YEAR_IN_SECONDS)) { $score += 2; } else { $issues[] = __('Privacy policy may be outdated', 'tigerstyle-whiskers'); $recommendations[] = __('Update privacy policy with recent changes', 'tigerstyle-whiskers'); } // Check for GDPR-specific content $content = get_post_field('post_content', $policy_page); if (stripos($content, 'gdpr') !== false || stripos($content, 'data protection') !== false) { $score += 2; } else { $issues[] = __('Privacy policy lacks GDPR-specific content', 'tigerstyle-whiskers'); $recommendations[] = __('Add GDPR compliance information to privacy policy', 'tigerstyle-whiskers'); } // Check for contact information if (stripos($content, 'contact') !== false || stripos($content, 'email') !== false) { $score += 2; } else { $issues[] = __('Privacy policy lacks contact information', 'tigerstyle-whiskers'); $recommendations[] = __('Add privacy contact information', 'tigerstyle-whiskers'); } } else { $issues[] = __('Privacy policy page not found or not published', 'tigerstyle-whiskers'); $recommendations[] = __('Create and publish a comprehensive privacy policy', 'tigerstyle-whiskers'); } return array( 'score' => min($score, 10), 'status' => ($score >= 8) ? 'excellent' : (($score >= 6) ? 'good' : (($score >= 4) ? 'fair' : 'poor')), 'issues' => $issues, 'recommendations' => $recommendations ); } /** * Check data processing records */ private function check_data_processing() { $score = 5; // Base score for having Whiskers installed $issues = array(); $recommendations = array(); // Check if data mapper is active $data_mapper = tigerstyle_whiskers()->get_whisker('data_mapper'); if ($data_mapper) { $score += 3; } else { $issues[] = __('Data mapping not active', 'tigerstyle-whiskers'); $recommendations[] = __('Activate data mapping functionality', 'tigerstyle-whiskers'); } // Check for audit trail $audit_trail = tigerstyle_whiskers()->get_whisker('audit_trail'); if ($audit_trail) { $score += 2; } else { $issues[] = __('Audit trail not configured', 'tigerstyle-whiskers'); $recommendations[] = __('Enable audit trail for data processing activities', 'tigerstyle-whiskers'); } return array( 'score' => min($score, 10), 'status' => ($score >= 8) ? 'excellent' : (($score >= 6) ? 'good' : (($score >= 4) ? 'fair' : 'poor')), 'issues' => $issues, 'recommendations' => $recommendations ); } /** * Check user rights implementation */ private function check_user_rights() { $score = 0; $issues = array(); $recommendations = array(); // Check data deletion capability $data_deletion = tigerstyle_whiskers()->get_whisker('data_deletion'); if ($data_deletion) { $score += 3; } else { $issues[] = __('Data deletion (right to be forgotten) not implemented', 'tigerstyle-whiskers'); $recommendations[] = __('Implement data deletion functionality', 'tigerstyle-whiskers'); } // Check data access/export capability if ($data_deletion && method_exists($data_deletion, 'export_user_data')) { $score += 3; } else { $issues[] = __('Data access/export not available', 'tigerstyle-whiskers'); $recommendations[] = __('Implement data access and export functionality', 'tigerstyle-whiskers'); } // Check for data rectification process if ($this->check_data_rectification()) { $score += 2; } else { $issues[] = __('Data rectification process not defined', 'tigerstyle-whiskers'); $recommendations[] = __('Define process for data rectification requests', 'tigerstyle-whiskers'); } // Check for consent withdrawal $consent_module = tigerstyle_whiskers()->get_whisker('cookie_consent'); if ($consent_module && method_exists($consent_module, 'withdraw_consent')) { $score += 2; } else { $issues[] = __('Consent withdrawal not available', 'tigerstyle-whiskers'); $recommendations[] = __('Implement consent withdrawal mechanism', 'tigerstyle-whiskers'); } return array( 'score' => min($score, 10), 'status' => ($score >= 8) ? 'excellent' : (($score >= 6) ? 'good' : (($score >= 4) ? 'fair' : 'poor')), 'issues' => $issues, 'recommendations' => $recommendations ); } /** * Check data security measures */ private function check_data_security() { $score = 0; $issues = array(); $recommendations = array(); // Check for HTTPS if (is_ssl()) { $score += 3; } else { $issues[] = __('Website not using HTTPS', 'tigerstyle-whiskers'); $recommendations[] = __('Enable SSL/HTTPS for data protection', 'tigerstyle-whiskers'); } // Check for secure password policies if ($this->check_password_policies()) { $score += 2; } else { $issues[] = __('Weak password policies detected', 'tigerstyle-whiskers'); $recommendations[] = __('Implement strong password requirements', 'tigerstyle-whiskers'); } // Check for data encryption options if ($this->check_data_encryption()) { $score += 3; } else { $issues[] = __('Limited data encryption measures', 'tigerstyle-whiskers'); $recommendations[] = __('Consider additional data encryption measures', 'tigerstyle-whiskers'); } // Check for access controls if ($this->check_access_controls()) { $score += 2; } else { $issues[] = __('Basic access controls could be improved', 'tigerstyle-whiskers'); $recommendations[] = __('Review and strengthen access control measures', 'tigerstyle-whiskers'); } return array( 'score' => min($score, 10), 'status' => ($score >= 8) ? 'excellent' : (($score >= 6) ? 'good' : (($score >= 4) ? 'fair' : 'poor')), 'issues' => $issues, 'recommendations' => $recommendations ); } /** * Check third-party script compliance */ private function check_third_party_scripts() { $score = 8; // Base score assuming Whiskers is handling this $issues = array(); $recommendations = array(); // Check if consent-aware analytics is active if (class_exists('TigerStyleSEO')) { $score += 2; $issues[] = __('Heat integration active - analytics consent respected', 'tigerstyle-whiskers'); } else { $recommendations[] = __('Install TigerStyle Heat for enhanced analytics integration', 'tigerstyle-whiskers'); } return array( 'score' => min($score, 10), 'status' => ($score >= 8) ? 'excellent' : (($score >= 6) ? 'good' : (($score >= 4) ? 'fair' : 'poor')), 'issues' => $issues, 'recommendations' => $recommendations ); } /** * Helper methods for compliance checks */ private function check_cookie_blocking() { // Check if cookies are properly blocked before consent return true; // Assume Whiskers is handling this correctly } private function check_data_rectification() { // Check if data rectification process is defined return false; // This needs to be implemented } private function check_password_policies() { // Check WordPress password strength requirements return !empty(get_option('users_can_register')); } private function check_data_encryption() { // Check for basic data encryption measures return is_ssl(); // Basic check for HTTPS } private function check_access_controls() { // Check WordPress access control settings return !get_option('blog_public'); // If site is not public, access is more controlled } /** * Generate recommendations based on scan results */ private function generate_recommendations($results) { $recommendations = array(); foreach ($results as $check_id => $result) { if ($result['score'] < 8) { $recommendations = array_merge($recommendations, $result['recommendations']); } } return array_unique($recommendations); } /** * Get compliance status */ public static function get_status() { $instance = self::instance(); if (empty($instance->last_scan_results)) { // Load from database or run initial scan $stored_results = get_option('whiskers_compliance_scan_results'); if ($stored_results) { $instance->last_scan_results = $stored_results; } else { $instance->run_full_scan(); } } return $instance->last_scan_results; } /** * Schedule periodic compliance scan */ public function schedule_periodic_scan() { if (!wp_next_scheduled('whiskers_periodic_compliance_scan')) { wp_schedule_event(time(), 'daily', 'whiskers_periodic_compliance_scan'); } add_action('whiskers_periodic_compliance_scan', array($this, 'run_full_scan')); } /** * AJAX handler for compliance scan */ public function ajax_run_compliance_scan() { check_ajax_referer('whiskers_admin_nonce', 'nonce'); if (!current_user_can('manage_options')) { wp_die(__('Insufficient permissions', 'tigerstyle-whiskers')); } $results = $this->run_full_scan(); wp_send_json_success(array( 'message' => __('Compliance scan completed with feline precision!', 'tigerstyle-whiskers'), 'results' => $results )); } }