tigerstyle-whiskers/includes/whiskers/class-privacy-policy.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

1071 lines
43 KiB
PHP

<?php
/**
* Privacy Policy Generator Whisker for TigerStyle Whiskers
*
* AI-powered privacy policy generation with feline intelligence - like a cat
* understanding its territory and documenting every detail with precision
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
class TigerStyleWhiskers_PrivacyPolicy {
/**
* Single instance
*/
private static $instance = null;
/**
* Policy templates for different jurisdictions
*/
private $policy_templates = array();
/**
* Data processing activities scanner
*/
private $activity_scanner = null;
/**
* Get instance
*/
public static function instance() {
if (is_null(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor
*/
private function __construct() {
$this->init_policy_generator();
}
/**
* Initialize privacy policy generator
*/
private function init_policy_generator() {
// Admin hooks
if (is_admin()) {
add_action('admin_post_generate_privacy_policy', array($this, 'generate_policy'));
add_action('admin_post_update_policy_settings', array($this, 'update_policy_settings'));
add_action('wp_ajax_tigerstyle_whiskers_scan_site', array($this, 'ajax_scan_site'));
}
// Frontend hooks
add_shortcode('tigerstyle_privacy_policy', array($this, 'privacy_policy_shortcode'));
add_action('wp_head', array($this, 'inject_policy_metadata'));
// Initialize activity scanner
if (class_exists('TigerStyleWhiskers_DataMapper')) {
$this->activity_scanner = TigerStyleWhiskers_DataMapper::instance();
}
// Load policy templates
$this->load_policy_templates();
if (defined('WP_DEBUG') && WP_DEBUG) {
error_log('TigerStyle Whiskers: Privacy policy generator whisker is ready to document with feline precision!');
}
}
/**
* Load policy templates for different jurisdictions
*/
private function load_policy_templates() {
$this->policy_templates = array(
'gdpr' => array(
'name' => 'GDPR (European Union)',
'description' => 'Comprehensive GDPR-compliant privacy policy',
'required_sections' => array(
'data_controller',
'legal_basis',
'data_categories',
'processing_purposes',
'data_retention',
'user_rights',
'data_transfers',
'security_measures',
'contact_dpo'
),
'optional_sections' => array(
'cookies_policy',
'marketing_communications',
'third_party_integrations'
)
),
'ccpa' => array(
'name' => 'CCPA (California)',
'description' => 'California Consumer Privacy Act compliant policy',
'required_sections' => array(
'business_identity',
'personal_info_categories',
'sources_of_info',
'business_purposes',
'third_party_sharing',
'consumer_rights',
'non_discrimination'
),
'optional_sections' => array(
'sale_of_personal_info',
'minors_privacy'
)
),
'generic' => array(
'name' => 'Generic Privacy Policy',
'description' => 'General privacy policy for global compliance',
'required_sections' => array(
'information_collection',
'information_use',
'information_sharing',
'data_security',
'user_choices',
'contact_information'
),
'optional_sections' => array(
'cookies_tracking',
'third_party_links',
'policy_updates'
)
)
);
}
/**
* Generate privacy policy based on site scan
*/
public function generate_policy() {
if (!current_user_can('manage_options')) {
wp_die(__('You do not have sufficient permissions', 'tigerstyle-whiskers'));
}
if (!wp_verify_nonce($_POST['policy_nonce'], 'generate_privacy_policy')) {
wp_die(__('Security check failed', 'tigerstyle-whiskers'));
}
$template_type = sanitize_text_field($_POST['template_type'] ?? 'gdpr');
$company_info = array(
'name' => sanitize_text_field($_POST['company_name'] ?? get_bloginfo('name')),
'email' => sanitize_email($_POST['contact_email'] ?? get_option('admin_email')),
'address' => sanitize_textarea_field($_POST['company_address'] ?? ''),
'phone' => sanitize_text_field($_POST['company_phone'] ?? ''),
'dpo_email' => sanitize_email($_POST['dpo_email'] ?? ''),
'website_url' => home_url()
);
// Scan website for data processing activities
$site_scan_results = $this->scan_website_comprehensively();
// Generate policy content
$policy_content = $this->build_policy_content($template_type, $company_info, $site_scan_results);
// Save the generated policy
$policy_id = $this->save_generated_policy($policy_content, $template_type, $company_info);
if ($policy_id) {
wp_redirect(admin_url('admin.php?page=tigerstyle-whiskers&tab=privacy-policy&message=policy_generated&policy_id=' . $policy_id));
} else {
wp_redirect(admin_url('admin.php?page=tigerstyle-whiskers&tab=privacy-policy&message=policy_generation_failed'));
}
exit;
}
/**
* Scan website comprehensively for data processing activities
*/
private function scan_website_comprehensively() {
$scan_results = array(
'wordpress_core' => $this->scan_wordpress_core(),
'active_plugins' => $this->scan_active_plugins(),
'theme_analysis' => $this->scan_active_theme(),
'third_party_services' => $this->scan_third_party_services(),
'data_collection_points' => $this->scan_data_collection_points(),
'cookies_analysis' => $this->scan_cookies_usage(),
'external_integrations' => $this->scan_external_integrations(),
'user_generated_content' => $this->scan_user_content_features()
);
// Use data mapper if available for enhanced scanning
if ($this->activity_scanner) {
$scan_results['processing_activities'] = $this->activity_scanner->get_processing_activities();
$scan_results['data_categories'] = $this->activity_scanner->get_data_categories();
}
return $scan_results;
}
/**
* Scan WordPress core data processing
*/
private function scan_wordpress_core() {
$core_features = array(
'user_registration' => get_option('users_can_register', 0),
'comments_enabled' => get_option('default_comment_status', 'closed') === 'open',
'user_profiles' => true, // Always present
'admin_access_logs' => true, // WordPress logs admin access
'automatic_updates' => get_option('auto_update_core_minor', true),
'error_logging' => defined('WP_DEBUG_LOG') && WP_DEBUG_LOG,
'version_info' => array(
'wordpress' => get_bloginfo('version'),
'php' => PHP_VERSION,
'mysql' => $this->get_mysql_version()
)
);
return $core_features;
}
/**
* Scan active plugins for data processing
*/
private function scan_active_plugins() {
// Ensure we have the required WordPress functions loaded
if (!function_exists('get_plugin_data')) {
require_once(ABSPATH . 'wp-admin/includes/plugin.php');
}
$active_plugins = get_option('active_plugins', array());
$plugin_analysis = array();
foreach ($active_plugins as $plugin_file) {
// Skip if plugin file doesn't exist
if (!file_exists(WP_PLUGIN_DIR . '/' . $plugin_file)) {
continue;
}
$plugin_data = get_plugin_data(WP_PLUGIN_DIR . '/' . $plugin_file);
$plugin_slug = dirname($plugin_file);
$analysis = array(
'name' => $plugin_data['Name'],
'version' => $plugin_data['Version'],
'author' => $plugin_data['Author'],
'description' => $plugin_data['Description'],
'data_processing_type' => $this->analyze_plugin_data_processing($plugin_slug, $plugin_data),
'privacy_implications' => $this->get_plugin_privacy_implications($plugin_slug),
'gdpr_compliance' => $this->check_plugin_gdpr_features($plugin_slug)
);
$plugin_analysis[$plugin_slug] = $analysis;
}
return $plugin_analysis;
}
/**
* Analyze plugin data processing patterns
*/
private function analyze_plugin_data_processing($plugin_slug, $plugin_data) {
$processing_types = array();
// Common plugin patterns
$plugin_patterns = array(
'contact' => array('contact-form', 'ninja-forms', 'wpforms', 'gravityforms'),
'analytics' => array('google-analytics', 'jetpack', 'monster-insights', 'tigerstyle-heat'),
'ecommerce' => array('woocommerce', 'easy-digital-downloads', 'wp-ecommerce'),
'social' => array('social', 'facebook', 'twitter', 'instagram'),
'marketing' => array('mailchimp', 'constant-contact', 'newsletter'),
'security' => array('wordfence', 'sucuri', 'ithemes-security'),
'backup' => array('updraftplus', 'backwpup', 'tigerstyle-life9'),
'seo' => array('yoast', 'rankmath', 'tigerstyle-heat'),
'membership' => array('memberpress', 'restrict-content', 'wishlist-member'),
'forum' => array('bbpress', 'buddypress', 'wpforo')
);
$name_lower = strtolower($plugin_data['Name']);
$slug_lower = strtolower($plugin_slug);
foreach ($plugin_patterns as $type => $patterns) {
foreach ($patterns as $pattern) {
if (strpos($name_lower, $pattern) !== false || strpos($slug_lower, $pattern) !== false) {
$processing_types[] = $type;
break;
}
}
}
return array_unique($processing_types);
}
/**
* Get plugin privacy implications
*/
private function get_plugin_privacy_implications($plugin_slug) {
$implications = array();
// Known plugin privacy implications
$plugin_implications = array(
'woocommerce' => array(
'collects_payment_data' => true,
'stores_customer_profiles' => true,
'tracks_purchase_history' => true,
'requires_gdpr_compliance' => true,
'data_retention_required' => '7 years'
),
'contact-form-7' => array(
'collects_form_data' => true,
'stores_submissions' => false,
'sends_email_notifications' => true,
'requires_consent' => true
),
'google-analytics' => array(
'tracks_user_behavior' => true,
'uses_cookies' => true,
'shares_data_with_google' => true,
'requires_consent' => true,
'anonymization_available' => true
),
'mailchimp-for-wp' => array(
'collects_email_addresses' => true,
'syncs_with_external_service' => true,
'requires_double_opt_in' => 'recommended',
'data_transfers_to_us' => true
)
);
return $plugin_implications[$plugin_slug] ?? array();
}
/**
* Check plugin GDPR compliance features
*/
private function check_plugin_gdpr_features($plugin_slug) {
$compliance_features = array(
'has_privacy_policy' => false,
'supports_data_export' => false,
'supports_data_deletion' => false,
'consent_integration' => false,
'anonymization_options' => false
);
// Check if plugin registers privacy exporters/erasers
$privacy_exporters = apply_filters('wp_privacy_personal_data_exporters', array());
$privacy_erasers = apply_filters('wp_privacy_personal_data_erasers', array());
foreach ($privacy_exporters as $exporter) {
if (strpos($exporter['exporter_friendly_name'], $plugin_slug) !== false) {
$compliance_features['supports_data_export'] = true;
break;
}
}
foreach ($privacy_erasers as $eraser) {
if (strpos($eraser['eraser_friendly_name'], $plugin_slug) !== false) {
$compliance_features['supports_data_deletion'] = true;
break;
}
}
return $compliance_features;
}
/**
* Scan active theme for data processing
*/
private function scan_active_theme() {
$theme = wp_get_theme();
$theme_analysis = array(
'name' => $theme->get('Name'),
'version' => $theme->get('Version'),
'author' => $theme->get('Author'),
'has_custom_scripts' => $this->theme_has_custom_scripts(),
'uses_google_fonts' => $this->theme_uses_google_fonts(),
'has_social_integration' => $this->theme_has_social_features(),
'custom_forms' => $this->theme_has_custom_forms(),
'tracking_codes' => $this->theme_has_tracking_codes()
);
return $theme_analysis;
}
/**
* Scan for third-party services
*/
private function scan_third_party_services() {
$services = array();
// Common third-party services to detect
$service_patterns = array(
'google_analytics' => array('google-analytics.com', 'googletagmanager.com'),
'google_fonts' => array('fonts.googleapis.com', 'fonts.gstatic.com'),
'facebook_pixel' => array('facebook.net', 'connect.facebook.net'),
'twitter_widgets' => array('platform.twitter.com'),
'youtube_embeds' => array('youtube.com', 'youtu.be'),
'vimeo_embeds' => array('vimeo.com'),
'gravatar' => array('gravatar.com'),
'recaptcha' => array('recaptcha.net', 'google.com/recaptcha'),
'disqus' => array('disqus.com'),
'mailchimp' => array('mailchimp.com'),
'stripe' => array('stripe.com'),
'paypal' => array('paypal.com')
);
// Scan page content for external service references
$home_content = $this->get_page_content(home_url());
foreach ($service_patterns as $service => $patterns) {
foreach ($patterns as $pattern) {
if (strpos($home_content, $pattern) !== false) {
$services[$service] = array(
'detected' => true,
'pattern_matched' => $pattern,
'privacy_implications' => $this->get_service_privacy_implications($service)
);
break;
}
}
}
return $services;
}
/**
* Get service privacy implications
*/
private function get_service_privacy_implications($service) {
$implications = array(
'google_analytics' => array(
'data_shared' => 'Usage data, IP addresses, device information',
'purpose' => 'Website analytics and optimization',
'retention' => '26 months (default)',
'location' => 'United States (Google servers)',
'user_rights' => 'Users can opt-out via browser settings or privacy policy'
),
'google_fonts' => array(
'data_shared' => 'IP address, browser information',
'purpose' => 'Font delivery',
'retention' => 'Up to 1 year',
'location' => 'United States (Google servers)',
'user_rights' => 'No specific opt-out mechanism'
),
'facebook_pixel' => array(
'data_shared' => 'Website activity, device information, IP address',
'purpose' => 'Advertising and marketing analytics',
'retention' => 'Varies (see Facebook privacy policy)',
'location' => 'United States (Facebook servers)',
'user_rights' => 'Users can opt-out via Facebook privacy settings'
),
'recaptcha' => array(
'data_shared' => 'IP address, mouse movements, browser information',
'purpose' => 'Spam and bot protection',
'retention' => 'Varies (see Google privacy policy)',
'location' => 'United States (Google servers)',
'user_rights' => 'No specific opt-out mechanism (necessary for functionality)'
)
);
return $implications[$service] ?? array();
}
/**
* Scan data collection points
*/
private function scan_data_collection_points() {
// Ensure we have the required WordPress functions loaded
if (!function_exists('is_plugin_active')) {
require_once(ABSPATH . 'wp-admin/includes/plugin.php');
}
$collection_points = array();
// Registration forms
if (get_option('users_can_register')) {
$collection_points['user_registration'] = array(
'type' => 'User Registration',
'data_collected' => 'Username, email address, password',
'purpose' => 'Account creation and management',
'legal_basis' => 'Consent',
'required' => true
);
}
// Comment forms
if (comments_open()) {
$collection_points['comments'] = array(
'type' => 'Comment Forms',
'data_collected' => 'Name, email address, website URL, IP address, comment content',
'purpose' => 'Comment moderation and display',
'legal_basis' => 'Legitimate interest',
'required' => false
);
}
// Contact forms (detect common plugins)
$contact_form_plugins = array(
'contact-form-7' => 'Contact Form 7',
'wpforms' => 'WPForms',
'gravityforms' => 'Gravity Forms',
'ninja-forms' => 'Ninja Forms'
);
foreach ($contact_form_plugins as $plugin => $name) {
if (function_exists('is_plugin_active') && is_plugin_active($plugin . '/' . $plugin . '.php')) {
$collection_points['contact_forms'] = array(
'type' => 'Contact Forms (' . $name . ')',
'data_collected' => 'Name, email address, message content, and other form fields',
'purpose' => 'Customer support and communication',
'legal_basis' => 'Legitimate interest',
'required' => false
);
break;
}
}
// E-commerce (WooCommerce)
if (class_exists('WooCommerce')) {
$collection_points['ecommerce'] = array(
'type' => 'E-commerce Orders',
'data_collected' => 'Billing information, shipping address, payment details, order history',
'purpose' => 'Order processing and customer service',
'legal_basis' => 'Contract performance',
'required' => true
);
}
return $collection_points;
}
/**
* Scan cookies usage
*/
private function scan_cookies_usage() {
$cookies_analysis = array(
'wordpress_core' => array(
'wp_logged_in' => 'User authentication',
'wp_session' => 'Session management',
'comment_author' => 'Comment form pre-filling'
),
'third_party' => array(),
'analytics' => array(),
'marketing' => array()
);
// Detect analytics cookies
if ((function_exists('is_plugin_active') && is_plugin_active('google-analytics-for-wordpress/googleanalytics.php')) ||
get_option('google_analytics_id')) {
$cookies_analysis['analytics']['google_analytics'] = array(
'cookies' => '_ga, _ga_*, _gid, _gat',
'purpose' => 'Website analytics and user behavior tracking',
'duration' => 'Up to 2 years',
'provider' => 'Google Analytics'
);
}
// Detect marketing cookies (Facebook Pixel, etc.)
if ($this->detect_facebook_pixel()) {
$cookies_analysis['marketing']['facebook_pixel'] = array(
'cookies' => '_fbp, _fbc',
'purpose' => 'Advertising and marketing analytics',
'duration' => 'Up to 90 days',
'provider' => 'Facebook'
);
}
return $cookies_analysis;
}
/**
* Scan external integrations
*/
private function scan_external_integrations() {
$integrations = array();
// Email marketing integrations
if (function_exists('is_plugin_active') && is_plugin_active('mailchimp-for-wp/mailchimp-for-wp.php')) {
$integrations['mailchimp'] = array(
'service' => 'Mailchimp',
'purpose' => 'Email marketing and newsletters',
'data_shared' => 'Email addresses, subscriber preferences',
'location' => 'United States'
);
}
// Payment processors
if (class_exists('WooCommerce')) {
// Detect payment gateways
$payment_gateways = WC()->payment_gateways()->get_available_payment_gateways();
foreach ($payment_gateways as $gateway_id => $gateway) {
if ($gateway->enabled === 'yes') {
$integrations[$gateway_id] = array(
'service' => $gateway->get_title(),
'purpose' => 'Payment processing',
'data_shared' => 'Payment information, billing details',
'location' => $this->get_payment_gateway_location($gateway_id)
);
}
}
}
return $integrations;
}
/**
* Scan user-generated content features
*/
private function scan_user_content_features() {
$user_content = array();
// Comments
if (comments_open()) {
$user_content['comments'] = array(
'type' => 'Comments',
'moderation' => get_option('comment_moderation') ? 'enabled' : 'disabled',
'registration_required' => get_option('comment_registration'),
'data_retention' => 'Until manually deleted'
);
}
// User profiles
if (get_option('users_can_register')) {
$user_content['user_profiles'] = array(
'type' => 'User Profiles',
'editable_by_user' => true,
'data_retention' => 'Until account deletion'
);
}
// Forum features (if BuddyPress/bbPress active)
if (function_exists('is_plugin_active') && is_plugin_active('buddypress/bp-loader.php')) {
$user_content['social_features'] = array(
'type' => 'Social Community Features',
'features' => 'Profiles, activity streams, messaging',
'data_retention' => 'Until account deletion or manual removal'
);
}
return $user_content;
}
/**
* Build comprehensive policy content
*/
private function build_policy_content($template_type, $company_info, $scan_results) {
$policy_sections = array();
$template = $this->policy_templates[$template_type];
// Build each required section
foreach ($template['required_sections'] as $section) {
$policy_sections[$section] = $this->generate_policy_section($section, $template_type, $company_info, $scan_results);
}
// Build optional sections if relevant
foreach ($template['optional_sections'] as $section) {
if ($this->should_include_optional_section($section, $scan_results)) {
$policy_sections[$section] = $this->generate_policy_section($section, $template_type, $company_info, $scan_results);
}
}
return array(
'template_type' => $template_type,
'template_name' => $template['name'],
'generated_date' => current_time('mysql'),
'company_info' => $company_info,
'scan_results_summary' => $this->summarize_scan_results($scan_results),
'sections' => $policy_sections,
'last_updated' => current_time('mysql'),
'version' => '1.0'
);
}
/**
* Generate individual policy section
*/
private function generate_policy_section($section, $template_type, $company_info, $scan_results) {
$section_content = array(
'title' => $this->get_section_title($section),
'content' => '',
'subsections' => array()
);
switch ($section) {
case 'data_controller':
$section_content['content'] = $this->generate_data_controller_section($company_info);
break;
case 'legal_basis':
$section_content['content'] = $this->generate_legal_basis_section($scan_results);
break;
case 'data_categories':
$section_content['content'] = $this->generate_data_categories_section($scan_results);
break;
case 'processing_purposes':
$section_content['content'] = $this->generate_processing_purposes_section($scan_results);
break;
case 'user_rights':
$section_content['content'] = $this->generate_user_rights_section($template_type);
break;
case 'cookies_policy':
$section_content['content'] = $this->generate_cookies_section($scan_results);
break;
// Add more sections as needed
default:
$section_content['content'] = $this->generate_generic_section($section, $scan_results);
}
return $section_content;
}
/**
* Generate data controller section
*/
private function generate_data_controller_section($company_info) {
return sprintf(
"The data controller for this website is:\n\n" .
"**%s**\n" .
"%s\n" .
"Email: %s\n" .
"%s\n\n" .
"If you have any questions about this privacy policy or our data processing practices, " .
"please contact us using the information above.",
$company_info['name'],
!empty($company_info['address']) ? $company_info['address'] : '',
$company_info['email'],
!empty($company_info['phone']) ? 'Phone: ' . $company_info['phone'] : ''
);
}
/**
* Generate legal basis section
*/
private function generate_legal_basis_section($scan_results) {
$content = "We process personal data based on the following legal grounds:\n\n";
$legal_bases = array(
'consent' => 'Your explicit consent (e.g., newsletter signup, cookie consent)',
'contract' => 'Performance of a contract (e.g., processing orders, user accounts)',
'legal_obligation' => 'Compliance with legal obligations (e.g., tax records, accounting)',
'legitimate_interest' => 'Our legitimate business interests (e.g., website security, analytics)',
'vital_interests' => 'Protection of vital interests (e.g., emergency situations)',
'public_task' => 'Performance of public tasks (if applicable)'
);
foreach ($legal_bases as $basis => $description) {
if ($this->scan_indicates_legal_basis($basis, $scan_results)) {
$content .= "- **" . ucwords(str_replace('_', ' ', $basis)) . "**: " . $description . "\n";
}
}
return $content;
}
/**
* Generate data categories section
*/
private function generate_data_categories_section($scan_results) {
$content = "We may collect and process the following categories of personal data:\n\n";
$data_categories = array(
'identity_data' => array(
'examples' => 'Name, username, title, date of birth',
'detected' => $this->has_identity_data($scan_results)
),
'contact_data' => array(
'examples' => 'Email address, phone number, postal address',
'detected' => $this->has_contact_data($scan_results)
),
'technical_data' => array(
'examples' => 'IP address, browser type, device information',
'detected' => $this->has_technical_data($scan_results)
),
'usage_data' => array(
'examples' => 'Pages visited, time spent, click patterns',
'detected' => $this->has_usage_data($scan_results)
),
'financial_data' => array(
'examples' => 'Payment information, billing details',
'detected' => $this->has_financial_data($scan_results)
)
);
foreach ($data_categories as $category => $info) {
if ($info['detected']) {
$category_name = ucwords(str_replace('_', ' ', $category));
$content .= "- **{$category_name}**: {$info['examples']}\n";
}
}
return $content;
}
/**
* Generate user rights section
*/
private function generate_user_rights_section($template_type) {
$content = "Under applicable privacy laws, you have the following rights regarding your personal data:\n\n";
if ($template_type === 'gdpr') {
$rights = array(
'access' => 'Right to access your personal data and receive information about our processing',
'rectification' => 'Right to correct inaccurate or incomplete personal data',
'erasure' => 'Right to deletion of your personal data ("right to be forgotten")',
'restrict_processing' => 'Right to restrict processing of your personal data',
'data_portability' => 'Right to receive your data in a portable format',
'object' => 'Right to object to processing based on legitimate interests',
'withdraw_consent' => 'Right to withdraw consent at any time'
);
} elseif ($template_type === 'ccpa') {
$rights = array(
'know' => 'Right to know what personal information we collect and how we use it',
'delete' => 'Right to delete personal information we have collected',
'opt_out' => 'Right to opt-out of the sale of personal information',
'non_discrimination' => 'Right to non-discriminatory treatment for exercising privacy rights'
);
} else {
$rights = array(
'access' => 'Right to access your personal information',
'correction' => 'Right to correct inaccurate information',
'deletion' => 'Right to request deletion of your information',
'opt_out' => 'Right to opt-out of certain data processing'
);
}
foreach ($rights as $right => $description) {
$right_name = ucwords(str_replace('_', ' ', $right));
$content .= "- **{$right_name}**: {$description}\n";
}
$content .= "\nTo exercise these rights, please contact us using the information provided in this policy.";
return $content;
}
/**
* Helper methods for checking scan results
*/
private function has_identity_data($scan_results) {
return $scan_results['wordpress_core']['user_registration'] ||
isset($scan_results['data_collection_points']['user_registration']);
}
private function has_contact_data($scan_results) {
return !empty($scan_results['data_collection_points']);
}
private function has_technical_data($scan_results) {
return !empty($scan_results['third_party_services']) ||
!empty($scan_results['cookies_analysis']['analytics']);
}
private function has_usage_data($scan_results) {
return !empty($scan_results['third_party_services']['google_analytics']) ||
!empty($scan_results['cookies_analysis']['analytics']);
}
private function has_financial_data($scan_results) {
return isset($scan_results['data_collection_points']['ecommerce']);
}
/**
* Save generated policy
*/
private function save_generated_policy($policy_content, $template_type, $company_info) {
global $wpdb;
$table_name = $wpdb->prefix . 'tigerstyle_whiskers_privacy_policies';
// Create table if it doesn't exist
$this->create_privacy_policies_table();
$result = $wpdb->insert(
$table_name,
array(
'template_type' => $template_type,
'company_name' => $company_info['name'],
'policy_content' => json_encode($policy_content),
'generated_date' => current_time('mysql'),
'status' => 'draft'
),
array('%s', '%s', '%s', '%s', '%s')
);
return $result ? $wpdb->insert_id : false;
}
/**
* Create privacy policies table
*/
private function create_privacy_policies_table() {
global $wpdb;
$table_name = $wpdb->prefix . 'tigerstyle_whiskers_privacy_policies';
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
template_type varchar(50) NOT NULL,
company_name varchar(255) NOT NULL,
policy_content longtext NOT NULL,
generated_date datetime DEFAULT CURRENT_TIMESTAMP,
status varchar(20) DEFAULT 'draft',
published_date datetime DEFAULT NULL,
last_updated datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY template_type (template_type),
KEY status (status),
KEY generated_date (generated_date)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}
/**
* Render admin page for privacy policy generator
*/
public function render_admin_page() {
?>
<div class="tigerstyle-whiskers-admin-section">
<h2><?php _e('Privacy Policy Generator', 'tigerstyle-whiskers'); ?></h2>
<p class="description">
<?php _e('Generate comprehensive privacy policies with feline intelligence - automatically scan your website and create compliant policies for your jurisdiction.', 'tigerstyle-whiskers'); ?>
</p>
<?php $this->render_policy_generator_form(); ?>
<?php $this->render_generated_policies_list(); ?>
</div>
<?php
}
/**
* Render policy generator form
*/
private function render_policy_generator_form() {
?>
<div class="tw-policy-generator">
<h3><?php _e('Generate New Privacy Policy', 'tigerstyle-whiskers'); ?></h3>
<form method="post" action="<?php echo admin_url('admin-post.php'); ?>">
<input type="hidden" name="action" value="generate_privacy_policy">
<?php wp_nonce_field('generate_privacy_policy', 'policy_nonce'); ?>
<table class="form-table">
<tr>
<th scope="row">
<label for="template_type"><?php _e('Policy Template', 'tigerstyle-whiskers'); ?></label>
</th>
<td>
<select id="template_type" name="template_type" class="regular-text">
<?php foreach ($this->policy_templates as $type => $template): ?>
<option value="<?php echo esc_attr($type); ?>">
<?php echo esc_html($template['name']); ?>
</option>
<?php endforeach; ?>
</select>
<p class="description"><?php _e('Choose the appropriate template based on your primary jurisdiction.', 'tigerstyle-whiskers'); ?></p>
</td>
</tr>
<tr>
<th scope="row">
<label for="company_name"><?php _e('Company/Website Name', 'tigerstyle-whiskers'); ?></label>
</th>
<td>
<input type="text" id="company_name" name="company_name"
value="<?php echo esc_attr(get_bloginfo('name')); ?>" class="regular-text">
</td>
</tr>
<tr>
<th scope="row">
<label for="contact_email"><?php _e('Contact Email', 'tigerstyle-whiskers'); ?></label>
</th>
<td>
<input type="email" id="contact_email" name="contact_email"
value="<?php echo esc_attr(get_option('admin_email')); ?>" class="regular-text">
</td>
</tr>
<tr>
<th scope="row">
<label for="company_address"><?php _e('Company Address', 'tigerstyle-whiskers'); ?></label>
</th>
<td>
<textarea id="company_address" name="company_address" rows="3" class="large-text"></textarea>
<p class="description"><?php _e('Required for GDPR compliance if you are a business.', 'tigerstyle-whiskers'); ?></p>
</td>
</tr>
</table>
<?php submit_button(__('Scan Website & Generate Policy', 'tigerstyle-whiskers'), 'primary', 'generate_policy'); ?>
</form>
</div>
<?php
}
/**
* Render generated policies list
*/
private function render_generated_policies_list() {
global $wpdb;
$table_name = $wpdb->prefix . 'tigerstyle_whiskers_privacy_policies';
$policies = $wpdb->get_results("SELECT * FROM $table_name ORDER BY generated_date DESC LIMIT 10");
if (!empty($policies)): ?>
<div class="tw-generated-policies">
<h3><?php _e('Generated Privacy Policies', 'tigerstyle-whiskers'); ?></h3>
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th><?php _e('Company', 'tigerstyle-whiskers'); ?></th>
<th><?php _e('Template', 'tigerstyle-whiskers'); ?></th>
<th><?php _e('Generated', 'tigerstyle-whiskers'); ?></th>
<th><?php _e('Status', 'tigerstyle-whiskers'); ?></th>
<th><?php _e('Actions', 'tigerstyle-whiskers'); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($policies as $policy): ?>
<tr>
<td><?php echo esc_html($policy->company_name); ?></td>
<td><?php echo esc_html(ucwords($policy->template_type)); ?></td>
<td><?php echo esc_html(date_i18n(get_option('date_format'), strtotime($policy->generated_date))); ?></td>
<td>
<span class="tw-status-<?php echo esc_attr($policy->status); ?>">
<?php echo esc_html(ucwords($policy->status)); ?>
</span>
</td>
<td>
<a href="<?php echo admin_url('admin.php?page=tigerstyle-whiskers&tab=privacy-policy&action=view&policy_id=' . $policy->id); ?>"
class="button button-small">
<?php _e('View', 'tigerstyle-whiskers'); ?>
</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif;
}
/**
* Inject privacy policy metadata into wp_head
*/
public function inject_policy_metadata() {
$policy_url = get_privacy_policy_url();
if (!$policy_url) {
return;
}
echo "\n<!-- TigerStyle Whiskers Privacy Policy Metadata -->\n";
echo '<meta name="privacy-policy" content="' . esc_url($policy_url) . '">' . "\n";
echo '<link rel="privacy-policy" href="' . esc_url($policy_url) . '">' . "\n";
echo "<!-- End TigerStyle Whiskers Privacy Policy Metadata -->\n\n";
}
// Additional helper methods would continue here...
// (get_mysql_version, theme detection methods, etc.)
}