init_sensing(); } /** * Initialize sensing capabilities */ private function init_sensing() { // Hook into WordPress to sense boundaries add_action('init', array($this, 'sense_visitor_boundaries')); add_action('wp_head', array($this, 'inject_boundary_detection_script'), 1); // Sense plugin boundaries (what other plugins are active) add_action('plugins_loaded', array($this, 'sense_plugin_boundaries')); // Log our sensing activity if (defined('WP_DEBUG') && WP_DEBUG) { error_log('TigerStyle Whiskers: Boundary detector whiskers are twitching - ready to sense!'); } } /** * Sense visitor boundaries (geographic, regulatory, technical) */ public function sense_visitor_boundaries() { $boundaries = array(); // Geographic boundary detection $boundaries['geographic'] = $this->detect_geographic_boundary(); // Regulatory boundary detection $boundaries['regulatory'] = $this->detect_regulatory_boundary(); // Technical boundary detection $boundaries['technical'] = $this->detect_technical_boundary(); // Data processing boundary detection $boundaries['data_processing'] = $this->detect_data_processing_boundary(); // Cache the detected boundaries self::$boundaries_cache = $boundaries; // Store in session for JavaScript access if (!headers_sent()) { $this->store_boundaries_for_js($boundaries); } return $boundaries; } /** * Detect geographic boundaries (where is the visitor?) */ private function detect_geographic_boundary() { $geographic = array( 'country_code' => $this->get_visitor_country_code(), 'is_gdpr_territory' => false, 'is_ccpa_territory' => false, 'detection_method' => 'server_based' ); // Check if visitor is in GDPR territory if (in_array($geographic['country_code'], self::$gdpr_territories)) { $geographic['is_gdpr_territory'] = true; } // Check if visitor is in CCPA territory (California) if ($geographic['country_code'] === 'US') { $geographic['is_ccpa_territory'] = $this->detect_california_visitor(); } return $geographic; } /** * Detect regulatory boundaries (what laws apply?) */ private function detect_regulatory_boundary() { $regulatory = array( 'gdpr_applies' => false, 'ccpa_applies' => false, 'lgpd_applies' => false, // Brazil 'pipeda_applies' => false, // Canada 'cookies_law_applies' => false, 'detection_confidence' => 'high' ); $geographic = $this->detect_geographic_boundary(); // GDPR detection if ($geographic['is_gdpr_territory']) { $regulatory['gdpr_applies'] = true; $regulatory['cookies_law_applies'] = true; } // CCPA detection if ($geographic['is_ccpa_territory']) { $regulatory['ccpa_applies'] = true; } // LGPD detection (Brazil) if ($geographic['country_code'] === 'BR') { $regulatory['lgpd_applies'] = true; } // PIPEDA detection (Canada) if ($geographic['country_code'] === 'CA') { $regulatory['pipeda_applies'] = true; } return $regulatory; } /** * Detect technical boundaries (what capabilities do we have?) */ private function detect_technical_boundary() { $technical = array( 'cookies_enabled' => $this->detect_cookies_enabled(), 'javascript_enabled' => $this->detect_javascript_enabled(), 'local_storage_available' => false, // Will be detected by JS 'tracking_protection' => $this->detect_tracking_protection(), 'ad_blocker' => false, // Will be detected by JS 'do_not_track' => $this->detect_do_not_track(), ); return $technical; } /** * Detect data processing boundaries (what data are we handling?) */ private function detect_data_processing_boundary() { $data_processing = array( 'analytics_active' => $this->detect_analytics_active(), 'marketing_cookies' => $this->detect_marketing_cookies(), 'social_media_pixels' => $this->detect_social_pixels(), 'third_party_integrations' => $this->detect_third_party_integrations(), 'user_accounts' => $this->detect_user_accounts(), 'contact_forms' => $this->detect_contact_forms(), 'ecommerce' => $this->detect_ecommerce(), ); return $data_processing; } /** * Get visitor country code */ private function get_visitor_country_code() { // Try multiple methods to detect country // Method 1: CloudFlare header if (isset($_SERVER['HTTP_CF_IPCOUNTRY'])) { return strtoupper($_SERVER['HTTP_CF_IPCOUNTRY']); } // Method 2: MaxMind GeoIP (if available) if (function_exists('geoip_country_code_by_name')) { $ip = $this->get_visitor_ip(); $country = geoip_country_code_by_name($ip); if ($country) { return strtoupper($country); } } // Method 3: Accept-Language header (rough approximation) if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { $lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2); $country_map = array( 'en' => 'US', 'de' => 'DE', 'fr' => 'FR', 'es' => 'ES', 'it' => 'IT', 'pt' => 'PT', 'nl' => 'NL', 'pl' => 'PL' ); if (isset($country_map[$lang])) { return $country_map[$lang]; } } // Default: Unknown return 'UNKNOWN'; } /** * Detect if visitor is from California (for CCPA) */ private function detect_california_visitor() { // This would need more sophisticated geo-detection // For now, we'll use a conservative approach return false; // TODO: Implement proper California detection } /** * Get visitor IP address */ private function get_visitor_ip() { // Check for IP from various sources if (!empty($_SERVER['HTTP_CLIENT_IP'])) { return $_SERVER['HTTP_CLIENT_IP']; } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { return $_SERVER['HTTP_X_FORWARDED_FOR']; } elseif (!empty($_SERVER['REMOTE_ADDR'])) { return $_SERVER['REMOTE_ADDR']; } return '127.0.0.1'; } /** * Detect if cookies are enabled */ private function detect_cookies_enabled() { // This will be verified by JavaScript return !isset($_SERVER['HTTP_COOKIE']) ? false : true; } /** * Detect if JavaScript is enabled */ private function detect_javascript_enabled() { // This will be detected by JavaScript and stored return true; // Assume true initially } /** * Detect Do Not Track header */ private function detect_do_not_track() { return isset($_SERVER['HTTP_DNT']) && $_SERVER['HTTP_DNT'] == '1'; } /** * Detect tracking protection */ private function detect_tracking_protection() { // Check for common tracking protection headers return isset($_SERVER['HTTP_SEC_GPC']) && $_SERVER['HTTP_SEC_GPC'] == '1'; } /** * Detect if analytics are active */ private function detect_analytics_active() { // Check if TigerStyle Heat is active if (class_exists('TigerStyleSEO_Google_setup')) { return !empty(get_option('google_analytics_id', '')); } // Check for other analytics plugins $analytics_plugins = array( 'google-analytics-for-wordpress/googleanalytics.php', 'google-analytics-dashboard-for-wp/gadwp.php', 'ga-google-analytics/ga-google-analytics.php' ); foreach ($analytics_plugins as $plugin) { if (is_plugin_active($plugin)) { return true; } } return false; } /** * Detect marketing cookies */ private function detect_marketing_cookies() { // Check for common marketing cookie patterns $marketing_domains = array('facebook.com', 'google.com', 'doubleclick.net', 'googlesyndication.com'); foreach ($marketing_domains as $domain) { if (isset($_COOKIE) && $this->has_cookies_from_domain($domain)) { return true; } } return false; } /** * Check if cookies exist from a specific domain */ private function has_cookies_from_domain($domain) { // This is a simplified check - in reality, we'd need more sophisticated domain detection foreach ($_COOKIE as $name => $value) { if (strpos($name, str_replace('.', '_', $domain)) !== false) { return true; } } return false; } /** * Detect social media pixels */ private function detect_social_pixels() { // Check for Facebook Pixel, Twitter Pixel, etc. return $this->scan_for_social_tracking_code(); } /** * Scan for social tracking code */ private function scan_for_social_tracking_code() { // This would scan the page content for social tracking scripts // For now, we'll check for known plugins $social_plugins = array( 'facebook-for-woocommerce/facebook-for-woocommerce.php', 'pixel-caffeine/pixel-caffeine.php' ); foreach ($social_plugins as $plugin) { if (is_plugin_active($plugin)) { return true; } } return false; } /** * Detect third-party integrations */ private function detect_third_party_integrations() { $integrations = array(); // Check for common third-party services if ($this->detect_analytics_active()) { $integrations[] = 'analytics'; } if ($this->detect_social_pixels()) { $integrations[] = 'social_media'; } // Check for email marketing if (is_plugin_active('mailchimp-for-wp/mailchimp-for-wp.php')) { $integrations[] = 'email_marketing'; } // Check for live chat if (is_plugin_active('tidio-live-chat/tidio-live-chat.php')) { $integrations[] = 'live_chat'; } return $integrations; } /** * Detect user accounts */ private function detect_user_accounts() { return get_option('users_can_register', 0) == 1 || is_plugin_active('woocommerce/woocommerce.php'); } /** * Detect contact forms */ private function detect_contact_forms() { $form_plugins = array( 'contact-form-7/wp-contact-form-7.php', 'wpforms-lite/wpforms.php', 'gravityforms/gravityforms.php' ); foreach ($form_plugins as $plugin) { if (is_plugin_active($plugin)) { return true; } } return false; } /** * Detect ecommerce */ private function detect_ecommerce() { return is_plugin_active('woocommerce/woocommerce.php') || is_plugin_active('easy-digital-downloads/easy-digital-downloads.php'); } /** * Sense plugin boundaries (what other plugins might affect compliance) */ public function sense_plugin_boundaries() { $plugins = array( 'analytics' => $this->detect_analytics_plugins(), 'cookies' => $this->detect_cookie_plugins(), 'forms' => $this->detect_form_plugins(), 'ecommerce' => $this->detect_ecommerce_plugins(), 'social' => $this->detect_social_plugins(), ); // Store plugin boundaries update_option('tigerstyle_whiskers_plugin_boundaries', $plugins); return $plugins; } /** * Detect analytics plugins */ private function detect_analytics_plugins() { $plugins = array(); if (class_exists('TigerStyleSEO_Google_setup')) { $plugins[] = 'tigerstyle-heat'; } // Add other analytics plugin detection return $plugins; } /** * Detect cookie plugins */ private function detect_cookie_plugins() { $cookie_plugins = array( 'cookie-notice/cookie-notice.php' => 'Cookie Notice', 'cookie-law-info/cookie-law-info.php' => 'GDPR Cookie Consent', 'gdpr-cookie-compliance/gdpr-cookie-compliance.php' => 'GDPR Cookie Compliance' ); $active_plugins = array(); foreach ($cookie_plugins as $plugin => $name) { if (is_plugin_active($plugin)) { $active_plugins[] = $name; } } return $active_plugins; } /** * Detect form plugins */ private function detect_form_plugins() { // Implementation similar to detect_contact_forms but more detailed return array(); } /** * Detect ecommerce plugins */ private function detect_ecommerce_plugins() { // Implementation similar to detect_ecommerce but more detailed return array(); } /** * Detect social plugins */ private function detect_social_plugins() { // Implementation for social media plugins return array(); } /** * Store boundaries for JavaScript access */ private function store_boundaries_for_js($boundaries) { // Store in a way that JavaScript can access setcookie( 'tigerstyle_whiskers_boundaries', json_encode($boundaries), time() + 3600, '/', '', is_ssl(), true ); } /** * Inject boundary detection script */ public function inject_boundary_detection_script() { ?> sense_visitor_boundaries(); } return isset(self::$boundaries_cache[$boundary_type]); } /** * Check if visitor is in GDPR territory */ public static function is_gdpr_territory() { if (empty(self::$boundaries_cache)) { $instance = self::instance(); $instance->sense_visitor_boundaries(); } return isset(self::$boundaries_cache['regulatory']['gdpr_applies']) && self::$boundaries_cache['regulatory']['gdpr_applies']; } /** * Get all detected boundaries */ public static function get_all_boundaries() { if (empty(self::$boundaries_cache)) { $instance = self::instance(); $instance->sense_visitor_boundaries(); } return self::$boundaries_cache; } /** * Force boundary re-detection */ public static function refresh_boundaries() { self::$boundaries_cache = array(); $instance = self::instance(); return $instance->sense_visitor_boundaries(); } }