is_dashboard_action()) { return; } $plugin_data = get_plugin_data(WP_PLUGIN_DIR . '/' . $plugin); $plugin_name = !empty($plugin_data['Name']) ? $plugin_data['Name'] : $plugin; $plugin_version = !empty($plugin_data['Version']) ? $plugin_data['Version'] : ''; $this->log_activity('activation', $plugin_name, $plugin, $plugin_version); } /** * Track plugin deactivation. */ public function track_plugin_deactivation($plugin) { if (!$this->is_dashboard_action()) { return; } $plugin_data = get_plugin_data(WP_PLUGIN_DIR . '/' . $plugin); $plugin_name = !empty($plugin_data['Name']) ? $plugin_data['Name'] : $plugin; $plugin_version = !empty($plugin_data['Version']) ? $plugin_data['Version'] : ''; $this->log_activity('deactivation', $plugin_name, $plugin, $plugin_version); } /** * Track plugin deletion. */ public function track_plugin_deletion($plugin, $deleted) { if (!$this->is_dashboard_action()) { return; } $plugin_parts = explode('/', $plugin); $plugin_name = $plugin_parts[0]; $this->log_activity('deletion', $plugin_name, $plugin, ''); } /** * Track plugin updates and installations. */ public function track_plugin_update_or_install($upgrader, $options) { if (!$this->is_dashboard_action()) { return; } if (empty($options['type']) || $options['type'] !== 'plugin') { return; } if ($options['action'] === 'update' && !empty($options['plugins']) && is_array($options['plugins'])) { foreach ($options['plugins'] as $plugin) { $plugin_data = get_plugin_data(WP_PLUGIN_DIR . '/' . $plugin); $plugin_name = !empty($plugin_data['Name']) ? $plugin_data['Name'] : $plugin; $plugin_version = !empty($plugin_data['Version']) ? $plugin_data['Version'] : ''; $this->log_activity('update', $plugin_name, $plugin, $plugin_version); } } if ($options['action'] === 'install' && $upgrader instanceof Plugin_Upgrader) { $plugin_file = $this->get_plugin_file_from_upgrader($upgrader, $options); if (!empty($plugin_file) && file_exists(WP_PLUGIN_DIR . '/' . $plugin_file)) { $plugin_data = get_plugin_data(WP_PLUGIN_DIR . '/' . $plugin_file); $plugin_name = !empty($plugin_data['Name']) ? $plugin_data['Name'] : $plugin_file; $plugin_version = !empty($plugin_data['Version']) ? $plugin_data['Version'] : ''; $this->log_activity('installation', $plugin_name, $plugin_file, $plugin_version); } } } /** * Get plugin file from upgrader */ private function get_plugin_file_from_upgrader($upgrader, $options) { $plugin_file = $upgrader->plugin_info(); if (empty($plugin_file) && isset($options['plugin'])) { $plugin_file = $options['plugin']; } elseif (empty($plugin_file) && !empty($upgrader->result) && is_array($upgrader->result) && isset($upgrader->result['destination_name'])) { $plugin_file = $this->find_main_plugin_file($upgrader->result['destination_name']); } return $plugin_file; } /** * Find main plugin file */ private function find_main_plugin_file($destination_name) { $plugin_file = $destination_name . '/' . $destination_name . '.php'; if (!file_exists(WP_PLUGIN_DIR . '/' . $plugin_file)) { $plugin_dir = WP_PLUGIN_DIR . '/' . $destination_name; if (is_dir($plugin_dir)) { $plugin_files = glob($plugin_dir . '/*.php'); if (!empty($plugin_files)) { foreach ($plugin_files as $file) { $plugin_data = get_plugin_data($file); if (!empty($plugin_data['Name'])) { $plugin_file = $destination_name . '/' . basename($file); break; } } } } } return $plugin_file; } /** * Check if current request is a dashboard action. */ private function is_dashboard_action() { return is_admin(); } /** * Log plugin activity. */ private function log_activity($action, $plugin_name, $plugin_file, $plugin_version) { try { $logs = $this->get_logs(); $logs[] = array( 'action' => sanitize_text_field($action), 'plugin_name' => sanitize_text_field($plugin_name), 'plugin_file' => sanitize_text_field($plugin_file), 'plugin_version' => sanitize_text_field($plugin_version), 'user_id' => get_current_user_id(), 'timestamp' => current_time('mysql') ); if (count($logs) > self::MAX_LOGS) { $logs = array_slice($logs, -self::MAX_LOGS); } $this->update_logs($logs); } catch (Exception $e) { error_log('Activity History Tracker Error: ' . $e->getMessage()); } } /** * Get logs from cache or database */ private function get_logs() { $logs = get_transient('actihitr_activity_logs_transient'); if (false === $logs) { $logs = get_option('actihitr_activity_logs', array()); set_transient('actihitr_activity_logs_transient', $logs, self::CACHE_DURATION); } return $logs; } /** * Update logs in database and cache */ private function update_logs($logs) { update_option('actihitr_activity_logs', $logs, true); set_transient('actihitr_activity_logs_transient', $logs, self::CACHE_DURATION); } /** * Add admin menu item. */ public function admin_menu() { add_submenu_page( 'plugins.php', __('Activity History Tracker', 'activity-history-tracker'), __('Activity History', 'activity-history-tracker'), 'manage_options', 'activity-history-tracker', array($this, 'display_activity_page') ); } /** * Display the activity page. */ public function display_activity_page() { if (!$this->check_user_cap()) { wp_die(__('You do not have sufficient permissions to access this page.', 'activity-history-tracker')); } // Handle clear logs action if (isset($_POST['clear_logs']) && check_admin_referer('actihitr_clear_logs', 'clear_logs_nonce')) { delete_transient('actihitr_activity_logs_transient'); delete_option('actihitr_activity_logs'); } // Get paginated logs $current_page = isset($_GET['paged']) ? max(1, intval($_GET['paged'])) : 1; $logs = $this->get_paginated_logs($current_page); $total_items = count($this->get_logs()); $total_pages = ceil($total_items / self::ITEMS_PER_PAGE); // Display page echo '
'; echo '

' . esc_html__('Activity History Tracker', 'activity-history-tracker') . '

'; settings_errors('activity_history_tracker'); // Filter form $this->display_filter_form(); // Export and Clear buttons $this->display_action_buttons(); // Display table if (empty($logs)) { echo '

' . esc_html__('No plugin activity has been recorded yet.', 'activity-history-tracker') . '

'; } else { $this->display_logs_table($logs); $this->display_pagination($current_page, $total_pages); } echo '
'; } /** * Display filter form */ private function display_filter_form() { echo '
'; echo '
'; echo ''; echo wp_nonce_field('actihitr_filter_logs', 'filter_nonce', true, false); echo ''; echo ''; echo ''; echo '
'; echo '
'; } /** * Display action buttons */ private function display_action_buttons() { echo '
'; echo '
'; echo wp_nonce_field('actihitr_clear_logs', 'clear_logs_nonce', true, false); echo ''; echo '
'; // echo ''; echo '
'; } /** * Display logs table */ private function display_logs_table($logs) { echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; foreach ($logs as $log) { $user_info = get_userdata($log['user_id']); $username = $user_info ? $user_info->display_name : __('Unknown User', 'activity-history-tracker'); $action_labels = array( 'activation' => __('Activated', 'activity-history-tracker'), 'deactivation' => __('Deactivated', 'activity-history-tracker'), 'update' => __('Updated', 'activity-history-tracker'), 'deletion' => __('Deleted', 'activity-history-tracker'), 'installation' => __('Installed', 'activity-history-tracker') ); $action_label = isset($action_labels[$log['action']]) ? $action_labels[$log['action']] : $log['action']; $action_class = 'action-' . $log['action']; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; } echo '
' . esc_html__('Date & Time', 'activity-history-tracker') . '' . esc_html__('User', 'activity-history-tracker') . '' . esc_html__('Action', 'activity-history-tracker') . '' . esc_html__('Plugin', 'activity-history-tracker') . '' . esc_html__('Version', 'activity-history-tracker') . '
' . esc_html(get_date_from_gmt($log['timestamp'])) . '' . esc_html($username) . '' . esc_html($action_label) . '' . esc_html($log['plugin_name']) . '' . esc_html($log['plugin_version']) . '
'; } /** * Display pagination */ private function display_pagination($current_page, $total_pages) { if ($total_pages > 1) { echo '
'; echo paginate_links(array( 'base' => add_query_arg('paged', '%#%'), 'format' => '', 'prev_text' => __('«'), 'next_text' => __('»'), 'total' => $total_pages, 'current' => $current_page )); echo '
'; } } /** * Get paginated logs */ private function get_paginated_logs($current_page) { $logs = $this->get_logs(); $logs = array_reverse($logs); $action_filter = isset($_GET['action']) ? sanitize_text_field($_GET['action']) : ''; if (!empty($action_filter)) { $logs = array_filter($logs, function($log) use ($action_filter) { return $log['action'] === $action_filter; }); } $offset = ($current_page - 1) * self::ITEMS_PER_PAGE; return array_slice($logs, $offset, self::ITEMS_PER_PAGE); } /** * Handle export logs */ public function handle_export_logs() { if (!check_ajax_referer('actihitr_export_logs_nonce', 'nonce', false)) { wp_send_json_error(__('Invalid nonce', 'activity-history-tracker')); } if (!$this->check_user_cap()) { wp_send_json_error(__('Insufficient permissions', 'activity-history-tracker')); } $logs = $this->get_logs(); $filename = 'activity-history-logs-' . date('Y-m-d') . '.csv'; header('Content-Type: text/csv'); header('Content-Disposition: attachment; filename="' . $filename . '"'); $output = fopen('php://output', 'w'); // Add CSV headers fputcsv($output, array( __('Date & Time', 'activity-history-tracker'), __('User', 'activity-history-tracker'), __('Action', 'activity-history-tracker'), __('Plugin', 'activity-history-tracker'), __('Version', 'activity-history-tracker') )); // Add data rows foreach ($logs as $log) { $user_info = get_userdata($log['user_id']); $username = $user_info ? $user_info->display_name : __('Unknown User', 'activity-history-tracker'); fputcsv($output, array( get_date_from_gmt($log['timestamp']), $username, $log['action'], $log['plugin_name'], $log['plugin_version'] )); } fclose($output); wp_die(); } } // Initialize the plugin add_action('plugins_loaded', function() { if (current_user_can('manage_options')) { new ACTIHITR_Plugin_Activity_Tracker(); } });