stats = get_site_option('mpc_stats', [
'total_sites' => 0,
'total_activations' => 0,
'total_deactivations' => 0,
'last_action_time' => null
]);
$this->plugin_report = new RT_Plugin_Report($this);
$this->plugin_report->init();
add_action('network_admin_menu', [$this, 'add_menu']);
add_action('wpmu_new_blog', [$this, 'new_blog'], 50);
if (!(defined('WP_CLI') && WP_CLI)) {
add_filter('all_plugins', [$this, 'remove_plugins']);
}
add_filter('plugin_action_links', [$this, 'action_links'], 10, 4);
add_action('admin_notices', [$this, 'supporter_message']);
add_action('plugins_loaded', [$this, 'localization']);
add_action('wpmueditblogaction', [$this, 'blog_options_form']);
add_action('wpmu_update_blog_options', [$this, 'blog_options_form_process']);
add_filter('plugin_row_meta', [$this, 'remove_plugin_meta'], 10, 2);
add_action('admin_init', [$this, 'remove_plugin_update_row']);
add_action('wp_ajax_mpc_save_settings', [$this, 'ajax_save_settings']);
add_action('wp_ajax_mpc_mass_activate', [$this, 'ajax_mass_activate']);
add_action('wp_ajax_mpc_mass_deactivate', [$this, 'ajax_mass_deactivate']);
}
public function localization() {
load_plugin_textdomain('multisite-plugin-control', false, dirname(plugin_basename(__FILE__)) . '/languages/');
}
public function add_menu() {
add_submenu_page(
'plugins.php',
__('Plugin Control', 'multisite-plugin-control'),
__('Plugin Control', 'multisite-plugin-control'),
'manage_network_options',
'multisite-plugin-control',
[$this, 'admin_page']
);
}
public function admin_page() {
if (!current_user_can('manage_network_options')) {
wp_die(__('You do not have sufficient permissions to access this page.', 'multisite-plugin-control'));
}
$active_tab = isset($_GET['tab']) ? sanitize_text_field($_GET['tab']) : 'management';
?>
get_plugin_usage_stats();
if (isset($usage_stats['error'])) {
echo '
' . esc_html($usage_stats['error']) . '
';
} else {
?>
plugin_report->render_report(); ?>
|
|
|
stats['total_sites']); ?> |
|
stats['total_activations']); ?> |
|
stats['total_deactivations']); ?> |
|
stats['last_action_time'] ?: __('Never', 'multisite-plugin-control')); ?> |
__('Network too large to calculate usage stats.', 'multisite-plugin-control')];
}
$blogs = $wpdb->get_col($wpdb->prepare("SELECT blog_id FROM {$wpdb->blogs} WHERE site_id = %d AND spam = 0", $wpdb->siteid));
foreach ($plugins as $file => $p) {
if (is_network_only_plugin($file) || is_plugin_active_for_network($file)) {
continue;
}
$count = 0;
foreach ($blogs as $blog_id) {
switch_to_blog($blog_id);
if (is_plugin_active($file)) {
$count++;
}
restore_current_blog();
}
$usage_stats[$file] = [
'name' => $p['Name'],
'active_sites' => $count
];
}
return $usage_stats;
}
public function ajax_save_settings() {
check_ajax_referer('multisite_plugin_control_nonce', '_ajax_nonce') || wp_send_json_error(__('Invalid nonce.', 'multisite-plugin-control'));
if (!current_user_can('manage_network_options')) wp_send_json_error(__('Permission denied.', 'multisite-plugin-control'));
$settings = isset($_POST['settings']['control']) ? (array)$_POST['settings']['control'] : [];
$supporter_control = [];
$user_control = [];
$auto_activate = [];
foreach ($settings as $plugin => $value) {
switch ($value) {
case 'supporters':
$supporter_control[] = sanitize_text_field($plugin);
break;
case 'all':
$user_control[] = sanitize_text_field($plugin);
break;
case 'auto':
$auto_activate[] = sanitize_text_field($plugin);
break;
}
}
update_site_option('mpc_supporter_control_list', $supporter_control ?: 'EMPTY');
update_site_option('mpc_user_control_list', $user_control ?: 'EMPTY');
update_site_option('mpc_auto_activate_list', $auto_activate ?: 'EMPTY');
wp_send_json_success(['message' => __('Settings saved successfully!', 'multisite-plugin-control')]);
}
public function ajax_mass_activate() {
check_ajax_referer('multisite_plugin_control_nonce', '_ajax_nonce') || wp_send_json_error(__('Invalid nonce.', 'multisite-plugin-control'));
if (!current_user_can('manage_network_options')) wp_send_json_error(__('Permission denied.', 'multisite-plugin-control'));
$plugin = sanitize_text_field($_POST['plugin']);
$this->mass_activate($plugin);
wp_send_json_success(['message' => sprintf(__('%s has been mass activated.', 'multisite-plugin-control'), $plugin)]);
}
public function ajax_mass_deactivate() {
check_ajax_referer('multisite_plugin_control_nonce', '_ajax_nonce') || wp_send_json_error(__('Invalid nonce.', 'multisite-plugin-control'));
if (!current_user_can('manage_network_options')) wp_send_json_error(__('Permission denied.', 'multisite-plugin-control'));
$plugin = sanitize_text_field($_POST['plugin']);
$this->mass_deactivate($plugin);
wp_send_json_success(['message' => sprintf(__('%s has been mass deactivated.', 'multisite-plugin-control'), $plugin)]);
}
public function mass_activate($plugin) {
global $wpdb;
if (wp_is_large_network()) {
add_settings_error('mpc_messages', 'mass_activate_fail', __('Network too large for mass activation.', 'multisite-plugin-control'), 'error');
return false;
}
set_time_limit(120);
$blogs = $wpdb->get_col($wpdb->prepare("SELECT blog_id FROM {$wpdb->blogs} WHERE site_id = %d AND spam = 0", $wpdb->siteid));
$count = 0;
if ($blogs) {
foreach ($blogs as $blog_id) {
switch_to_blog($blog_id);
if (!is_plugin_active($plugin)) {
activate_plugin($plugin, '', false);
$count++;
}
restore_current_blog();
}
$this->update_stats('activate', count($blogs), $count);
add_settings_error('mpc_messages', 'mass_activate_success', sprintf(__('%s activated on %d sites.', 'multisite-plugin-control'), esc_html($plugin), $count), 'success');
} else {
add_settings_error('mpc_messages', 'mass_activate_fail', __('Failed to select blogs.', 'multisite-plugin-control'), 'error');
}
}
public function mass_deactivate($plugin) {
global $wpdb;
if (wp_is_large_network()) {
add_settings_error('mpc_messages', 'mass_deactivate_fail', __('Network too large for mass deactivation.', 'multisite-plugin-control'), 'error');
return false;
}
set_time_limit(120);
$blogs = $wpdb->get_col($wpdb->prepare("SELECT blog_id FROM {$wpdb->blogs} WHERE site_id = %d AND spam = 0", $wpdb->siteid));
$count = 0;
if ($blogs) {
foreach ($blogs as $blog_id) {
switch_to_blog($blog_id);
if (is_plugin_active($plugin)) {
deactivate_plugins($plugin, true);
$count++;
}
restore_current_blog();
}
$this->update_stats('deactivate', count($blogs), $count);
add_settings_error('mpc_messages', 'mass_deactivate_success', sprintf(__('%s deactivated on %d sites.', 'multisite-plugin-control'), esc_html($plugin), $count), 'success');
} else {
add_settings_error('mpc_messages', 'mass_deactivate_fail', __('Failed to select blogs.', 'multisite-plugin-control'), 'error');
}
}
private function update_stats($action, $total_sites, $changed) {
$this->stats['total_sites'] = $total_sites;
if ($action === 'activate') {
$this->stats['total_activations'] += $changed;
} else {
$this->stats['total_deactivations'] += $changed;
}
$this->stats['last_action_time'] = current_time('mysql');
update_site_option('mpc_stats', $this->stats);
}
public function new_blog($blog_id) {
require_once(ABSPATH . 'wp-admin/includes/plugin.php');
$auto_activate = (array) get_site_option('mpc_auto_activate_list', []);
if ($auto_activate && $auto_activate[0] !== 'EMPTY') {
switch_to_blog($blog_id);
activate_plugins($auto_activate, '', false);
restore_current_blog();
}
}
public function remove_plugins($all_plugins) {
if (is_super_admin()) return $all_plugins;
$auto_activate = (array) get_site_option('mpc_auto_activate_list', []);
$user_control = (array) get_site_option('mpc_user_control_list', []);
$supporter_control = (array) get_site_option('mpc_supporter_control_list', []);
$override_plugins = (array) get_option('mpc_plugin_override_list', []);
foreach ($all_plugins as $plugin_file => $plugin_data) {
if (!in_array($plugin_file, $user_control) && !in_array($plugin_file, $auto_activate) && !in_array($plugin_file, $supporter_control) && !in_array($plugin_file, $override_plugins)) {
unset($all_plugins[$plugin_file]);
}
}
return $all_plugins;
}
public function action_links($action_links, $plugin_file, $plugin_data, $context) {
global $psts, $blog_id;
if (is_network_admin() || is_super_admin()) return $action_links;
$auto_activate = (array) get_site_option('mpc_auto_activate_list', []);
$user_control = (array) get_site_option('mpc_user_control_list', []);
$supporter_control = (array) get_site_option('mpc_supporter_control_list', []);
$override_plugins = (array) get_option('mpc_plugin_override_list', []);
if ($context !== 'active') {
if (in_array($plugin_file, $user_control) || in_array($plugin_file, $auto_activate) || in_array($plugin_file, $override_plugins)) {
return $action_links;
} elseif (in_array($plugin_file, $supporter_control) && function_exists('is_pro_site')) {
return is_pro_site() ? $action_links : ['' . __('Pro Sites Only', 'multisite-plugin-control') . ''];
}
}
return $action_links;
}
public function supporter_message() {
global $pagenow;
if (is_super_admin() || $pagenow !== 'plugins.php' || !function_exists('is_pro_site')) return;
if (!is_pro_site()) {
if (function_exists('supporter_feature_notice')) {
supporter_feature_notice();
}
} else {
echo '' . sprintf(__('As a %s Pro Site, you now have access to all our premium plugins!', 'multisite-plugin-control'), get_site_option('site_name')) . '
';
}
}
public function remove_plugin_meta($plugin_meta, $plugin_file) {
if (is_network_admin() || is_super_admin()) return $plugin_meta;
remove_all_actions("after_plugin_row_$plugin_file");
return [];
}
public function remove_plugin_update_row() {
if (!is_network_admin() && !is_super_admin()) {
remove_all_actions('after_plugin_row');
}
}
public function blog_options_form($blog_id) {
$plugins = get_plugins();
$override_plugins = (array) get_blog_option($blog_id, 'mpc_plugin_override_list', []);
?>
$value) {
$override_plugins[] = sanitize_text_field($plugin);
}
}
update_option('mpc_plugin_override_list', $override_plugins);
}
}
new MultisitePluginControl();