mirror of
https://github.com/WPMultisite/multisite-plugin-control.git
synced 2025-08-03 05:33:22 +08:00
Updated the plugin version to 1.9.2 and changed the minimum required WordPress version to 5.9 in the plugin header.
742 lines
No EOL
38 KiB
PHP
742 lines
No EOL
38 KiB
PHP
<?php
|
|
/*
|
|
* Plugin Name: Multisite Plugin Control
|
|
* Plugin URI: https://wpmultisite.com/plugins/multisite-plugin-control
|
|
* Description: Manage plugin access permissions across your entire WordPress multisite network with enhanced UI and statistics.
|
|
* Version: 1.9.2
|
|
* Author: WPMultisite.com
|
|
* Author URI: https://wpmultisite.com
|
|
* Network: true
|
|
* Requires at least: 5.9
|
|
* License: GPL v2 or later
|
|
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
|
* Text Domain: multisite-plugin-control
|
|
* Domain Path: /languages
|
|
*/
|
|
|
|
if (!defined('WPINC')) {
|
|
die;
|
|
}
|
|
|
|
define('MULTISITE_PLUGIN_CONTROL_VERSION', '1.9.2');
|
|
define('MULTISITE_PLUGIN_CONTROL_PATH', plugin_dir_path(__FILE__));
|
|
define('MULTISITE_PLUGIN_CONTROL_URL', plugin_dir_url(__FILE__));
|
|
|
|
|
|
require_once plugin_dir_path(__FILE__) . 'class-plugin-report.php';
|
|
|
|
class MultisitePluginControl {
|
|
private $stats;
|
|
private $plugin_report;
|
|
|
|
public function __construct() {
|
|
$this->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';
|
|
?>
|
|
<div class="wrap">
|
|
<h1><?php echo esc_html__('Multisite Plugin Control', 'multisite-plugin-control'); ?>
|
|
<span style="font-size: 13px; padding-left: 10px;"><?php printf(esc_html__('Version: %s', 'multisite-plugin-control'), esc_html(MULTISITE_PLUGIN_CONTROL_VERSION)); ?></span>
|
|
<a href="https://wpmultisite.com/document/multisite-plugin-control" target="_blank" class="button button-secondary" style="margin-left: 10px;"><?php esc_html_e('Document', 'multisite-plugin-control'); ?></a>
|
|
<a href="https://wpmultisite.com/forums/" target="_blank" class="button button-secondary"><?php esc_html_e('Support', 'multisite-plugin-control'); ?></a>
|
|
</h1>
|
|
<div class="card">
|
|
<h2><?php _e('Plugin Dashboard', 'multisite-plugin-control'); ?></h2>
|
|
<span id="save-status" class="notice" style="display:none; margin-top: 10px;"></span>
|
|
<p><?php _e('Manage plugin access permissions across your multisite network.', 'multisite-plugin-control'); ?></p>
|
|
|
|
<div class="styles-sync-tabs">
|
|
<button type="button" class="styles-tab <?php echo $active_tab === 'management' ? 'active' : ''; ?>" data-tab="management"><?php _e('Plugin Management', 'multisite-plugin-control'); ?></button>
|
|
<button type="button" class="styles-tab <?php echo $active_tab === 'usage' ? 'active' : ''; ?>" data-tab="usage"><?php _e('Plugin Usage', 'multisite-plugin-control'); ?></button>
|
|
<button type="button" class="styles-tab <?php echo $active_tab === 'report' ? 'active' : ''; ?>" data-tab="report"><?php _e('Plugin Report', 'multisite-plugin-control'); ?></button>
|
|
<button type="button" class="styles-tab <?php echo $active_tab === 'help' ? 'active' : ''; ?>" data-tab="help"><?php _e('Help', 'multisite-plugin-control'); ?></button>
|
|
</div>
|
|
|
|
<div class="styles-sync-content">
|
|
<div class="tab-section" data-section="management" style="<?php echo $active_tab !== 'management' ? 'display: none;' : ''; ?>">
|
|
<div style="margin-bottom: 20px;">
|
|
<input type="text" id="plugin-search" placeholder="<?php _e('Search plugins by name...', 'multisite-plugin-control'); ?>" style="width: 300px;">
|
|
<select id="plugin-filter" style="margin-left: 10px;">
|
|
<option value="all"><?php _e('All Statuses', 'multisite-plugin-control'); ?></option>
|
|
<option value="none"><?php _e('None', 'multisite-plugin-control'); ?></option>
|
|
<option value="all"><?php _e('All Users', 'multisite-plugin-control'); ?></option>
|
|
<option value="auto"><?php _e('Auto-Activate', 'multisite-plugin-control'); ?></option>
|
|
<?php if (function_exists('is_pro_site')): ?>
|
|
<option value="supporters"><?php _e('Pro Sites', 'multisite-plugin-control'); ?></option>
|
|
<?php endif; ?>
|
|
</select>
|
|
</div>
|
|
|
|
<form id="plugin-control-form" method="post">
|
|
<?php wp_nonce_field('multisite_plugin_control_nonce', 'control_nonce'); ?>
|
|
<table class="wp-list-table widefat fixed striped">
|
|
<thead>
|
|
<tr>
|
|
<th><input type="checkbox" id="select-all-plugins"></th>
|
|
<th><?php _e('Name', 'multisite-plugin-control'); ?></th>
|
|
<th><?php _e('Version', 'multisite-plugin-control'); ?></th>
|
|
<th><?php _e('Author', 'multisite-plugin-control'); ?></th>
|
|
<th><?php _e('User Control', 'multisite-plugin-control'); ?></th>
|
|
<th><?php _e('Mass Activate', 'multisite-plugin-control'); ?></th>
|
|
<th><?php _e('Mass Deactivate', 'multisite-plugin-control'); ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php
|
|
$plugins = get_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', []);
|
|
|
|
foreach ($plugins as $file => $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';
|
|
?>
|
|
<tr data-status="<?php echo esc_attr($selected); ?>">
|
|
<td><input type="checkbox" name="selected_plugins[]" value="<?php echo esc_attr($file); ?>" class="plugin-checkbox"></td>
|
|
<td><?php echo esc_html($p['Name']); ?></td>
|
|
<td><?php echo esc_html($p['Version']); ?></td>
|
|
<td><?php echo wp_kses_post($p['Author']); ?></td>
|
|
<td>
|
|
<select name="control[<?php echo esc_attr($file); ?>]" class="control-select">
|
|
<?php
|
|
$options = [
|
|
'none' => __('None', 'multisite-plugin-control'),
|
|
'all' => __('All Users', 'multisite-plugin-control'),
|
|
'auto' => __('Auto-Activate (All Users)', 'multisite-plugin-control'),
|
|
];
|
|
if (function_exists('is_pro_site')) {
|
|
$options['supporters'] = __('Pro Sites', 'multisite-plugin-control');
|
|
}
|
|
foreach ($options as $value => $label) {
|
|
$is_selected = ($selected === $value) ? ' selected="selected"' : '';
|
|
echo '<option value="' . esc_attr($value) . '"' . $is_selected . '>' . esc_html($label) . '</option>';
|
|
}
|
|
?>
|
|
</select>
|
|
</td>
|
|
<td>
|
|
<button type="button" class="button mass-activate" data-plugin="<?php echo esc_attr($file); ?>">
|
|
<?php _e('Activate All', 'multisite-plugin-control'); ?>
|
|
</button>
|
|
</td>
|
|
<td>
|
|
<button type="button" class="button mass-deactivate" data-plugin="<?php echo esc_attr($file); ?>">
|
|
<?php _e('Deactivate All', 'multisite-plugin-control'); ?>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
<?php
|
|
}
|
|
?>
|
|
</tbody>
|
|
</table>
|
|
<p class="submit">
|
|
<select id="bulk-action" style="margin-right: 10px;">
|
|
<option value=""><?php _e('Bulk Actions', 'multisite-plugin-control'); ?></option>
|
|
<option value="set-none"><?php _e('Set to None', 'multisite-plugin-control'); ?></option>
|
|
<option value="set-all"><?php _e('Set to All Users', 'multisite-plugin-control'); ?></option>
|
|
<option value="set-auto"><?php _e('Set to Auto-Activate', 'multisite-plugin-control'); ?></option>
|
|
<?php if (function_exists('is_pro_site')): ?>
|
|
<option value="set-supporters"><?php _e('Set to Pro Sites', 'multisite-plugin-control'); ?></option>
|
|
<?php endif; ?>
|
|
</select>
|
|
<button type="button" id="apply-bulk" class="button"><?php _e('Apply', 'multisite-plugin-control'); ?></button>
|
|
<button type="button" id="save-settings" class="button button-primary"><?php _e('Save Settings', 'multisite-plugin-control'); ?></button>
|
|
</p>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="tab-section" data-section="usage" style="<?php echo $active_tab !== 'usage' ? 'display: none;' : ''; ?>">
|
|
<p><?php _e('View plugin usage across the network.', 'multisite-plugin-control'); ?></p>
|
|
<?php
|
|
$usage_stats = $this->get_plugin_usage_stats();
|
|
if (isset($usage_stats['error'])) {
|
|
echo '<p class="description">' . esc_html($usage_stats['error']) . '</p>';
|
|
} else {
|
|
?>
|
|
<table class="wp-list-table widefat fixed striped">
|
|
<thead>
|
|
<tr>
|
|
<th><?php _e('Plugin Name', 'multisite-plugin-control'); ?></th>
|
|
<th><?php _e('Active Sites', 'multisite-plugin-control'); ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($usage_stats as $stats): ?>
|
|
<tr>
|
|
<td><?php echo esc_html($stats['name']); ?></td>
|
|
<td><?php echo esc_html($stats['active_sites']); ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
<?php
|
|
}
|
|
?>
|
|
</div>
|
|
|
|
<div class="tab-section" data-section="report" style="<?php echo $active_tab !== 'report' ? 'display: none;' : ''; ?>">
|
|
<?php $this->plugin_report->render_report(); ?>
|
|
</div>
|
|
|
|
<div class="tab-section" data-section="help" style="<?php echo $active_tab !== 'help' ? 'display: none;' : ''; ?>">
|
|
<p><strong><?php _e('Auto Activation', 'multisite-plugin-control'); ?></strong><br>
|
|
<?php _e('When enabled, new blogs will have the plugin activated automatically.', 'multisite-plugin-control'); ?></p>
|
|
<p><strong><?php _e('User Control', 'multisite-plugin-control'); ?></strong><br>
|
|
<?php
|
|
if (function_exists('is_pro_site')) {
|
|
_e('Choose who can activate/deactivate plugins: all users, Pro Sites only, or none.', 'multisite-plugin-control');
|
|
} else {
|
|
_e('Enable to allow all users to activate/deactivate plugins.', 'multisite-plugin-control');
|
|
}
|
|
?></p>
|
|
<p><strong><?php _e('Mass Activation/Deactivation', 'multisite-plugin-control'); ?></strong><br>
|
|
<?php _e('Activate or deactivate plugins across all existing blogs.', 'multisite-plugin-control'); ?></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h2><?php _e('Statistics', 'multisite-plugin-control'); ?></h2>
|
|
<p><?php _e('View plugin control activity across the network.', 'multisite-plugin-control'); ?></p>
|
|
<table class="wp-list-table widefat fixed">
|
|
<thead>
|
|
<tr>
|
|
<th><?php _e('Metric', 'multisite-plugin-control'); ?></th>
|
|
<th><?php _e('Value', 'multisite-plugin-control'); ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<th><?php _e('Total Sites', 'multisite-plugin-control'); ?></th>
|
|
<td><?php echo esc_html($this->stats['total_sites']); ?></td>
|
|
</tr>
|
|
<tr>
|
|
<th><?php _e('Total Activations', 'multisite-plugin-control'); ?></th>
|
|
<td><?php echo esc_html($this->stats['total_activations']); ?></td>
|
|
</tr>
|
|
<tr>
|
|
<th><?php _e('Total Deactivations', 'multisite-plugin-control'); ?></th>
|
|
<td><?php echo esc_html($this->stats['total_deactivations']); ?></td>
|
|
</tr>
|
|
<tr>
|
|
<th><?php _e('Last Action Time', 'multisite-plugin-control'); ?></th>
|
|
<td><?php echo esc_html($this->stats['last_action_time'] ?: __('Never', 'multisite-plugin-control')); ?></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<script type="text/javascript">
|
|
jQuery(document).ready(function($) {
|
|
$('.styles-tab').on('click', function() {
|
|
var tab = $(this).data('tab');
|
|
window.history.pushState({}, document.title, '<?php echo admin_url('network/plugins.php?page=multisite-plugin-control'); ?>&tab=' + tab);
|
|
$('.styles-tab').removeClass('active');
|
|
$(this).addClass('active');
|
|
$('.tab-section').hide();
|
|
$('.tab-section[data-section="' + tab + '"]').show();
|
|
});
|
|
|
|
function filterPlugins() {
|
|
var search = $('#plugin-search').val().toLowerCase();
|
|
var filter = $('#plugin-filter').val();
|
|
$('.wp-list-table tbody tr').each(function() {
|
|
var name = $(this).find('td:eq(1)').text().toLowerCase();
|
|
var status = $(this).data('status');
|
|
var matchesSearch = search === '' || name.includes(search);
|
|
var matchesFilter = filter === 'all' || status === filter;
|
|
$(this).toggle(matchesSearch && matchesFilter);
|
|
});
|
|
}
|
|
$('#plugin-search').on('input', filterPlugins);
|
|
$('#plugin-filter').on('change', filterPlugins);
|
|
|
|
$('#select-all-plugins').on('change', function() {
|
|
$('.plugin-checkbox').prop('checked', $(this).prop('checked'));
|
|
});
|
|
|
|
$('#apply-bulk').on('click', function() {
|
|
var action = $('#bulk-action').val();
|
|
if (!action) return;
|
|
var selected = $('.plugin-checkbox:checked');
|
|
if (selected.length === 0) {
|
|
alert('<?php _e('Please select at least one plugin.', 'multisite-plugin-control'); ?>');
|
|
return;
|
|
}
|
|
selected.each(function() {
|
|
var plugin = $(this).val();
|
|
$('select[name="control[' + plugin + ']"]').val(action.replace('set-', ''));
|
|
});
|
|
});
|
|
|
|
$('#save-settings').on('click', function() {
|
|
var $button = $(this);
|
|
var formData = $('#plugin-control-form').serializeArray();
|
|
var settings = { control: {}, nonce: '' };
|
|
|
|
formData.forEach(function(item) {
|
|
if (item.name.startsWith('control[')) {
|
|
var plugin = item.name.replace('control[', '').replace(']', '');
|
|
settings.control[plugin] = item.value;
|
|
} else if (item.name === 'control_nonce') {
|
|
settings.nonce = item.value;
|
|
}
|
|
});
|
|
|
|
$button.prop('disabled', true);
|
|
$('#save-status').text('<?php _e('Saving...', 'multisite-plugin-control'); ?>').show();
|
|
|
|
$.ajax({
|
|
url: ajaxurl,
|
|
type: 'POST',
|
|
data: {
|
|
action: 'mpc_save_settings',
|
|
settings: settings,
|
|
_ajax_nonce: settings.nonce
|
|
},
|
|
success: function(response) {
|
|
if (response.success) {
|
|
$('#save-status')
|
|
.removeClass('notice-error')
|
|
.addClass('notice-success')
|
|
.text('<?php _e('Settings saved successfully!', 'multisite-plugin-control'); ?>')
|
|
.show()
|
|
.delay(3000)
|
|
.fadeOut();
|
|
$('.wp-list-table tbody tr').each(function() {
|
|
var plugin = $(this).find('.plugin-checkbox').val();
|
|
$(this).data('status', settings.control[plugin]);
|
|
});
|
|
} else {
|
|
$('#save-status')
|
|
.removeClass('notice-success')
|
|
.addClass('notice-error')
|
|
.text(response.data || '<?php _e('Failed to save settings.', 'multisite-plugin-control'); ?>')
|
|
.show();
|
|
}
|
|
$button.prop('disabled', false);
|
|
},
|
|
error: function() {
|
|
$('#save-status')
|
|
.removeClass('notice-success')
|
|
.addClass('notice-error')
|
|
.text('<?php _e('An error occurred while saving.', 'multisite-plugin-control'); ?>')
|
|
.show();
|
|
$button.prop('disabled', false);
|
|
}
|
|
});
|
|
});
|
|
|
|
$('.mass-activate, .mass-deactivate').on('click', function() {
|
|
var $button = $(this);
|
|
var plugin = $button.data('plugin');
|
|
var actionType = $button.hasClass('mass-activate') ? 'mass_activate' : 'mass_deactivate';
|
|
|
|
if (!confirm('<?php _e('Are you sure you want to '); ?>' + (actionType === 'mass_activate' ? '<?php _e('activate'); ?>' : '<?php _e('deactivate'); ?>') + ' <?php _e('this plugin across all sites?'); ?>')) {
|
|
return;
|
|
}
|
|
|
|
$button.prop('disabled', true);
|
|
$('#save-status').text('<?php _e('Processing...', 'multisite-plugin-control'); ?>').show();
|
|
|
|
$.ajax({
|
|
url: ajaxurl,
|
|
type: 'POST',
|
|
data: {
|
|
action: 'mpc_' + actionType,
|
|
plugin: plugin,
|
|
_ajax_nonce: '<?php echo wp_create_nonce('multisite_plugin_control_nonce'); ?>'
|
|
},
|
|
success: function(response) {
|
|
if (response.success) {
|
|
$('#save-status')
|
|
.removeClass('notice-error')
|
|
.addClass('notice-success')
|
|
.text(response.data.message)
|
|
.show()
|
|
.delay(3000)
|
|
.fadeOut();
|
|
} else {
|
|
$('#save-status')
|
|
.removeClass('notice-success')
|
|
.addClass('notice-error')
|
|
.text(response.data || '<?php _e('Operation failed.', 'multisite-plugin-control'); ?>')
|
|
.show();
|
|
}
|
|
$button.prop('disabled', false);
|
|
},
|
|
error: function() {
|
|
$('#save-status')
|
|
.removeClass('notice-success')
|
|
.addClass('notice-error')
|
|
.text('<?php _e('Server error occurred.', 'multisite-plugin-control'); ?>')
|
|
.show();
|
|
$button.prop('disabled', false);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
</script>
|
|
|
|
<style>
|
|
.card {
|
|
background: #fff;
|
|
border: 1px solid #ccd0d4;
|
|
border-radius: 4px;
|
|
max-width: unset;
|
|
margin-top: 20px;
|
|
padding: 20px;
|
|
}
|
|
.notice {
|
|
padding: 8px 12px;
|
|
border-radius: 3px;
|
|
}
|
|
.notice-success {
|
|
background-color: #dff0d8;
|
|
border-left: 4px solid #46b450;
|
|
}
|
|
.notice-error {
|
|
background-color: #f2dede;
|
|
border-left: 4px solid #dc3232;
|
|
}
|
|
.styles-sync-tabs {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 5px;
|
|
border-bottom: 1px solid #c3c4c7;
|
|
margin-bottom: 20px;
|
|
}
|
|
.styles-tab {
|
|
padding: 8px 16px;
|
|
border: none;
|
|
background: none;
|
|
cursor: pointer;
|
|
font-size: 14px;
|
|
border-bottom: 2px solid transparent;
|
|
}
|
|
.styles-tab.active {
|
|
border-bottom: 2px solid #007cba;
|
|
font-weight: 600;
|
|
background: #f0f0f1;
|
|
}
|
|
.styles-tab:hover:not(.active) {
|
|
background: #f0f0f1;
|
|
border-bottom-color: #dcdcde;
|
|
}
|
|
.styles-sync-content {
|
|
flex: 1;
|
|
}
|
|
table.fixed {
|
|
table-layout: auto;
|
|
}
|
|
</style>
|
|
<?php
|
|
}
|
|
|
|
private function get_plugin_usage_stats() {
|
|
global $wpdb;
|
|
$plugins = get_plugins();
|
|
$usage_stats = [];
|
|
|
|
if (wp_is_large_network()) {
|
|
return ['error' => __('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 : ['<a style="color:red;" href="' . esc_url($psts->checkout_url($blog_id)) . '">' . __('Pro Sites Only', 'multisite-plugin-control') . '</a>'];
|
|
}
|
|
}
|
|
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 '<div class="error" style="background-color:#F9F9F9;border:0;font-weight:bold;"><p>' . sprintf(__('As a %s Pro Site, you now have access to all our premium plugins!', 'multisite-plugin-control'), get_site_option('site_name')) . '</p></div>';
|
|
}
|
|
}
|
|
|
|
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', []);
|
|
?>
|
|
</table>
|
|
<h3><?php _e('Plugin Override Options', 'multisite-plugin-control'); ?></h3>
|
|
<p><?php _e('Checked plugins will override network settings for this site.', 'multisite-plugin-control'); ?></p>
|
|
<table class="widefat" style="margin:10px;width:95%;">
|
|
<thead>
|
|
<tr>
|
|
<th><?php _e('User Control', 'multisite-plugin-control'); ?></th>
|
|
<th><?php _e('Name', 'multisite-plugin-control'); ?></th>
|
|
<th><?php _e('Version', 'multisite-plugin-control'); ?></th>
|
|
<th><?php _e('Author', 'multisite-plugin-control'); ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php
|
|
foreach ($plugins as $file => $p) {
|
|
if (is_network_only_plugin($file) || is_plugin_active_for_network($file)) continue;
|
|
$checked = in_array($file, $override_plugins) ? 'checked="checked"' : '';
|
|
echo "<tr><td><label><input name='plugins[$file]' type='checkbox' value='1' $checked> " . __('Enable', 'multisite-plugin-control') . "</label></td><td>" . esc_html($p['Name']) . "</td><td>" . esc_html($p['Version']) . "</td><td>" . wp_kses_post($p['Author']) . "</td></tr>";
|
|
}
|
|
?>
|
|
</tbody>
|
|
</table>
|
|
<?php
|
|
}
|
|
|
|
public function blog_options_form_process() {
|
|
$override_plugins = [];
|
|
if (isset($_POST['plugins']) && is_array($_POST['plugins'])) {
|
|
foreach ($_POST['plugins'] as $plugin => $value) {
|
|
$override_plugins[] = sanitize_text_field($plugin);
|
|
}
|
|
}
|
|
update_option('mpc_plugin_override_list', $override_plugins);
|
|
}
|
|
}
|
|
|
|
new MultisitePluginControl();
|