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'; ?>

$p) { if (is_network_only_plugin($file) || is_plugin_active_for_network($file)) { continue; } $selected = 'none'; if (in_array($file, $user_control)) $selected = 'all'; elseif (in_array($file, $auto_activate)) $selected = 'auto'; elseif (in_array($file, $supporter_control)) $selected = 'supporters'; ?>

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', []); ?>

$p) { if (is_network_only_plugin($file) || is_plugin_active_for_network($file)) continue; $checked = in_array($file, $override_plugins) ? 'checked="checked"' : ''; echo ""; } ?>
" . esc_html($p['Name']) . "" . esc_html($p['Version']) . "" . wp_kses_post($p['Author']) . "
$value) { $override_plugins[] = sanitize_text_field($plugin); } } update_option('mpc_plugin_override_list', $override_plugins); } } new MultisitePluginControl();