From cd593f68d3f259ef39d93c63c8d8ed2eb235ecff Mon Sep 17 00:00:00 2001 From: Marcus Quinn <6428977+marcusquinn@users.noreply.github.com> Date: Thu, 10 Apr 2025 00:06:07 +0100 Subject: [PATCH] Complete redesign to use WordPress plugins list directly (v1.3.0) --- CHANGELOG.md | 15 ++ README.md | 9 +- plugin-reference-cleaner.php | 386 +++++++++++++---------------------- readme.txt | 9 +- 4 files changed, 175 insertions(+), 244 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91cbe45..0e5ae4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,21 @@ All notable changes to this project will be documented in this file. +## [1.3.0] - 2023-10-05 +### Changed +- Complete redesign for maximum compatibility with all WordPress themes +- Now uses the plugins list table for missing plugin references +- Uses standard WordPress admin UI patterns and hooks + +### Added +- Missing plugins now appear directly in the plugins list +- "Remove Reference" action link in the plugins list +- Success/error notices after removing references + +### Fixed +- Compatibility issues with various WordPress admin themes +- Reliability issues with notification detection + ## [1.2.4] - 2023-10-05 ### Fixed - Compatibility with more WordPress admin UI variations diff --git a/README.md b/README.md index f97182a..95a758f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Plugin Reference Cleaner Author: Marcus Quinn Author URI: https://www.wpallstars.com -Version: 1.2.4 +Version: 1.3.0 License: GPL-2.0+ ## Description @@ -47,6 +47,13 @@ If you don't have this notification perpetually showing on your /wp-admin/plugin ## Changelog +### 1.3.0 +* Complete redesign for maximum compatibility with all WordPress themes +* Now adds missing plugins directly to the plugins list table +* Uses standard WordPress admin UI patterns instead of DOM manipulation +* Added "Remove Reference" action link in the plugins list +* Significantly improved reliability across all WordPress configurations + ### 1.2.4 * Fixed compatibility with more WordPress admin themes * Added advanced DOM traversal to find error messages diff --git a/plugin-reference-cleaner.php b/plugin-reference-cleaner.php index 3ec1d35..8de4c7a 100644 --- a/plugin-reference-cleaner.php +++ b/plugin-reference-cleaner.php @@ -2,7 +2,7 @@ /* * Plugin Name: Plugin Reference Cleaner * Description: Adds a "Remove Reference" button to plugin deactivation error notices, allowing users to clean up invalid plugin entries. - * Version: 1.2.4 + * Version: 1.3.0 * Author: Marcus Quinn * Author URI: https://www.wpallstars.com * License: GPL-2.0+ @@ -15,252 +15,108 @@ if (!defined('ABSPATH')) { class Plugin_Reference_Cleaner { public function __construct() { - // Only hook into admin actions when on the plugins page - add_action('current_screen', function($screen) { - if (isset($screen->id) && ($screen->id === 'plugins' || $screen->id === 'plugins-network')) { - // Hook into admin notices to modify plugin error messages - add_action('admin_notices', array($this, 'inject_remove_button'), 100); - add_action('network_admin_notices', array($this, 'inject_remove_button'), 100); - } - }); + // Add our plugin to the plugins list + add_filter('all_plugins', array($this, 'add_missing_plugins_references')); - // Handle the AJAX request to remove the plugin reference - add_action('wp_ajax_remove_plugin_reference', array($this, 'remove_plugin_reference')); + // Add our action link to the plugins list + add_filter('plugin_action_links', array($this, 'add_remove_reference_action'), 20, 4); + + // Handle the remove reference action + add_action('admin_init', array($this, 'handle_remove_reference')); + + // Add admin notices for operation feedback + add_action('admin_notices', array($this, 'admin_notices')); } + + /** + * Find and add invalid plugin references to the plugins list + */ + public function add_missing_plugins_references($plugins) { + // Only run on the plugins page + if (!$this->is_plugins_page()) { + return $plugins; + } - // Inject "Remove Reference" button only if a relevant notice exists - public function inject_remove_button() { - // Check if a "Plugin file does not exist" notice exists - $notices = $this->get_admin_notices(); - $has_error_notice = false; - $plugin_files = array(); - - if (!empty($notices)) { - foreach ($notices as $notice) { - // Look for both variations of the error message - if (strpos($notice, 'has been deactivated due to an error: Plugin file does not exist') !== false || - strpos($notice, 'deactivated due to an error: Plugin file does not exist') !== false) { - // Extract plugin file from notice using various patterns - if (preg_match('/The plugin ([^ ]+)/', $notice, $match)) { - $plugin_files[] = $match[1]; - $has_error_notice = true; - } - } + // Get active plugins that don't exist + $invalid_plugins = $this->get_invalid_plugins(); + + // Add each invalid plugin to the plugin list + foreach ($invalid_plugins as $plugin_path) { + if (!isset($plugins[$plugin_path])) { + $plugin_name = basename($plugin_path); + $plugins[$plugin_path] = array( + 'Name' => $plugin_name . ' (File Missing)', + 'Description' => 'This plugin file does not exist. You can safely remove this reference.', + 'Version' => 'N/A', + 'Author' => '', + 'PluginURI' => '', + 'AuthorURI' => '', + 'Title' => $plugin_name . ' (Missing)', + 'AuthorName' => '' + ); } } - // Only proceed if a relevant notice was found - if (!$has_error_notice || empty($plugin_files)) { + return $plugins; + } + + /** + * Add the Remove Reference action link to invalid plugins + */ + public function add_remove_reference_action($actions, $plugin_file, $plugin_data, $context) { + // Only run on the plugins page + if (!$this->is_plugins_page()) { + return $actions; + } + + // Check if this is a missing plugin + if (isset($plugin_data['Name']) && strpos($plugin_data['Name'], '(File Missing)') !== false) { + // Clear existing actions + $actions = array(); + + // Add our action + $nonce = wp_create_nonce('remove_plugin_reference_' . $plugin_file); + $remove_url = admin_url('plugins.php?action=remove_reference&plugin=' . urlencode($plugin_file) . '&_wpnonce=' . $nonce); + $actions['remove_reference'] = 'Remove Reference'; + } + + return $actions; + } + + /** + * Handle the remove reference action + */ + public function handle_remove_reference() { + // Check if we're removing a reference + if (!isset($_GET['action']) || $_GET['action'] !== 'remove_reference' || !isset($_GET['plugin'])) { return; } - - // Inject JavaScript with the specific plugin files - ?> - - remove_plugin_reference($plugin_file); + + // Redirect back to plugins page with a message + $redirect = admin_url('plugins.php'); + $redirect = add_query_arg($success ? 'reference_removed' : 'reference_removal_failed', '1', $redirect); + wp_redirect($redirect); + exit; + } + + /** + * Remove a plugin reference from the active plugins + */ + public function remove_plugin_reference($plugin_file) { $success = false; // Handle multisite network admin @@ -281,14 +137,60 @@ class Plugin_Reference_Cleaner { $success = update_option('active_plugins', $active_plugins); } } - - if ($success) { - wp_send_json_success('Plugin reference removed successfully.'); - } else { - wp_send_json_error('Plugin reference not found or could not be removed.'); + + return $success; + } + + /** + * Display admin notices + */ + public function admin_notices() { + // Only run on the plugins page + if (!$this->is_plugins_page()) { + return; } - wp_die(); + // Show success message + if (isset($_GET['reference_removed']) && $_GET['reference_removed'] === '1') { + echo '
Plugin reference removed successfully.
Failed to remove plugin reference. The plugin may already have been removed.