diff --git a/plugin-reference-cleaner.php b/plugin-reference-cleaner.php index 718e644..51b55ee 100644 --- a/plugin-reference-cleaner.php +++ b/plugin-reference-cleaner.php @@ -8,10 +8,16 @@ * License: GPL-2.0+ */ +// Exit if accessed directly +if (!defined('ABSPATH')) { + exit; +} + class Plugin_Reference_Cleaner { public function __construct() { // 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); // Ensure notices in network admin // Handle the AJAX request to remove the plugin reference add_action('wp_ajax_remove_plugin_reference', array($this, 'remove_plugin_reference')); } @@ -21,7 +27,7 @@ class Plugin_Reference_Cleaner { global $pagenow; // Only run on plugins.php or network admin plugins page - if (!in_array($pagenow, array('plugins.php', 'network/plugins.php'))) { + if (!in_array($pagenow, array('plugins.php', 'plugins.php'))) { return; } @@ -30,18 +36,20 @@ class Plugin_Reference_Cleaner { $has_error_notice = false; $plugin_files = array(); - foreach ($notices as $notice) { - if (strpos($notice, 'has been deactivated due to an error: Plugin file does not exist') !== false) { - // Extract plugin file from notice - if (preg_match('/The plugin ([^ ]+)/', $notice, $match)) { - $plugin_files[] = $match[1]; - $has_error_notice = true; + if (!empty($notices)) { + foreach ($notices as $notice) { + if (strpos($notice, 'has been deactivated due to an error: Plugin file does not exist') !== false) { + // Extract plugin file from notice + if (preg_match('/The plugin ([^ ]+)/', $notice, $match)) { + $plugin_files[] = $match[1]; + $has_error_notice = true; + } } } } // Only proceed if a relevant notice was found - if (!$has_error_notice) { + if (!$has_error_notice || empty($plugin_files)) { return; } @@ -49,8 +57,13 @@ class Plugin_Reference_Cleaner { ?> <script type="text/javascript"> document.addEventListener('DOMContentLoaded', function() { - var pluginFiles = <?php echo json_encode($plugin_files); ?>; + var pluginFiles = <?php echo wp_json_encode($plugin_files); ?>; var notices = document.querySelectorAll('.notice-error p'); + + if (notices.length === 0) { + return; + } + notices.forEach(function(notice) { pluginFiles.forEach(function(pluginFile) { if (notice.textContent.includes('The plugin ' + pluginFile)) { @@ -70,16 +83,29 @@ class Plugin_Reference_Cleaner { var pluginFile = this.dataset.plugin; if (confirm('Are you sure you want to remove the reference to ' + pluginFile + '?')) { var xhr = new XMLHttpRequest(); - xhr.open('POST', '<?php echo admin_url('admin-ajax.php'); ?>', true); + xhr.open('POST', '<?php echo esc_url(admin_url('admin-ajax.php')); ?>', true); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.onload = function() { if (xhr.status === 200) { - alert('Plugin reference removed successfully.'); - location.reload(); + try { + var response = JSON.parse(xhr.responseText); + if (response.success) { + alert('Plugin reference removed successfully.'); + location.reload(); + } else { + alert('Failed to remove plugin reference: ' + (response.data || 'Unknown error')); + } + } catch (e) { + alert('Failed to parse server response.'); + console.error(e); + } } else { - alert('Failed to remove plugin reference.'); + alert('Failed to remove plugin reference. Server returned status ' + xhr.status); } }; + xhr.onerror = function() { + alert('Network error occurred while trying to remove plugin reference.'); + }; xhr.send('action=remove_plugin_reference&plugin=' + encodeURIComponent(pluginFile) + '&nonce=<?php echo wp_create_nonce('remove_plugin_reference'); ?>'); } }); @@ -93,48 +119,67 @@ class Plugin_Reference_Cleaner { private function get_admin_notices() { ob_start(); do_action('admin_notices'); + do_action('network_admin_notices'); $output = ob_get_clean(); + + if (empty($output)) { + return array(); + } + return array_filter(explode("\n", $output)); } // Handle the AJAX request to remove the plugin reference public function remove_plugin_reference() { + // Verify nonce if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'remove_plugin_reference')) { - wp_send_json_error('Invalid nonce'); + wp_send_json_error('Invalid security token. Please refresh the page and try again.'); wp_die(); } + // Check user permissions if (!current_user_can('activate_plugins')) { - wp_send_json_error('Insufficient permissions'); + wp_send_json_error('You do not have sufficient permissions to perform this action.'); wp_die(); } + // Get and validate plugin file parameter $plugin_file = isset($_POST['plugin']) ? sanitize_text_field($_POST['plugin']) : ''; if (empty($plugin_file)) { - wp_send_json_error('No plugin specified'); + wp_send_json_error('No plugin specified.'); wp_die(); } + $success = false; + + // Handle multisite network admin if (is_multisite() && is_network_admin()) { $active_plugins = get_site_option('active_sitewide_plugins', array()); if (isset($active_plugins[$plugin_file])) { unset($active_plugins[$plugin_file]); - update_site_option('active_sitewide_plugins', $active_plugins); + $success = update_site_option('active_sitewide_plugins', $active_plugins); } - } else { - $site_id = get_current_blog_id(); - $active_plugins = get_blog_option($site_id, 'active_plugins', array()); + } + // Handle single site or multisite subsite + else { + $active_plugins = get_option('active_plugins', array()); $key = array_search($plugin_file, $active_plugins); if ($key !== false) { unset($active_plugins[$key]); - $active_plugins = array_values($active_plugins); - update_blog_option($site_id, 'active_plugins', $active_plugins); + $active_plugins = array_values($active_plugins); // Re-index array + $success = update_option('active_plugins', $active_plugins); } } - wp_send_json_success('Plugin reference removed'); + if ($success) { + wp_send_json_success('Plugin reference removed successfully.'); + } else { + wp_send_json_error('Plugin reference not found or could not be removed.'); + } + wp_die(); } } +// Initialize the plugin new Plugin_Reference_Cleaner(); \ No newline at end of file