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

450 lines
15 KiB
PHP

<?php
/**
* TigerStyle Whiskers Core
*
* Navigate privacy territories with feline precision - the heart of the whiskers network!
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
class TigerStyleWhiskers_Core {
/**
* Single instance
*/
private static $instance = null;
/**
* Available whiskers (modules)
*/
private $whiskers = array();
/**
* Active whiskers
*/
private $active_whiskers = array();
/**
* Get instance
*/
public static function instance() {
if (is_null(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor
*/
private function __construct() {
$this->init_core();
}
/**
* Initialize core functionality
*/
private function init_core() {
// Define available whiskers
$this->define_whiskers();
// Load active whiskers
$this->load_active_whiskers();
// Initialize boundary detection
$this->init_boundary_detection();
// Initialize compliance scanner
$this->init_compliance_scanner();
// Initialize admin interface
if (is_admin()) {
$this->init_admin();
}
// Initialize frontend functionality
if (!is_admin()) {
$this->init_frontend();
}
}
/**
* Define available whiskers
*/
private function define_whiskers() {
$this->whiskers = array(
'cookie_consent' => array(
'name' => __('Cookie Consent', 'tigerstyle-whiskers'),
'description' => __('Granular cookie consent management', 'tigerstyle-whiskers'),
'file' => 'class-cookie-consent.php',
'class' => 'TigerStyleWhiskers_CookieConsent',
'priority' => 10,
'required' => true
),
'geo_detector' => array(
'name' => __('Geographic Detection', 'tigerstyle-whiskers'),
'description' => __('Advanced geographic boundary detection', 'tigerstyle-whiskers'),
'file' => 'class-advanced-geo-detector.php',
'class' => 'TigerStyleWhiskers_AdvancedGeoDetector',
'priority' => 5,
'required' => true
),
'privacy_policy' => array(
'name' => __('Privacy Policy Generator', 'tigerstyle-whiskers'),
'description' => __('AI-powered privacy policy generation', 'tigerstyle-whiskers'),
'file' => 'class-privacy-policy.php',
'class' => 'TigerStyleWhiskers_PrivacyPolicy',
'priority' => 15,
'required' => false
),
'consent_analytics' => array(
'name' => __('Consent Analytics', 'tigerstyle-whiskers'),
'description' => __('Privacy-focused consent analytics', 'tigerstyle-whiskers'),
'file' => 'class-consent-analytics.php',
'class' => 'TigerStyleWhiskers_ConsentAnalytics',
'priority' => 20,
'required' => false
),
'data_mapper' => array(
'name' => __('Data Mapper', 'tigerstyle-whiskers'),
'description' => __('Data processing activity mapping', 'tigerstyle-whiskers'),
'file' => 'class-data-mapper.php',
'class' => 'TigerStyleWhiskers_DataMapper',
'priority' => 25,
'required' => false
),
'data_deletion' => array(
'name' => __('Data Deletion', 'tigerstyle-whiskers'),
'description' => __('Right to be forgotten implementation', 'tigerstyle-whiskers'),
'file' => 'class-data-deletion.php',
'class' => 'TigerStyleWhiskers_DataDeletion',
'priority' => 30,
'required' => false
),
'cross_border' => array(
'name' => __('Cross-border Compliance', 'tigerstyle-whiskers'),
'description' => __('Multi-jurisdiction privacy compliance', 'tigerstyle-whiskers'),
'file' => 'class-cross-border.php',
'class' => 'TigerStyleWhiskers_CrossBorder',
'priority' => 35,
'required' => false
),
'audit_trail' => array(
'name' => __('Audit Trail', 'tigerstyle-whiskers'),
'description' => __('Compliance audit logging', 'tigerstyle-whiskers'),
'file' => 'class-audit-trail.php',
'class' => 'TigerStyleWhiskers_AuditTrail',
'priority' => 40,
'required' => false
)
);
}
/**
* Load active whiskers
*/
private function load_active_whiskers() {
$active_whiskers = get_option('tigerstyle_whiskers_active', array_keys($this->whiskers));
// Always ensure required whiskers are active
foreach ($this->whiskers as $whisker_id => $whisker) {
if ($whisker['required'] && !in_array($whisker_id, $active_whiskers)) {
$active_whiskers[] = $whisker_id;
}
}
// Sort by priority
$sorted_whiskers = array();
foreach ($active_whiskers as $whisker_id) {
if (isset($this->whiskers[$whisker_id])) {
$sorted_whiskers[$whisker_id] = $this->whiskers[$whisker_id];
}
}
uasort($sorted_whiskers, function($a, $b) {
return $a['priority'] - $b['priority'];
});
// Load whisker files
foreach ($sorted_whiskers as $whisker_id => $whisker) {
$file_path = TIGERSTYLE_WHISKERS_PLUGIN_DIR . 'includes/whiskers/' . $whisker['file'];
if (file_exists($file_path)) {
require_once $file_path;
if (class_exists($whisker['class'])) {
$this->active_whiskers[$whisker_id] = $whisker['class']::instance();
}
}
}
}
/**
* Initialize boundary detection
*/
private function init_boundary_detection() {
require_once TIGERSTYLE_WHISKERS_PLUGIN_DIR . 'includes/class-boundary-detector.php';
TigerStyleWhiskers_BoundaryDetector::instance();
}
/**
* Initialize compliance scanner
*/
private function init_compliance_scanner() {
require_once TIGERSTYLE_WHISKERS_PLUGIN_DIR . 'includes/class-compliance-scanner.php';
TigerStyleWhiskers_ComplianceScanner::instance();
}
/**
* Initialize admin interface
*/
private function init_admin() {
require_once TIGERSTYLE_WHISKERS_PLUGIN_DIR . 'admin/class-admin.php';
TigerStyleWhiskers_Admin::instance();
}
/**
* Initialize frontend functionality
*/
private function init_frontend() {
// Add frontend consent banner
add_action('wp_footer', array($this, 'render_consent_banner'));
// Enqueue frontend assets
add_action('wp_enqueue_scripts', array($this, 'enqueue_frontend_assets'));
}
/**
* Get a specific whisker instance
*/
public function get_whisker($whisker_id) {
return isset($this->active_whiskers[$whisker_id]) ? $this->active_whiskers[$whisker_id] : null;
}
/**
* Get all active whiskers
*/
public function get_active_whiskers() {
return $this->active_whiskers;
}
/**
* Render consent banner
*/
public function render_consent_banner() {
$cookie_consent = $this->get_whisker('cookie_consent');
if ($cookie_consent && method_exists($cookie_consent, 'render_banner')) {
$cookie_consent->render_banner();
}
}
/**
* Enqueue frontend assets
*/
public function enqueue_frontend_assets() {
// Frontend CSS
wp_enqueue_style(
'whiskers-frontend',
TIGERSTYLE_WHISKERS_PLUGIN_URL . 'assets/css/frontend.css',
array(),
TIGERSTYLE_WHISKERS_VERSION
);
// Frontend JavaScript
wp_enqueue_script(
'whiskers-consent',
TIGERSTYLE_WHISKERS_PLUGIN_URL . 'assets/js/consent.js',
array('jquery'),
TIGERSTYLE_WHISKERS_VERSION,
true
);
// Localize script
wp_localize_script('whiskers-consent', 'whiskersConsent', array(
'ajaxurl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('whiskers_consent_nonce'),
'strings' => array(
'acceptAll' => __('Accept All', 'tigerstyle-whiskers'),
'rejectAll' => __('Reject All', 'tigerstyle-whiskers'),
'manageCookies' => __('Manage Cookies', 'tigerstyle-whiskers'),
'savePreferences' => __('Save Preferences', 'tigerstyle-whiskers'),
)
));
}
/**
* Plugin activation
*/
public static function activate() {
// Create database tables
self::create_tables();
// Set default options
self::set_defaults();
// Schedule cleanup events
self::schedule_events();
// Flush rewrite rules
flush_rewrite_rules();
}
/**
* Plugin deactivation
*/
public static function deactivate() {
// Clear scheduled events
wp_clear_scheduled_hook('tigerstyle_whiskers_cleanup');
wp_clear_scheduled_hook('tigerstyle_whiskers_compliance_scan');
// Flush rewrite rules
flush_rewrite_rules();
}
/**
* Create database tables
*/
public static function create_tables() {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
// Consent logs table
$consent_table = $wpdb->prefix . 'whiskers_consent_logs';
$consent_sql = "CREATE TABLE $consent_table (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
user_id bigint(20) unsigned DEFAULT NULL,
session_id varchar(64) NOT NULL,
consent_type varchar(50) NOT NULL,
consent_value text NOT NULL,
ip_address varchar(45) NOT NULL,
user_agent text NOT NULL,
country_code varchar(2) DEFAULT NULL,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY user_id (user_id),
KEY session_id (session_id),
KEY consent_type (consent_type),
KEY created_at (created_at)
) $charset_collate;";
// Data requests table
$requests_table = $wpdb->prefix . 'whiskers_data_requests';
$requests_sql = "CREATE TABLE $requests_table (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
request_type varchar(50) NOT NULL,
email varchar(254) NOT NULL,
status varchar(50) NOT NULL DEFAULT 'pending',
verification_token varchar(64) NOT NULL,
verified_at datetime DEFAULT NULL,
processed_at datetime DEFAULT NULL,
notes text DEFAULT NULL,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY request_type (request_type),
KEY email (email),
KEY status (status),
KEY verification_token (verification_token),
KEY created_at (created_at)
) $charset_collate;";
// Audit log table
$audit_table = $wpdb->prefix . 'whiskers_audit_log';
$audit_sql = "CREATE TABLE $audit_table (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
event_type varchar(50) NOT NULL,
user_id bigint(20) unsigned DEFAULT NULL,
session_id varchar(64) DEFAULT NULL,
event_data text DEFAULT NULL,
ip_address varchar(45) DEFAULT NULL,
user_agent text DEFAULT NULL,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY event_type (event_type),
KEY user_id (user_id),
KEY session_id (session_id),
KEY created_at (created_at)
) $charset_collate;";
// Consent analytics table
$analytics_table = $wpdb->prefix . 'tigerstyle_whiskers_consent_analytics';
$analytics_sql = "CREATE TABLE $analytics_table (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
event_type varchar(50) NOT NULL,
event_data longtext NOT NULL,
timestamp datetime NOT NULL,
date_created date NOT NULL,
hour_created tinyint(2) NOT NULL,
country_code varchar(2) NOT NULL,
session_id_hash varchar(64) NOT NULL,
PRIMARY KEY (id),
KEY event_type (event_type),
KEY date_created (date_created),
KEY hour_created (hour_created),
KEY country_code (country_code),
KEY timestamp (timestamp)
) $charset_collate;";
// Consent analytics daily aggregation table
$analytics_daily_table = $wpdb->prefix . 'tigerstyle_whiskers_consent_analytics_daily';
$analytics_daily_sql = "CREATE TABLE $analytics_daily_table (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
date_aggregated date NOT NULL,
total_consent_requests bigint(20) DEFAULT 0,
total_accepted bigint(20) DEFAULT 0,
total_denied bigint(20) DEFAULT 0,
unique_visitors bigint(20) DEFAULT 0,
acceptance_rate decimal(5,2) DEFAULT 0,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY date_aggregated (date_aggregated),
KEY created_at (created_at)
) $charset_collate;";
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
dbDelta($consent_sql);
dbDelta($requests_sql);
dbDelta($audit_sql);
dbDelta($analytics_sql);
dbDelta($analytics_daily_sql);
}
/**
* Set default options
*/
public static function set_defaults() {
$defaults = array(
'tigerstyle_whiskers_active' => array('cookie_consent', 'geo_detector'),
'tigerstyle_whiskers_settings' => array(
'consent_banner_position' => 'bottom',
'consent_banner_style' => 'minimal',
'required_consent_categories' => array('necessary'),
'geo_detection_enabled' => true,
'compliance_monitoring' => true,
),
'tigerstyle_whiskers_version' => TIGERSTYLE_WHISKERS_VERSION
);
foreach ($defaults as $option => $value) {
if (!get_option($option)) {
add_option($option, $value);
}
}
}
/**
* Schedule events
*/
public static function schedule_events() {
// Schedule daily cleanup
if (!wp_next_scheduled('tigerstyle_whiskers_cleanup')) {
wp_schedule_event(time(), 'daily', 'tigerstyle_whiskers_cleanup');
}
// Schedule compliance scan
if (!wp_next_scheduled('tigerstyle_whiskers_compliance_scan')) {
wp_schedule_event(time(), 'daily', 'tigerstyle_whiskers_compliance_scan');
}
}
}