added additional plugins

This commit is contained in:
Rodolfo Martinez 2025-12-12 19:05:48 -05:00
parent c85895d306
commit 00e60ec1b7
132 changed files with 27514 additions and 0 deletions

View file

@ -0,0 +1,721 @@
<?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');