<?php
/*
 * 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.1
 * Author: Marcus Quinn
 * Author URI: https://wpallstars.com
 * 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'));
    }

    // Inject "Remove Reference" button only if a relevant notice exists
    public function inject_remove_button() {
        global $pagenow;

        // Only run on plugins.php or network admin plugins page
        if (!in_array($pagenow, array('plugins.php', 'plugins.php'))) {
            return;
        }

        // 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) {
                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 || empty($plugin_files)) {
            return;
        }

        // Inject JavaScript with the specific plugin files
        ?>
        <script type="text/javascript">
            document.addEventListener('DOMContentLoaded', function() {
                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)) {
                            var button = document.createElement('button');
                            button.textContent = 'Remove Reference';
                            button.className = 'button button-secondary remove-plugin-ref';
                            button.dataset.plugin = pluginFile;
                            button.style.marginLeft = '10px';
                            notice.appendChild(button);
                        }
                    });
                });

                document.querySelectorAll('.remove-plugin-ref').forEach(function(button) {
                    button.addEventListener('click', function(e) {
                        e.preventDefault();
                        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 esc_url(admin_url('admin-ajax.php')); ?>', true);
                            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
                            xhr.onload = function() {
                                if (xhr.status === 200) {
                                    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. 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'); ?>');
                        }
                    });
                });
            });
        </script>
        <?php
    }

    // Helper function to capture admin notices
    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 security token. Please refresh the page and try again.');
            wp_die();
        }

        // Check user permissions
        if (!current_user_can('activate_plugins')) {
            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_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]);
                $success = update_site_option('active_sitewide_plugins', $active_plugins);
            }
        } 
        // 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); // Re-index array
                $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.');
        }
        
        wp_die();
    }
}

// Initialize the plugin
new Plugin_Reference_Cleaner();