A while ago I had an issue where I missed a security update, it rolled out, i found out about it and i pushed for updates using my MainWP dashboard and thought I was all good. An issue didn’t transpire for about 24 hours when it turned out one site didn’t update (because the update window wasn’t in the period of the check) at that time I thought about how to get around it.
Initially I used my utility plugin Ninja Updater, to allow me to manually force these update checks before hand using a button on my stream deck but this isn’t very user friendly especially when away from my desk.
So I developed a snippet which went into my utility plugin that allows me to call it using the code snippet library in MainWP and it effectively ear marks for a future update I then call it via a snippet and it will force an update the snippet is below
<?php
/**
* Snippet: Force update transient refresh and report
* Triggered when the option 'ninja_run_forced_update_check' is set to 'yes'
*/
if ( get_option( 'ninja_run_forced_update_check' ) !== 'yes' ) {
return; // Only run when triggered
}
// Reset the trigger immediately so it doesn't run again
update_option( 'ninja_run_forced_update_check', 'no' );
// Ensure required functions are available
if ( ! function_exists( 'get_plugins' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
if ( ! function_exists( 'wp_get_themes' ) ) {
require_once ABSPATH . 'wp-includes/theme.php';
}
include_once ABSPATH . 'wp-admin/includes/update.php';
// Clear native update transients
delete_site_transient('update_plugins');
delete_site_transient('update_themes');
delete_site_transient('update_core');
wp_clean_update_cache();
// Clear GitHub release caches
global $wpdb;
$wpdb->query( "DELETE FROM $wpdb->options WHERE option_name LIKE '_transient_urup_github_release_%'" );
// Force update checks
wp_version_check();
wp_update_plugins();
wp_update_themes();
// Short delay to allow async update registration
sleep(3);
// Reporting
$core_updates = get_site_transient('update_core');
$plugin_updates = get_site_transient('update_plugins');
$theme_updates = get_site_transient('update_themes');
$report = "Forced Update Check Summary:\n\n";
// Core
if ( ! empty( $core_updates->updates ) ) {
foreach ( $core_updates->updates as $core ) {
if ( isset( $core->current ) ) {
$report .= "WordPress Core: Update to {$core->current} available\n";
}
}
} else {
$report .= " WordPress Core: Up to date\n";
}
// Plugins
if ( ! empty( $plugin_updates->response ) ) {
$all_plugins = get_plugins();
$report .= "Plugin Updates:\n";
foreach ( $plugin_updates->response as $plugin_file => $data ) {
$name = $all_plugins[ $plugin_file ]['Name'] ?? $plugin_file;
$report .= " - {$name} ({$plugin_file}) → v{$data->new_version}\n";
}
} else {
$report .= " Plugins: All up to date\n";
}
// Themes
if ( ! empty( $theme_updates->response ) ) {
$report .= "Theme Updates:\n";
foreach ( $theme_updates->response as $slug => $data ) {
$theme = wp_get_theme( $slug );
$name = $theme->get( 'Name' ) ?: $slug;
$report .= " - {$name} ({$slug}) → v{$data['new_version']}\n";
}
} else {
$report .= " Themes: All up to date\n";
}
// Optional: Log to debug.log
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
error_log( $report );
}
PHPI then call it within MainWP code snippet sent to the site with the following
update_option( 'ninja_run_forced_update_check', 'yes' );
echo 'Forced update check triggered. It will run on next page load or cron.';
// Include the file immediately and run
$snippet_path = WP_PLUGIN_DIR . '/ninja-updater/snippets/force-update-check.php';
if ( file_exists( $snippet_path ) ) {
include $snippet_path;
}
PHPwhich returns to the MainWP dashboard the following

WARNING: if you want to reuse this script you should remove lines 6-13 as you don’t have access to ninja-updater and you would push and run this to your sites rather than my second activation script – Make sure to check it works with your install first as always BACKUP and be careful about code you run from the internet.
Then I go and sync the sites and hey presto the update is there ready to apply.
Now i’ve tested this about 50 times since he day I implemented it and i’ve used it twice hot i.e. for a security update in the last two weeks ACF and Bricks and both times its worked flawlessly and today I checked and in about 90 seconds I had updated all site from knowing about the issue to pushing the updates.
I did the prep and can now be 100% confident as long as I check the logs afterwards that my solution allows me to push security updates in minutes to my sites with certainty
Now ninja-updater has lots of uses but the more I build on it the better it becomes, I am even able to remotely override where a plugin update comes from using UUPD and a little bit of custom code and a couple of options in the options table, all remotely using the code snippets in my dashboard, which means when recently dPlugins had an issue with the devkit update, I uploaded it to my private repo and told my sites to grab the update from there no manual installs necessary.
So there are two morals to this story prep is important and everyone needs there own utility plugin.