721 lines
22 KiB
PHP
721 lines
22 KiB
PHP
<?php
|
|
/**
|
|
* Plugin Name: Maple GDPR Cookies
|
|
* Plugin URI: https://mapleopentech.ca/maple-gdpr-cookies
|
|
* Description: A lightweight, secure, and fully GDPR-compliant cookie consent plugin with script blocking
|
|
* Version: 4.1.3
|
|
* Requires at least: 5.0
|
|
* Requires PHP: 7.2
|
|
* Author: Your Name
|
|
* License: GPL v2 or later
|
|
* Text Domain: maple-gdpr-cookies
|
|
* WC requires at least: 3.0
|
|
* WC tested up to: 8.5
|
|
*/
|
|
|
|
// Prevent direct access
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
// Define plugin constants
|
|
define('MGC_PLUGIN_FILE', __FILE__);
|
|
define('MGC_PLUGIN_PATH', plugin_dir_path(__FILE__));
|
|
define('MGC_PLUGIN_URL', plugin_dir_url(__FILE__));
|
|
define('MGC_PLUGIN_VERSION', '4.1.3');
|
|
define('MGC_DB_VERSION', '2.0');
|
|
define('MGC_MIN_PHP_VERSION', '7.2');
|
|
define('MGC_MIN_WP_VERSION', '5.0');
|
|
|
|
/**
|
|
* Plugin activation checks
|
|
*/
|
|
function mgc_check_requirements() {
|
|
$errors = array();
|
|
|
|
// Check PHP version
|
|
if (version_compare(PHP_VERSION, MGC_MIN_PHP_VERSION, '<')) {
|
|
$errors[] = sprintf(
|
|
__('Maple GDPR Cookies requires PHP %s or higher. Your server is running PHP %s.', 'maple-gdpr-cookies'),
|
|
MGC_MIN_PHP_VERSION,
|
|
PHP_VERSION
|
|
);
|
|
}
|
|
|
|
// Check WordPress version
|
|
if (version_compare(get_bloginfo('version'), MGC_MIN_WP_VERSION, '<')) {
|
|
$errors[] = sprintf(
|
|
__('Maple GDPR Cookies requires WordPress %s or higher. You are running WordPress %s.', 'maple-gdpr-cookies'),
|
|
MGC_MIN_WP_VERSION,
|
|
get_bloginfo('version')
|
|
);
|
|
}
|
|
|
|
// Check for MySQL version if using utf8mb4
|
|
global $wpdb;
|
|
if ($wpdb->db_version() && version_compare($wpdb->db_version(), '5.5.3', '<')) {
|
|
$errors[] = __('Maple GDPR Cookies requires MySQL 5.5.3 or higher for utf8mb4 support.', 'maple-gdpr-cookies');
|
|
}
|
|
|
|
return $errors;
|
|
}
|
|
|
|
/**
|
|
* Create database tables on activation
|
|
*/
|
|
function mgc_create_tables() {
|
|
global $wpdb;
|
|
|
|
$charset_collate = $wpdb->get_charset_collate();
|
|
$table_name = $wpdb->prefix . 'mgc_consent_logs';
|
|
|
|
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
|
|
id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
user_id bigint(20) UNSIGNED NULL,
|
|
ip_address varchar(45) NOT NULL,
|
|
user_agent varchar(255) NOT NULL,
|
|
consent_type varchar(20) NOT NULL,
|
|
categories text NULL,
|
|
consent_given tinyint(1) NOT NULL,
|
|
consent_date datetime NOT NULL,
|
|
PRIMARY KEY (id),
|
|
KEY user_id (user_id),
|
|
KEY ip_address (ip_address),
|
|
KEY consent_date (consent_date)
|
|
) $charset_collate;";
|
|
|
|
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
|
dbDelta($sql);
|
|
|
|
// Store database version
|
|
update_option('mgc_db_version', MGC_DB_VERSION);
|
|
}
|
|
|
|
/**
|
|
* Set default options on activation
|
|
*/
|
|
function mgc_set_defaults() {
|
|
$default_options = array(
|
|
'enabled' => true,
|
|
'notice_text' => __('We use cookies to make this site work properly and to understand how you use it. This includes <strong>essential cookies</strong> (required), <strong>analytics cookies</strong> (to understand site usage), and <strong>marketing cookies</strong> (for personalized content). You can accept all, reject optional cookies, or customize your preferences.', 'maple-gdpr-cookies'),
|
|
'accept_button_text' => __('Accept All', 'maple-gdpr-cookies'),
|
|
'reject_button_text' => __('Reject Optional', 'maple-gdpr-cookies'),
|
|
'settings_button_text' => __('Cookie Settings', 'maple-gdpr-cookies'),
|
|
'privacy_policy_url' => get_privacy_policy_url(),
|
|
'privacy_policy_text' => __('Privacy Policy', 'maple-gdpr-cookies'),
|
|
'cookie_expiry' => 365,
|
|
'position' => 'bottom',
|
|
'theme' => 'light',
|
|
'animation' => 'slide',
|
|
'button_color' => 'blue',
|
|
'custom_button_color' => '',
|
|
'custom_button_hover_color' => '',
|
|
'show_reject_button' => true,
|
|
'show_settings_button' => true,
|
|
'preference_display_type' => 'icon',
|
|
'custom_css' => '',
|
|
'enable_analytics' => true,
|
|
'enable_marketing' => true,
|
|
'enable_functional' => true,
|
|
'enable_logging' => true
|
|
);
|
|
|
|
foreach ($default_options as $key => $value) {
|
|
if (get_option('mgc_' . $key) === false) {
|
|
add_option('mgc_' . $key, $value);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clear all plugin caches - FIXED VERSION
|
|
*/
|
|
function mgc_clear_all_caches() {
|
|
// Method 1: Clear WordPress object cache (if available)
|
|
if (function_exists('wp_cache_flush')) {
|
|
wp_cache_flush();
|
|
}
|
|
|
|
// Method 2: Clear plugin-specific transients
|
|
global $wpdb;
|
|
|
|
// Get all mgc transients
|
|
$transients = $wpdb->get_col(
|
|
"SELECT option_name FROM $wpdb->options
|
|
WHERE option_name LIKE '_transient_mgc_%'
|
|
OR option_name LIKE '_transient_timeout_mgc_%'"
|
|
);
|
|
|
|
// Delete each transient
|
|
foreach ($transients as $transient) {
|
|
if (strpos($transient, '_transient_timeout_') === 0) {
|
|
continue; // Skip timeout entries, they'll be deleted with the transient
|
|
}
|
|
|
|
$transient_key = str_replace('_transient_', '', $transient);
|
|
delete_transient($transient_key);
|
|
}
|
|
|
|
// Method 3: Clear specific plugin caches
|
|
$cache_keys = array(
|
|
'mgc_settings',
|
|
'mgc_stats',
|
|
'mgc_consent_logs'
|
|
);
|
|
|
|
foreach ($cache_keys as $key) {
|
|
wp_cache_delete($key, 'maple-gdpr-cookies');
|
|
delete_transient($key);
|
|
}
|
|
|
|
// Method 4: Clear WooCommerce cache if present
|
|
if (function_exists('wc_delete_shop_order_transients')) {
|
|
wc_delete_shop_order_transients();
|
|
}
|
|
|
|
// Method 5: Trigger cache clear hooks for other plugins
|
|
do_action('mgc_clear_caches');
|
|
}
|
|
|
|
/**
|
|
* Plugin activation
|
|
*/
|
|
function mgc_activate() {
|
|
// Check requirements
|
|
$errors = mgc_check_requirements();
|
|
if (!empty($errors)) {
|
|
deactivate_plugins(plugin_basename(__FILE__));
|
|
wp_die(
|
|
implode('<br>', $errors),
|
|
__('Plugin Activation Error', 'maple-gdpr-cookies'),
|
|
array('back_link' => true)
|
|
);
|
|
}
|
|
|
|
// Create database tables
|
|
mgc_create_tables();
|
|
|
|
// Set default options
|
|
mgc_set_defaults();
|
|
|
|
// Clear all caches - now using fixed function
|
|
mgc_clear_all_caches();
|
|
|
|
// Set activation flag
|
|
set_transient('mgc_activation_redirect', true, 30);
|
|
}
|
|
register_activation_hook(__FILE__, 'mgc_activate');
|
|
|
|
/**
|
|
* Plugin deactivation
|
|
*/
|
|
function mgc_deactivate() {
|
|
// Clear all caches
|
|
mgc_clear_all_caches();
|
|
|
|
// Clear scheduled events
|
|
wp_clear_scheduled_hook('mgc_cleanup_logs');
|
|
wp_clear_scheduled_hook('mgc_optimize_database');
|
|
}
|
|
register_deactivation_hook(__FILE__, 'mgc_deactivate');
|
|
|
|
/**
|
|
* Plugin uninstall - only if user chooses to delete data
|
|
*/
|
|
function mgc_uninstall() {
|
|
global $wpdb;
|
|
|
|
// Always clear scheduled tasks even if keeping data
|
|
wp_clear_scheduled_hook('mgc_cleanup_logs');
|
|
wp_clear_scheduled_hook('mgc_optimize_database');
|
|
|
|
// Check if user wants to keep data
|
|
if (get_option('mgc_keep_data_on_uninstall', false)) {
|
|
return;
|
|
}
|
|
|
|
// Drop database tables
|
|
$table_name = $wpdb->prefix . 'mgc_consent_logs';
|
|
$wpdb->query("DROP TABLE IF EXISTS $table_name");
|
|
|
|
// Delete all plugin options
|
|
$wpdb->query("DELETE FROM $wpdb->options WHERE option_name LIKE 'mgc_%'");
|
|
|
|
// Clear all caches
|
|
mgc_clear_all_caches();
|
|
}
|
|
register_uninstall_hook(__FILE__, 'mgc_uninstall');
|
|
|
|
/**
|
|
* Load plugin textdomain for translations
|
|
*/
|
|
function mgc_load_textdomain() {
|
|
load_plugin_textdomain(
|
|
'maple-gdpr-cookies',
|
|
false,
|
|
dirname(plugin_basename(__FILE__)) . '/languages'
|
|
);
|
|
}
|
|
add_action('plugins_loaded', 'mgc_load_textdomain');
|
|
|
|
/**
|
|
* Enqueue frontend scripts and styles
|
|
*/
|
|
function mgc_enqueue_frontend_assets() {
|
|
// Only load if enabled
|
|
if (!get_option('mgc_enabled', true)) {
|
|
return;
|
|
}
|
|
|
|
// Check if user already has consent cookie
|
|
$has_consent = isset($_COOKIE['mgc_consent']);
|
|
|
|
// Enqueue CSS
|
|
wp_enqueue_style(
|
|
'mgc-frontend',
|
|
MGC_PLUGIN_URL . 'public/css/frontend.css',
|
|
array(),
|
|
MGC_PLUGIN_VERSION
|
|
);
|
|
|
|
// Add custom CSS if provided
|
|
$custom_css = get_option('mgc_custom_css');
|
|
if (!empty($custom_css)) {
|
|
wp_add_inline_style('mgc-frontend', $custom_css);
|
|
}
|
|
|
|
// Add custom button colors if provided
|
|
$custom_button_color = get_option('mgc_custom_button_color');
|
|
$custom_button_hover_color = get_option('mgc_custom_button_hover_color');
|
|
|
|
if (!empty($custom_button_color) || !empty($custom_button_hover_color)) {
|
|
$color_css = '';
|
|
|
|
if (!empty($custom_button_color)) {
|
|
$color_css .= '.mgc-button { background: ' . esc_attr($custom_button_color) . ' !important; }';
|
|
$color_css .= '.mgc-floating-button { background: ' . esc_attr($custom_button_color) . ' !important; }';
|
|
}
|
|
|
|
if (!empty($custom_button_hover_color)) {
|
|
$color_css .= '.mgc-button:hover { background: ' . esc_attr($custom_button_hover_color) . ' !important; }';
|
|
$color_css .= '.mgc-floating-button:hover { background: ' . esc_attr($custom_button_hover_color) . ' !important; }';
|
|
}
|
|
|
|
wp_add_inline_style('mgc-frontend', $color_css);
|
|
}
|
|
|
|
// Enqueue the compliant JS (blocks scripts before consent)
|
|
wp_enqueue_script(
|
|
'mgc-frontend-compliant',
|
|
MGC_PLUGIN_URL . 'public/js/frontend-compliant.js',
|
|
array(),
|
|
MGC_PLUGIN_VERSION,
|
|
false // Load in head for early script blocking
|
|
);
|
|
|
|
// Localize script with settings
|
|
wp_localize_script('mgc-frontend-compliant', 'mgcSettings', array(
|
|
'ajaxUrl' => admin_url('admin-ajax.php'),
|
|
'nonce' => wp_create_nonce('mgc_consent_nonce'),
|
|
'noticeText' => get_option('mgc_notice_text'),
|
|
'acceptButtonText' => get_option('mgc_accept_button_text'),
|
|
'rejectButtonText' => get_option('mgc_reject_button_text'),
|
|
'settingsButtonText' => get_option('mgc_settings_button_text'),
|
|
'privacyPolicyUrl' => get_option('mgc_privacy_policy_url'),
|
|
'privacyPolicyText' => get_option('mgc_privacy_policy_text'),
|
|
'cookieExpiry' => intval(get_option('mgc_cookie_expiry', 365)),
|
|
'position' => get_option('mgc_position', 'bottom'),
|
|
'theme' => get_option('mgc_theme', 'light'),
|
|
'animation' => get_option('mgc_animation', 'slide'),
|
|
'buttonColor' => get_option('mgc_button_color', 'blue'),
|
|
'showRejectButton' => (bool) get_option('mgc_show_reject_button', true),
|
|
'showSettingsButton' => (bool) get_option('mgc_show_settings_button', true),
|
|
'preferenceDisplayType' => get_option('mgc_preference_display_type', 'icon')
|
|
));
|
|
}
|
|
add_action('wp_enqueue_scripts', 'mgc_enqueue_frontend_assets');
|
|
|
|
/**
|
|
* Enqueue admin scripts and styles
|
|
*/
|
|
function mgc_enqueue_admin_assets($hook) {
|
|
// Only load on plugin settings pages
|
|
if (strpos($hook, 'maple-gdpr-cookies') === false) {
|
|
return;
|
|
}
|
|
|
|
// Enqueue WordPress color picker
|
|
wp_enqueue_style('wp-color-picker');
|
|
|
|
// Enqueue admin CSS
|
|
wp_enqueue_style(
|
|
'mgc-admin',
|
|
MGC_PLUGIN_URL . 'admin/css/admin.css',
|
|
array(),
|
|
MGC_PLUGIN_VERSION
|
|
);
|
|
|
|
// Enqueue admin JS
|
|
wp_enqueue_script(
|
|
'mgc-admin',
|
|
MGC_PLUGIN_URL . 'admin/js/admin.js',
|
|
array('jquery', 'wp-color-picker'),
|
|
MGC_PLUGIN_VERSION,
|
|
true
|
|
);
|
|
}
|
|
add_action('admin_enqueue_scripts', 'mgc_enqueue_admin_assets');
|
|
|
|
/**
|
|
* Add admin menu
|
|
*/
|
|
function mgc_add_admin_menu() {
|
|
add_menu_page(
|
|
__('Maple GDPR Cookies', 'maple-gdpr-cookies'),
|
|
__('Cookie Settings', 'maple-gdpr-cookies'),
|
|
'manage_options',
|
|
'maple-gdpr-cookies',
|
|
'mgc_admin_page',
|
|
'dashicons-shield',
|
|
100
|
|
);
|
|
|
|
add_submenu_page(
|
|
'maple-gdpr-cookies',
|
|
__('Settings', 'maple-gdpr-cookies'),
|
|
__('Settings', 'maple-gdpr-cookies'),
|
|
'manage_options',
|
|
'maple-gdpr-cookies',
|
|
'mgc_admin_page'
|
|
);
|
|
|
|
add_submenu_page(
|
|
'maple-gdpr-cookies',
|
|
__('Consent Logs', 'maple-gdpr-cookies'),
|
|
__('Consent Logs', 'maple-gdpr-cookies'),
|
|
'manage_options',
|
|
'maple-gdpr-cookies-logs',
|
|
'mgc_logs_page'
|
|
);
|
|
}
|
|
add_action('admin_menu', 'mgc_add_admin_menu');
|
|
|
|
/**
|
|
* Admin page callback
|
|
*/
|
|
function mgc_admin_page() {
|
|
if (!current_user_can('manage_options')) {
|
|
return;
|
|
}
|
|
|
|
// Handle form submission
|
|
if (isset($_POST['mgc_save_settings']) && check_admin_referer('mgc_settings_nonce')) {
|
|
mgc_save_settings();
|
|
}
|
|
|
|
include MGC_PLUGIN_PATH . 'admin/views/settings.php';
|
|
}
|
|
|
|
/**
|
|
* Logs page callback
|
|
*/
|
|
function mgc_logs_page() {
|
|
if (!current_user_can('manage_options')) {
|
|
return;
|
|
}
|
|
|
|
include MGC_PLUGIN_PATH . 'admin/views/logs.php';
|
|
}
|
|
|
|
/**
|
|
* Save settings
|
|
*/
|
|
function mgc_save_settings() {
|
|
$settings = array(
|
|
'enabled',
|
|
'notice_text',
|
|
'accept_button_text',
|
|
'reject_button_text',
|
|
'settings_button_text',
|
|
'privacy_policy_url',
|
|
'privacy_policy_text',
|
|
'cookie_expiry',
|
|
'position',
|
|
'theme',
|
|
'animation',
|
|
'button_color',
|
|
'custom_button_color',
|
|
'custom_button_hover_color',
|
|
'show_reject_button',
|
|
'show_settings_button',
|
|
'preference_display_type',
|
|
'custom_css',
|
|
'enable_analytics',
|
|
'enable_marketing',
|
|
'enable_functional',
|
|
'enable_logging'
|
|
);
|
|
|
|
// List of checkbox fields (need special handling since unchecked = no POST data)
|
|
$checkbox_fields = array(
|
|
'enabled',
|
|
'show_reject_button',
|
|
'show_settings_button',
|
|
'enable_analytics',
|
|
'enable_marketing',
|
|
'enable_functional',
|
|
'enable_logging'
|
|
);
|
|
|
|
foreach ($settings as $setting) {
|
|
// Special handling for checkboxes
|
|
if (in_array($setting, $checkbox_fields)) {
|
|
// Checkbox: if it's in POST and = '1', it's checked. Otherwise it's unchecked.
|
|
$value = (isset($_POST['mgc_' . $setting]) && $_POST['mgc_' . $setting] == '1') ? true : false;
|
|
} else {
|
|
$value = isset($_POST['mgc_' . $setting]) ? $_POST['mgc_' . $setting] : '';
|
|
|
|
// Sanitize based on type
|
|
if ($setting === 'cookie_expiry') {
|
|
$value = absint($value);
|
|
// Enforce minimum and maximum values for GDPR compliance
|
|
if ($value < 1) $value = 1;
|
|
if ($value > 365) $value = 365;
|
|
} elseif ($setting === 'custom_css') {
|
|
$value = wp_strip_all_tags($value);
|
|
// Remove any javascript: or data: URLs to prevent CSS injection attacks
|
|
$value = preg_replace('/url\s*\(\s*[\'"]?\s*(?:javascript|data):/i', 'url(blocked:', $value);
|
|
// Limit length to prevent abuse (10KB should be more than enough for custom CSS)
|
|
$value = substr($value, 0, 10000);
|
|
} elseif (in_array($setting, array('custom_button_color', 'custom_button_hover_color'))) {
|
|
// Sanitize hex color
|
|
$value = sanitize_text_field($value);
|
|
// Validate hex color format
|
|
if (!empty($value) && !preg_match('/^#[a-fA-F0-9]{6}$/', $value)) {
|
|
$value = ''; // Clear invalid hex colors
|
|
}
|
|
} elseif ($setting === 'preference_display_type') {
|
|
// Validate preference display type
|
|
$value = sanitize_text_field($value);
|
|
if (!in_array($value, array('icon', 'footer', 'neither'))) {
|
|
$value = 'icon'; // Default to icon if invalid
|
|
}
|
|
} else {
|
|
$value = sanitize_text_field($value);
|
|
}
|
|
}
|
|
|
|
update_option('mgc_' . $setting, $value);
|
|
}
|
|
|
|
// Clear caches after saving
|
|
mgc_clear_all_caches();
|
|
|
|
add_settings_error(
|
|
'mgc_messages',
|
|
'mgc_message',
|
|
__('Settings saved successfully.', 'maple-gdpr-cookies'),
|
|
'updated'
|
|
);
|
|
}
|
|
|
|
/**
|
|
* AJAX handler for saving consent
|
|
*/
|
|
function mgc_save_consent() {
|
|
check_ajax_referer('mgc_consent_nonce', 'nonce');
|
|
|
|
// Rate limiting - max 10 consent saves per hour per IP to prevent abuse
|
|
$ip = mgc_get_ip_address();
|
|
$rate_key = 'mgc_consent_rate_' . md5($ip);
|
|
$attempts = get_transient($rate_key);
|
|
|
|
if ($attempts && $attempts >= 10) {
|
|
wp_send_json_error(array(
|
|
'message' => __('Too many requests. Please try again later.', 'maple-gdpr-cookies')
|
|
), 429);
|
|
return;
|
|
}
|
|
|
|
// Increment rate limit counter
|
|
set_transient($rate_key, ($attempts ? $attempts + 1 : 1), HOUR_IN_SECONDS);
|
|
|
|
$consent_type = sanitize_text_field($_POST['consent_type']);
|
|
$categories = isset($_POST['categories']) ? array_map('sanitize_text_field', $_POST['categories']) : array();
|
|
|
|
// Log consent if enabled
|
|
if (get_option('mgc_enable_logging', true)) {
|
|
mgc_log_consent($consent_type, $categories);
|
|
}
|
|
|
|
wp_send_json_success(array(
|
|
'message' => __('Consent saved successfully', 'maple-gdpr-cookies')
|
|
));
|
|
}
|
|
add_action('wp_ajax_mgc_save_consent', 'mgc_save_consent');
|
|
add_action('wp_ajax_nopriv_mgc_save_consent', 'mgc_save_consent');
|
|
|
|
/**
|
|
* Log user consent
|
|
*/
|
|
function mgc_log_consent($consent_type, $categories = array()) {
|
|
global $wpdb;
|
|
|
|
$table_name = $wpdb->prefix . 'mgc_consent_logs';
|
|
|
|
// Get and anonymize IP address (GDPR compliance)
|
|
$ip_address = mgc_anonymize_ip(mgc_get_ip_address());
|
|
|
|
$wpdb->insert(
|
|
$table_name,
|
|
array(
|
|
'user_id' => get_current_user_id(),
|
|
'ip_address' => $ip_address,
|
|
'user_agent' => sanitize_text_field(substr($_SERVER['HTTP_USER_AGENT'], 0, 255)),
|
|
'consent_type' => $consent_type,
|
|
'categories' => json_encode($categories),
|
|
'consent_given' => ($consent_type === 'accept'),
|
|
'consent_date' => current_time('mysql')
|
|
),
|
|
array('%d', '%s', '%s', '%s', '%s', '%d', '%s')
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get user IP address
|
|
*/
|
|
function mgc_get_ip_address() {
|
|
$ip = '';
|
|
|
|
// Check if behind a proxy and validate
|
|
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
|
// X-Forwarded-For can contain multiple IPs, get the first one (original client)
|
|
$ip_list = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
|
|
$ip = trim($ip_list[0]);
|
|
} elseif (!empty($_SERVER['HTTP_CLIENT_IP'])) {
|
|
$ip = $_SERVER['HTTP_CLIENT_IP'];
|
|
} else {
|
|
$ip = $_SERVER['REMOTE_ADDR'];
|
|
}
|
|
|
|
// Validate it's a real IP address
|
|
if (!filter_var($ip, FILTER_VALIDATE_IP)) {
|
|
// If invalid, fall back to direct connection IP
|
|
$ip = !empty($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '0.0.0.0';
|
|
}
|
|
|
|
return sanitize_text_field($ip);
|
|
}
|
|
|
|
/**
|
|
* Anonymize IP address (GDPR compliance)
|
|
* Removes last octet for IPv4, last segment for IPv6
|
|
*/
|
|
function mgc_anonymize_ip($ip) {
|
|
// Validate and anonymize IPv4
|
|
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
|
|
return preg_replace('/\.\d+$/', '.0', $ip);
|
|
}
|
|
|
|
// Validate and anonymize IPv6
|
|
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
|
|
return preg_replace('/:[^:]+$/', ':0', $ip);
|
|
}
|
|
|
|
// If invalid IP, return masked version
|
|
return '0.0.0.0';
|
|
}
|
|
|
|
/**
|
|
* Schedule cleanup tasks
|
|
*/
|
|
function mgc_schedule_cleanup() {
|
|
if (!wp_next_scheduled('mgc_cleanup_logs')) {
|
|
wp_schedule_event(time(), 'daily', 'mgc_cleanup_logs');
|
|
}
|
|
|
|
if (!wp_next_scheduled('mgc_optimize_database')) {
|
|
wp_schedule_event(time(), 'weekly', 'mgc_optimize_database');
|
|
}
|
|
}
|
|
add_action('wp', 'mgc_schedule_cleanup');
|
|
|
|
/**
|
|
* Cleanup old consent logs
|
|
*/
|
|
function mgc_cleanup_old_logs() {
|
|
global $wpdb;
|
|
|
|
$table_name = $wpdb->prefix . 'mgc_consent_logs';
|
|
$retention_days = apply_filters('mgc_log_retention_days', 365);
|
|
|
|
$wpdb->query(
|
|
$wpdb->prepare(
|
|
"DELETE FROM $table_name WHERE consent_date < DATE_SUB(NOW(), INTERVAL %d DAY)",
|
|
$retention_days
|
|
)
|
|
);
|
|
}
|
|
add_action('mgc_cleanup_logs', 'mgc_cleanup_old_logs');
|
|
|
|
/**
|
|
* Optimize database tables
|
|
*/
|
|
function mgc_optimize_database_tables() {
|
|
global $wpdb;
|
|
|
|
$table_name = $wpdb->prefix . 'mgc_consent_logs';
|
|
$wpdb->query("OPTIMIZE TABLE $table_name");
|
|
}
|
|
add_action('mgc_optimize_database', 'mgc_optimize_database_tables');
|
|
|
|
/**
|
|
* Add settings link on plugins page
|
|
*/
|
|
function mgc_add_settings_link($links) {
|
|
$settings_link = '<a href="' . admin_url('admin.php?page=maple-gdpr-cookies') . '">' . __('Settings', 'maple-gdpr-cookies') . '</a>';
|
|
array_unshift($links, $settings_link);
|
|
return $links;
|
|
}
|
|
add_filter('plugin_action_links_' . plugin_basename(__FILE__), 'mgc_add_settings_link');
|
|
|
|
/**
|
|
* Redirect to settings page on activation
|
|
*/
|
|
function mgc_activation_redirect() {
|
|
if (get_transient('mgc_activation_redirect')) {
|
|
delete_transient('mgc_activation_redirect');
|
|
|
|
if (!isset($_GET['activate-multi'])) {
|
|
wp_safe_redirect(admin_url('admin.php?page=maple-gdpr-cookies'));
|
|
exit;
|
|
}
|
|
}
|
|
}
|
|
add_action('admin_init', 'mgc_activation_redirect');
|
|
|
|
/**
|
|
* Cookie Preferences Shortcode
|
|
* Usage: [mgc_cookie_preferences] or [mgc_cookie_preferences text="Manage Cookies"]
|
|
*/
|
|
function mgc_cookie_preferences_shortcode($atts) {
|
|
// Only show if plugin is enabled
|
|
if (!get_option('mgc_enabled', true)) {
|
|
return '';
|
|
}
|
|
|
|
// Parse attributes
|
|
$atts = shortcode_atts(array(
|
|
'text' => __('Cookie Preferences', 'maple-gdpr-cookies'),
|
|
'class' => 'mgc-preferences-link'
|
|
), $atts);
|
|
|
|
// Return link with data attribute that JavaScript will handle
|
|
return sprintf(
|
|
'<a href="#" class="%s" data-mgc-preferences-trigger aria-label="%s">%s</a>',
|
|
esc_attr($atts['class']),
|
|
esc_attr($atts['text']),
|
|
esc_html($atts['text'])
|
|
);
|
|
}
|
|
add_shortcode('mgc_cookie_preferences', 'mgc_cookie_preferences_shortcode');
|