<?php
/**
* Plugin Name: WPMU Storage Quota Monitor
* Plugin URI: https://example.com/
* Description: Emails the network administrator when a site in a Multisite network approaches its upload storage quota.
* Version: 1.0
* Author: Your Name
* Author URI: https://example.com/
* License: GPL2
*/
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class WPMU_Storage_Quota_Monitor {
private $threshold_percentage = 80; // Email when usage reaches 80% of the quota
private $email_interval_hours = 24; // Only send email once every 24 hours per site
private $option_name_last_notified = 'wpmu_sqm_last_notified';
public function __construct() {
if ( is_multisite() ) {
add_action( 'admin_init', array( $this, 'schedule_quota_check' ) );
add_action( 'wpmu_storage_quota_check', array( $this, 'check_all_site_quotas' ) );
add_action( 'admin_menu', array( $this, 'add_settings_page' ) );
add_action( 'admin_init', array( $this, 'register_settings' ) );
}
}
/**
* Schedules the daily quota check.
*/
public function schedule_quota_check() {
if ( ! wp_next_scheduled( 'wpmu_storage_quota_check' ) ) {
wp_schedule_event( time(), 'daily', 'wpmu_storage_quota_check' );
}
}
/**
* Unschedule the event on plugin deactivation.
*/
public static function unschedule_quota_check_on_deactivation() {
wp_clear_scheduled_hook( 'wpmu_storage_quota_check' );
}
/**
* Checks the upload quota for all sites in the network.
*/
public function check_all_site_quotas() {
// Get the threshold percentage from settings, fallback to default.
$this->threshold_percentage = get_site_option( 'wpmu_sqm_threshold_percentage', 80 );
$this->email_interval_hours = get_site_option( 'wpmu_sqm_email_interval_hours', 24 );
$sites = get_sites( array( 'fields' => 'ids', 'limit' => -1 ) );
foreach ( $sites as $site_id ) {
$this->check_single_site_quota( $site_id );
}
}
/**
* Checks the upload quota for a single site and sends an email if near limit.
*
* @param int $site_id The ID of the site to check.
*/
private function check_single_site_quota( $site_id ) {
switch_to_blog( $site_id );
$quota_bytes = get_option( 'blog_upload_space' ); // Quota in MB, convert to bytes.
if ( empty( $quota_bytes ) || $quota_bytes == 0 ) {
restore_current_blog();
return; // No quota set for this site, or quota is unlimited.
}
$quota_bytes *= MB_IN_BYTES; // Convert MB to bytes.
$used_bytes = get_option( 'blog_upload_space_used' ); // Used space in MB, convert to bytes.
$used_bytes *= MB_IN_BYTES; // Convert MB to bytes.
if ( $quota_bytes <= 0 ) { // Ensure quota is positive to avoid division by zero.
restore_current_blog();
return;
}
$percentage_used = ( $used_bytes / $quota_bytes ) * 100;
if ( $percentage_used >= $this->threshold_percentage ) {
$this->send_quota_notification_email( $site_id, $used_bytes, $quota_bytes, $percentage_used );
}
restore_current_blog();
}
/**
* Sends an email notification if the site is near its quota and not recently notified.
*
* @param int $site_id The ID of the site.
* @param int $used_bytes The amount of storage used in bytes.
* @param int $quota_bytes The total quota in bytes.
* @param float $percentage_used The percentage of quota used.
*/
private function send_quota_notification_email( $site_id, $used_bytes, $quota_bytes, $percentage_used ) {
$last_notified = get_site_option( $this->option_name_last_notified . '_' . $site_id );
$current_time = time();
// Check if enough time has passed since the last notification for this site.
if ( $last_notified && ( $current_time - $last_notified ) < ( $this->email_interval_hours * HOUR_IN_SECONDS ) ) {
return; // Too soon to send another email for this site.
}
$network_admin_email = get_site_option( 'admin_email' ); // Get the network admin email.
if ( ! $network_admin_email ) {
return; // No network admin email set.
}
$site_name = get_blog_details( $site_id )->blogname;
$site_url = get_blog_details( $site_id )->siteurl;
$subject = sprintf( __( 'Storage Quota Alert for %s', 'wpmu-storage-quota-monitor' ), $site_name );
$message = sprintf(
__( "Hello Network Administrator,\n\n" .
"The site '%1\$s' (%2\$s) is nearing its upload storage quota.\n\n" .
"Current Usage: %3\$s MB (%.2f%% of quota)\n" .
"Total Quota: %4\$s MB\n\n" .
"Please consider increasing the site's upload space or advising the site administrator to reduce file usage.\n\n" .
"This is an automated notification.",
'wpmu-storage-quota-monitor' ),
$site_name,
$site_url,
round( $used_bytes / MB_IN_BYTES, 2 ),
$percentage_used,
round( $quota_bytes / MB_IN_BYTES, 2 )
);
$headers = array( 'Content-Type: text/plain; charset=UTF-8' );
// Send the email.
if ( wp_mail( $network_admin_email, $subject, $message, $headers ) ) {
// Update the last notified timestamp for this site.
update_site_option( $this->option_name_last_notified . '_' . $site_id, $current_time );
}
}
/**
* Adds the settings page to the Network Admin menu.
*/
public function add_settings_page() {
add_submenu_page(
'settings.php', // Parent slug for Network Settings.
__( 'Storage Quota Monitor Settings', 'wpmu-storage-quota-monitor' ),
__( 'Quota Monitor', 'wpmu-storage-quota-monitor' ),
'manage_network_options', // Capability required to access.
'wpmu-storage-quota-monitor-settings',
array( $this, 'settings_page_content' )
);
}
/**
* Registers plugin settings.
*/
public function register_settings() {
add_action( 'network_admin_edit_wpmu_storage_quota_monitor_settings', array( $this, 'save_settings' ) );
add_settings_section(
'wpmu_sqm_general_settings',
__( 'General Settings', 'wpmu-storage-quota-monitor' ),
null,
'wpmu-storage-quota-monitor-settings'
);
add_settings_field(
'wpmu_sqm_threshold_percentage',
__( 'Notification Threshold (%)', 'wpmu-storage-quota-monitor' ),
array( $this, 'threshold_percentage_callback' ),
'wpmu-storage-quota-monitor-settings',
'wpmu_sqm_general_settings'
);
add_settings_field(
'wpmu_sqm_email_interval_hours',
__( 'Email Notification Interval (hours)', 'wpmu-storage-quota-monitor' ),
array( $this, 'email_interval_hours_callback' ),
'wpmu-storage-quota-monitor-settings',
'wpmu_sqm_general_settings'
);
}
/**
* Callback for the threshold percentage setting field.
*/
public function threshold_percentage_callback() {
$threshold = get_site_option( 'wpmu_sqm_threshold_percentage', 80 );
echo '<input type="number" name="wpmu_sqm_threshold_percentage" min="1" max="100" value="' . esc_attr( $threshold ) . '"/>';
echo '<p class="description">' . __( 'Send an email notification when a site\'s upload space usage reaches this percentage of its quota.', 'wpmu-storage-quota-monitor' ) . '</p>';
}
/**
* Callback for the email interval hours setting field.
*/
public function email_interval_hours_callback() {
$interval = get_site_option( 'wpmu_sqm_email_interval_hours', 24 );
echo '<input type="number" name="wpmu_sqm_email_interval_hours" min="1" value="' . esc_attr( $interval ) . '"/>';
echo '<p class="description">' . __( 'How often (in hours) to send email notifications for the same site if it remains above the threshold. Set to 0 for every check.', 'wpmu-storage-quota-monitor' ) . '</p>';
}
/**
* Saves the plugin settings.
*/
public function save_settings() {
if ( ! current_user_can( 'manage_network_options' ) ) {
wp_die( __( 'You do not have sufficient permissions to access this page.', 'wpmu-storage-quota-monitor' ) );
}
check_admin_referer( 'wpmu-storage-quota-monitor-settings-options' ); // Verify nonce.
$threshold = isset( $_POST['wpmu_sqm_threshold_percentage'] ) ? intval( $_POST['wpmu_sqm_threshold_percentage'] ) : 80;
$interval = isset( $_POST['wpmu_sqm_email_interval_hours'] ) ? intval( $_POST['wpmu_sqm_email_interval_hours'] ) : 24;
update_site_option( 'wpmu_sqm_threshold_percentage', max( 1, min( 100, $threshold ) ) );
update_site_option( 'wpmu_sqm_email_interval_hours', max( 0, $interval ) );
wp_redirect( add_query_arg( array( 'page' => 'wpmu-storage-quota-monitor-settings', 'updated' => 'true' ), network_admin_url( 'settings.php' ) ) );
exit();
}
/**
* Displays the settings page content.
*/
public function settings_page_content() {
?>
<div class="wrap">
<h1><?php _e( 'WPMU Storage Quota Monitor Settings', 'wpmu-storage-quota-monitor' ); ?></h1>
<form method="post" action="<?php echo esc_url( network_admin_url( 'edit.php?action=wpmu_storage_quota_monitor_settings' ) ); ?>">
<?php
settings_fields( 'wpmu-storage-quota-monitor-settings-options' ); // Nonce for the settings page.
do_settings_sections( 'wpmu-storage-quota-monitor-settings' );
submit_button();
?>
</form>
</div>
<?php
}
}
// Initialize the plugin.
$wpmu_storage_quota_monitor = new WPMU_Storage_Quota_Monitor();
// Register deactivation hook.
register_deactivation_hook( __FILE__, array( 'WPMU_Storage_Quota_Monitor', 'unschedule_quota_check_on_deactivation' ) );