# plugin-memory-usage/trunk/plugin-memory-usage.php

Plugin Memory Usage, version trunk. 1,289 lines.

- Page: https://pluginprobe.com/plugins/plugin-memory-usage/trunk/code/plugin-memory-usage.php
- Raw: https://pluginprobe.com/plugins/plugin-memory-usage/trunk/raw/plugin-memory-usage.php
- Modified: 2026-05-25T13:49:00+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/plugin-memory-usage/trunk/code/plugin-memory-usage.php#L10-L20`.

```php
<?php
/*
Plugin Name: Plugin Memory Usage
Plugin URI: https://nett.pro/en/plugins/
Description: Display different plugins memory usage and impact on Wordpress.
Version: 1.3.0
Author: NETT.PRO
Author URI: https://nett.pro/en/
License: GPLv3
*/

// Prevent direct access to this file
if (!defined('ABSPATH')) {
    exit;
}

define('PLUGINMEMORYUSAGE_VERSION', '1.3.0');


function pmusage_memory_usage_admin_menu() {
    add_menu_page(
        'Plugin Memory Usage',
        'Memory Usage',
        'manage_options',
        'wp_plugin_memory_usage',
        'pmusage_memory_usage_admin_page',
        'dashicons-performance',
        100
    );
}
add_action('admin_menu', 'pmusage_memory_usage_admin_menu');




// Function to register the dashboard widget
function pmusage_memory_usage_widget() {

    wp_add_dashboard_widget(
        'wp_memory_usage',
        'Plugin Memory Usage <span class="wpmem-version">'.PLUGINMEMORYUSAGE_VERSION.'</span>',
        'pmusage_display_memory_usage_dashboard'
    );
}

// Hook to add the widget to the dashboard
add_action('wp_dashboard_setup', 'pmusage_memory_usage_widget', 1);







// Get supported PHP versions with caching
function pmusage_get_supported_php_versions() {
    $supported_versions = get_transient('pmusage_supported_php_versions');
    
    if (false === $supported_versions) {
        $response = wp_remote_get('https://www.php.net/supported-versions.php', array(
            'sslverify' => false,
            'timeout' => 5
        ));
        
        if (!is_wp_error($response) && 200 === wp_remote_retrieve_response_code($response)) {
            $html = wp_remote_retrieve_body($response);
            $supported_versions = pmusage_parse_supported_versions($html);
            set_transient('pmusage_supported_php_versions', $supported_versions, WEEK_IN_SECONDS);
        }
    }
    
    return is_array($supported_versions) ? $supported_versions : [];
}



// Parse HTML response from PHP.net
function pmusage_parse_supported_versions($html) {
    $versions = [];
    $dom = new DOMDocument();
    @$dom->loadHTML($html);
    $tables = $dom->getElementsByTagName('table');
    
    foreach ($tables as $table) {
        $rows = $table->getElementsByTagName('tr');
        foreach ($rows as $row) {
            $cells = $row->getElementsByTagName('td');
            if ($cells->length >= 5) {
                $version = trim($cells->item(0)->textContent);
                $eol_date = DateTime::createFromFormat('d M Y', trim($cells->item(3)->textContent));
                
                if ($eol_date) {
                    $versions[$version] = [
                        'eol' => $eol_date->format('Y-m-d'),
                        'status' => (new DateTime() < $eol_date) ? 'supported' : 'eol'
                    ];
                }
            }
        }
    }
    
    return $versions;
}






function pmusage_get_php_status($current_version) {
    $supported_versions = pmusage_get_supported_php_versions();
    $current_branch = preg_replace('/^(\d+\.\d+).*$/', '$1', $current_version);

    if ( isset($supported_versions[$current_branch]) && $supported_versions[$current_branch]['status'] === 'supported' ) {
        return 'supported';
    }
    return 'eol';
}





/**
 * Get latest WordPress version from WordPress.org API with extensive debugging
 */
function pmusage_get_latest_wp_version() {

    // Try to get from cache first
    $latest_version = get_transient('pmusage_latest_wp_version');
    
    if (false !== $latest_version) {
        return $latest_version;
    }
    
    
    // Use version 1.7 which returns JSON format
    $url = 'https://api.wordpress.org/core/version-check/1.7/';

    
    $response = wp_remote_get($url, array(
        'timeout' => 10,
        'sslverify' => true,
        'user-agent' => 'WordPress/' . get_bloginfo('version') . '; ' . get_bloginfo('url')
    ));
    
    // Check for errors
    if (is_wp_error($response)) {
        return 'Unknown';
    }
    
    $response_code = wp_remote_retrieve_response_code($response);
    
    if (200 !== $response_code) {
        return 'Unknown';
    }
    
    $body = wp_remote_retrieve_body($response);
    
    if (empty($body)) {
        return 'Unknown';
    }
    
    $data = json_decode($body, true);
    
    if (json_last_error() !== JSON_ERROR_NONE) {
        return 'Unknown';
    }

    
    if (isset($data['offers']) && is_array($data['offers']) && !empty($data['offers'])) {
        // Get the first offer which is the latest stable version
        $latest_version = $data['offers'][0]['version'] ?? 'Unknown';
    } else {
        return 'Unknown';
    }
    
    // Only cache if we got a valid version
    if ($latest_version !== 'Unknown' && preg_match('/^\d+\.\d+/', $latest_version)) {
        set_transient('pmusage_latest_wp_version', $latest_version, 12 * HOUR_IN_SECONDS);
    } 
    
    return $latest_version;
}








function pmusage_get_cpu_usage() {
    if ( ! function_exists('sys_getloadavg') ) {
        return null;
    }
    $load  = sys_getloadavg();
    $cores = 1;
    if ( is_readable('/proc/cpuinfo') ) {
        $cpuinfo = file_get_contents('/proc/cpuinfo');
        preg_match_all('/^processor/m', $cpuinfo, $matches);
        $cores = max(1, count($matches[0]));
    }
    return round(($load[0] / $cores) * 100, 1);
}

function pmusage_get_disk_usage() {

    $path = defined('ABSPATH') ? ABSPATH : '/';
    $total = @disk_total_space($path);
    $free  = @disk_free_space($path);
    if ( ! $total || ! $free ) {
        return null;
    }
    $used    = $total - $free;
    $percent = round(($used / $total) * 100, 1);
    return [
        'used'    => $used,
        'total'   => $total,
        'free'    => $free,
        'percent' => $percent,
    ];
    
}











// to be shown in several places
function pmusage_render_system_info() {
    global $wpdb;

    // Get PHP version and status
    $php_version = phpversion();
    $php_status = pmusage_get_php_status($php_version);

    // Dashicons for PHP version status
    $icons = [
        'supported' => '<span class="dashicons dashicons-yes-alt" style="color:#46b450; margin-left:5px;" title="PHP version is supported"></span>',
        'eol' => '<span class="dashicons dashicons-warning" style="color:#dc3232; margin-left:5px;" title="PHP version is end-of-life"></span>'
    ];

   

    // Fetch latest PHP version with error handling
    $latest_php_version = get_transient('pmusage_latest_php_version');
    if (false === $latest_php_version) {
        $response = wp_remote_get('https://www.php.net/releases/?json', array(
            'sslverify' => false,
            'timeout' => 5
        ));
        
        if (!is_wp_error($response) && 200 === wp_remote_retrieve_response_code($response)) {
            $data = json_decode(wp_remote_retrieve_body($response), true);
            if (is_array($data) && !empty($data)) {
                // Extract versions
                $versions = array();
                foreach ($data as $major_version => $release_info) {
                    if (isset($release_info['version'])) {
                        $versions[] = $release_info['version'];
                    }
                }
                
                usort($versions, 'version_compare');
                $latest_php_version = end($versions);
                set_transient('pmusage_latest_php_version', $latest_php_version, 12 * HOUR_IN_SECONDS);
            }
        }
    }

    // Validation
    if (empty($latest_php_version) || !preg_match('/^\d+\.\d+(\.\d+)?$/', $latest_php_version)) {
        $latest_php_version = 'Unknown';
    }


    $is_latest = ($latest_php_version !== 'Unknown') ? version_compare($php_version, $latest_php_version, '>=') : false;

 

    // Get MySQL version and status
    $mysql_version = wp_cache_get('pmusage_mysql_version');
    if (false === $mysql_version) {
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Getting MySQL version requires direct query, no WordPress alternative available
        $mysql_version = $wpdb->get_var("SELECT VERSION()");
        wp_cache_set('pmusage_mysql_version', $mysql_version, '', 12 * HOUR_IN_SECONDS);
    }

    $mysql_status = pmusage_get_mysql_status($mysql_version);
    $latest_mysql_version = pmusage_get_mysql_latest_version($mysql_version);

    // Enhanced icons for MySQL status with tooltips
    $mysql_icons = [
        'supported' => '<span class="dashicons dashicons-yes-alt" style="color: #46b450;" title="MySQL/MariaDB version is currently supported"></span>',
        'eol' => '<span class="dashicons dashicons-warning" style="color: #dc3232;" title="MySQL/MariaDB version has reached end-of-life - upgrade recommended"></span>',
        'innovation' => '<span class="dashicons dashicons-lightbulb" style="color: #ffb900;" title="MySQL Innovation Release - shorter support cycle"></span>',
    '   unknown' => '<span class="dashicons dashicons-editor-help" style="color: #666;" title="Unable to determine MySQL/MariaDB version support status"></span>'
    ];

    // Check if current version is latest
    $current_version_number = '';
    preg_match('/(\d+\.\d+\.\d+)/', $mysql_version, $matches);
    if (!empty($matches[1])) {
        $current_version_number = $matches[1];
    }
    $is_latest_mysql = ($latest_mysql_version !== 'Unknown' && !empty($current_version_number)) ? 
    version_compare($current_version_number, $latest_mysql_version, '>=') : false;




    // Get max upload size
    $max_upload = ini_get('upload_max_filesize');
    $max_post = ini_get('post_max_size');
    $memory_limit = ini_get('memory_limit');
    $upload_mb = min(
        wp_convert_hr_to_bytes($max_upload),
        wp_convert_hr_to_bytes($max_post),
        wp_convert_hr_to_bytes($memory_limit)
    );

    // Get WP and PHP memory limits
    $wp_memory_limit = wp_convert_hr_to_bytes(WP_MEMORY_LIMIT);
    $php_memory_limit = ini_get('memory_limit');






    // Get current and latest WordPress version
    $wp_version = get_bloginfo('version');


    $latest_wp_version = pmusage_get_latest_wp_version();


    // Check if current version is latest
    $is_wp_latest = ($latest_wp_version !== 'Unknown') ? version_compare($wp_version, $latest_wp_version, '>=') : null;


    // Display WordPress version with status
    echo '<p class="pluginmemoryusage-system-info-line"><strong>WordPress Version:</strong> ' . esc_html($wp_version);

    // Add badge if version is up to date
    if ($is_wp_latest === true) {
        echo ' <span class="dashicons dashicons-yes-alt" style="color: #46b450; margin-left: 5px;" title="WordPress is up to date"></span>';
    } elseif ($is_wp_latest === false) {
        echo ' <span class="dashicons dashicons-warning" style="color: #dc3232; margin-left: 5px;" title="WordPress update available"></span>';
    }

    // Show latest version info
    if ('Unknown' !== $latest_wp_version) {
        $label = $is_wp_latest ? 'Latest' : 'Latest: ' . esc_html($latest_wp_version);
        $class = $is_wp_latest ? 'pluginmemoryusage_version-latest' : 'pluginmemoryusage_version-outdated';
        echo ' <span class="' . esc_attr($class) . '">' . esc_html($label) . '</span>';
    } else {
        echo ' <span class="pluginmemoryusage_version-unknown">Version check failed</span>';
    }

    echo '</p>';








    echo '<p class="pluginmemoryusage-system-info-line"><strong>PHP Version:</strong> ' . esc_html($php_version);
    echo wp_kses_post($icons[$php_status]);
    if ('Unknown' !== $latest_php_version) {
        $label = $is_latest ? 'Latest' : 'Latest: ' . esc_html($latest_php_version);
        $class = $is_latest ? 'pluginmemoryusage_version-latest' : 'pluginmemoryusage_version-outdated';
        echo ' <span class="' . esc_attr($class) . '">' . esc_html($label) . '</span>';
    } else {
        echo ' <span class="php-version-outdated">(Version check failed)</span>';
    }
    echo '</p>';

    // Display MySQL version with status
    echo '<strong>MySQL Version:</strong> ' . esc_html($mysql_version) . ' ';
    echo wp_kses_post($mysql_icons[$mysql_status]);

    // Show latest version info (similar to PHP version display)
    if ('Unknown' !== $latest_mysql_version) {
        $label = $is_latest_mysql ? 'Latest' : 'Latest: ' . esc_html($latest_mysql_version);
        $class = $is_latest_mysql ? 'pluginmemoryusage_version-latest' : 'pluginmemoryusage_version-outdated';
        echo ' <span class="' . esc_attr($class) . '">' . esc_html($label) . '</span>';

    } else {
        echo ' <span class="pluginmemoryusage_version-unknown">(Version check failed)</span>';
    }

    echo '</p>';


    echo '<p class="pluginmemoryusage-system-info-line"><strong>Max Upload Size:</strong> ' . esc_html(size_format($upload_mb)) . '</p>';
    echo '<p class="pluginmemoryusage-system-info-line"><strong>WordPress Memory Limit:</strong> ' . esc_html(size_format($wp_memory_limit)) . '</p>';
    echo '<p class="pluginmemoryusage-system-info-line"><strong>PHP Memory Limit:</strong> ' . esc_html($php_memory_limit) . '</p>';
    

    // CPU Usage
    $cpu_usage = pmusage_get_cpu_usage();
    if ( $cpu_usage !== null ) {
        if ( $cpu_usage >= 90 )       $cpu_class = 'pmusage-bar-critical';
        elseif ( $cpu_usage >= 75 )   $cpu_class = 'pmusage-bar-warning';
        elseif ( $cpu_usage >= 50 )   $cpu_class = 'pmusage-bar-moderate';
        else                          $cpu_class = 'pmusage-bar-good';

        echo '<p class="pluginmemoryusage-system-info-line"><strong>CPU Load (1 min avg):</strong> ' . esc_html($cpu_usage) . '%</p>';
        echo '<div class="pmusage-mini-bar"><div class="pmusage-mini-bar-fill ' . esc_attr($cpu_class) . '" style="width:' . esc_attr(min($cpu_usage, 100)) . '%"></div></div>';
    } else {
        echo '<p class="pluginmemoryusage-system-info-line"><strong>CPU Load:</strong> <span class="pluginmemoryusage_version-unknown">Unavailable</span></p>';
    }

    // Disk Usage
    $disk = pmusage_get_disk_usage();
    if ( $disk !== null ) {
        if ( $disk['percent'] >= 90 )       $disk_class = 'pmusage-bar-critical';
        elseif ( $disk['percent'] >= 75 )   $disk_class = 'pmusage-bar-warning';
        elseif ( $disk['percent'] >= 50 )   $disk_class = 'pmusage-bar-moderate';
        else                                $disk_class = 'pmusage-bar-good';

        echo '<p class="pluginmemoryusage-system-info-line"><strong>Disk Usage:</strong> ' . esc_html(size_format($disk['used'])) . ' of ' . esc_html(size_format($disk['total'])) . ' (' . esc_html($disk['percent']) . '%)</p>';
        echo '<div class="pmusage-mini-bar"><div class="pmusage-mini-bar-fill ' . esc_attr($disk_class) . '" style="width:' . esc_attr($disk['percent']) . '%"></div></div>';
    } else {
        echo '<p class="pluginmemoryusage-system-info-line"><strong>Disk Usage:</strong> <span class="pluginmemoryusage_version-unknown">Unavailable</span></p>';
    }





}









// Function to display content in the dashboard widget 
function pmusage_display_memory_usage_dashboard() {
    global $wpdb;


    // Get WordPress memory limit
    $wp_memory_limit = wp_convert_hr_to_bytes(WP_MEMORY_LIMIT);
    
    // Get current memory usage
    $current_memory_usage = memory_get_usage(true);

    // Calculate percentage used
    $percentage_used = ($current_memory_usage / $wp_memory_limit) * 100;



    // Display the data - In seperate function for reusability
    pmusage_render_system_info();

    // Display memory usage
    echo '<p>Current Memory Usage: ';
    echo esc_html(size_format($current_memory_usage)) . ' of ' . esc_html(size_format($wp_memory_limit)) . '</p>';
    echo '<div style="width: 100%; background: #e0e0e0; height: 24px; border-radius: 10px; overflow: hidden;">
            <div style="width: ' . esc_html(round($percentage_used, 1)) . '%; background: #76c7c0; height: 100%; text-align: center; line-height: 24px;" class="memory-bar-fill">' . esc_html(round($percentage_used, 1)) . '%</div>
        </div>';

    // Message to increase memory limit if usage is high
    if ($current_memory_usage > $wp_memory_limit * 0.8) {
        echo 'You are using more than 80% of allocated memory. Please go to Memory Control Panel to try to increase memory limit ';
        echo '<p id="memory-increase-result"></p>';
    }


    // Add button to Plugin Memory Control Panel
    echo '<p><a href="' . esc_html(admin_url('admin.php?page=wp_plugin_memory_usage')) . '" class="button">Plugin Memory Control Panel</a></p>';
}










function pmusage_memory_usage_admin_page() {
    ?>
    <div class="wrap">
        <h1>Plugin Memory Usage - Control Panel</h1>
        
        <div class="card-container">
            <div class="card-row">
                <div class="card card-system-info">
                    <h2>System Information</h2>
                    <?php pmusage_render_system_info(); ?>
                </div>

                <div class="card card-memory-usage">
                    <h2>Current Memory Usage</h2>
                    <?php
                    $wp_memory_limit = wp_convert_hr_to_bytes(WP_MEMORY_LIMIT);
                    $current_memory_usage = memory_get_usage(true);
                    $percentage_used = ($current_memory_usage / $wp_memory_limit) * 100;
                    ?>
                    <p>Using <span id="current-memory"><?php echo esc_html(size_format($current_memory_usage)); ?></span> of <?php echo esc_html(size_format($wp_memory_limit)); ?></p>
                    <div class="memory-bar">
                        <div id="memory-bar-fill" class="memory-bar-fill" style="width: <?php echo esc_html(round($percentage_used, 1)); ?>%;">
                            <span id="memory-percentage"><?php echo esc_html(round($percentage_used, 1)); ?>%</span>
                        </div>
                    </div>

                    <br><button id="refresh-memory" class="button">Refresh Memory Usage</button>
                    <br><br>Memory fluctuate. Please press button once after entering panel.

                    <?php
                    if ($current_memory_usage > $wp_memory_limit * 0.8) {
                        echo '<p style="color:red;">You are using more than 80% of allocated memory. Please click button below to try to increase memory limit.</p> ';
                        echo '<p><button id="increase-memory-limit" class="button">Increase Memory Limit</button></p>';
                        echo '<p id="memory-increase-result"></p>';
                    }  ?>
                </div>

                <div class="card card-memory-history">
                    <h2>Memory Usage History</h2>
					
					<ul id="memory-history-list">
					
					
					<hr>
					<p>This plugin measures changes in WordPress memory usage as you activate and deactivate plugins. Here's how it works:</p>
					<ol>
						<li>It records the current memory usage of WordPress.</li>
						<li>When you activate or deactivate a plugin, it measures the memory usage again.</li>
						<li>The difference between these measurements gives an estimate of the plugin's memory impact.</li>
						<li>This process is repeated each time you toggle a plugin.</li>
					</ol>
					<p>Note: These measurements are estimates and may vary. Factors like caching, other active plugins, and WordPress itself can influence memory usage. For the most accurate results, consider testing in a controlled environment.</p>
					<p>To begin, try activating or deactivating plugins using the buttons provided. The memory usage history will appear here.</p>|
					
					
					
					</ul>
                </div>
            </div>

            <div class="card card-plugins">
                <h2>Plugins</h2>
                <?php
                $all_plugins = get_plugins();
                $active_plugins = get_option('active_plugins');





                echo '<ul class="plugin-list">';
                foreach ($all_plugins as $plugin_path => $plugin_data) {
    $is_active = in_array($plugin_path, $active_plugins);
    $plugin_id = sanitize_title($plugin_data['Name']);
    $is_memory_usage_plugin = (strpos($plugin_path, 'plugin-memory-usage') !== false);
    $li_class = $is_active ? 'plugin-active' : 'plugin-inactive';
    if ($is_memory_usage_plugin) {
        $li_class .= ' memory-usage-plugin';
    }
    $avg_memory = pmusage_get_average_memory_usage($plugin_path);
    
    echo '<li class="' . esc_attr($li_class) . '">';
    echo '<div class="plugin-info">';
    echo '<span class="plugin-name">' . esc_html($plugin_data['Name']) . ' <span class="avg-memory" title="The average memory usage represents the typical amount of memory consumed by this plugin over time.">(' . esc_html($avg_memory) . ' MB)</span></span>';
    echo '<div class="plugin-memory-bar" title="Absolute value of last memory change"><div class="plugin-memory-fill"><span class="plugin-memory-text"></span></div></div>';
    echo '</div>';
    echo '<div class="plugin-actions">';
    if ($is_memory_usage_plugin) {
        echo '<button class="button" disabled>Active</button>';
    } else {
        echo '<button class="button toggle-plugin" data-plugin="' . esc_attr($plugin_path) . '" data-action="' . ($is_active ? 'deactivate' : 'activate') . '">';
        echo $is_active ? 'Deactivate' : 'Activate';
        echo '</button>';
    }
    echo '</div>';
    echo '</li>';
}

                echo '</ul>';





                ?>
            </div>
        </div>
    </div>

    
    <?php
}





function pmusage_toggle_plugin() {
    check_ajax_referer('wp_memory_usage_nonce', 'nonce');
    if (!current_user_can('activate_plugins')) {
        wp_send_json_error('Insufficient permissions');
    }


    $plugin = isset($_POST['plugin']) ? sanitize_text_field(wp_unslash($_POST['plugin'])) : '';
    $action = isset($_POST['toggle_action']) ? sanitize_text_field(wp_unslash($_POST['toggle_action'])) : '';

    if (empty($plugin) || empty($action)) {
        wp_send_json_error('Invalid plugin or action');
        return;
    }



    if ($action === 'activate') {
        $result = activate_plugin($plugin);
    } else {
        $result = deactivate_plugins($plugin);
    }

    if (is_wp_error($result)) {
        wp_send_json_error($result->get_error_message());
    } else {
        wp_send_json_success();
    }
}
add_action('wp_ajax_pmusage_toggle_plugin', 'pmusage_toggle_plugin');






function pmusage_table_exists($table_name) {
    global $wpdb;
    $full_table_name = $wpdb->prefix . $table_name;
    
    // Create a unique cache key
    $cache_key = 'pmusage_table_exists_' . md5($full_table_name);

    // Try to get the result from cache
    $table_exists = wp_cache_get($cache_key);

    if (false === $table_exists) {
        // Cache miss, perform the database query
		// There isn't a reliable way to check if a table exists in WordPress without making a direct database call
        $result = $wpdb->get_var( // phpcs:ignore WordPress.DB.DirectDatabaseQuery
            $wpdb->prepare(
                "SHOW TABLES LIKE %s",
                $full_table_name
            )
        );
        
        $table_exists = ($result === $full_table_name);

        // Cache the result for future use (cache for 1 hour)
        wp_cache_set($cache_key, $table_exists, '', 3600);
    }

    return $table_exists;
}





function pmusage_refresh_memory_usage() {
    check_ajax_referer('wp_memory_usage_nonce', 'nonce');

    global $wpdb;
    $table_name = $wpdb->prefix . 'wpmem_plugin_history';

    // Check if the table exists
    if (!pmusage_table_exists('wpmem_plugin_history')) {
        pmusage_create_history_table();
    }


    $current_memory = memory_get_usage(true);
    $formatted_memory = size_format($current_memory, 2);
    $percentage = round(($current_memory / wp_convert_hr_to_bytes(WP_MEMORY_LIMIT)) * 100, 2);

    // Save the measurement if a plugin was toggled
    if (isset($_POST['plugin']) && isset($_POST['toggle_action'])) {
        $plugin = sanitize_text_field(wp_unslash($_POST['plugin']));
        $previous_memory = isset($_POST['previous_memory']) ? intval($_POST['previous_memory']) : 0;
        $memory_change = $current_memory - $previous_memory;
        pmusage_save_plugin_measurement($plugin, $memory_change);
    }

    wp_send_json_success(array(
        'current_memory' => $formatted_memory,
        'current_memory_bytes' => $current_memory,
        'percentage' => $percentage,
    ));
}
add_action('wp_ajax_pmusage_refresh_memory_usage', 'pmusage_refresh_memory_usage');




add_action('admin_enqueue_scripts', 'pmusage_enqueue_styles');

function pmusage_enqueue_styles($hook) {
    // Load on all admin pages where the dashboard widget appears
    wp_enqueue_style('pmusage-styles', 
        plugins_url('plugin-memory-usage.css', __FILE__),
        array(),
        filemtime(plugin_dir_path(__FILE__) . 'plugin-memory-usage.css')
    );
}




function pmusage_enqueue_scripts($hook) {
    if ($hook != 'toplevel_page_wp_plugin_memory_usage') {
        return;
    }
    wp_enqueue_script('pmusage-script', plugins_url('plugin-memory-usage.js', __FILE__), array(), '1.0', true);
    $nonce = wp_create_nonce('wp_memory_usage_nonce');
    wp_localize_script('pmusage-script', 'pmusageData', array(
        'pmusage_ajaxurl' => admin_url('admin-ajax.php'),
        'nonce' => $nonce,
        'initialMemoryUsage' => memory_get_usage(true),
        'pluginHistory' => pmusage_get_all_plugin_history()
    ));
}
add_action('admin_enqueue_scripts', 'pmusage_enqueue_scripts');





function pmusage_create_history_table() {
    global $wpdb;
    $table_name = $wpdb->prefix . 'wpmem_plugin_history';
    $charset_collate = $wpdb->get_charset_collate();

    $sql = "CREATE TABLE $table_name (
        id mediumint(9) NOT NULL AUTO_INCREMENT,
        plugin_path varchar(255) NOT NULL,
        memory_change bigint(20) NOT NULL,
        zero_count int(11) NOT NULL DEFAULT 0,
        timestamp datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
        PRIMARY KEY  (id)
    ) $charset_collate;";

    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    $result = dbDelta($sql);
    
    if (!empty($wpdb->last_error)) {
        return false;
    }
    return true;
}


register_activation_hook(__FILE__, 'pmusage_create_history_table');



function pmusage_save_plugin_measurement($plugin_path, $memory_change) {
    global $wpdb;
    $table_name = $wpdb->prefix . 'wpmem_plugin_history';

	// Convert memory_change to its absolute value
    $memory_change = abs($memory_change);

    if ($memory_change == 0) {
        // Increment zero count for the most recent entry
        $wpdb->query( // phpcs:ignore WordPress.DB.DirectDatabaseQuery
            $wpdb->prepare(
                "UPDATE `" . esc_sql($table_name) . "` SET zero_count = zero_count + 1 
                WHERE plugin_path = %s 
                ORDER BY timestamp DESC 
                LIMIT 1",
                $plugin_path
            )
        );
    } else {
        // Insert new non-zero measurement
        $wpdb->insert( // phpcs:ignore WordPress.DB.DirectDatabaseQuery
            $table_name,
            array(
                'plugin_path' => $plugin_path,
                'memory_change' => $memory_change,
                'zero_count' => 0,
            )
        );
    }

    // Clear caches
    pmusage_clear_plugin_history_cache($plugin_path);
    pmusage_clear_all_plugin_history_cache();
    pmusage_clear_average_memory_cache($plugin_path);
}



function pmusage_get_plugin_history($plugin_path) {
    global $wpdb;
    $table_name = $wpdb->prefix . 'wpmem_plugin_history';

    // Create a unique cache key for this query
    $cache_key = 'wpmem_plugin_history_' . md5($plugin_path);

    // Try to get the results from cache
    $results = wp_cache_get($cache_key);

    // If the results are not in cache, query the database
    if (false === $results) {
        $results = $wpdb->get_results( // phpcs:ignore WordPress.DB.DirectDatabaseQuery
            $wpdb->prepare(
                "SELECT memory_change, timestamp FROM `" . esc_sql($table_name) . "` WHERE plugin_path = %s ORDER BY timestamp DESC LIMIT 5",
                $plugin_path
            )
        );

        // Cache the results for future use
        wp_cache_set($cache_key, $results, '', 3600); // Cache for 1 hour
    }

    return $results;
}



function pmusage_clear_plugin_history_cache($plugin_path) {
    $cache_key = 'wpmem_plugin_history_' . md5($plugin_path);
    wp_cache_delete($cache_key);
}



add_action('wp_ajax_pmusage_get_plugin_history', 'pmusage_get_plugin_history_ajax');
function pmusage_get_plugin_history_ajax() {
    check_ajax_referer('wp_memory_usage_nonce', 'nonce');
    if (!isset($_POST['plugin'])) {
        wp_send_json_error('Plugin not specified');
    }

    $plugin = sanitize_text_field(wp_unslash($_POST['plugin']));
    $history = pmusage_get_plugin_history($plugin);

    wp_send_json_success($history);
}








function pmusage_get_all_plugin_history() {
    global $wpdb;
    $table_name = $wpdb->prefix . 'wpmem_plugin_history';

    // Create a unique cache key for this query
    $cache_key = 'pmusage_all_plugin_history';

    // Try to get the results from cache
    $results = wp_cache_get($cache_key);

    // If the results are not in cache, query the database
    if (false === $results) {
        $results = $wpdb->get_results( // phpcs:ignore WordPress.DB.DirectDatabaseQuery
            $wpdb->prepare(
                "SELECT plugin_path, memory_change, timestamp 
                FROM `" . esc_sql($table_name) . "` 
                WHERE plugin_path IN (SELECT DISTINCT plugin_path FROM `" . esc_sql($table_name) . "`)
                ORDER BY timestamp DESC
                -- %d",
                1
            )
        );

        // Cache the results for future use
        wp_cache_set($cache_key, $results, '', 3600); // Cache for 1 hour
    }

    // Process results...
    $history = array();
    foreach ($results as $row) {
        if (!isset($history[$row->plugin_path])) {
            $history[$row->plugin_path] = array();
        }
        if (count($history[$row->plugin_path]) < 5) {
            $history[$row->plugin_path][] = array(
                'memory_change' => $row->memory_change,
                'timestamp' => $row->timestamp
            );
        }
    }

    return $history;
}




function pmusage_clear_all_plugin_history_cache() {
    wp_cache_delete('pmusage_all_plugin_history');
}



function pmusage_clear_table_exists_cache() {
    global $wpdb;
    $table_name = $wpdb->prefix . 'wpmem_plugin_history';
    $cache_key = 'pmusage_table_exists_' . $table_name;
    wp_cache_delete($cache_key);
}


// Reset table verification cache when changing plugin state
register_activation_hook(__FILE__, 'pmusage_clear_table_exists_cache'); // Pre-activation check
register_deactivation_hook(__FILE__, 'pmusage_clear_table_exists_cache'); // Post-deactivation cleanup





function pmusage_get_average_memory_usage($plugin_path) {
    global $wpdb;
    $table_name = $wpdb->prefix . 'wpmem_plugin_history';
    
    // Create a unique cache key
    $cache_key = 'pmusage_avg_memory_' . md5($plugin_path);

    // Try to get the result from cache
    $avg_memory = wp_cache_get($cache_key);

    if (false === $avg_memory) {
        // Cache miss, perform the database query
        $result = $wpdb->get_row( // phpcs:ignore WordPress.DB.DirectDatabaseQuery
            $wpdb->prepare(
                "SELECT SUM(memory_change) as total_change, 
                        COUNT(*) as non_zero_count, 
                        SUM(zero_count) as zero_count
                FROM `" . esc_sql($table_name) . "`
                WHERE plugin_path = %s",
                $plugin_path
            )
        );
        
        if ($result) {
            $total_count = $result->non_zero_count + $result->zero_count;
            $avg_memory = $total_count > 0 ? ($result->total_change / $total_count) / (1024 * 1024) : 0;
            $avg_memory = round($avg_memory, 2); // Round to 2 decimal places
        } else {
            $avg_memory = 0;
        }

        // Cache the result for future use (cache for 5 minutes)
        wp_cache_set($cache_key, $avg_memory, '', 300);
    }
    
    return $avg_memory;
}



function pmusage_clear_average_memory_cache($plugin_path) {
    $cache_key = 'pmusage_avg_memory_' . md5($plugin_path);
    wp_cache_delete($cache_key);
}



add_action('wp_ajax_pmusage_update_average_memory', 'pmusage_update_average_memory');
add_action('wp_ajax_nopriv_update_average_memory', 'pmusage_update_average_memory');

function pmusage_update_average_memory() {
    // Check nonce for security
    if (!isset($_POST['nonce'])) {
        wp_send_json_error('Security token not provided');
    }

    $nonce = sanitize_text_field(wp_unslash($_POST['nonce']));
    if (!wp_verify_nonce($nonce, 'wp_memory_usage_nonce')) {
        wp_send_json_error('Invalid security token');
    }

    if (!isset($_POST['plugin_path'])) {
        wp_send_json_error('Plugin path not provided');
    }

    $plugin_path = sanitize_text_field(wp_unslash($_POST['plugin_path']));
    $avg_memory = pmusage_get_average_memory_usage($plugin_path);

    wp_send_json_success(array('avg_memory' => $avg_memory));
}






function pmusage_add_increase_memory_button($content) {
    $wp_memory_limit = wp_convert_hr_to_bytes(WP_MEMORY_LIMIT);
    $current_memory_usage = memory_get_usage(true);
    
    if ($current_memory_usage > $wp_memory_limit) {
        $content .= '<button id="increase-memory-limit" class="button">Increase Memory Limit</button>';
        $content .= '<span id="memory-increase-result"></span>';
    }
    
    return $content;
}
add_filter('pmusage_memory_usage_content', 'pmusage_add_increase_memory_button');




function pmusage_increase_memory_limit() {
    check_ajax_referer('wp_memory_usage_nonce', 'nonce');
    
    if (!current_user_can('manage_options')) {
        wp_send_json_error(array('message' => 'Insufficient permissions'));
    }
    
    $current_limit = wp_convert_hr_to_bytes(WP_MEMORY_LIMIT);
    
    // If current limit is 160MB or less, double it. Otherwise, increase by 25%.
    if ($current_limit < 160 * 1024 * 1024) { // 160 MB in bytes
        $new_limit = $current_limit * 2;
    } else {
        $new_limit = (int)($current_limit * 1.25); // Increase by 25%
    }
    
    // Optional: Cap the maximum limit to avoid runaway values (e.g., 512MB)
    $max_limit = 512 * 1024 * 1024; // 512 MB in bytes
    if ($new_limit > $max_limit) {
        $new_limit = $max_limit;
    }

    // Attempt to increase the limit
    if (pmusage_set_memory_limit($new_limit)) {
        wp_send_json_success(array('new_limit' => size_format($new_limit)));
    } else {
        wp_send_json_error(array('message' => 'Unable to increase memory limit. You may need to contact your hosting provider.'));
    }
}
add_action('wp_ajax_pmusage_increase_memory_limit', 'pmusage_increase_memory_limit');



function pmusage_set_memory_limit($new_limit) {
    global $wp_filesystem;

    // Initialize the WP filesystem
    if (empty($wp_filesystem)) {
        require_once (ABSPATH . '/wp-admin/includes/file.php');
        WP_Filesystem();
    }

    $wp_config_file = ABSPATH . 'wp-config.php';
    $config_content = $wp_filesystem->get_contents($wp_config_file);
    
    if ($config_content === false) {
        return false;
    }
    
    $new_limit_formatted = size_format($new_limit);
    
    if (preg_match("/define\(\s*'WP_MEMORY_LIMIT',\s*'.*?'\s*\);/", $config_content)) {
        // WP_MEMORY_LIMIT is already defined, so update it
        $new_content = preg_replace(
            "/define\(\s*'WP_MEMORY_LIMIT',\s*'.*?'\s*\);/",
            "define('WP_MEMORY_LIMIT', '$new_limit_formatted');",
            $config_content
        );
    } else {
        // WP_MEMORY_LIMIT is not defined, so add it
        $new_content = preg_replace(
            "/<\?php/",
            "<?php\ndefine('WP_MEMORY_LIMIT', '$new_limit_formatted');",
            $config_content,
            1
        );
    }
    
    if ($wp_filesystem->put_contents($wp_config_file, $new_content) === false) {
        return false;
    }
    
    return true;
}






function pmusage_add_settings_link($links) {
    $settings_link = '<a href="' . admin_url('admin.php?page=wp_plugin_memory_usage') . '">Settings</a>';
    array_unshift($links, $settings_link);
    return $links;
}

$plugin = plugin_basename(__FILE__);
add_filter("plugin_action_links_$plugin", 'pmusage_add_settings_link');





function pmusage_add_memory_to_admin_bar($wp_admin_bar) {
    $wp_memory_limit = wp_convert_hr_to_bytes(WP_MEMORY_LIMIT);
    $current_memory_usage = memory_get_usage(true);
    $percentage_used = round(($current_memory_usage / $wp_memory_limit) * 100, 1);
    

    // Determine color class based on memory usage
    if ($percentage_used >= 90) {
        $color_class = 'wpmem-critical'; // Red
    } elseif ($percentage_used >= 75) {
        $color_class = 'wpmem-warning'; // Orange
    } elseif ($percentage_used >= 50) {
        $color_class = 'wpmem-moderate'; // Yellow
    } else {
        $color_class = 'wpmem-good'; // Green
    }
    
    $wp_admin_bar->add_node(array(
        'id' => 'pmusage_memory_usage',
        'title' => '<span class="' . esc_attr($color_class) . '">MEM: ' . $percentage_used . '%</span>',
        'href' => admin_url('admin.php?page=wp_plugin_memory_usage'),
        'meta' => array(
            'title' => 'Current memory usage: ' . size_format($current_memory_usage) . ' of ' . size_format($wp_memory_limit),
        ),
    ));
}
add_action('admin_bar_menu', 'pmusage_add_memory_to_admin_bar', 100);





function pmusage_get_mysql_versions_from_api() {
    $mysql_versions = get_transient('pmusage_mysql_eol_data');
    if (false === $mysql_versions) {
        // Get MySQL data
        $mysql_response = wp_remote_get('https://endoflife.date/api/mysql.json', array(
            'sslverify' => false,
            'timeout' => 5
        ));
        
        // Get MariaDB data
        $mariadb_response = wp_remote_get('https://endoflife.date/api/mariadb.json', array(
            'sslverify' => false,
            'timeout' => 5
        ));
        
        $versions_data = ['mysql' => [], 'mariadb' => []];
        
        if (!is_wp_error($mysql_response) && 200 === wp_remote_retrieve_response_code($mysql_response)) {
            $mysql_data = json_decode(wp_remote_retrieve_body($mysql_response), true);
            if (is_array($mysql_data)) {
                foreach ($mysql_data as $version_info) {
                    $cycle = $version_info['cycle'];
                    $eol_date = $version_info['eol'] ?? null;
                    
                    if ($eol_date && $eol_date !== false) {
                        $versions_data['mysql'][$cycle] = [
                            'eol_date' => $eol_date,
                            'latest' => $version_info['latest'] ?? '',
                            'support_end' => $version_info['support'] ?? $eol_date
                        ];
                    }
                }
            }
        }
        
        if (!is_wp_error($mariadb_response) && 200 === wp_remote_retrieve_response_code($mariadb_response)) {
            $mariadb_data = json_decode(wp_remote_retrieve_body($mariadb_response), true);
            if (is_array($mariadb_data)) {
                foreach ($mariadb_data as $version_info) {
                    $cycle = $version_info['cycle'];
                    $eol_date = $version_info['eol'] ?? null;
                    
                    if ($eol_date && $eol_date !== false) {
                        $versions_data['mariadb'][$cycle] = [
                            'eol_date' => $eol_date,
                            'latest' => $version_info['latest'] ?? '', // This is the key addition
                            'lts' => $version_info['lts'] ?? false
                        ];
                    }
                }
            }
        }
        
        // Cache for one week
        set_transient('pmusage_mysql_eol_data', $versions_data, WEEK_IN_SECONDS);
        $mysql_versions = $versions_data;
    }
    
    return $mysql_versions;
}


function pmusage_get_mysql_latest_version($current_version) {
    $version_data = pmusage_get_mysql_versions_from_api();
    $is_mariadb = stripos($current_version, 'mariadb') !== false;
    
    // Extract version number
    preg_match('/(\d+\.\d+)/', $current_version, $matches);
    $version_number = $matches[1] ?? '';
    
    if (empty($version_number)) {
        return 'Unknown';
    }
    
    $database_type = $is_mariadb ? 'mariadb' : 'mysql';
    $versions = $version_data[$database_type] ?? [];
    
    if (isset($versions[$version_number]) && !empty($versions[$version_number]['latest'])) {
        return $versions[$version_number]['latest'];
    }
    
    return 'Unknown';
}





function pmusage_get_mysql_status($current_version) {
    $version_data = pmusage_get_mysql_versions_from_api();
    $is_mariadb = stripos($current_version, 'mariadb') !== false;
    
    // Extract version number
    preg_match('/(\d+\.\d+)/', $current_version, $matches);
    $version_number = $matches[1] ?? '';
    
    if (empty($version_number)) {
        return 'unknown';
    }
    
    $database_type = $is_mariadb ? 'mariadb' : 'mysql';
    $versions = $version_data[$database_type] ?? [];
    
    if (isset($versions[$version_number])) {
        $version_info = $versions[$version_number];
        $eol_date_str = $version_info['eol_date'];
        
        // Handle different date formats from API
        if ($eol_date_str === true || $eol_date_str === false) {
            return $eol_date_str === false ? 'supported' : 'eol';
        }
        
        try {
            $eol_date = new DateTime($eol_date_str);
            $now = new DateTime();
            
            return ($now < $eol_date) ? 'supported' : 'eol';
        } catch (Exception $e) {
            return 'unknown';
        }
    }
    
    return 'unknown';
}






?>
```
