$plugin, 'plugin_version' => $plugin_version ); // Log the event with consistent format $this->log( 'plugin', 'activate', $plugin_name, 'Plugin Activated: ' . $plugin_name, $metadata ); } /** * Log plugin deactivation event * * @param string $plugin Plugin path relative to plugins directory */ public function log_plugin_deactivated($plugin) { // Make sure get_plugins is available if (!function_exists('get_plugins')) { require_once(ABSPATH . 'wp-admin/includes/plugin.php'); } // Get plugin data $all_plugins = get_plugins(); $plugin_data = isset($all_plugins[$plugin]) ? $all_plugins[$plugin] : array(); $plugin_name = isset($plugin_data['Name']) ? $plugin_data['Name'] : $plugin; $plugin_version = isset($plugin_data['Version']) ? $plugin_data['Version'] : ''; // Create metadata $metadata = array( 'plugin_file' => $plugin, 'plugin_version' => $plugin_version ); // Log the event with direct string format $this->log( 'plugin', 'deactivate', $plugin_name, 'Plugin Deactivated: ' . $plugin_name, $metadata ); } /** * Log plugin update event * * @param object $upgrader Plugin_Upgrader instance * @param array $data Update data */ public function log_plugin_updated($upgrader, $data) { // Only proceed if this is a plugin update if ($data['type'] !== 'plugin' || !isset($data['plugins']) || empty($data['plugins'])) { return; } // Make sure get_plugins is available if (!function_exists('get_plugins')) { require_once(ABSPATH . 'wp-admin/includes/plugin.php'); } // Get all plugins data once $all_plugins = get_plugins(); // Log each updated plugin foreach ($data['plugins'] as $plugin) { // Get plugin data $plugin_data = isset($all_plugins[$plugin]) ? $all_plugins[$plugin] : array(); $plugin_name = isset($plugin_data['Name']) ? $plugin_data['Name'] : $plugin; $plugin_version = isset($plugin_data['Version']) ? $plugin_data['Version'] : ''; // Create metadata $metadata = array( 'plugin_file' => $plugin, 'plugin_version' => $plugin_version ); // Log the event with direct string format $this->log( 'plugin', 'update', $plugin_name, 'Plugin Updated: ' . $plugin_name . ' to version ' . $plugin_version, $metadata ); } } /** * Get network information from current request * * @return array Network information (user_agent, referer, request_method, request_uri) */ private function get_network_info() { $network_info = array(); // User Agent - browser/client identifier if (!empty($_SERVER['HTTP_USER_AGENT'])) { $network_info['user_agent'] = sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT'])); } // Referer - page user came from if (!empty($_SERVER['HTTP_REFERER'])) { $network_info['referer'] = esc_url_raw(wp_unslash($_SERVER['HTTP_REFERER'])); } // Request Method - HTTP method used if (!empty($_SERVER['REQUEST_METHOD'])) { $network_info['request_method'] = sanitize_text_field(wp_unslash($_SERVER['REQUEST_METHOD'])); } // Request URI - specific URL path and query if (!empty($_SERVER['REQUEST_URI'])) { $network_info['request_uri'] = sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI'])); } return $network_info; } /** * Log an activity * * @param string $event_type Type of event (post, page, user, etc.) * @param string $action Action performed (create, update, delete, etc.) * @param string $object_name Name of the object affected * @param string $description Description of the activity * @param array $metadata Additional metadata about the activity * @param int $object_id Optional object ID to enhance the description with * @return int|false The ID of the inserted log entry, or false on failure */ public function log($event_type, $action, $object_name, $description, $metadata = array(), $object_id = 0) { // Auto-enhance description with object ID for relevant object types $object_types_to_enhance = array('post', 'page', 'product', 'coupon', 'comment', 'user', 'media', 'attachment'); if (in_array($event_type, $object_types_to_enhance) && !empty($object_id) && $object_id > 0) { // Check if description already contains the ID to avoid duplication if (!preg_match('/\(ID:\s*' . preg_quote($object_id, '/') . '\)/', $description)) { $description = $description . sprintf(' (ID: %d)', $object_id); } } // Get current user $current_user = wp_get_current_user(); $user_id = $current_user->ID; // If no user is logged in, use "System" as the user if (empty($user_id) || $user_id === 0) { $user_id = 0; $user_login = 'system'; $user_display_name = 'System'; $user_role = 'system'; } else { // Get user information for logged-in users $user_login = $current_user->user_login; $user_display_name = $current_user->display_name; $user_role = ''; if (!empty($current_user->roles) && is_array($current_user->roles)) { $user_role = reset($current_user->roles); } } // Get network information and merge with provided metadata $network_info = $this->get_network_info(); if (!empty($metadata) && is_array($metadata)) { $metadata = array_merge($metadata, $network_info); } else { $metadata = $network_info; } // Prepare data for insertion $data = array( 'user_id' => $user_id, 'user_login' => $user_login, 'user_display_name' => $user_display_name, 'user_role' => $user_role, 'ip_address' => $this->get_user_ip(), 'event_type' => $event_type, 'object_type' => $event_type, 'object_id' => $object_id, // Use the provided object_id 'action' => $action, 'object_name' => $object_name, 'description' => $description, 'created_at' => current_time('mysql'), 'metadata' => !empty($metadata) ? maybe_serialize($metadata) : null ); // Load database class if not already loaded if (!class_exists('ACTLOGPRO_Database')) { require_once dirname(__FILE__) . '/class-alp-database.php'; } // Use the database abstraction layer to insert the log entry return ACTLOGPRO_Database::log_activity($data); } /** * Log an activity with explicit object ID (enhanced version) * * @param string $event_type Type of event (post, page, user, etc.) * @param string $action Action performed (create, update, delete, etc.) * @param string $object_name Name of the object affected * @param string $description Description of the activity * @param int $object_id ID of the object * @param array $metadata Additional metadata about the activity * @return int|false The ID of the inserted log entry, or false on failure */ public function log_with_id($event_type, $action, $object_name, $description, $object_id, $metadata = array()) { return $this->log($event_type, $action, $object_name, $description, $metadata, $object_id); } /** * Get user IP address * * @return string IP address */ private function get_user_ip() { // Use existing actlogpro_Logger method if available if (class_exists('ACTLOGPRO_Logger') && method_exists('ACTLOGPRO_Logger', 'get_ip_address')) { return ACTLOGPRO_Logger::get_ip_address(); } // Fallback IP detection $ip_keys = array('HTTP_CF_CONNECTING_IP', 'HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR'); foreach ($ip_keys as $key) { if (array_key_exists($key, $_SERVER) === true) { $server_value = sanitize_text_field(wp_unslash($_SERVER[$key])); foreach (explode(',', $server_value) as $ip) { $ip = trim($ip); if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false) { return $ip; } } } } return isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : 'unknown'; } }