Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
bcc9f984f6 | |||
db662096e4 | |||
d6b89887fc | |||
cd593f68d3 | |||
7ac72fd3c0 | |||
0a394fa671 | |||
f200ff6f96 |
66
CHANGELOG.md
66
CHANGELOG.md
@ -2,6 +2,72 @@
|
|||||||
|
|
||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
## [1.3.3] - 2023-10-05
|
||||||
|
### Added
|
||||||
|
- "Click here to scroll" button to automatically find missing plugins
|
||||||
|
- Visual arrow pointing from notification to error message
|
||||||
|
- Smooth scrolling with highlighting of missing plugin rows
|
||||||
|
|
||||||
|
### Improved
|
||||||
|
- Notification reliability using multiple injection methods
|
||||||
|
- Earlier placement in page load cycle for better visibility
|
||||||
|
- Enhanced error detection for all WordPress error message formats
|
||||||
|
|
||||||
|
## [1.3.2] - 2023-10-05
|
||||||
|
### Added
|
||||||
|
- Prominent notification that appears directly below WordPress error messages
|
||||||
|
- Visual styling to help users connect error message with solution
|
||||||
|
- Direction arrows and highlighted text to improve user guidance
|
||||||
|
|
||||||
|
## [1.3.1] - 2023-10-05
|
||||||
|
### Added
|
||||||
|
- Instructional notification explaining how to use the plugin
|
||||||
|
- Step-by-step guidance for removing plugin references
|
||||||
|
- Clear visual indicators for missing plugins
|
||||||
|
|
||||||
|
## [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
|
||||||
|
- Specific targeting for admin notices in various themes
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Advanced DOM traversal using TreeWalker API
|
||||||
|
- Multiple fallback approaches to ensure button appears
|
||||||
|
- Enhanced console logging for troubleshooting
|
||||||
|
|
||||||
|
## [1.2.3] - 2023-10-05
|
||||||
|
### Fixed
|
||||||
|
- Button not appearing in some WordPress admin themes
|
||||||
|
- Error message detection for greater theme compatibility
|
||||||
|
|
||||||
|
### Improved
|
||||||
|
- DOM traversal to find notification elements in various themes
|
||||||
|
- Added console logging for troubleshooting
|
||||||
|
|
||||||
|
## [1.2.2] - 2023-10-05
|
||||||
|
### Fixed
|
||||||
|
- Timeout issue during plugin activation
|
||||||
|
- Potential infinite recursion in admin notices handling
|
||||||
|
|
||||||
|
### Improved
|
||||||
|
- Hook management to prevent performance issues
|
||||||
|
- Optimized by only loading on plugins page
|
||||||
|
|
||||||
## [1.2.1] - 2025-04-07
|
## [1.2.1] - 2025-04-07
|
||||||
### Improved
|
### Improved
|
||||||
- Fixed typos in documentation
|
- Fixed typos in documentation
|
||||||
|
43
README.md
43
README.md
@ -1,7 +1,7 @@
|
|||||||
# Plugin Reference Cleaner
|
# Plugin Reference Cleaner
|
||||||
Author: Marcus Quinn
|
Author: Marcus Quinn
|
||||||
Author URI: https://wpallstars.com
|
Author URI: https://www.wpallstars.com
|
||||||
Version: 1.2.1
|
Version: 1.3.3
|
||||||
License: GPL-2.0+
|
License: GPL-2.0+
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
@ -47,6 +47,45 @@ If you don't have this notification perpetually showing on your /wp-admin/plugin
|
|||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
### 1.3.3
|
||||||
|
* Improved notification placement next to WordPress error messages
|
||||||
|
* Added "Click here to scroll" button that automatically locates missing plugins
|
||||||
|
* Enhanced reliability with multiple injection methods
|
||||||
|
* Added visual arrow pointing from notification to error message
|
||||||
|
|
||||||
|
### 1.3.2
|
||||||
|
* Added prominent notification directly below WordPress error messages
|
||||||
|
* Improved user guidance with visual cues to connect error and solution
|
||||||
|
* Added eye-catching styling to help users understand how to fix errors
|
||||||
|
|
||||||
|
### 1.3.1
|
||||||
|
* Added instructional notification explaining how to use the plugin
|
||||||
|
* Improved user guidance with step-by-step instructions
|
||||||
|
* Enhanced visual identification of missing plugins
|
||||||
|
|
||||||
|
### 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
|
||||||
|
* Implemented fallback mechanisms to ensure button appears
|
||||||
|
* Added detailed console logging for troubleshooting
|
||||||
|
|
||||||
|
### 1.2.3
|
||||||
|
* Fixed button not appearing in some WordPress admin themes
|
||||||
|
* Improved error message detection for greater compatibility
|
||||||
|
* Enhanced DOM traversal to find notification elements
|
||||||
|
|
||||||
|
### 1.2.2
|
||||||
|
* Fixed timeout issue during plugin activation
|
||||||
|
* Improved hook management to prevent potential infinite recursion
|
||||||
|
* Optimized performance by only loading on plugins page
|
||||||
|
|
||||||
### 1.2.1
|
### 1.2.1
|
||||||
* Fixed typos in documentation
|
* Fixed typos in documentation
|
||||||
* Improved text clarity
|
* Improved text clarity
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
/*
|
/*
|
||||||
* Plugin Name: Plugin Reference Cleaner
|
* Plugin Name: Plugin Reference Cleaner
|
||||||
* Description: Adds a "Remove Reference" button to plugin deactivation error notices, allowing users to clean up invalid plugin entries.
|
* Description: Adds a "Remove Reference" button to plugin deactivation error notices, allowing users to clean up invalid plugin entries.
|
||||||
* Version: 1.2.1
|
* Version: 1.3.3
|
||||||
* Author: Marcus Quinn
|
* Author: Marcus Quinn
|
||||||
* Author URI: https://wpallstars.com
|
* Author URI: https://www.wpallstars.com
|
||||||
* License: GPL-2.0+
|
* License: GPL-2.0+
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -15,141 +15,108 @@ if (!defined('ABSPATH')) {
|
|||||||
|
|
||||||
class Plugin_Reference_Cleaner {
|
class Plugin_Reference_Cleaner {
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
// Hook into admin notices to modify plugin error messages
|
// Add our plugin to the plugins list
|
||||||
add_action('admin_notices', array($this, 'inject_remove_button'), 100);
|
add_filter('all_plugins', array($this, 'add_missing_plugins_references'));
|
||||||
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 our action link to the plugins list
|
||||||
add_action('wp_ajax_remove_plugin_reference', array($this, 'remove_plugin_reference'));
|
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'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inject "Remove Reference" button only if a relevant notice exists
|
/**
|
||||||
public function inject_remove_button() {
|
* Find and add invalid plugin references to the plugins list
|
||||||
global $pagenow;
|
*/
|
||||||
|
public function add_missing_plugins_references($plugins) {
|
||||||
|
// Only run on the plugins page
|
||||||
|
if (!$this->is_plugins_page()) {
|
||||||
|
return $plugins;
|
||||||
|
}
|
||||||
|
|
||||||
// Only run on plugins.php or network admin plugins page
|
// Get active plugins that don't exist
|
||||||
if (!in_array($pagenow, array('plugins.php', 'plugins.php'))) {
|
$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 . ' <span class="error">(File Missing)</span>',
|
||||||
|
'Description' => 'This plugin file does not exist. You can safely remove this reference.',
|
||||||
|
'Version' => 'N/A',
|
||||||
|
'Author' => '',
|
||||||
|
'PluginURI' => '',
|
||||||
|
'AuthorURI' => '',
|
||||||
|
'Title' => $plugin_name . ' (Missing)',
|
||||||
|
'AuthorName' => ''
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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'], '<span class="error">(File Missing)</span>') !== 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'] = '<a href="' . esc_url($remove_url) . '" class="delete" aria-label="' . esc_attr__('Remove Reference', 'plugin-reference-cleaner') . '">Remove Reference</a>';
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if a "Plugin file does not exist" notice exists
|
// Verify permissions
|
||||||
$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')) {
|
if (!current_user_can('activate_plugins')) {
|
||||||
wp_send_json_error('You do not have sufficient permissions to perform this action.');
|
wp_die(__('You do not have sufficient permissions to perform this action.', 'plugin-reference-cleaner'));
|
||||||
wp_die();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get and validate plugin file parameter
|
// Get the plugin file
|
||||||
$plugin_file = isset($_POST['plugin']) ? sanitize_text_field($_POST['plugin']) : '';
|
$plugin_file = isset($_GET['plugin']) ? $_GET['plugin'] : '';
|
||||||
if (empty($plugin_file)) {
|
|
||||||
wp_send_json_error('No plugin specified.');
|
// Verify nonce
|
||||||
wp_die();
|
check_admin_referer('remove_plugin_reference_' . $plugin_file);
|
||||||
|
|
||||||
|
// Remove the plugin reference
|
||||||
|
$success = $this->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;
|
$success = false;
|
||||||
|
|
||||||
// Handle multisite network admin
|
// Handle multisite network admin
|
||||||
@ -171,13 +138,178 @@ class Plugin_Reference_Cleaner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($success) {
|
return $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();
|
/**
|
||||||
|
* Display admin notices
|
||||||
|
*/
|
||||||
|
public function admin_notices() {
|
||||||
|
// Only run on the plugins page
|
||||||
|
if (!$this->is_plugins_page()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get invalid plugins
|
||||||
|
$invalid_plugins = $this->get_invalid_plugins();
|
||||||
|
|
||||||
|
// Create a highlighted notice immediately after WordPress error messages
|
||||||
|
if (!empty($invalid_plugins)) {
|
||||||
|
// Add a notice specifically targeting the WordPress error notification
|
||||||
|
// Use admin_head to ensure it runs early in the page load process
|
||||||
|
add_action('admin_head', function() use ($invalid_plugins) {
|
||||||
|
?>
|
||||||
|
<style type="text/css">
|
||||||
|
.prc-notice {
|
||||||
|
border-left: 4px solid #ffba00;
|
||||||
|
background-color: #fff8e5;
|
||||||
|
padding: 10px 12px;
|
||||||
|
margin: 5px 0 15px;
|
||||||
|
font-size: 14px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.prc-notice h3 {
|
||||||
|
margin-top: 0;
|
||||||
|
color: #826200;
|
||||||
|
}
|
||||||
|
.prc-notice::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: -10px;
|
||||||
|
left: 20px;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
border-left: 10px solid transparent;
|
||||||
|
border-right: 10px solid transparent;
|
||||||
|
border-bottom: 10px solid #fff8e5;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script type="text/javascript">
|
||||||
|
// Function to inject our notice
|
||||||
|
function injectNotice() {
|
||||||
|
// Find all notification containers first
|
||||||
|
var noticeContainers = document.querySelectorAll('.notice, .error, .updated');
|
||||||
|
|
||||||
|
// Find all error notifications about missing plugins
|
||||||
|
noticeContainers.forEach(function(notice) {
|
||||||
|
if (notice.textContent.includes('Plugin file does not exist') ||
|
||||||
|
notice.textContent.includes('has been deactivated due to an error')) {
|
||||||
|
|
||||||
|
// Check if we already added our notice
|
||||||
|
if (notice.nextElementSibling && notice.nextElementSibling.classList.contains('prc-notice')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create our custom notice
|
||||||
|
var ourNotice = document.createElement('div');
|
||||||
|
ourNotice.className = 'prc-notice';
|
||||||
|
|
||||||
|
// Add content
|
||||||
|
ourNotice.innerHTML = '<h3 style="margin-top:0;color:#826200;">👉 Plugin Reference Cleaner Can Fix This</h3>' +
|
||||||
|
'<p>To remove the above error notification, scroll down to find the plugin marked with "<strong style="color:red">(File Missing)</strong>" and click its "<strong>Remove Reference</strong>" link.</p>' +
|
||||||
|
'<p>This will permanently remove the missing plugin reference from your database.</p>' +
|
||||||
|
'<p><a href="#" id="prc-scroll-to-plugin" style="font-weight:bold;text-decoration:underline;color:#826200;">Click here to scroll to the missing plugin</a></p>';
|
||||||
|
|
||||||
|
// Insert our notice right after the error
|
||||||
|
notice.parentNode.insertBefore(ourNotice, notice.nextSibling);
|
||||||
|
|
||||||
|
// Add scroll behavior
|
||||||
|
var scrollLink = document.getElementById('prc-scroll-to-plugin');
|
||||||
|
if (scrollLink) {
|
||||||
|
scrollLink.addEventListener('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var missingPlugins = document.querySelectorAll('tr.inactive:not(.plugin-update-tr)');
|
||||||
|
for (var i = 0; i < missingPlugins.length; i++) {
|
||||||
|
if (missingPlugins[i].textContent.includes('(File Missing)')) {
|
||||||
|
missingPlugins[i].style.backgroundColor = '#fff8e5';
|
||||||
|
missingPlugins[i].scrollIntoView({behavior: 'smooth', block: 'center'});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to inject notices on multiple events to ensure it works
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
injectNotice();
|
||||||
|
|
||||||
|
// Also set up a MutationObserver to watch for dynamically added notices
|
||||||
|
var observer = new MutationObserver(function(mutations) {
|
||||||
|
mutations.forEach(function(mutation) {
|
||||||
|
if (mutation.addedNodes && mutation.addedNodes.length > 0) {
|
||||||
|
injectNotice();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Start observing the body for changes
|
||||||
|
observer.observe(document.body, { childList: true, subtree: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
// Backup attempt with window.onload
|
||||||
|
window.onload = function() {
|
||||||
|
setTimeout(injectNotice, 500);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Final backup in case other methods fail
|
||||||
|
setTimeout(injectNotice, 1000);
|
||||||
|
</script>
|
||||||
|
<?php
|
||||||
|
});
|
||||||
|
|
||||||
|
// Also display our standard info notice with more details
|
||||||
|
echo '<div class="notice notice-info is-dismissible">';
|
||||||
|
echo '<h3>Plugin Reference Cleaner</h3>';
|
||||||
|
echo '<p><strong>Missing plugin files detected:</strong> The plugins listed below with <span style="color:red;">(File Missing)</span> tag no longer exist but are still referenced in your database.</p>';
|
||||||
|
echo '<p><strong>How to fix:</strong> Click the "Remove Reference" link next to each missing plugin to safely remove it from your active plugins list.</p>';
|
||||||
|
echo '<p>This will clean up your database and remove the error notifications.</p>';
|
||||||
|
echo '</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show success message
|
||||||
|
if (isset($_GET['reference_removed']) && $_GET['reference_removed'] === '1') {
|
||||||
|
echo '<div class="notice notice-success is-dismissible"><p>Plugin reference removed successfully.</p></div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show error message
|
||||||
|
if (isset($_GET['reference_removal_failed']) && $_GET['reference_removal_failed'] === '1') {
|
||||||
|
echo '<div class="notice notice-error is-dismissible"><p>Failed to remove plugin reference. The plugin may already have been removed.</p></div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if we're on the plugins page
|
||||||
|
*/
|
||||||
|
private function is_plugins_page() {
|
||||||
|
global $pagenow;
|
||||||
|
return is_admin() && $pagenow === 'plugins.php';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of invalid plugin references
|
||||||
|
*/
|
||||||
|
private function get_invalid_plugins() {
|
||||||
|
$invalid_plugins = array();
|
||||||
|
|
||||||
|
// Get all active plugins
|
||||||
|
if (is_multisite() && is_network_admin()) {
|
||||||
|
$active_plugins = array_keys(get_site_option('active_sitewide_plugins', array()));
|
||||||
|
} else {
|
||||||
|
$active_plugins = get_option('active_plugins', array());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if each plugin exists
|
||||||
|
foreach ($active_plugins as $plugin) {
|
||||||
|
$plugin_path = WP_PLUGIN_DIR . '/' . $plugin;
|
||||||
|
if (!file_exists($plugin_path)) {
|
||||||
|
$invalid_plugins[] = $plugin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $invalid_plugins;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
43
readme.txt
43
readme.txt
@ -1,7 +1,7 @@
|
|||||||
=== Plugin Reference Cleaner ===
|
=== Plugin Reference Cleaner ===
|
||||||
Author: Marcus Quinn
|
Author: Marcus Quinn
|
||||||
Author URI: https://wpallstars.com
|
Author URI: https://www.wpallstars.com
|
||||||
Version: 1.2.1
|
Version: 1.3.3
|
||||||
License: GPL-2.0+
|
License: GPL-2.0+
|
||||||
|
|
||||||
== Description ==
|
== Description ==
|
||||||
@ -47,6 +47,45 @@ If you don't have this notification perpetually showing on your /wp-admin/plugin
|
|||||||
|
|
||||||
== Changelog ==
|
== Changelog ==
|
||||||
|
|
||||||
|
= 1.3.3 =
|
||||||
|
* Improved notification placement next to WordPress error messages
|
||||||
|
* Added "Click here to scroll" button that automatically locates missing plugins
|
||||||
|
* Enhanced reliability with multiple injection methods
|
||||||
|
* Added visual arrow pointing from notification to error message
|
||||||
|
|
||||||
|
= 1.3.2 =
|
||||||
|
* Added prominent notification directly below WordPress error messages
|
||||||
|
* Improved user guidance with visual cues to connect error and solution
|
||||||
|
* Added eye-catching styling to help users understand how to fix errors
|
||||||
|
|
||||||
|
= 1.3.1 =
|
||||||
|
* Added instructional notification explaining how to use the plugin
|
||||||
|
* Improved user guidance with step-by-step instructions
|
||||||
|
* Enhanced visual identification of missing plugins
|
||||||
|
|
||||||
|
= 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
|
||||||
|
* Implemented fallback mechanisms to ensure button appears
|
||||||
|
* Added detailed console logging for troubleshooting
|
||||||
|
|
||||||
|
= 1.2.3 =
|
||||||
|
* Fixed button not appearing in some WordPress admin themes
|
||||||
|
* Improved error message detection for greater compatibility
|
||||||
|
* Enhanced DOM traversal to find notification elements
|
||||||
|
|
||||||
|
= 1.2.2 =
|
||||||
|
* Fixed timeout issue during plugin activation
|
||||||
|
* Improved hook management to prevent potential infinite recursion
|
||||||
|
* Optimized performance by only loading on plugins page
|
||||||
|
|
||||||
= 1.2.1 =
|
= 1.2.1 =
|
||||||
* Fixed typos in documentation
|
* Fixed typos in documentation
|
||||||
* Improved text clarity
|
* Improved text clarity
|
||||||
|
Reference in New Issue
Block a user