Plugin Directory

Changeset 3427251


Ignore:
Timestamp:
12/25/2025 11:46:12 AM (3 months ago)
Author:
loghin
Message:

1.2.998

Location:
dynamic-front-end-heartbeat-control
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • dynamic-front-end-heartbeat-control/tags/1.2.998/admin/affix.php

    r3427163 r3427251  
    3535    private function s_text( $v ) {
    3636        return sanitize_text_field( is_string($v) ? $v : '' );
     37    }
     38
     39    private function s_cap( $v ) {
     40        $v = sanitize_key( is_string($v) ? $v : '' );
     41        return $v !== '' ? $v : 'read';
    3742    }
    3843
     
    6469    }
    6570
    66     private function f_text( string $key, string $placeholder = '' ): void {
    67         $val = get_option($key, '');
     71    private function f_text( string $key, string $placeholder = '', $default = '' ): void {
     72        $val = get_option($key, $default);
    6873        echo '<input type="text" class="regular-text" name="'.esc_attr($key).'" value="'.esc_attr((string)$val).'" placeholder="'.esc_attr($placeholder).'" />';
    6974        echo '<p class="description"><code>'.esc_html($key).'</code></p>';
    7075    }
    7176
    72     private function f_number( string $key, string $step = '1', string $min = '', string $max = '' ): void {
    73         $val = get_option($key, '');
     77    private function f_number( string $key, string $step = '1', string $min = '', string $max = '', $default = '' ): void {
     78        $val = get_option($key, $default);
    7479        echo '<input type="number" name="'.esc_attr($key).'" value="'.esc_attr((string)$val).'" step="'.esc_attr($step).'"'.($min!==''?' min="'.esc_attr($min).'"':'').($max!==''?' max="'.esc_attr($max).'"':'').' />';
    7580        echo '<p class="description"><code>'.esc_html($key).'</code></p>';
    7681    }
    7782
    78     private function f_checkbox( string $key ): void {
    79         $val = (int) get_option($key, 0);
     83    private function f_checkbox( string $key, $default = 0 ): void {
     84        $val = (int) get_option($key, $default);
     85        echo '<input type="hidden" name="'.esc_attr($key).'" value="0" />';
    8086        echo '<label><input type="checkbox" name="'.esc_attr($key).'" value="1" '.checked(1,$val,false).' /> ' . esc_html__('Enabled', 'dfehc') . '</label>';
    8187        echo '<p class="description"><code>'.esc_html($key).'</code></p>';
    8288    }
    8389
    84     private function f_textarea( string $key, string $placeholder = '' ): void {
    85         $val = get_option($key, '');
     90    private function f_textarea( string $key, string $placeholder = '', $default = '' ): void {
     91        $val = get_option($key, $default);
    8692        echo '<textarea name="'.esc_attr($key).'" rows="5" class="large-text code" placeholder="'.esc_attr($placeholder).'">'.esc_textarea((string)$val).'</textarea>';
    8793        echo '<p class="description"><code>'.esc_html($key).'</code></p>';
    8894    }
    8995
    90     private function f_json( string $key, string $placeholder = '' ): void {
    91         $val = get_option($key, '');
     96    private function f_json( string $key, string $placeholder = '', $default = '' ): void {
     97        $val = get_option($key, $default);
    9298        echo '<textarea name="'.esc_attr($key).'" rows="6" class="large-text code" placeholder="'.esc_attr($placeholder).'">'.esc_textarea((string)$val).'</textarea>';
    9399        echo '<p class="description">'.esc_html__('JSON format. Leave empty to use defaults.', 'dfehc').' <code>'.esc_html($key).'</code></p>';
     
    120126
    121127    public function reg() {
     128        $keep = function(string $key, callable $san) {
     129            return function($v) use ($key, $san) {
     130                if ($v === null) return get_option($key);
     131                if (is_string($v) && trim($v) === '') return get_option($key);
     132                return call_user_func($san, $v);
     133            };
     134        };
     135
    122136        register_setting( $this->plugin->og, 'dfehc_heartbeat_zoom', 'floatval' );
    123137        register_setting( $this->plugin->og, 'dfehc_priority_slider', 'intval' );
     
    135149        register_setting( $this->plugin->og, 'add_to_menu', 'absint' );
    136150
    137         register_setting( $this->plugin->og, 'dfehc_client_ip_public_only', [$this,'s_bool'] );
    138         register_setting( $this->plugin->og, 'dfehc_trusted_proxies', [$this,'s_lines'] );
    139         register_setting( $this->plugin->og, 'dfehc_proxy_ip_headers', [$this,'s_lines'] );
    140         register_setting( $this->plugin->og, 'dfehc_client_ip', [$this,'s_text'] );
    141 
    142         register_setting( $this->plugin->og, 'dfehc_default_response_time', [$this,'s_float'] );
    143         register_setting( $this->plugin->og, 'dfehc_spike_threshold_factor', [$this,'s_float'] );
    144         register_setting( $this->plugin->og, 'dfehc_spike_increment_floor', [$this,'s_float'] );
    145         register_setting( $this->plugin->og, 'dfehc_spike_increment_cap', [$this,'s_float'] );
    146         register_setting( $this->plugin->og, 'dfehc_spike_decay', [$this,'s_float'] );
    147         register_setting( $this->plugin->og, 'dfehc_recalibrate_threshold', [$this,'s_float'] );
    148         register_setting( $this->plugin->og, 'dfehc_trim_extremes', [$this,'s_bool'] );
    149 
    150         register_setting( $this->plugin->og, 'dfehc_high_traffic_cache_expiration', [$this,'s_int'] );
    151         register_setting( $this->plugin->og, 'dfehc_max_baseline_age', [$this,'s_int'] );
    152         register_setting( $this->plugin->og, 'dfehc_baseline_min_samples', [$this,'s_int'] );
    153         register_setting( $this->plugin->og, 'dfehc_baseline_expiration', [$this,'s_int'] );
    154         register_setting( $this->plugin->og, 'dfehc_cache_expiration', [$this,'s_int'] );
    155         register_setting( $this->plugin->og, 'dfehc_head_negative_ttl', [$this,'s_int'] );
    156         register_setting( $this->plugin->og, 'dfehc_head_positive_ttl', [$this,'s_int'] );
    157         register_setting( $this->plugin->og, 'dfehc_probe_fail_ttl', [$this,'s_int'] );
    158 
    159         register_setting( $this->plugin->og, 'dfehc_disable_loopback', [$this,'s_bool'] );
    160         register_setting( $this->plugin->og, 'dfehc_probe_headers', [$this,'s_lines'] );
    161         register_setting( $this->plugin->og, 'dfehc_total_timeout', [$this,'s_float'] );
    162         register_setting( $this->plugin->og, 'dfehc_request_timeout', [$this,'s_float'] );
    163         register_setting( $this->plugin->og, 'dfehc_num_requests', [$this,'s_int'] );
    164         register_setting( $this->plugin->og, 'dfehc_request_pause_us', [$this,'s_int'] );
    165         register_setting( $this->plugin->og, 'dfehc_ssl_verify', [$this,'s_bool'] );
    166         register_setting( $this->plugin->og, 'dfehc_use_get_fallback', [$this,'s_bool'] );
    167         register_setting( $this->plugin->og, 'dfehc_use_head_method', [$this,'s_bool'] );
    168         register_setting( $this->plugin->og, 'dfehc_redirection', [$this,'s_int'] );
    169         register_setting( $this->plugin->og, 'dfehc_limit_response_size', [$this,'s_int'] );
    170 
    171         register_setting( $this->plugin->og, 'dfehc_ping_rl_ttl', [$this,'s_int'] );
    172         register_setting( $this->plugin->og, 'dfehc_ping_rl_limit', [$this,'s_int'] );
    173         register_setting( $this->plugin->og, 'dfehc_enable_public_ping', [$this,'s_bool'] );
    174         register_setting( $this->plugin->og, 'dfehc_high_traffic_threshold', [$this,'s_int'] );
    175         register_setting( $this->plugin->og, 'dfehc_website_visitors', [$this,'s_int'] );
    176         register_setting( $this->plugin->og, 'dfehc_current_server_load', [$this,'s_float'] );
    177         register_setting( $this->plugin->og, 'dfehc_high_traffic_load_threshold', [$this,'s_float'] );
    178         register_setting( $this->plugin->og, 'dfehc_allow_public_server_load', [$this,'s_bool'] );
    179         register_setting( $this->plugin->og, 'dfehc_allow_public_async', [$this,'s_bool'] );
    180 
    181         register_setting( $this->plugin->og, 'dfehc_min_interval', [$this,'s_int'] );
    182         register_setting( $this->plugin->og, 'dfehc_max_interval', [$this,'s_int'] );
    183         register_setting( $this->plugin->og, 'dfehc_fallback_interval', [$this,'s_int'] );
    184         register_setting( $this->plugin->og, 'dfehc_unknown_load', [$this,'s_float'] );
    185         register_setting( $this->plugin->og, 'dfehc_max_server_load', [$this,'s_float'] );
    186 
    187         register_setting( $this->plugin->og, 'dfehc_interval_factors', [$this,'s_json'] );
    188         register_setting( $this->plugin->og, 'dfehc_interval_weights', [$this,'s_json'] );
    189         register_setting( $this->plugin->og, 'dfehc_load_weights', [$this,'s_json'] );
    190         register_setting( $this->plugin->og, 'dfehc_normalize_load', [$this,'s_bool'] );
    191         register_setting( $this->plugin->og, 'dfehc_assumed_cores_for_normalization', [$this,'s_int'] );
    192         register_setting( $this->plugin->og, 'dfehc_max_increase_rate', [$this,'s_float'] );
    193         register_setting( $this->plugin->og, 'dfehc_interval_snap', [$this,'s_int'] );
    194         register_setting( $this->plugin->og, 'dfehc_response_time_is_ms', [$this,'s_bool'] );
    195         register_setting( $this->plugin->og, 'dfehc_contextual_load_value', [$this,'s_float'] );
    196         register_setting( $this->plugin->og, 'dfehc_divide_cpu_load', [$this,'s_bool'] );
    197         register_setting( $this->plugin->og, 'dfehc_cpu_cores', [$this,'s_int'] );
    198 
    199         register_setting( $this->plugin->og, 'dfehc_server_load_ttl', [$this,'s_int'] );
    200         register_setting( $this->plugin->og, 'dfehc_transient_ttl', [$this,'s_int'] );
    201         register_setting( $this->plugin->og, 'dfehc_ema_ttl', [$this,'s_int'] );
    202         register_setting( $this->plugin->og, 'dfehc_prev_interval_ttl', [$this,'s_int'] );
    203         register_setting( $this->plugin->og, 'dfehc_cache_retry_after', [$this,'s_int'] );
    204         register_setting( $this->plugin->og, 'dfehc_redis_auth', [$this,'s_text'] );
    205         register_setting( $this->plugin->og, 'dfehc_redis_user', [$this,'s_text'] );
     151        register_setting( $this->plugin->og, 'dfehc_client_ip_public_only', $keep('dfehc_client_ip_public_only', [$this,'s_bool']) );
     152        register_setting( $this->plugin->og, 'dfehc_trusted_proxies', $keep('dfehc_trusted_proxies', [$this,'s_lines']) );
     153        register_setting( $this->plugin->og, 'dfehc_proxy_ip_headers', $keep('dfehc_proxy_ip_headers', [$this,'s_lines']) );
     154        register_setting( $this->plugin->og, 'dfehc_client_ip', $keep('dfehc_client_ip', [$this,'s_text']) );
     155
     156        register_setting( $this->plugin->og, 'dfehc_default_response_time', $keep('dfehc_default_response_time', [$this,'s_float']) );
     157        register_setting( $this->plugin->og, 'dfehc_spike_threshold_factor', $keep('dfehc_spike_threshold_factor', [$this,'s_float']) );
     158        register_setting( $this->plugin->og, 'dfehc_spike_increment_floor', $keep('dfehc_spike_increment_floor', [$this,'s_float']) );
     159        register_setting( $this->plugin->og, 'dfehc_spike_increment_cap', $keep('dfehc_spike_increment_cap', [$this,'s_float']) );
     160        register_setting( $this->plugin->og, 'dfehc_spike_decay', $keep('dfehc_spike_decay', [$this,'s_float']) );
     161        register_setting( $this->plugin->og, 'dfehc_recalibrate_threshold', $keep('dfehc_recalibrate_threshold', [$this,'s_float']) );
     162        register_setting( $this->plugin->og, 'dfehc_trim_extremes', $keep('dfehc_trim_extremes', [$this,'s_bool']) );
     163
     164        register_setting( $this->plugin->og, 'dfehc_high_traffic_cache_expiration', $keep('dfehc_high_traffic_cache_expiration', [$this,'s_int']) );
     165        register_setting( $this->plugin->og, 'dfehc_max_baseline_age', $keep('dfehc_max_baseline_age', [$this,'s_int']) );
     166        register_setting( $this->plugin->og, 'dfehc_baseline_min_samples', $keep('dfehc_baseline_min_samples', [$this,'s_int']) );
     167        register_setting( $this->plugin->og, 'dfehc_baseline_expiration', $keep('dfehc_baseline_expiration', [$this,'s_int']) );
     168        register_setting( $this->plugin->og, 'dfehc_cache_expiration', $keep('dfehc_cache_expiration', [$this,'s_int']) );
     169        register_setting( $this->plugin->og, 'dfehc_head_negative_ttl', $keep('dfehc_head_negative_ttl', [$this,'s_int']) );
     170        register_setting( $this->plugin->og, 'dfehc_head_positive_ttl', $keep('dfehc_head_positive_ttl', [$this,'s_int']) );
     171        register_setting( $this->plugin->og, 'dfehc_probe_fail_ttl', $keep('dfehc_probe_fail_ttl', [$this,'s_int']) );
     172
     173        register_setting( $this->plugin->og, 'dfehc_disable_loopback', $keep('dfehc_disable_loopback', [$this,'s_bool']) );
     174        register_setting( $this->plugin->og, 'dfehc_probe_headers', $keep('dfehc_probe_headers', [$this,'s_lines']) );
     175        register_setting( $this->plugin->og, 'dfehc_total_timeout', $keep('dfehc_total_timeout', [$this,'s_float']) );
     176        register_setting( $this->plugin->og, 'dfehc_request_timeout', $keep('dfehc_request_timeout', [$this,'s_float']) );
     177        register_setting( $this->plugin->og, 'dfehc_num_requests', $keep('dfehc_num_requests', [$this,'s_int']) );
     178        register_setting( $this->plugin->og, 'dfehc_request_pause_us', $keep('dfehc_request_pause_us', [$this,'s_int']) );
     179        register_setting( $this->plugin->og, 'dfehc_ssl_verify', $keep('dfehc_ssl_verify', [$this,'s_bool']) );
     180        register_setting( $this->plugin->og, 'dfehc_use_get_fallback', $keep('dfehc_use_get_fallback', [$this,'s_bool']) );
     181        register_setting( $this->plugin->og, 'dfehc_use_head_method', $keep('dfehc_use_head_method', [$this,'s_bool']) );
     182        register_setting( $this->plugin->og, 'dfehc_redirection', $keep('dfehc_redirection', [$this,'s_int']) );
     183        register_setting( $this->plugin->og, 'dfehc_limit_response_size', $keep('dfehc_limit_response_size', [$this,'s_int']) );
     184
     185        register_setting( $this->plugin->og, 'dfehc_ping_rl_ttl', $keep('dfehc_ping_rl_ttl', [$this,'s_int']) );
     186        register_setting( $this->plugin->og, 'dfehc_ping_rl_limit', $keep('dfehc_ping_rl_limit', [$this,'s_int']) );
     187        register_setting( $this->plugin->og, 'dfehc_enable_public_ping', $keep('dfehc_enable_public_ping', [$this,'s_bool']) );
     188        register_setting( $this->plugin->og, 'dfehc_high_traffic_threshold', $keep('dfehc_high_traffic_threshold', [$this,'s_int']) );
     189        register_setting( $this->plugin->og, 'dfehc_website_visitors', $keep('dfehc_website_visitors', [$this,'s_int']) );
     190        register_setting( $this->plugin->og, 'dfehc_current_server_load', $keep('dfehc_current_server_load', [$this,'s_float']) );
     191        register_setting( $this->plugin->og, 'dfehc_high_traffic_load_threshold', $keep('dfehc_high_traffic_load_threshold', [$this,'s_float']) );
     192        register_setting( $this->plugin->og, 'dfehc_allow_public_server_load', $keep('dfehc_allow_public_server_load', [$this,'s_bool']) );
     193        register_setting( $this->plugin->og, 'dfehc_allow_public_async', $keep('dfehc_allow_public_async', [$this,'s_bool']) );
     194
     195        register_setting( $this->plugin->og, 'dfehc_min_interval', $keep('dfehc_min_interval', [$this,'s_int']) );
     196        register_setting( $this->plugin->og, 'dfehc_max_interval', $keep('dfehc_max_interval', [$this,'s_int']) );
     197        register_setting( $this->plugin->og, 'dfehc_fallback_interval', $keep('dfehc_fallback_interval', [$this,'s_int']) );
     198        register_setting( $this->plugin->og, 'dfehc_unknown_load', $keep('dfehc_unknown_load', [$this,'s_float']) );
     199        register_setting( $this->plugin->og, 'dfehc_max_server_load', $keep('dfehc_max_server_load', [$this,'s_float']) );
     200
     201        register_setting( $this->plugin->og, 'dfehc_interval_factors', $keep('dfehc_interval_factors', [$this,'s_json']) );
     202        register_setting( $this->plugin->og, 'dfehc_interval_weights', $keep('dfehc_interval_weights', [$this,'s_json']) );
     203        register_setting( $this->plugin->og, 'dfehc_load_weights', $keep('dfehc_load_weights', [$this,'s_json']) );
     204        register_setting( $this->plugin->og, 'dfehc_normalize_load', $keep('dfehc_normalize_load', [$this,'s_bool']) );
     205        register_setting( $this->plugin->og, 'dfehc_assumed_cores_for_normalization', $keep('dfehc_assumed_cores_for_normalization', [$this,'s_float']) );
     206        register_setting( $this->plugin->og, 'dfehc_max_increase_rate', $keep('dfehc_max_increase_rate', [$this,'s_float']) );
     207        register_setting( $this->plugin->og, 'dfehc_interval_snap', $keep('dfehc_interval_snap', [$this,'s_int']) );
     208        register_setting( $this->plugin->og, 'dfehc_response_time_is_ms', $keep('dfehc_response_time_is_ms', [$this,'s_bool']) );
     209        register_setting( $this->plugin->og, 'dfehc_contextual_load_value', $keep('dfehc_contextual_load_value', [$this,'s_float']) );
     210        register_setting( $this->plugin->og, 'dfehc_divide_cpu_load', $keep('dfehc_divide_cpu_load', [$this,'s_bool']) );
     211        register_setting( $this->plugin->og, 'dfehc_cpu_cores', $keep('dfehc_cpu_cores', [$this,'s_int']) );
     212
     213        register_setting( $this->plugin->og, 'dfehc_server_load_ttl', $keep('dfehc_server_load_ttl', [$this,'s_int']) );
     214        register_setting( $this->plugin->og, 'dfehc_transient_ttl', $keep('dfehc_transient_ttl', [$this,'s_int']) );
     215        register_setting( $this->plugin->og, 'dfehc_ema_ttl', $keep('dfehc_ema_ttl', [$this,'s_int']) );
     216        register_setting( $this->plugin->og, 'dfehc_prev_interval_ttl', $keep('dfehc_prev_interval_ttl', [$this,'s_int']) );
     217        register_setting( $this->plugin->og, 'dfehc_cache_retry_after', $keep('dfehc_cache_retry_after', [$this,'s_int']) );
     218        register_setting( $this->plugin->og, 'dfehc_redis_auth', $keep('dfehc_redis_auth', [$this,'s_text']) );
     219        register_setting( $this->plugin->og, 'dfehc_redis_user', $keep('dfehc_redis_user', [$this,'s_text']) );
     220
     221        register_setting( $this->plugin->og, 'dfehc_required_capability', $keep('dfehc_required_capability', [$this,'s_cap']) );
     222        register_setting( $this->plugin->og, 'dfehc_public_rate_limit', $keep('dfehc_public_rate_limit', [$this,'s_int']) );
     223        register_setting( $this->plugin->og, 'dfehc_public_rate_window', $keep('dfehc_public_rate_window', [$this,'s_int']) );
     224
     225        register_setting( $this->plugin->og, 'dfehc_enable_load_logging', $keep('dfehc_enable_load_logging', [$this,'s_bool']) );
     226        register_setting( $this->plugin->og, 'dfehc_log_retention_seconds', $keep('dfehc_log_retention_seconds', [$this,'s_int']) );
     227        register_setting( $this->plugin->og, 'dfehc_log_retention_max', $keep('dfehc_log_retention_max', [$this,'s_int']) );
     228        register_setting( $this->plugin->og, 'dfehc_prune_chunk_size', $keep('dfehc_prune_chunk_size', [$this,'s_int']) );
    206229
    207230        add_settings_section( 'dfhcsl_heartbeat_settings_section', __('Heartbeat Control Settings','dfehc'), [$this,'shb'], $this->plugin->slug );
     
    220243        add_settings_section( 'dfehc_adv_algorithm_logic', __('Algorithm & Logic','dfehc'), '__return_false', $this->plugin->slug );
    221244        add_settings_section( 'dfehc_adv_caching_persistence', __('Caching & Persistence','dfehc'), '__return_false', $this->plugin->slug );
     245        add_settings_section( 'dfehc_adv_access_security', __('Access & Security','dfehc'), '__return_false', $this->plugin->slug );
     246        add_settings_section( 'dfehc_adv_logging_maintenance', __('Logging & Maintenance','dfehc'), '__return_false', $this->plugin->slug );
    222247
    223248        add_settings_field( 'dfehc_disable_heartbeat', __('Disable Heartbeat','dfehc'), [$this,'fdis'], $this->plugin->slug, 'dfhcsl_heartbeat_settings_section' );
     
    238263        add_settings_field( 'dfehc_heartbeat_zoom', __('Heartbeat Zoom Multiplier','dfehc'), [$this,'fzm'], $this->plugin->slug, 'dfehc_load_display_settings_section' );
    239264
    240         add_settings_field( 'dfehc_client_ip_public_only', __('Public IP only','dfehc'), function(){ $this->f_checkbox('dfehc_client_ip_public_only'); }, $this->plugin->slug, 'dfehc_adv_ip_proxy' );
    241         add_settings_field( 'dfehc_trusted_proxies', __('Trusted proxies (one per line)','dfehc'), function(){ $this->f_textarea('dfehc_trusted_proxies',"127.0.0.1\n10.0.0.0/8"); }, $this->plugin->slug, 'dfehc_adv_ip_proxy' );
    242         add_settings_field( 'dfehc_proxy_ip_headers', __('Proxy IP headers (one per line)','dfehc'), function(){ $this->f_textarea('dfehc_proxy_ip_headers',"X-Forwarded-For\nCF-Connecting-IP"); }, $this->plugin->slug, 'dfehc_adv_ip_proxy' );
    243         add_settings_field( 'dfehc_client_ip', __('Client IP override','dfehc'), function(){ $this->f_text('dfehc_client_ip'); }, $this->plugin->slug, 'dfehc_adv_ip_proxy' );
    244 
    245         add_settings_field( 'dfehc_default_response_time', __('Default response time','dfehc'), function(){ $this->f_number('dfehc_default_response_time','0.01'); }, $this->plugin->slug, 'dfehc_adv_response_spike' );
    246         add_settings_field( 'dfehc_spike_threshold_factor', __('Spike threshold factor','dfehc'), function(){ $this->f_number('dfehc_spike_threshold_factor','0.01'); }, $this->plugin->slug, 'dfehc_adv_response_spike' );
    247         add_settings_field( 'dfehc_spike_increment_floor', __('Spike increment floor','dfehc'), function(){ $this->f_number('dfehc_spike_increment_floor','0.01'); }, $this->plugin->slug, 'dfehc_adv_response_spike' );
    248         add_settings_field( 'dfehc_spike_increment_cap', __('Spike increment cap','dfehc'), function(){ $this->f_number('dfehc_spike_increment_cap','0.01'); }, $this->plugin->slug, 'dfehc_adv_response_spike' );
    249         add_settings_field( 'dfehc_spike_decay', __('Spike decay','dfehc'), function(){ $this->f_number('dfehc_spike_decay','0.01'); }, $this->plugin->slug, 'dfehc_adv_response_spike' );
    250         add_settings_field( 'dfehc_recalibrate_threshold', __('Recalibrate threshold','dfehc'), function(){ $this->f_number('dfehc_recalibrate_threshold','0.01'); }, $this->plugin->slug, 'dfehc_adv_response_spike' );
    251         add_settings_field( 'dfehc_trim_extremes', __('Trim extremes','dfehc'), function(){ $this->f_checkbox('dfehc_trim_extremes'); }, $this->plugin->slug, 'dfehc_adv_response_spike' );
    252 
    253         add_settings_field( 'dfehc_high_traffic_cache_expiration', __('High traffic cache expiration (s)','dfehc'), function(){ $this->f_number('dfehc_high_traffic_cache_expiration','1','0'); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
    254         add_settings_field( 'dfehc_max_baseline_age', __('Max baseline age (s)','dfehc'), function(){ $this->f_number('dfehc_max_baseline_age','1','0'); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
    255         add_settings_field( 'dfehc_baseline_min_samples', __('Baseline min samples','dfehc'), function(){ $this->f_number('dfehc_baseline_min_samples','1','0'); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
    256         add_settings_field( 'dfehc_baseline_expiration', __('Baseline expiration (s)','dfehc'), function(){ $this->f_number('dfehc_baseline_expiration','1','0'); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
    257         add_settings_field( 'dfehc_cache_expiration', __('Cache expiration (s)','dfehc'), function(){ $this->f_number('dfehc_cache_expiration','1','0'); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
    258         add_settings_field( 'dfehc_head_negative_ttl', __('HEAD negative TTL (s)','dfehc'), function(){ $this->f_number('dfehc_head_negative_ttl','1','0'); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
    259         add_settings_field( 'dfehc_head_positive_ttl', __('HEAD positive TTL (s)','dfehc'), function(){ $this->f_number('dfehc_head_positive_ttl','1','0'); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
    260         add_settings_field( 'dfehc_probe_fail_ttl', __('Probe fail TTL (s)','dfehc'), function(){ $this->f_number('dfehc_probe_fail_ttl','1','0'); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
    261 
    262         add_settings_field( 'dfehc_disable_loopback', __('Disable loopback','dfehc'), function(){ $this->f_checkbox('dfehc_disable_loopback'); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
    263         add_settings_field( 'dfehc_probe_headers', __('Probe headers (one per line: Key: Value)','dfehc'), function(){ $this->f_textarea('dfehc_probe_headers',"User-Agent: DFEHC\nAccept: */*"); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
    264         add_settings_field( 'dfehc_total_timeout', __('Total timeout (s)','dfehc'), function(){ $this->f_number('dfehc_total_timeout','0.1','0'); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
    265         add_settings_field( 'dfehc_request_timeout', __('Request timeout (s)','dfehc'), function(){ $this->f_number('dfehc_request_timeout','0.1','0'); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
    266         add_settings_field( 'dfehc_num_requests', __('Number of requests','dfehc'), function(){ $this->f_number('dfehc_num_requests','1','0'); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
    267         add_settings_field( 'dfehc_request_pause_us', __('Pause between requests (µs)','dfehc'), function(){ $this->f_number('dfehc_request_pause_us','1','0'); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
    268         add_settings_field( 'dfehc_ssl_verify', __('SSL verify','dfehc'), function(){ $this->f_checkbox('dfehc_ssl_verify'); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
    269         add_settings_field( 'dfehc_use_get_fallback', __('Use GET fallback','dfehc'), function(){ $this->f_checkbox('dfehc_use_get_fallback'); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
    270         add_settings_field( 'dfehc_use_head_method', __('Use HEAD method','dfehc'), function(){ $this->f_checkbox('dfehc_use_head_method'); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
    271         add_settings_field( 'dfehc_redirection', __('Max redirections','dfehc'), function(){ $this->f_number('dfehc_redirection','1','0'); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
    272         add_settings_field( 'dfehc_limit_response_size', __('Limit response size (bytes)','dfehc'), function(){ $this->f_number('dfehc_limit_response_size','1','0'); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
    273 
    274         add_settings_field( 'dfehc_ping_rl_ttl', __('Ping rate-limit TTL (s)','dfehc'), function(){ $this->f_number('dfehc_ping_rl_ttl','1','0'); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
    275         add_settings_field( 'dfehc_ping_rl_limit', __('Ping rate-limit limit','dfehc'), function(){ $this->f_number('dfehc_ping_rl_limit','1','0'); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
    276         add_settings_field( 'dfehc_enable_public_ping', __('Enable public ping','dfehc'), function(){ $this->f_checkbox('dfehc_enable_public_ping'); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
    277         add_settings_field( 'dfehc_high_traffic_threshold', __('High traffic threshold','dfehc'), function(){ $this->f_number('dfehc_high_traffic_threshold','1','0'); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
    278         add_settings_field( 'dfehc_website_visitors', __('Website visitors override','dfehc'), function(){ $this->f_number('dfehc_website_visitors','1','0'); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
    279         add_settings_field( 'dfehc_current_server_load', __('Current server load override','dfehc'), function(){ $this->f_number('dfehc_current_server_load','0.01'); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
    280         add_settings_field( 'dfehc_high_traffic_load_threshold', __('High traffic load threshold','dfehc'), function(){ $this->f_number('dfehc_high_traffic_load_threshold','0.01'); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
    281         add_settings_field( 'dfehc_allow_public_server_load', __('Allow public server load','dfehc'), function(){ $this->f_checkbox('dfehc_allow_public_server_load'); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
    282         add_settings_field( 'dfehc_allow_public_async', __('Allow public async','dfehc'), function(){ $this->f_checkbox('dfehc_allow_public_async'); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
    283 
    284         add_settings_field( 'dfehc_min_interval', __('Min interval (s)','dfehc'), function(){ $this->f_number('dfehc_min_interval','1','0'); }, $this->plugin->slug, 'dfehc_adv_core_thresholds' );
    285         add_settings_field( 'dfehc_max_interval', __('Max interval (s)','dfehc'), function(){ $this->f_number('dfehc_max_interval','1','0'); }, $this->plugin->slug, 'dfehc_adv_core_thresholds' );
    286         add_settings_field( 'dfehc_fallback_interval', __('Fallback interval (s)','dfehc'), function(){ $this->f_number('dfehc_fallback_interval','1','0'); }, $this->plugin->slug, 'dfehc_adv_core_thresholds' );
    287         add_settings_field( 'dfehc_unknown_load', __('Unknown load sentinel','dfehc'), function(){ $this->f_number('dfehc_unknown_load','0.001'); }, $this->plugin->slug, 'dfehc_adv_core_thresholds' );
    288         add_settings_field( 'dfehc_max_server_load', __('Max server load','dfehc'), function(){ $this->f_number('dfehc_max_server_load','0.01'); }, $this->plugin->slug, 'dfehc_adv_core_thresholds' );
    289 
    290         add_settings_field( 'dfehc_interval_factors', __('Interval factors (JSON)','dfehc'), function(){ $this->f_json('dfehc_interval_factors'); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
    291         add_settings_field( 'dfehc_interval_weights', __('Interval weights (JSON)','dfehc'), function(){ $this->f_json('dfehc_interval_weights'); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
    292         add_settings_field( 'dfehc_load_weights', __('Load weights (JSON)','dfehc'), function(){ $this->f_json('dfehc_load_weights'); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
    293         add_settings_field( 'dfehc_normalize_load', __('Normalize load','dfehc'), function(){ $this->f_checkbox('dfehc_normalize_load'); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
    294         add_settings_field( 'dfehc_assumed_cores_for_normalization', __('Assumed cores for normalization','dfehc'), function(){ $this->f_number('dfehc_assumed_cores_for_normalization','1','0'); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
    295         add_settings_field( 'dfehc_max_increase_rate', __('Max increase rate','dfehc'), function(){ $this->f_number('dfehc_max_increase_rate','0.01'); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
    296         add_settings_field( 'dfehc_interval_snap', __('Interval snap','dfehc'), function(){ $this->f_number('dfehc_interval_snap','1','0'); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
    297         add_settings_field( 'dfehc_response_time_is_ms', __('Response time is ms','dfehc'), function(){ $this->f_checkbox('dfehc_response_time_is_ms'); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
    298         add_settings_field( 'dfehc_contextual_load_value', __('Contextual load value','dfehc'), function(){ $this->f_number('dfehc_contextual_load_value','0.01'); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
    299         add_settings_field( 'dfehc_divide_cpu_load', __('Divide CPU load','dfehc'), function(){ $this->f_checkbox('dfehc_divide_cpu_load'); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
    300         add_settings_field( 'dfehc_cpu_cores', __('CPU cores override','dfehc'), function(){ $this->f_number('dfehc_cpu_cores','1','0'); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
    301 
    302         add_settings_field( 'dfehc_server_load_ttl', __('Server load TTL (s)','dfehc'), function(){ $this->f_number('dfehc_server_load_ttl','1','0'); }, $this->plugin->slug, 'dfehc_adv_caching_persistence' );
    303         add_settings_field( 'dfehc_transient_ttl', __('Transient TTL (s)','dfehc'), function(){ $this->f_number('dfehc_transient_ttl','1','0'); }, $this->plugin->slug, 'dfehc_adv_caching_persistence' );
    304         add_settings_field( 'dfehc_ema_ttl', __('EMA TTL (s)','dfehc'), function(){ $this->f_number('dfehc_ema_ttl','1','0'); }, $this->plugin->slug, 'dfehc_adv_caching_persistence' );
    305         add_settings_field( 'dfehc_prev_interval_ttl', __('Previous interval TTL (s)','dfehc'), function(){ $this->f_number('dfehc_prev_interval_ttl','1','0'); }, $this->plugin->slug, 'dfehc_adv_caching_persistence' );
    306         add_settings_field( 'dfehc_cache_retry_after', __('Cache retry-after (s)','dfehc'), function(){ $this->f_number('dfehc_cache_retry_after','1','0'); }, $this->plugin->slug, 'dfehc_adv_caching_persistence' );
    307         add_settings_field( 'dfehc_redis_user', __('Redis user','dfehc'), function(){ $this->f_text('dfehc_redis_user'); }, $this->plugin->slug, 'dfehc_adv_caching_persistence' );
    308         add_settings_field( 'dfehc_redis_auth', __('Redis auth','dfehc'), function(){ $this->f_text('dfehc_redis_auth'); }, $this->plugin->slug, 'dfehc_adv_caching_persistence' );
     265        add_settings_field( 'dfehc_client_ip_public_only', __('Public IP only','dfehc'), function(){ $this->f_checkbox('dfehc_client_ip_public_only', 1); }, $this->plugin->slug, 'dfehc_adv_ip_proxy' );
     266        add_settings_field( 'dfehc_trusted_proxies', __('Trusted proxies (one per line)','dfehc'), function(){ $this->f_textarea('dfehc_trusted_proxies',"127.0.0.1\n10.0.0.0/8", ''); }, $this->plugin->slug, 'dfehc_adv_ip_proxy' );
     267        add_settings_field( 'dfehc_proxy_ip_headers', __('Proxy IP headers (one per line)','dfehc'), function(){ $this->f_textarea('dfehc_proxy_ip_headers',"X-Forwarded-For\nCF-Connecting-IP", "HTTP_CF_CONNECTING_IP\nHTTP_TRUE_CLIENT_IP\nHTTP_X_REAL_IP\nHTTP_X_FORWARDED_FOR"); }, $this->plugin->slug, 'dfehc_adv_ip_proxy' );
     268        add_settings_field( 'dfehc_client_ip', __('Client IP override','dfehc'), function(){ $this->f_text('dfehc_client_ip','', ''); }, $this->plugin->slug, 'dfehc_adv_ip_proxy' );
     269
     270        add_settings_field( 'dfehc_default_response_time', __('Default response time','dfehc'), function(){ $this->f_number('dfehc_default_response_time','0.01','','', 0.0); }, $this->plugin->slug, 'dfehc_adv_response_spike' );
     271        add_settings_field( 'dfehc_spike_threshold_factor', __('Spike threshold factor','dfehc'), function(){ $this->f_number('dfehc_spike_threshold_factor','0.01','','', 0.0); }, $this->plugin->slug, 'dfehc_adv_response_spike' );
     272        add_settings_field( 'dfehc_spike_increment_floor', __('Spike increment floor','dfehc'), function(){ $this->f_number('dfehc_spike_increment_floor','0.01','','', 0.0); }, $this->plugin->slug, 'dfehc_adv_response_spike' );
     273        add_settings_field( 'dfehc_spike_increment_cap', __('Spike increment cap','dfehc'), function(){ $this->f_number('dfehc_spike_increment_cap','0.01','','', 0.0); }, $this->plugin->slug, 'dfehc_adv_response_spike' );
     274        add_settings_field( 'dfehc_spike_decay', __('Spike decay','dfehc'), function(){ $this->f_number('dfehc_spike_decay','0.01','','', 0.0); }, $this->plugin->slug, 'dfehc_adv_response_spike' );
     275        add_settings_field( 'dfehc_recalibrate_threshold', __('Recalibrate threshold','dfehc'), function(){ $this->f_number('dfehc_recalibrate_threshold','0.01','','', 0.0); }, $this->plugin->slug, 'dfehc_adv_response_spike' );
     276        add_settings_field( 'dfehc_trim_extremes', __('Trim extremes','dfehc'), function(){ $this->f_checkbox('dfehc_trim_extremes', 0); }, $this->plugin->slug, 'dfehc_adv_response_spike' );
     277
     278        add_settings_field( 'dfehc_high_traffic_cache_expiration', __('High traffic cache expiration (s)','dfehc'), function(){ $this->f_number('dfehc_high_traffic_cache_expiration','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
     279        add_settings_field( 'dfehc_max_baseline_age', __('Max baseline age (s)','dfehc'), function(){ $this->f_number('dfehc_max_baseline_age','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
     280        add_settings_field( 'dfehc_baseline_min_samples', __('Baseline min samples','dfehc'), function(){ $this->f_number('dfehc_baseline_min_samples','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
     281        add_settings_field( 'dfehc_baseline_expiration', __('Baseline expiration (s)','dfehc'), function(){ $this->f_number('dfehc_baseline_expiration','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
     282        add_settings_field( 'dfehc_cache_expiration', __('Cache expiration (s)','dfehc'), function(){ $this->f_number('dfehc_cache_expiration','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
     283        add_settings_field( 'dfehc_head_negative_ttl', __('HEAD negative TTL (s)','dfehc'), function(){ $this->f_number('dfehc_head_negative_ttl','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
     284        add_settings_field( 'dfehc_head_positive_ttl', __('HEAD positive TTL (s)','dfehc'), function(){ $this->f_number('dfehc_head_positive_ttl','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
     285        add_settings_field( 'dfehc_probe_fail_ttl', __('Probe fail TTL (s)','dfehc'), function(){ $this->f_number('dfehc_probe_fail_ttl','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
     286
     287        add_settings_field( 'dfehc_disable_loopback', __('Disable loopback','dfehc'), function(){ $this->f_checkbox('dfehc_disable_loopback', 0); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
     288        add_settings_field( 'dfehc_probe_headers', __('Probe headers (one per line: Key: Value)','dfehc'), function(){ $this->f_textarea('dfehc_probe_headers',"User-Agent: DFEHC\nAccept: */*", ''); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
     289        add_settings_field( 'dfehc_total_timeout', __('Total timeout (s)','dfehc'), function(){ $this->f_number('dfehc_total_timeout','0.1','0','', 0.0); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
     290        add_settings_field( 'dfehc_request_timeout', __('Request timeout (s)','dfehc'), function(){ $this->f_number('dfehc_request_timeout','0.1','0','', 0.0); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
     291        add_settings_field( 'dfehc_num_requests', __('Number of requests','dfehc'), function(){ $this->f_number('dfehc_num_requests','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
     292        add_settings_field( 'dfehc_request_pause_us', __('Pause between requests (µs)','dfehc'), function(){ $this->f_number('dfehc_request_pause_us','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
     293        add_settings_field( 'dfehc_ssl_verify', __('SSL verify','dfehc'), function(){ $this->f_checkbox('dfehc_ssl_verify', 0); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
     294        add_settings_field( 'dfehc_use_get_fallback', __('Use GET fallback','dfehc'), function(){ $this->f_checkbox('dfehc_use_get_fallback', 0); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
     295        add_settings_field( 'dfehc_use_head_method', __('Use HEAD method','dfehc'), function(){ $this->f_checkbox('dfehc_use_head_method', 0); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
     296        add_settings_field( 'dfehc_redirection', __('Max redirections','dfehc'), function(){ $this->f_number('dfehc_redirection','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
     297        add_settings_field( 'dfehc_limit_response_size', __('Limit response size (bytes)','dfehc'), function(){ $this->f_number('dfehc_limit_response_size','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
     298
     299        add_settings_field( 'dfehc_ping_rl_ttl', __('Ping rate-limit TTL (s)','dfehc'), function(){ $this->f_number('dfehc_ping_rl_ttl','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
     300        add_settings_field( 'dfehc_ping_rl_limit', __('Ping rate-limit limit','dfehc'), function(){ $this->f_number('dfehc_ping_rl_limit','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
     301        add_settings_field( 'dfehc_enable_public_ping', __('Enable public ping','dfehc'), function(){ $this->f_checkbox('dfehc_enable_public_ping', 0); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
     302        add_settings_field( 'dfehc_high_traffic_threshold', __('High traffic threshold','dfehc'), function(){ $this->f_number('dfehc_high_traffic_threshold','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
     303        add_settings_field( 'dfehc_website_visitors', __('Website visitors override','dfehc'), function(){ $this->f_number('dfehc_website_visitors','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
     304        add_settings_field( 'dfehc_current_server_load', __('Current server load override','dfehc'), function(){ $this->f_number('dfehc_current_server_load','0.01','','', 0.0); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
     305        add_settings_field( 'dfehc_high_traffic_load_threshold', __('High traffic load threshold','dfehc'), function(){ $this->f_number('dfehc_high_traffic_load_threshold','0.01','','', 0.0); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
     306        add_settings_field( 'dfehc_allow_public_server_load', __('Allow public server load','dfehc'), function(){ $this->f_checkbox('dfehc_allow_public_server_load', 0); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
     307        add_settings_field( 'dfehc_allow_public_async', __('Allow public async','dfehc'), function(){ $this->f_checkbox('dfehc_allow_public_async', 0); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
     308
     309        add_settings_field( 'dfehc_min_interval', __('Min interval (s)','dfehc'), function(){ $this->f_number('dfehc_min_interval','1','0','', 15); }, $this->plugin->slug, 'dfehc_adv_core_thresholds' );
     310        add_settings_field( 'dfehc_max_interval', __('Max interval (s)','dfehc'), function(){ $this->f_number('dfehc_max_interval','1','0','', 300); }, $this->plugin->slug, 'dfehc_adv_core_thresholds' );
     311        add_settings_field( 'dfehc_fallback_interval', __('Fallback interval (s)','dfehc'), function(){ $this->f_number('dfehc_fallback_interval','1','0','', 60); }, $this->plugin->slug, 'dfehc_adv_core_thresholds' );
     312        add_settings_field( 'dfehc_unknown_load', __('Unknown load sentinel','dfehc'), function(){ $this->f_number('dfehc_unknown_load','0.001','','', 0.404); }, $this->plugin->slug, 'dfehc_adv_core_thresholds' );
     313        add_settings_field( 'dfehc_max_server_load', __('Max server load','dfehc'), function(){ $this->f_number('dfehc_max_server_load','0.01','','', 85); }, $this->plugin->slug, 'dfehc_adv_core_thresholds' );
     314
     315        add_settings_field( 'dfehc_interval_factors', __('Interval factors (JSON)','dfehc'), function(){ $this->f_json('dfehc_interval_factors','', ''); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
     316        add_settings_field( 'dfehc_interval_weights', __('Interval weights (JSON)','dfehc'), function(){ $this->f_json('dfehc_interval_weights','', ''); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
     317        add_settings_field( 'dfehc_load_weights', __('Load weights (JSON)','dfehc'), function(){ $this->f_json('dfehc_load_weights','', ''); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
     318        add_settings_field( 'dfehc_normalize_load', __('Normalize load','dfehc'), function(){ $this->f_checkbox('dfehc_normalize_load', 0); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
     319        add_settings_field( 'dfehc_assumed_cores_for_normalization', __('Assumed cores for normalization','dfehc'), function(){ $this->f_number('dfehc_assumed_cores_for_normalization','0.1','0','', 8.0); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
     320        add_settings_field( 'dfehc_max_increase_rate', __('Max increase rate','dfehc'), function(){ $this->f_number('dfehc_max_increase_rate','0.01','','', 0.5); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
     321        add_settings_field( 'dfehc_interval_snap', __('Interval snap','dfehc'), function(){ $this->f_number('dfehc_interval_snap','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
     322        add_settings_field( 'dfehc_response_time_is_ms', __('Response time is ms','dfehc'), function(){ $this->f_checkbox('dfehc_response_time_is_ms', 0); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
     323        add_settings_field( 'dfehc_contextual_load_value', __('Contextual load value','dfehc'), function(){ $this->f_number('dfehc_contextual_load_value','0.01','','', 0.0); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
     324        add_settings_field( 'dfehc_divide_cpu_load', __('Divide CPU load','dfehc'), function(){ $this->f_checkbox('dfehc_divide_cpu_load', 1); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
     325        add_settings_field( 'dfehc_cpu_cores', __('CPU cores override','dfehc'), function(){ $this->f_number('dfehc_cpu_cores','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
     326
     327        add_settings_field( 'dfehc_server_load_ttl', __('Server load TTL (s)','dfehc'), function(){ $this->f_number('dfehc_server_load_ttl','1','0','', 180); }, $this->plugin->slug, 'dfehc_adv_caching_persistence' );
     328        add_settings_field( 'dfehc_transient_ttl', __('Transient TTL (s)','dfehc'), function(){ $this->f_number('dfehc_transient_ttl','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_caching_persistence' );
     329        add_settings_field( 'dfehc_ema_ttl', __('EMA TTL (s)','dfehc'), function(){ $this->f_number('dfehc_ema_ttl','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_caching_persistence' );
     330        add_settings_field( 'dfehc_prev_interval_ttl', __('Previous interval TTL (s)','dfehc'), function(){ $this->f_number('dfehc_prev_interval_ttl','1','0','', 1800); }, $this->plugin->slug, 'dfehc_adv_caching_persistence' );
     331        add_settings_field( 'dfehc_cache_retry_after', __('Cache retry-after (s)','dfehc'), function(){ $this->f_number('dfehc_cache_retry_after','1','0','', 60); }, $this->plugin->slug, 'dfehc_adv_caching_persistence' );
     332        add_settings_field( 'dfehc_redis_user', __('Redis user','dfehc'), function(){ $this->f_text('dfehc_redis_user','', (string) (getenv('REDIS_USERNAME') ?: '')); }, $this->plugin->slug, 'dfehc_adv_caching_persistence' );
     333        add_settings_field( 'dfehc_redis_auth', __('Redis auth','dfehc'), function(){ $this->f_text('dfehc_redis_auth','', (string) (getenv('REDIS_PASSWORD') ?: '')); }, $this->plugin->slug, 'dfehc_adv_caching_persistence' );
     334
     335        add_settings_field( 'dfehc_required_capability', __('Required capability','dfehc'), function(){ $this->f_text('dfehc_required_capability','read', 'read'); }, $this->plugin->slug, 'dfehc_adv_access_security' );
     336        add_settings_field( 'dfehc_public_rate_limit', __('Public rate limit','dfehc'), function(){ $this->f_number('dfehc_public_rate_limit','1','0','', 60); }, $this->plugin->slug, 'dfehc_adv_access_security' );
     337        add_settings_field( 'dfehc_public_rate_window', __('Public rate window (s)','dfehc'), function(){ $this->f_number('dfehc_public_rate_window','1','0','', 60); }, $this->plugin->slug, 'dfehc_adv_access_security' );
     338
     339        add_settings_field( 'dfehc_enable_load_logging', __('Enable load logging','dfehc'), function(){ $this->f_checkbox('dfehc_enable_load_logging', 1); }, $this->plugin->slug, 'dfehc_adv_logging_maintenance' );
     340        add_settings_field( 'dfehc_log_retention_seconds', __('Log retention seconds','dfehc'), function(){ $this->f_number('dfehc_log_retention_seconds','1','0','', 86400); }, $this->plugin->slug, 'dfehc_adv_logging_maintenance' );
     341        add_settings_field( 'dfehc_log_retention_max', __('Log retention max','dfehc'), function(){ $this->f_number('dfehc_log_retention_max','1','0','', 2000); }, $this->plugin->slug, 'dfehc_adv_logging_maintenance' );
     342        add_settings_field( 'dfehc_prune_chunk_size', __('Prune chunk size','dfehc'), function(){ $this->f_number('dfehc_prune_chunk_size','1','1','', 50); }, $this->plugin->slug, 'dfehc_adv_logging_maintenance' );
    309343    }
    310344
     
    392426        echo '</details>';
    393427
     428        echo '<details class="dfehc-adv-group"><summary>'.esc_html__('Access & Security','dfehc').'</summary>';
     429        $this->render_section( $this->plugin->slug, 'dfehc_adv_access_security', false );
     430        echo '</details>';
     431
     432        echo '<details class="dfehc-adv-group"><summary>'.esc_html__('Logging & Maintenance','dfehc').'</summary>';
     433        $this->render_section( $this->plugin->slug, 'dfehc_adv_logging_maintenance', false );
     434        echo '</details>';
     435
    394436        echo '<details class="dfehc-adv-group"><summary>'.esc_html__('Heartbeat Zoom Settings','dfehc').'</summary>';
    395437        $this->render_section( $this->plugin->slug, 'dfehc_load_display_settings_section', false );
     
    398440        submit_button( null, 'primary', 'submit', true );
    399441        echo '</div>';
     442
     443        echo '<script>
     444(function(){
     445    var form = document.getElementById("dfehc-settings-form");
     446    if (!form) return;
     447
     448    function setPanelEnabled(panel, enabled){
     449        var els = panel.querySelectorAll("input,select,textarea,button");
     450        els.forEach(function(el){
     451            var isNamed = !!el.name || el.tagName === "BUTTON";
     452            if (!isNamed) return;
     453
     454            if (!enabled) {
     455                if (el.dataset.dfehcPrevDisabled === undefined) {
     456                    el.dataset.dfehcPrevDisabled = el.disabled ? "1" : "0";
     457                }
     458                el.disabled = true;
     459                return;
     460            }
     461
     462            if (el.dataset.dfehcPrevDisabled !== undefined) {
     463                el.disabled = (el.dataset.dfehcPrevDisabled === "1");
     464                delete el.dataset.dfehcPrevDisabled;
     465            }
     466        });
     467    }
     468
     469    function getActiveTabId(){
     470        var p = form.querySelector(".dfehc-tab-panel.is-active");
     471        return p ? p.id : "dfehc_tab_heartbeat";
     472    }
     473
     474    function sync(){
     475        var activeId = getActiveTabId();
     476        var panels = form.querySelectorAll(".dfehc-tab-panel");
     477        panels.forEach(function(p){
     478            setPanelEnabled(p, p.id === activeId);
     479        });
     480    }
     481
     482    sync();
     483
     484    window.addEventListener("load", sync);
     485    document.addEventListener("visibilitychange", function(){
     486        if (!document.hidden) sync();
     487    });
     488
     489    document.querySelectorAll(".dfehc-tabs a[data-tab]").forEach(function(a){
     490        a.addEventListener("click", function(){
     491            var id = a.getAttribute("data-tab");
     492            if (!id) return;
     493
     494            var panels = form.querySelectorAll(".dfehc-tab-panel");
     495            panels.forEach(function(p){
     496                setPanelEnabled(p, p.id === id);
     497            });
     498
     499            setTimeout(sync, 0);
     500        });
     501    });
     502
     503    form.addEventListener("submit", function(){
     504        sync();
     505    });
     506
     507    var mo = new MutationObserver(function(){
     508        sync();
     509    });
     510
     511    mo.observe(form, { attributes: true, subtree: true, attributeFilter: ["class"] });
     512})();
     513</script>';
    400514
    401515        echo '</form>';
  • dynamic-front-end-heartbeat-control/trunk/admin/affix.php

    r3427163 r3427251  
    3535    private function s_text( $v ) {
    3636        return sanitize_text_field( is_string($v) ? $v : '' );
     37    }
     38
     39    private function s_cap( $v ) {
     40        $v = sanitize_key( is_string($v) ? $v : '' );
     41        return $v !== '' ? $v : 'read';
    3742    }
    3843
     
    6469    }
    6570
    66     private function f_text( string $key, string $placeholder = '' ): void {
    67         $val = get_option($key, '');
     71    private function f_text( string $key, string $placeholder = '', $default = '' ): void {
     72        $val = get_option($key, $default);
    6873        echo '<input type="text" class="regular-text" name="'.esc_attr($key).'" value="'.esc_attr((string)$val).'" placeholder="'.esc_attr($placeholder).'" />';
    6974        echo '<p class="description"><code>'.esc_html($key).'</code></p>';
    7075    }
    7176
    72     private function f_number( string $key, string $step = '1', string $min = '', string $max = '' ): void {
    73         $val = get_option($key, '');
     77    private function f_number( string $key, string $step = '1', string $min = '', string $max = '', $default = '' ): void {
     78        $val = get_option($key, $default);
    7479        echo '<input type="number" name="'.esc_attr($key).'" value="'.esc_attr((string)$val).'" step="'.esc_attr($step).'"'.($min!==''?' min="'.esc_attr($min).'"':'').($max!==''?' max="'.esc_attr($max).'"':'').' />';
    7580        echo '<p class="description"><code>'.esc_html($key).'</code></p>';
    7681    }
    7782
    78     private function f_checkbox( string $key ): void {
    79         $val = (int) get_option($key, 0);
     83    private function f_checkbox( string $key, $default = 0 ): void {
     84        $val = (int) get_option($key, $default);
     85        echo '<input type="hidden" name="'.esc_attr($key).'" value="0" />';
    8086        echo '<label><input type="checkbox" name="'.esc_attr($key).'" value="1" '.checked(1,$val,false).' /> ' . esc_html__('Enabled', 'dfehc') . '</label>';
    8187        echo '<p class="description"><code>'.esc_html($key).'</code></p>';
    8288    }
    8389
    84     private function f_textarea( string $key, string $placeholder = '' ): void {
    85         $val = get_option($key, '');
     90    private function f_textarea( string $key, string $placeholder = '', $default = '' ): void {
     91        $val = get_option($key, $default);
    8692        echo '<textarea name="'.esc_attr($key).'" rows="5" class="large-text code" placeholder="'.esc_attr($placeholder).'">'.esc_textarea((string)$val).'</textarea>';
    8793        echo '<p class="description"><code>'.esc_html($key).'</code></p>';
    8894    }
    8995
    90     private function f_json( string $key, string $placeholder = '' ): void {
    91         $val = get_option($key, '');
     96    private function f_json( string $key, string $placeholder = '', $default = '' ): void {
     97        $val = get_option($key, $default);
    9298        echo '<textarea name="'.esc_attr($key).'" rows="6" class="large-text code" placeholder="'.esc_attr($placeholder).'">'.esc_textarea((string)$val).'</textarea>';
    9399        echo '<p class="description">'.esc_html__('JSON format. Leave empty to use defaults.', 'dfehc').' <code>'.esc_html($key).'</code></p>';
     
    120126
    121127    public function reg() {
     128        $keep = function(string $key, callable $san) {
     129            return function($v) use ($key, $san) {
     130                if ($v === null) return get_option($key);
     131                if (is_string($v) && trim($v) === '') return get_option($key);
     132                return call_user_func($san, $v);
     133            };
     134        };
     135
    122136        register_setting( $this->plugin->og, 'dfehc_heartbeat_zoom', 'floatval' );
    123137        register_setting( $this->plugin->og, 'dfehc_priority_slider', 'intval' );
     
    135149        register_setting( $this->plugin->og, 'add_to_menu', 'absint' );
    136150
    137         register_setting( $this->plugin->og, 'dfehc_client_ip_public_only', [$this,'s_bool'] );
    138         register_setting( $this->plugin->og, 'dfehc_trusted_proxies', [$this,'s_lines'] );
    139         register_setting( $this->plugin->og, 'dfehc_proxy_ip_headers', [$this,'s_lines'] );
    140         register_setting( $this->plugin->og, 'dfehc_client_ip', [$this,'s_text'] );
    141 
    142         register_setting( $this->plugin->og, 'dfehc_default_response_time', [$this,'s_float'] );
    143         register_setting( $this->plugin->og, 'dfehc_spike_threshold_factor', [$this,'s_float'] );
    144         register_setting( $this->plugin->og, 'dfehc_spike_increment_floor', [$this,'s_float'] );
    145         register_setting( $this->plugin->og, 'dfehc_spike_increment_cap', [$this,'s_float'] );
    146         register_setting( $this->plugin->og, 'dfehc_spike_decay', [$this,'s_float'] );
    147         register_setting( $this->plugin->og, 'dfehc_recalibrate_threshold', [$this,'s_float'] );
    148         register_setting( $this->plugin->og, 'dfehc_trim_extremes', [$this,'s_bool'] );
    149 
    150         register_setting( $this->plugin->og, 'dfehc_high_traffic_cache_expiration', [$this,'s_int'] );
    151         register_setting( $this->plugin->og, 'dfehc_max_baseline_age', [$this,'s_int'] );
    152         register_setting( $this->plugin->og, 'dfehc_baseline_min_samples', [$this,'s_int'] );
    153         register_setting( $this->plugin->og, 'dfehc_baseline_expiration', [$this,'s_int'] );
    154         register_setting( $this->plugin->og, 'dfehc_cache_expiration', [$this,'s_int'] );
    155         register_setting( $this->plugin->og, 'dfehc_head_negative_ttl', [$this,'s_int'] );
    156         register_setting( $this->plugin->og, 'dfehc_head_positive_ttl', [$this,'s_int'] );
    157         register_setting( $this->plugin->og, 'dfehc_probe_fail_ttl', [$this,'s_int'] );
    158 
    159         register_setting( $this->plugin->og, 'dfehc_disable_loopback', [$this,'s_bool'] );
    160         register_setting( $this->plugin->og, 'dfehc_probe_headers', [$this,'s_lines'] );
    161         register_setting( $this->plugin->og, 'dfehc_total_timeout', [$this,'s_float'] );
    162         register_setting( $this->plugin->og, 'dfehc_request_timeout', [$this,'s_float'] );
    163         register_setting( $this->plugin->og, 'dfehc_num_requests', [$this,'s_int'] );
    164         register_setting( $this->plugin->og, 'dfehc_request_pause_us', [$this,'s_int'] );
    165         register_setting( $this->plugin->og, 'dfehc_ssl_verify', [$this,'s_bool'] );
    166         register_setting( $this->plugin->og, 'dfehc_use_get_fallback', [$this,'s_bool'] );
    167         register_setting( $this->plugin->og, 'dfehc_use_head_method', [$this,'s_bool'] );
    168         register_setting( $this->plugin->og, 'dfehc_redirection', [$this,'s_int'] );
    169         register_setting( $this->plugin->og, 'dfehc_limit_response_size', [$this,'s_int'] );
    170 
    171         register_setting( $this->plugin->og, 'dfehc_ping_rl_ttl', [$this,'s_int'] );
    172         register_setting( $this->plugin->og, 'dfehc_ping_rl_limit', [$this,'s_int'] );
    173         register_setting( $this->plugin->og, 'dfehc_enable_public_ping', [$this,'s_bool'] );
    174         register_setting( $this->plugin->og, 'dfehc_high_traffic_threshold', [$this,'s_int'] );
    175         register_setting( $this->plugin->og, 'dfehc_website_visitors', [$this,'s_int'] );
    176         register_setting( $this->plugin->og, 'dfehc_current_server_load', [$this,'s_float'] );
    177         register_setting( $this->plugin->og, 'dfehc_high_traffic_load_threshold', [$this,'s_float'] );
    178         register_setting( $this->plugin->og, 'dfehc_allow_public_server_load', [$this,'s_bool'] );
    179         register_setting( $this->plugin->og, 'dfehc_allow_public_async', [$this,'s_bool'] );
    180 
    181         register_setting( $this->plugin->og, 'dfehc_min_interval', [$this,'s_int'] );
    182         register_setting( $this->plugin->og, 'dfehc_max_interval', [$this,'s_int'] );
    183         register_setting( $this->plugin->og, 'dfehc_fallback_interval', [$this,'s_int'] );
    184         register_setting( $this->plugin->og, 'dfehc_unknown_load', [$this,'s_float'] );
    185         register_setting( $this->plugin->og, 'dfehc_max_server_load', [$this,'s_float'] );
    186 
    187         register_setting( $this->plugin->og, 'dfehc_interval_factors', [$this,'s_json'] );
    188         register_setting( $this->plugin->og, 'dfehc_interval_weights', [$this,'s_json'] );
    189         register_setting( $this->plugin->og, 'dfehc_load_weights', [$this,'s_json'] );
    190         register_setting( $this->plugin->og, 'dfehc_normalize_load', [$this,'s_bool'] );
    191         register_setting( $this->plugin->og, 'dfehc_assumed_cores_for_normalization', [$this,'s_int'] );
    192         register_setting( $this->plugin->og, 'dfehc_max_increase_rate', [$this,'s_float'] );
    193         register_setting( $this->plugin->og, 'dfehc_interval_snap', [$this,'s_int'] );
    194         register_setting( $this->plugin->og, 'dfehc_response_time_is_ms', [$this,'s_bool'] );
    195         register_setting( $this->plugin->og, 'dfehc_contextual_load_value', [$this,'s_float'] );
    196         register_setting( $this->plugin->og, 'dfehc_divide_cpu_load', [$this,'s_bool'] );
    197         register_setting( $this->plugin->og, 'dfehc_cpu_cores', [$this,'s_int'] );
    198 
    199         register_setting( $this->plugin->og, 'dfehc_server_load_ttl', [$this,'s_int'] );
    200         register_setting( $this->plugin->og, 'dfehc_transient_ttl', [$this,'s_int'] );
    201         register_setting( $this->plugin->og, 'dfehc_ema_ttl', [$this,'s_int'] );
    202         register_setting( $this->plugin->og, 'dfehc_prev_interval_ttl', [$this,'s_int'] );
    203         register_setting( $this->plugin->og, 'dfehc_cache_retry_after', [$this,'s_int'] );
    204         register_setting( $this->plugin->og, 'dfehc_redis_auth', [$this,'s_text'] );
    205         register_setting( $this->plugin->og, 'dfehc_redis_user', [$this,'s_text'] );
     151        register_setting( $this->plugin->og, 'dfehc_client_ip_public_only', $keep('dfehc_client_ip_public_only', [$this,'s_bool']) );
     152        register_setting( $this->plugin->og, 'dfehc_trusted_proxies', $keep('dfehc_trusted_proxies', [$this,'s_lines']) );
     153        register_setting( $this->plugin->og, 'dfehc_proxy_ip_headers', $keep('dfehc_proxy_ip_headers', [$this,'s_lines']) );
     154        register_setting( $this->plugin->og, 'dfehc_client_ip', $keep('dfehc_client_ip', [$this,'s_text']) );
     155
     156        register_setting( $this->plugin->og, 'dfehc_default_response_time', $keep('dfehc_default_response_time', [$this,'s_float']) );
     157        register_setting( $this->plugin->og, 'dfehc_spike_threshold_factor', $keep('dfehc_spike_threshold_factor', [$this,'s_float']) );
     158        register_setting( $this->plugin->og, 'dfehc_spike_increment_floor', $keep('dfehc_spike_increment_floor', [$this,'s_float']) );
     159        register_setting( $this->plugin->og, 'dfehc_spike_increment_cap', $keep('dfehc_spike_increment_cap', [$this,'s_float']) );
     160        register_setting( $this->plugin->og, 'dfehc_spike_decay', $keep('dfehc_spike_decay', [$this,'s_float']) );
     161        register_setting( $this->plugin->og, 'dfehc_recalibrate_threshold', $keep('dfehc_recalibrate_threshold', [$this,'s_float']) );
     162        register_setting( $this->plugin->og, 'dfehc_trim_extremes', $keep('dfehc_trim_extremes', [$this,'s_bool']) );
     163
     164        register_setting( $this->plugin->og, 'dfehc_high_traffic_cache_expiration', $keep('dfehc_high_traffic_cache_expiration', [$this,'s_int']) );
     165        register_setting( $this->plugin->og, 'dfehc_max_baseline_age', $keep('dfehc_max_baseline_age', [$this,'s_int']) );
     166        register_setting( $this->plugin->og, 'dfehc_baseline_min_samples', $keep('dfehc_baseline_min_samples', [$this,'s_int']) );
     167        register_setting( $this->plugin->og, 'dfehc_baseline_expiration', $keep('dfehc_baseline_expiration', [$this,'s_int']) );
     168        register_setting( $this->plugin->og, 'dfehc_cache_expiration', $keep('dfehc_cache_expiration', [$this,'s_int']) );
     169        register_setting( $this->plugin->og, 'dfehc_head_negative_ttl', $keep('dfehc_head_negative_ttl', [$this,'s_int']) );
     170        register_setting( $this->plugin->og, 'dfehc_head_positive_ttl', $keep('dfehc_head_positive_ttl', [$this,'s_int']) );
     171        register_setting( $this->plugin->og, 'dfehc_probe_fail_ttl', $keep('dfehc_probe_fail_ttl', [$this,'s_int']) );
     172
     173        register_setting( $this->plugin->og, 'dfehc_disable_loopback', $keep('dfehc_disable_loopback', [$this,'s_bool']) );
     174        register_setting( $this->plugin->og, 'dfehc_probe_headers', $keep('dfehc_probe_headers', [$this,'s_lines']) );
     175        register_setting( $this->plugin->og, 'dfehc_total_timeout', $keep('dfehc_total_timeout', [$this,'s_float']) );
     176        register_setting( $this->plugin->og, 'dfehc_request_timeout', $keep('dfehc_request_timeout', [$this,'s_float']) );
     177        register_setting( $this->plugin->og, 'dfehc_num_requests', $keep('dfehc_num_requests', [$this,'s_int']) );
     178        register_setting( $this->plugin->og, 'dfehc_request_pause_us', $keep('dfehc_request_pause_us', [$this,'s_int']) );
     179        register_setting( $this->plugin->og, 'dfehc_ssl_verify', $keep('dfehc_ssl_verify', [$this,'s_bool']) );
     180        register_setting( $this->plugin->og, 'dfehc_use_get_fallback', $keep('dfehc_use_get_fallback', [$this,'s_bool']) );
     181        register_setting( $this->plugin->og, 'dfehc_use_head_method', $keep('dfehc_use_head_method', [$this,'s_bool']) );
     182        register_setting( $this->plugin->og, 'dfehc_redirection', $keep('dfehc_redirection', [$this,'s_int']) );
     183        register_setting( $this->plugin->og, 'dfehc_limit_response_size', $keep('dfehc_limit_response_size', [$this,'s_int']) );
     184
     185        register_setting( $this->plugin->og, 'dfehc_ping_rl_ttl', $keep('dfehc_ping_rl_ttl', [$this,'s_int']) );
     186        register_setting( $this->plugin->og, 'dfehc_ping_rl_limit', $keep('dfehc_ping_rl_limit', [$this,'s_int']) );
     187        register_setting( $this->plugin->og, 'dfehc_enable_public_ping', $keep('dfehc_enable_public_ping', [$this,'s_bool']) );
     188        register_setting( $this->plugin->og, 'dfehc_high_traffic_threshold', $keep('dfehc_high_traffic_threshold', [$this,'s_int']) );
     189        register_setting( $this->plugin->og, 'dfehc_website_visitors', $keep('dfehc_website_visitors', [$this,'s_int']) );
     190        register_setting( $this->plugin->og, 'dfehc_current_server_load', $keep('dfehc_current_server_load', [$this,'s_float']) );
     191        register_setting( $this->plugin->og, 'dfehc_high_traffic_load_threshold', $keep('dfehc_high_traffic_load_threshold', [$this,'s_float']) );
     192        register_setting( $this->plugin->og, 'dfehc_allow_public_server_load', $keep('dfehc_allow_public_server_load', [$this,'s_bool']) );
     193        register_setting( $this->plugin->og, 'dfehc_allow_public_async', $keep('dfehc_allow_public_async', [$this,'s_bool']) );
     194
     195        register_setting( $this->plugin->og, 'dfehc_min_interval', $keep('dfehc_min_interval', [$this,'s_int']) );
     196        register_setting( $this->plugin->og, 'dfehc_max_interval', $keep('dfehc_max_interval', [$this,'s_int']) );
     197        register_setting( $this->plugin->og, 'dfehc_fallback_interval', $keep('dfehc_fallback_interval', [$this,'s_int']) );
     198        register_setting( $this->plugin->og, 'dfehc_unknown_load', $keep('dfehc_unknown_load', [$this,'s_float']) );
     199        register_setting( $this->plugin->og, 'dfehc_max_server_load', $keep('dfehc_max_server_load', [$this,'s_float']) );
     200
     201        register_setting( $this->plugin->og, 'dfehc_interval_factors', $keep('dfehc_interval_factors', [$this,'s_json']) );
     202        register_setting( $this->plugin->og, 'dfehc_interval_weights', $keep('dfehc_interval_weights', [$this,'s_json']) );
     203        register_setting( $this->plugin->og, 'dfehc_load_weights', $keep('dfehc_load_weights', [$this,'s_json']) );
     204        register_setting( $this->plugin->og, 'dfehc_normalize_load', $keep('dfehc_normalize_load', [$this,'s_bool']) );
     205        register_setting( $this->plugin->og, 'dfehc_assumed_cores_for_normalization', $keep('dfehc_assumed_cores_for_normalization', [$this,'s_float']) );
     206        register_setting( $this->plugin->og, 'dfehc_max_increase_rate', $keep('dfehc_max_increase_rate', [$this,'s_float']) );
     207        register_setting( $this->plugin->og, 'dfehc_interval_snap', $keep('dfehc_interval_snap', [$this,'s_int']) );
     208        register_setting( $this->plugin->og, 'dfehc_response_time_is_ms', $keep('dfehc_response_time_is_ms', [$this,'s_bool']) );
     209        register_setting( $this->plugin->og, 'dfehc_contextual_load_value', $keep('dfehc_contextual_load_value', [$this,'s_float']) );
     210        register_setting( $this->plugin->og, 'dfehc_divide_cpu_load', $keep('dfehc_divide_cpu_load', [$this,'s_bool']) );
     211        register_setting( $this->plugin->og, 'dfehc_cpu_cores', $keep('dfehc_cpu_cores', [$this,'s_int']) );
     212
     213        register_setting( $this->plugin->og, 'dfehc_server_load_ttl', $keep('dfehc_server_load_ttl', [$this,'s_int']) );
     214        register_setting( $this->plugin->og, 'dfehc_transient_ttl', $keep('dfehc_transient_ttl', [$this,'s_int']) );
     215        register_setting( $this->plugin->og, 'dfehc_ema_ttl', $keep('dfehc_ema_ttl', [$this,'s_int']) );
     216        register_setting( $this->plugin->og, 'dfehc_prev_interval_ttl', $keep('dfehc_prev_interval_ttl', [$this,'s_int']) );
     217        register_setting( $this->plugin->og, 'dfehc_cache_retry_after', $keep('dfehc_cache_retry_after', [$this,'s_int']) );
     218        register_setting( $this->plugin->og, 'dfehc_redis_auth', $keep('dfehc_redis_auth', [$this,'s_text']) );
     219        register_setting( $this->plugin->og, 'dfehc_redis_user', $keep('dfehc_redis_user', [$this,'s_text']) );
     220
     221        register_setting( $this->plugin->og, 'dfehc_required_capability', $keep('dfehc_required_capability', [$this,'s_cap']) );
     222        register_setting( $this->plugin->og, 'dfehc_public_rate_limit', $keep('dfehc_public_rate_limit', [$this,'s_int']) );
     223        register_setting( $this->plugin->og, 'dfehc_public_rate_window', $keep('dfehc_public_rate_window', [$this,'s_int']) );
     224
     225        register_setting( $this->plugin->og, 'dfehc_enable_load_logging', $keep('dfehc_enable_load_logging', [$this,'s_bool']) );
     226        register_setting( $this->plugin->og, 'dfehc_log_retention_seconds', $keep('dfehc_log_retention_seconds', [$this,'s_int']) );
     227        register_setting( $this->plugin->og, 'dfehc_log_retention_max', $keep('dfehc_log_retention_max', [$this,'s_int']) );
     228        register_setting( $this->plugin->og, 'dfehc_prune_chunk_size', $keep('dfehc_prune_chunk_size', [$this,'s_int']) );
    206229
    207230        add_settings_section( 'dfhcsl_heartbeat_settings_section', __('Heartbeat Control Settings','dfehc'), [$this,'shb'], $this->plugin->slug );
     
    220243        add_settings_section( 'dfehc_adv_algorithm_logic', __('Algorithm & Logic','dfehc'), '__return_false', $this->plugin->slug );
    221244        add_settings_section( 'dfehc_adv_caching_persistence', __('Caching & Persistence','dfehc'), '__return_false', $this->plugin->slug );
     245        add_settings_section( 'dfehc_adv_access_security', __('Access & Security','dfehc'), '__return_false', $this->plugin->slug );
     246        add_settings_section( 'dfehc_adv_logging_maintenance', __('Logging & Maintenance','dfehc'), '__return_false', $this->plugin->slug );
    222247
    223248        add_settings_field( 'dfehc_disable_heartbeat', __('Disable Heartbeat','dfehc'), [$this,'fdis'], $this->plugin->slug, 'dfhcsl_heartbeat_settings_section' );
     
    238263        add_settings_field( 'dfehc_heartbeat_zoom', __('Heartbeat Zoom Multiplier','dfehc'), [$this,'fzm'], $this->plugin->slug, 'dfehc_load_display_settings_section' );
    239264
    240         add_settings_field( 'dfehc_client_ip_public_only', __('Public IP only','dfehc'), function(){ $this->f_checkbox('dfehc_client_ip_public_only'); }, $this->plugin->slug, 'dfehc_adv_ip_proxy' );
    241         add_settings_field( 'dfehc_trusted_proxies', __('Trusted proxies (one per line)','dfehc'), function(){ $this->f_textarea('dfehc_trusted_proxies',"127.0.0.1\n10.0.0.0/8"); }, $this->plugin->slug, 'dfehc_adv_ip_proxy' );
    242         add_settings_field( 'dfehc_proxy_ip_headers', __('Proxy IP headers (one per line)','dfehc'), function(){ $this->f_textarea('dfehc_proxy_ip_headers',"X-Forwarded-For\nCF-Connecting-IP"); }, $this->plugin->slug, 'dfehc_adv_ip_proxy' );
    243         add_settings_field( 'dfehc_client_ip', __('Client IP override','dfehc'), function(){ $this->f_text('dfehc_client_ip'); }, $this->plugin->slug, 'dfehc_adv_ip_proxy' );
    244 
    245         add_settings_field( 'dfehc_default_response_time', __('Default response time','dfehc'), function(){ $this->f_number('dfehc_default_response_time','0.01'); }, $this->plugin->slug, 'dfehc_adv_response_spike' );
    246         add_settings_field( 'dfehc_spike_threshold_factor', __('Spike threshold factor','dfehc'), function(){ $this->f_number('dfehc_spike_threshold_factor','0.01'); }, $this->plugin->slug, 'dfehc_adv_response_spike' );
    247         add_settings_field( 'dfehc_spike_increment_floor', __('Spike increment floor','dfehc'), function(){ $this->f_number('dfehc_spike_increment_floor','0.01'); }, $this->plugin->slug, 'dfehc_adv_response_spike' );
    248         add_settings_field( 'dfehc_spike_increment_cap', __('Spike increment cap','dfehc'), function(){ $this->f_number('dfehc_spike_increment_cap','0.01'); }, $this->plugin->slug, 'dfehc_adv_response_spike' );
    249         add_settings_field( 'dfehc_spike_decay', __('Spike decay','dfehc'), function(){ $this->f_number('dfehc_spike_decay','0.01'); }, $this->plugin->slug, 'dfehc_adv_response_spike' );
    250         add_settings_field( 'dfehc_recalibrate_threshold', __('Recalibrate threshold','dfehc'), function(){ $this->f_number('dfehc_recalibrate_threshold','0.01'); }, $this->plugin->slug, 'dfehc_adv_response_spike' );
    251         add_settings_field( 'dfehc_trim_extremes', __('Trim extremes','dfehc'), function(){ $this->f_checkbox('dfehc_trim_extremes'); }, $this->plugin->slug, 'dfehc_adv_response_spike' );
    252 
    253         add_settings_field( 'dfehc_high_traffic_cache_expiration', __('High traffic cache expiration (s)','dfehc'), function(){ $this->f_number('dfehc_high_traffic_cache_expiration','1','0'); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
    254         add_settings_field( 'dfehc_max_baseline_age', __('Max baseline age (s)','dfehc'), function(){ $this->f_number('dfehc_max_baseline_age','1','0'); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
    255         add_settings_field( 'dfehc_baseline_min_samples', __('Baseline min samples','dfehc'), function(){ $this->f_number('dfehc_baseline_min_samples','1','0'); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
    256         add_settings_field( 'dfehc_baseline_expiration', __('Baseline expiration (s)','dfehc'), function(){ $this->f_number('dfehc_baseline_expiration','1','0'); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
    257         add_settings_field( 'dfehc_cache_expiration', __('Cache expiration (s)','dfehc'), function(){ $this->f_number('dfehc_cache_expiration','1','0'); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
    258         add_settings_field( 'dfehc_head_negative_ttl', __('HEAD negative TTL (s)','dfehc'), function(){ $this->f_number('dfehc_head_negative_ttl','1','0'); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
    259         add_settings_field( 'dfehc_head_positive_ttl', __('HEAD positive TTL (s)','dfehc'), function(){ $this->f_number('dfehc_head_positive_ttl','1','0'); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
    260         add_settings_field( 'dfehc_probe_fail_ttl', __('Probe fail TTL (s)','dfehc'), function(){ $this->f_number('dfehc_probe_fail_ttl','1','0'); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
    261 
    262         add_settings_field( 'dfehc_disable_loopback', __('Disable loopback','dfehc'), function(){ $this->f_checkbox('dfehc_disable_loopback'); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
    263         add_settings_field( 'dfehc_probe_headers', __('Probe headers (one per line: Key: Value)','dfehc'), function(){ $this->f_textarea('dfehc_probe_headers',"User-Agent: DFEHC\nAccept: */*"); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
    264         add_settings_field( 'dfehc_total_timeout', __('Total timeout (s)','dfehc'), function(){ $this->f_number('dfehc_total_timeout','0.1','0'); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
    265         add_settings_field( 'dfehc_request_timeout', __('Request timeout (s)','dfehc'), function(){ $this->f_number('dfehc_request_timeout','0.1','0'); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
    266         add_settings_field( 'dfehc_num_requests', __('Number of requests','dfehc'), function(){ $this->f_number('dfehc_num_requests','1','0'); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
    267         add_settings_field( 'dfehc_request_pause_us', __('Pause between requests (µs)','dfehc'), function(){ $this->f_number('dfehc_request_pause_us','1','0'); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
    268         add_settings_field( 'dfehc_ssl_verify', __('SSL verify','dfehc'), function(){ $this->f_checkbox('dfehc_ssl_verify'); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
    269         add_settings_field( 'dfehc_use_get_fallback', __('Use GET fallback','dfehc'), function(){ $this->f_checkbox('dfehc_use_get_fallback'); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
    270         add_settings_field( 'dfehc_use_head_method', __('Use HEAD method','dfehc'), function(){ $this->f_checkbox('dfehc_use_head_method'); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
    271         add_settings_field( 'dfehc_redirection', __('Max redirections','dfehc'), function(){ $this->f_number('dfehc_redirection','1','0'); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
    272         add_settings_field( 'dfehc_limit_response_size', __('Limit response size (bytes)','dfehc'), function(){ $this->f_number('dfehc_limit_response_size','1','0'); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
    273 
    274         add_settings_field( 'dfehc_ping_rl_ttl', __('Ping rate-limit TTL (s)','dfehc'), function(){ $this->f_number('dfehc_ping_rl_ttl','1','0'); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
    275         add_settings_field( 'dfehc_ping_rl_limit', __('Ping rate-limit limit','dfehc'), function(){ $this->f_number('dfehc_ping_rl_limit','1','0'); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
    276         add_settings_field( 'dfehc_enable_public_ping', __('Enable public ping','dfehc'), function(){ $this->f_checkbox('dfehc_enable_public_ping'); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
    277         add_settings_field( 'dfehc_high_traffic_threshold', __('High traffic threshold','dfehc'), function(){ $this->f_number('dfehc_high_traffic_threshold','1','0'); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
    278         add_settings_field( 'dfehc_website_visitors', __('Website visitors override','dfehc'), function(){ $this->f_number('dfehc_website_visitors','1','0'); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
    279         add_settings_field( 'dfehc_current_server_load', __('Current server load override','dfehc'), function(){ $this->f_number('dfehc_current_server_load','0.01'); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
    280         add_settings_field( 'dfehc_high_traffic_load_threshold', __('High traffic load threshold','dfehc'), function(){ $this->f_number('dfehc_high_traffic_load_threshold','0.01'); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
    281         add_settings_field( 'dfehc_allow_public_server_load', __('Allow public server load','dfehc'), function(){ $this->f_checkbox('dfehc_allow_public_server_load'); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
    282         add_settings_field( 'dfehc_allow_public_async', __('Allow public async','dfehc'), function(){ $this->f_checkbox('dfehc_allow_public_async'); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
    283 
    284         add_settings_field( 'dfehc_min_interval', __('Min interval (s)','dfehc'), function(){ $this->f_number('dfehc_min_interval','1','0'); }, $this->plugin->slug, 'dfehc_adv_core_thresholds' );
    285         add_settings_field( 'dfehc_max_interval', __('Max interval (s)','dfehc'), function(){ $this->f_number('dfehc_max_interval','1','0'); }, $this->plugin->slug, 'dfehc_adv_core_thresholds' );
    286         add_settings_field( 'dfehc_fallback_interval', __('Fallback interval (s)','dfehc'), function(){ $this->f_number('dfehc_fallback_interval','1','0'); }, $this->plugin->slug, 'dfehc_adv_core_thresholds' );
    287         add_settings_field( 'dfehc_unknown_load', __('Unknown load sentinel','dfehc'), function(){ $this->f_number('dfehc_unknown_load','0.001'); }, $this->plugin->slug, 'dfehc_adv_core_thresholds' );
    288         add_settings_field( 'dfehc_max_server_load', __('Max server load','dfehc'), function(){ $this->f_number('dfehc_max_server_load','0.01'); }, $this->plugin->slug, 'dfehc_adv_core_thresholds' );
    289 
    290         add_settings_field( 'dfehc_interval_factors', __('Interval factors (JSON)','dfehc'), function(){ $this->f_json('dfehc_interval_factors'); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
    291         add_settings_field( 'dfehc_interval_weights', __('Interval weights (JSON)','dfehc'), function(){ $this->f_json('dfehc_interval_weights'); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
    292         add_settings_field( 'dfehc_load_weights', __('Load weights (JSON)','dfehc'), function(){ $this->f_json('dfehc_load_weights'); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
    293         add_settings_field( 'dfehc_normalize_load', __('Normalize load','dfehc'), function(){ $this->f_checkbox('dfehc_normalize_load'); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
    294         add_settings_field( 'dfehc_assumed_cores_for_normalization', __('Assumed cores for normalization','dfehc'), function(){ $this->f_number('dfehc_assumed_cores_for_normalization','1','0'); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
    295         add_settings_field( 'dfehc_max_increase_rate', __('Max increase rate','dfehc'), function(){ $this->f_number('dfehc_max_increase_rate','0.01'); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
    296         add_settings_field( 'dfehc_interval_snap', __('Interval snap','dfehc'), function(){ $this->f_number('dfehc_interval_snap','1','0'); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
    297         add_settings_field( 'dfehc_response_time_is_ms', __('Response time is ms','dfehc'), function(){ $this->f_checkbox('dfehc_response_time_is_ms'); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
    298         add_settings_field( 'dfehc_contextual_load_value', __('Contextual load value','dfehc'), function(){ $this->f_number('dfehc_contextual_load_value','0.01'); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
    299         add_settings_field( 'dfehc_divide_cpu_load', __('Divide CPU load','dfehc'), function(){ $this->f_checkbox('dfehc_divide_cpu_load'); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
    300         add_settings_field( 'dfehc_cpu_cores', __('CPU cores override','dfehc'), function(){ $this->f_number('dfehc_cpu_cores','1','0'); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
    301 
    302         add_settings_field( 'dfehc_server_load_ttl', __('Server load TTL (s)','dfehc'), function(){ $this->f_number('dfehc_server_load_ttl','1','0'); }, $this->plugin->slug, 'dfehc_adv_caching_persistence' );
    303         add_settings_field( 'dfehc_transient_ttl', __('Transient TTL (s)','dfehc'), function(){ $this->f_number('dfehc_transient_ttl','1','0'); }, $this->plugin->slug, 'dfehc_adv_caching_persistence' );
    304         add_settings_field( 'dfehc_ema_ttl', __('EMA TTL (s)','dfehc'), function(){ $this->f_number('dfehc_ema_ttl','1','0'); }, $this->plugin->slug, 'dfehc_adv_caching_persistence' );
    305         add_settings_field( 'dfehc_prev_interval_ttl', __('Previous interval TTL (s)','dfehc'), function(){ $this->f_number('dfehc_prev_interval_ttl','1','0'); }, $this->plugin->slug, 'dfehc_adv_caching_persistence' );
    306         add_settings_field( 'dfehc_cache_retry_after', __('Cache retry-after (s)','dfehc'), function(){ $this->f_number('dfehc_cache_retry_after','1','0'); }, $this->plugin->slug, 'dfehc_adv_caching_persistence' );
    307         add_settings_field( 'dfehc_redis_user', __('Redis user','dfehc'), function(){ $this->f_text('dfehc_redis_user'); }, $this->plugin->slug, 'dfehc_adv_caching_persistence' );
    308         add_settings_field( 'dfehc_redis_auth', __('Redis auth','dfehc'), function(){ $this->f_text('dfehc_redis_auth'); }, $this->plugin->slug, 'dfehc_adv_caching_persistence' );
     265        add_settings_field( 'dfehc_client_ip_public_only', __('Public IP only','dfehc'), function(){ $this->f_checkbox('dfehc_client_ip_public_only', 1); }, $this->plugin->slug, 'dfehc_adv_ip_proxy' );
     266        add_settings_field( 'dfehc_trusted_proxies', __('Trusted proxies (one per line)','dfehc'), function(){ $this->f_textarea('dfehc_trusted_proxies',"127.0.0.1\n10.0.0.0/8", ''); }, $this->plugin->slug, 'dfehc_adv_ip_proxy' );
     267        add_settings_field( 'dfehc_proxy_ip_headers', __('Proxy IP headers (one per line)','dfehc'), function(){ $this->f_textarea('dfehc_proxy_ip_headers',"X-Forwarded-For\nCF-Connecting-IP", "HTTP_CF_CONNECTING_IP\nHTTP_TRUE_CLIENT_IP\nHTTP_X_REAL_IP\nHTTP_X_FORWARDED_FOR"); }, $this->plugin->slug, 'dfehc_adv_ip_proxy' );
     268        add_settings_field( 'dfehc_client_ip', __('Client IP override','dfehc'), function(){ $this->f_text('dfehc_client_ip','', ''); }, $this->plugin->slug, 'dfehc_adv_ip_proxy' );
     269
     270        add_settings_field( 'dfehc_default_response_time', __('Default response time','dfehc'), function(){ $this->f_number('dfehc_default_response_time','0.01','','', 0.0); }, $this->plugin->slug, 'dfehc_adv_response_spike' );
     271        add_settings_field( 'dfehc_spike_threshold_factor', __('Spike threshold factor','dfehc'), function(){ $this->f_number('dfehc_spike_threshold_factor','0.01','','', 0.0); }, $this->plugin->slug, 'dfehc_adv_response_spike' );
     272        add_settings_field( 'dfehc_spike_increment_floor', __('Spike increment floor','dfehc'), function(){ $this->f_number('dfehc_spike_increment_floor','0.01','','', 0.0); }, $this->plugin->slug, 'dfehc_adv_response_spike' );
     273        add_settings_field( 'dfehc_spike_increment_cap', __('Spike increment cap','dfehc'), function(){ $this->f_number('dfehc_spike_increment_cap','0.01','','', 0.0); }, $this->plugin->slug, 'dfehc_adv_response_spike' );
     274        add_settings_field( 'dfehc_spike_decay', __('Spike decay','dfehc'), function(){ $this->f_number('dfehc_spike_decay','0.01','','', 0.0); }, $this->plugin->slug, 'dfehc_adv_response_spike' );
     275        add_settings_field( 'dfehc_recalibrate_threshold', __('Recalibrate threshold','dfehc'), function(){ $this->f_number('dfehc_recalibrate_threshold','0.01','','', 0.0); }, $this->plugin->slug, 'dfehc_adv_response_spike' );
     276        add_settings_field( 'dfehc_trim_extremes', __('Trim extremes','dfehc'), function(){ $this->f_checkbox('dfehc_trim_extremes', 0); }, $this->plugin->slug, 'dfehc_adv_response_spike' );
     277
     278        add_settings_field( 'dfehc_high_traffic_cache_expiration', __('High traffic cache expiration (s)','dfehc'), function(){ $this->f_number('dfehc_high_traffic_cache_expiration','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
     279        add_settings_field( 'dfehc_max_baseline_age', __('Max baseline age (s)','dfehc'), function(){ $this->f_number('dfehc_max_baseline_age','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
     280        add_settings_field( 'dfehc_baseline_min_samples', __('Baseline min samples','dfehc'), function(){ $this->f_number('dfehc_baseline_min_samples','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
     281        add_settings_field( 'dfehc_baseline_expiration', __('Baseline expiration (s)','dfehc'), function(){ $this->f_number('dfehc_baseline_expiration','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
     282        add_settings_field( 'dfehc_cache_expiration', __('Cache expiration (s)','dfehc'), function(){ $this->f_number('dfehc_cache_expiration','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
     283        add_settings_field( 'dfehc_head_negative_ttl', __('HEAD negative TTL (s)','dfehc'), function(){ $this->f_number('dfehc_head_negative_ttl','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
     284        add_settings_field( 'dfehc_head_positive_ttl', __('HEAD positive TTL (s)','dfehc'), function(){ $this->f_number('dfehc_head_positive_ttl','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
     285        add_settings_field( 'dfehc_probe_fail_ttl', __('Probe fail TTL (s)','dfehc'), function(){ $this->f_number('dfehc_probe_fail_ttl','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_caching_baselines' );
     286
     287        add_settings_field( 'dfehc_disable_loopback', __('Disable loopback','dfehc'), function(){ $this->f_checkbox('dfehc_disable_loopback', 0); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
     288        add_settings_field( 'dfehc_probe_headers', __('Probe headers (one per line: Key: Value)','dfehc'), function(){ $this->f_textarea('dfehc_probe_headers',"User-Agent: DFEHC\nAccept: */*", ''); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
     289        add_settings_field( 'dfehc_total_timeout', __('Total timeout (s)','dfehc'), function(){ $this->f_number('dfehc_total_timeout','0.1','0','', 0.0); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
     290        add_settings_field( 'dfehc_request_timeout', __('Request timeout (s)','dfehc'), function(){ $this->f_number('dfehc_request_timeout','0.1','0','', 0.0); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
     291        add_settings_field( 'dfehc_num_requests', __('Number of requests','dfehc'), function(){ $this->f_number('dfehc_num_requests','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
     292        add_settings_field( 'dfehc_request_pause_us', __('Pause between requests (µs)','dfehc'), function(){ $this->f_number('dfehc_request_pause_us','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
     293        add_settings_field( 'dfehc_ssl_verify', __('SSL verify','dfehc'), function(){ $this->f_checkbox('dfehc_ssl_verify', 0); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
     294        add_settings_field( 'dfehc_use_get_fallback', __('Use GET fallback','dfehc'), function(){ $this->f_checkbox('dfehc_use_get_fallback', 0); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
     295        add_settings_field( 'dfehc_use_head_method', __('Use HEAD method','dfehc'), function(){ $this->f_checkbox('dfehc_use_head_method', 0); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
     296        add_settings_field( 'dfehc_redirection', __('Max redirections','dfehc'), function(){ $this->f_number('dfehc_redirection','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
     297        add_settings_field( 'dfehc_limit_response_size', __('Limit response size (bytes)','dfehc'), function(){ $this->f_number('dfehc_limit_response_size','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_loopback_http' );
     298
     299        add_settings_field( 'dfehc_ping_rl_ttl', __('Ping rate-limit TTL (s)','dfehc'), function(){ $this->f_number('dfehc_ping_rl_ttl','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
     300        add_settings_field( 'dfehc_ping_rl_limit', __('Ping rate-limit limit','dfehc'), function(){ $this->f_number('dfehc_ping_rl_limit','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
     301        add_settings_field( 'dfehc_enable_public_ping', __('Enable public ping','dfehc'), function(){ $this->f_checkbox('dfehc_enable_public_ping', 0); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
     302        add_settings_field( 'dfehc_high_traffic_threshold', __('High traffic threshold','dfehc'), function(){ $this->f_number('dfehc_high_traffic_threshold','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
     303        add_settings_field( 'dfehc_website_visitors', __('Website visitors override','dfehc'), function(){ $this->f_number('dfehc_website_visitors','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
     304        add_settings_field( 'dfehc_current_server_load', __('Current server load override','dfehc'), function(){ $this->f_number('dfehc_current_server_load','0.01','','', 0.0); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
     305        add_settings_field( 'dfehc_high_traffic_load_threshold', __('High traffic load threshold','dfehc'), function(){ $this->f_number('dfehc_high_traffic_load_threshold','0.01','','', 0.0); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
     306        add_settings_field( 'dfehc_allow_public_server_load', __('Allow public server load','dfehc'), function(){ $this->f_checkbox('dfehc_allow_public_server_load', 0); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
     307        add_settings_field( 'dfehc_allow_public_async', __('Allow public async','dfehc'), function(){ $this->f_checkbox('dfehc_allow_public_async', 0); }, $this->plugin->slug, 'dfehc_adv_ping_traffic_load' );
     308
     309        add_settings_field( 'dfehc_min_interval', __('Min interval (s)','dfehc'), function(){ $this->f_number('dfehc_min_interval','1','0','', 15); }, $this->plugin->slug, 'dfehc_adv_core_thresholds' );
     310        add_settings_field( 'dfehc_max_interval', __('Max interval (s)','dfehc'), function(){ $this->f_number('dfehc_max_interval','1','0','', 300); }, $this->plugin->slug, 'dfehc_adv_core_thresholds' );
     311        add_settings_field( 'dfehc_fallback_interval', __('Fallback interval (s)','dfehc'), function(){ $this->f_number('dfehc_fallback_interval','1','0','', 60); }, $this->plugin->slug, 'dfehc_adv_core_thresholds' );
     312        add_settings_field( 'dfehc_unknown_load', __('Unknown load sentinel','dfehc'), function(){ $this->f_number('dfehc_unknown_load','0.001','','', 0.404); }, $this->plugin->slug, 'dfehc_adv_core_thresholds' );
     313        add_settings_field( 'dfehc_max_server_load', __('Max server load','dfehc'), function(){ $this->f_number('dfehc_max_server_load','0.01','','', 85); }, $this->plugin->slug, 'dfehc_adv_core_thresholds' );
     314
     315        add_settings_field( 'dfehc_interval_factors', __('Interval factors (JSON)','dfehc'), function(){ $this->f_json('dfehc_interval_factors','', ''); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
     316        add_settings_field( 'dfehc_interval_weights', __('Interval weights (JSON)','dfehc'), function(){ $this->f_json('dfehc_interval_weights','', ''); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
     317        add_settings_field( 'dfehc_load_weights', __('Load weights (JSON)','dfehc'), function(){ $this->f_json('dfehc_load_weights','', ''); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
     318        add_settings_field( 'dfehc_normalize_load', __('Normalize load','dfehc'), function(){ $this->f_checkbox('dfehc_normalize_load', 0); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
     319        add_settings_field( 'dfehc_assumed_cores_for_normalization', __('Assumed cores for normalization','dfehc'), function(){ $this->f_number('dfehc_assumed_cores_for_normalization','0.1','0','', 8.0); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
     320        add_settings_field( 'dfehc_max_increase_rate', __('Max increase rate','dfehc'), function(){ $this->f_number('dfehc_max_increase_rate','0.01','','', 0.5); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
     321        add_settings_field( 'dfehc_interval_snap', __('Interval snap','dfehc'), function(){ $this->f_number('dfehc_interval_snap','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
     322        add_settings_field( 'dfehc_response_time_is_ms', __('Response time is ms','dfehc'), function(){ $this->f_checkbox('dfehc_response_time_is_ms', 0); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
     323        add_settings_field( 'dfehc_contextual_load_value', __('Contextual load value','dfehc'), function(){ $this->f_number('dfehc_contextual_load_value','0.01','','', 0.0); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
     324        add_settings_field( 'dfehc_divide_cpu_load', __('Divide CPU load','dfehc'), function(){ $this->f_checkbox('dfehc_divide_cpu_load', 1); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
     325        add_settings_field( 'dfehc_cpu_cores', __('CPU cores override','dfehc'), function(){ $this->f_number('dfehc_cpu_cores','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_algorithm_logic' );
     326
     327        add_settings_field( 'dfehc_server_load_ttl', __('Server load TTL (s)','dfehc'), function(){ $this->f_number('dfehc_server_load_ttl','1','0','', 180); }, $this->plugin->slug, 'dfehc_adv_caching_persistence' );
     328        add_settings_field( 'dfehc_transient_ttl', __('Transient TTL (s)','dfehc'), function(){ $this->f_number('dfehc_transient_ttl','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_caching_persistence' );
     329        add_settings_field( 'dfehc_ema_ttl', __('EMA TTL (s)','dfehc'), function(){ $this->f_number('dfehc_ema_ttl','1','0','', 0); }, $this->plugin->slug, 'dfehc_adv_caching_persistence' );
     330        add_settings_field( 'dfehc_prev_interval_ttl', __('Previous interval TTL (s)','dfehc'), function(){ $this->f_number('dfehc_prev_interval_ttl','1','0','', 1800); }, $this->plugin->slug, 'dfehc_adv_caching_persistence' );
     331        add_settings_field( 'dfehc_cache_retry_after', __('Cache retry-after (s)','dfehc'), function(){ $this->f_number('dfehc_cache_retry_after','1','0','', 60); }, $this->plugin->slug, 'dfehc_adv_caching_persistence' );
     332        add_settings_field( 'dfehc_redis_user', __('Redis user','dfehc'), function(){ $this->f_text('dfehc_redis_user','', (string) (getenv('REDIS_USERNAME') ?: '')); }, $this->plugin->slug, 'dfehc_adv_caching_persistence' );
     333        add_settings_field( 'dfehc_redis_auth', __('Redis auth','dfehc'), function(){ $this->f_text('dfehc_redis_auth','', (string) (getenv('REDIS_PASSWORD') ?: '')); }, $this->plugin->slug, 'dfehc_adv_caching_persistence' );
     334
     335        add_settings_field( 'dfehc_required_capability', __('Required capability','dfehc'), function(){ $this->f_text('dfehc_required_capability','read', 'read'); }, $this->plugin->slug, 'dfehc_adv_access_security' );
     336        add_settings_field( 'dfehc_public_rate_limit', __('Public rate limit','dfehc'), function(){ $this->f_number('dfehc_public_rate_limit','1','0','', 60); }, $this->plugin->slug, 'dfehc_adv_access_security' );
     337        add_settings_field( 'dfehc_public_rate_window', __('Public rate window (s)','dfehc'), function(){ $this->f_number('dfehc_public_rate_window','1','0','', 60); }, $this->plugin->slug, 'dfehc_adv_access_security' );
     338
     339        add_settings_field( 'dfehc_enable_load_logging', __('Enable load logging','dfehc'), function(){ $this->f_checkbox('dfehc_enable_load_logging', 1); }, $this->plugin->slug, 'dfehc_adv_logging_maintenance' );
     340        add_settings_field( 'dfehc_log_retention_seconds', __('Log retention seconds','dfehc'), function(){ $this->f_number('dfehc_log_retention_seconds','1','0','', 86400); }, $this->plugin->slug, 'dfehc_adv_logging_maintenance' );
     341        add_settings_field( 'dfehc_log_retention_max', __('Log retention max','dfehc'), function(){ $this->f_number('dfehc_log_retention_max','1','0','', 2000); }, $this->plugin->slug, 'dfehc_adv_logging_maintenance' );
     342        add_settings_field( 'dfehc_prune_chunk_size', __('Prune chunk size','dfehc'), function(){ $this->f_number('dfehc_prune_chunk_size','1','1','', 50); }, $this->plugin->slug, 'dfehc_adv_logging_maintenance' );
    309343    }
    310344
     
    392426        echo '</details>';
    393427
     428        echo '<details class="dfehc-adv-group"><summary>'.esc_html__('Access & Security','dfehc').'</summary>';
     429        $this->render_section( $this->plugin->slug, 'dfehc_adv_access_security', false );
     430        echo '</details>';
     431
     432        echo '<details class="dfehc-adv-group"><summary>'.esc_html__('Logging & Maintenance','dfehc').'</summary>';
     433        $this->render_section( $this->plugin->slug, 'dfehc_adv_logging_maintenance', false );
     434        echo '</details>';
     435
    394436        echo '<details class="dfehc-adv-group"><summary>'.esc_html__('Heartbeat Zoom Settings','dfehc').'</summary>';
    395437        $this->render_section( $this->plugin->slug, 'dfehc_load_display_settings_section', false );
     
    398440        submit_button( null, 'primary', 'submit', true );
    399441        echo '</div>';
     442
     443        echo '<script>
     444(function(){
     445    var form = document.getElementById("dfehc-settings-form");
     446    if (!form) return;
     447
     448    function setPanelEnabled(panel, enabled){
     449        var els = panel.querySelectorAll("input,select,textarea,button");
     450        els.forEach(function(el){
     451            var isNamed = !!el.name || el.tagName === "BUTTON";
     452            if (!isNamed) return;
     453
     454            if (!enabled) {
     455                if (el.dataset.dfehcPrevDisabled === undefined) {
     456                    el.dataset.dfehcPrevDisabled = el.disabled ? "1" : "0";
     457                }
     458                el.disabled = true;
     459                return;
     460            }
     461
     462            if (el.dataset.dfehcPrevDisabled !== undefined) {
     463                el.disabled = (el.dataset.dfehcPrevDisabled === "1");
     464                delete el.dataset.dfehcPrevDisabled;
     465            }
     466        });
     467    }
     468
     469    function getActiveTabId(){
     470        var p = form.querySelector(".dfehc-tab-panel.is-active");
     471        return p ? p.id : "dfehc_tab_heartbeat";
     472    }
     473
     474    function sync(){
     475        var activeId = getActiveTabId();
     476        var panels = form.querySelectorAll(".dfehc-tab-panel");
     477        panels.forEach(function(p){
     478            setPanelEnabled(p, p.id === activeId);
     479        });
     480    }
     481
     482    sync();
     483
     484    window.addEventListener("load", sync);
     485    document.addEventListener("visibilitychange", function(){
     486        if (!document.hidden) sync();
     487    });
     488
     489    document.querySelectorAll(".dfehc-tabs a[data-tab]").forEach(function(a){
     490        a.addEventListener("click", function(){
     491            var id = a.getAttribute("data-tab");
     492            if (!id) return;
     493
     494            var panels = form.querySelectorAll(".dfehc-tab-panel");
     495            panels.forEach(function(p){
     496                setPanelEnabled(p, p.id === id);
     497            });
     498
     499            setTimeout(sync, 0);
     500        });
     501    });
     502
     503    form.addEventListener("submit", function(){
     504        sync();
     505    });
     506
     507    var mo = new MutationObserver(function(){
     508        sync();
     509    });
     510
     511    mo.observe(form, { attributes: true, subtree: true, attributeFilter: ["class"] });
     512})();
     513</script>';
    400514
    401515        echo '</form>';
Note: See TracChangeset for help on using the changeset viewer.