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

Colloquium 11/01 – Pascal Spino, MIT – Computer Science

Colloquium 11/01 - Pascal Spino, MIT

Computer Science Colloquium
Friday 11/01
2:35pm in Wege Auditorium

 

Towards mobile underwater robots at the centimeter scale


Underwater robots are indispensable for many aquatic tasks including exploration, infrastructure inspection, and environmental monitoring. However, the underwater environment remains a challenging medium for robotic development. Most systems tend to be large and complex, making them unsuitable for confined spaces like shipwrecks and caves as well as prohibitively expensive to build and deploy. There is a growing need for smaller, lower-cost underwater robots to address these challenges. There is also a growing interest in the coordination of underwater robotic swarms at this scale to unlock entirely new capabilities. This work will discuss the mechanical and computational challenges for developing these systems, and present research being conducted at MIT’s Distributed Robotics Lab.

 

Pascal Spino is a third year PhD candidate in the Mechanical Engineering department at the Massachusetts Institute of Technology (MIT). He works with Daniela Rus within MIT’s Computer Science and Artificial Intelligence Laboratory (CSAIL) and his work focusses on distributed robotic systems. Pascal completed his bachelor’s degree in mechanical engineering with a minor in computer science at Washington State University in 2021. He is the recipient of MIT’s School of Engineering Distinguished Graduate Fellowship.