Last active
December 11, 2024 17:07
-
-
Save brigleb/f404d784ab25cfeb6196ea1ceb8440c8 to your computer and use it in GitHub Desktop.
This Plugin Activity Logger is a lightweight WordPress must-use plugin that tracks and logs all plugin-related activities, including installation, activation, deactivation, updates, and deletions. It logs each event with a timestamp, the WordPress version, the site’s URL, the plugin name, and the username of the person who performed the action. …
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Plugin Name: Plugin Activity Logger | |
* Description: Logs plugin installations, activations, deactivations, updates (with from/to versions if available), and deletions. Handles both single and bulk updates. Attempts to log failed updates as well. | |
* Version: 3.3 | |
* Author: Needmore Designs | |
*/ | |
if (!defined('ABSPATH')) { | |
exit; // Exit if accessed directly. | |
} | |
define('PLUGIN_ACTIVITY_LOG', WP_CONTENT_DIR . '/plugin-activity.log'); | |
global $plugin_activity_logger_old_versions; | |
$plugin_activity_logger_old_versions = []; | |
/** | |
* Logs plugin activity to the log file. | |
*/ | |
function log_plugin_activity($action, $plugin_slug = '', $plugin_name = '', $plugin_version = '') { | |
$current_user = wp_get_current_user(); | |
$username = $current_user->exists() ? $current_user->user_login : 'System/CLI'; | |
$timestamp = current_time('Y-m-d H:i:s'); | |
$wordpress_version = get_bloginfo('version'); | |
$site_url = parse_url(get_bloginfo('url'), PHP_URL_HOST); | |
$log_entry = sprintf( | |
"[%s] v%s at %s: %s: Plugin '%s' (%s)%s by user '%s'", | |
$timestamp, | |
$wordpress_version, | |
$site_url, | |
ucfirst($action), | |
$plugin_name, | |
$plugin_slug, | |
$plugin_version ? " $plugin_version" : '', | |
$username | |
); | |
file_put_contents(PLUGIN_ACTIVITY_LOG, $log_entry . PHP_EOL, FILE_APPEND | LOCK_EX); | |
} | |
/** | |
* Extract the plugin slug from a plugin path. | |
*/ | |
function get_plugin_slug($plugin_path) { | |
$parts = explode('/', $plugin_path); | |
return $parts[0]; | |
} | |
/** | |
* Store the old version of a plugin before update. | |
*/ | |
function store_old_plugin_version($plugin_path) { | |
global $plugin_activity_logger_old_versions; | |
$plugin_file = WP_PLUGIN_DIR . '/' . $plugin_path; | |
if (file_exists($plugin_file)) { | |
$plugin_data = get_plugin_data($plugin_file, false, false); | |
$old_version = $plugin_data['Version'] ?? ''; | |
if ($old_version) { | |
$plugin_activity_logger_old_versions[$plugin_path] = $old_version; | |
} | |
} | |
} | |
/** | |
* Before the installation (including updates), record old versions for updates. | |
*/ | |
add_action('upgrader_pre_install', function($hook_extra) { | |
// Only run for plugin updates | |
if (isset($hook_extra['type']) && $hook_extra['type'] === 'plugin' && isset($hook_extra['action']) && $hook_extra['action'] === 'update') { | |
// Single plugin update | |
if (!empty($hook_extra['plugin'])) { | |
store_old_plugin_version($hook_extra['plugin']); | |
} | |
// Bulk plugin updates | |
if (!empty($hook_extra['plugins']) && is_array($hook_extra['plugins'])) { | |
foreach ($hook_extra['plugins'] as $p) { | |
store_old_plugin_version($p); | |
} | |
} | |
} | |
}, 10, 1); | |
/** | |
* Handle plugin installation, updates, and failures. | |
*/ | |
add_action('upgrader_process_complete', function($upgrader, $options) { | |
global $plugin_activity_logger_old_versions; | |
if (!isset($options['type']) || $options['type'] !== 'plugin') { | |
return; | |
} | |
$action = $options['action']; // install, update, etc. | |
$plugins = $options['plugins'] ?? []; | |
// Check for operation failure | |
$update_failed = false; | |
$error_message = ''; | |
if (is_wp_error($upgrader->result)) { | |
$update_failed = true; | |
$error_message = $upgrader->result->get_error_message(); | |
} elseif (method_exists($upgrader->skin, 'get_errors') && $upgrader->skin->get_errors()->get_error_messages()) { | |
$update_failed = true; | |
$errors = $upgrader->skin->get_errors()->get_error_messages(); | |
$error_message = implode('; ', $errors); | |
} | |
foreach ($plugins as $plugin_path) { | |
$plugin_slug = get_plugin_slug($plugin_path); | |
$plugin_file = WP_PLUGIN_DIR . '/' . $plugin_path; | |
$plugin_data = file_exists($plugin_file) ? get_plugin_data($plugin_file, false, false) : []; | |
$plugin_name = $plugin_data['Name'] ?? $plugin_slug; | |
$new_version = $plugin_data['Version'] ?? ''; | |
// Attempt to retrieve old version | |
$old_version = $plugin_activity_logger_old_versions[$plugin_path] ?? ''; | |
// If no old version found, try $upgrader->skin->plugin_info | |
// Sometimes WP_Upgrader stores info about the old plugin there. | |
if (!$old_version && isset($upgrader->skin->plugin_info) && is_array($upgrader->skin->plugin_info)) { | |
$old_version = $upgrader->skin->plugin_info['Version'] ?? $old_version; | |
} | |
if ($action === 'install') { | |
if ($update_failed) { | |
log_plugin_activity('install (failed)', $plugin_slug, $plugin_name, "Error: $error_message"); | |
} else { | |
log_plugin_activity('install', $plugin_slug, $plugin_name, $new_version ? "v{$new_version}" : ''); | |
} | |
} elseif ($action === 'update') { | |
if ($update_failed) { | |
log_plugin_activity('update (failed)', $plugin_slug, $plugin_name, "Error: $error_message"); | |
} else { | |
// If we have old and new versions and they differ, show "from vOld to vNew" | |
if ($old_version && $new_version && $old_version !== $new_version) { | |
log_plugin_activity('update', $plugin_slug, $plugin_name, "from v{$old_version} to v{$new_version}"); | |
} else { | |
// Fall back to just the new version | |
log_plugin_activity('update', $plugin_slug, $plugin_name, $new_version ? "v{$new_version}" : ''); | |
} | |
} | |
} | |
} | |
}, 10, 2); | |
/** | |
* Log plugin deletions. | |
*/ | |
add_action('deleted_plugin', function($plugin_path) { | |
$plugin_slug = get_plugin_slug($plugin_path); | |
$plugin_name = basename($plugin_slug, '.php'); | |
log_plugin_activity('delete', $plugin_slug, $plugin_name); | |
}); | |
/** | |
* Log activation. | |
*/ | |
add_action('activated_plugin', function($plugin_path) { | |
$plugin_slug = get_plugin_slug($plugin_path); | |
$plugin_file = WP_PLUGIN_DIR . '/' . $plugin_path; | |
$plugin_data = file_exists($plugin_file) ? get_plugin_data($plugin_file, false, false) : []; | |
$plugin_name = $plugin_data['Name'] ?? $plugin_slug; | |
$plugin_version = $plugin_data['Version'] ?? ''; | |
log_plugin_activity('activate', $plugin_slug, $plugin_name, $plugin_version ? "v{$plugin_version}" : ''); | |
}); | |
/** | |
* Log deactivation. | |
*/ | |
add_action('deactivated_plugin', function($plugin_path) { | |
$plugin_slug = get_plugin_slug($plugin_path); | |
$plugin_file = WP_PLUGIN_DIR . '/' . $plugin_path; | |
$plugin_data = file_exists($plugin_file) ? get_plugin_data($plugin_file, false, false) : []; | |
$plugin_name = $plugin_data['Name'] ?? $plugin_slug; | |
$plugin_version = $plugin_data['Version'] ?? ''; | |
log_plugin_activity('deactivate', $plugin_slug, $plugin_name, $plugin_version ? "v{$plugin_version}" : ''); | |
}); | |
/** | |
* Initialization log entry. | |
*/ | |
function initialize_plugin_activity_log() { | |
if (!file_exists(PLUGIN_ACTIVITY_LOG)) { | |
$timestamp = current_time('Y-m-d H:i:s'); | |
$wordpress_version = get_bloginfo('version'); | |
$site_url = parse_url(get_bloginfo('url'), PHP_URL_HOST); | |
$log_entry = sprintf( | |
"[%s] v%s at %s: Initialize: Plugin Activity Log Initialized by user 'System/CLI'", | |
$timestamp, | |
$wordpress_version, | |
$site_url | |
); | |
file_put_contents(PLUGIN_ACTIVITY_LOG, $log_entry . PHP_EOL, LOCK_EX); | |
} | |
} | |
initialize_plugin_activity_log(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment