Skip to content

Instantly share code, notes, and snippets.

@brigleb
Last active December 11, 2024 17:07
Show Gist options
  • Save brigleb/f404d784ab25cfeb6196ea1ceb8440c8 to your computer and use it in GitHub Desktop.
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. …
<?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