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() { ?>
render_policy_generator_form(); ?> render_generated_policies_list(); ?>