array( 'jpg', 'jpeg', 'png', 'gif', 'webp', 'avif', 'svg', 'ico' ), 'css_js' => array( 'css', 'js' ), 'fonts' => array( 'woff', 'woff2', 'ttf', 'otf', 'eot' ), ); public static function defaults() { return array( 'gzip_enabled' => false, 'brotli_enabled' => false, 'caching_enabled' => false, 'cache_days' => array( 'images' => 365, 'css_js' => 30, 'fonts' => 365, 'default' => 7, ), 'etags_removed' => false, 'remove_emojis' => false, 'remove_query_strings' => false, 'heartbeat_frontend' => true, 'heartbeat_admin_secs' => 60, 'defer_handles' => '', 'preconnect_hosts' => '', 'dns_prefetch_hosts' => '', ); } /** Sichere Empfehlung fuer den Quickstart-Button -- deckt sich mit DOCS.md "Quickstart". */ public static function quickstart_values() { $values = self::defaults(); $values['gzip_enabled'] = true; $values['brotli_enabled'] = true; $values['caching_enabled'] = true; $values['etags_removed'] = true; $values['remove_emojis'] = true; $values['remove_query_strings'] = true; $values['heartbeat_frontend'] = false; $values['heartbeat_admin_secs'] = 60; return $values; } public static function get() { $saved = get_option( self::OPTION_KEY, array() ); return self::sanitize( is_array( $saved ) ? $saved : array() ); } public static function apply_quickstart() { $settings = self::save( self::quickstart_values() ); Wp360_Speed_Optimizer_Htaccess::apply( $settings ); return $settings; } /** Nimmt beliebig geformte Eingaben entgegen und liefert garantiert vollstaendige, typsichere Settings zurueck -- unbekannte Schluessel werden verworfen. */ public static function sanitize( array $input ) { $defaults = self::defaults(); $out = $defaults; $out['gzip_enabled'] = ! empty( $input['gzip_enabled'] ); $out['brotli_enabled'] = ! empty( $input['brotli_enabled'] ); $out['caching_enabled'] = ! empty( $input['caching_enabled'] ); $out['etags_removed'] = ! empty( $input['etags_removed'] ); $out['remove_emojis'] = ! empty( $input['remove_emojis'] ); $out['remove_query_strings'] = ! empty( $input['remove_query_strings'] ); $out['heartbeat_frontend'] = ! empty( $input['heartbeat_frontend'] ); $out['heartbeat_admin_secs'] = self::clamp_int( $input['heartbeat_admin_secs'] ?? $defaults['heartbeat_admin_secs'], 15, 300, $defaults['heartbeat_admin_secs'] ); if ( isset( $input['cache_days'] ) && is_array( $input['cache_days'] ) ) { foreach ( array_keys( $defaults['cache_days'] ) as $group ) { $out['cache_days'][ $group ] = self::clamp_int( $input['cache_days'][ $group ] ?? $defaults['cache_days'][ $group ], 0, 3650, $defaults['cache_days'][ $group ] ); } } $out['defer_handles'] = self::sanitize_token_list( $input['defer_handles'] ?? '' ); $out['preconnect_hosts'] = self::sanitize_host_list( $input['preconnect_hosts'] ?? '' ); $out['dns_prefetch_hosts'] = self::sanitize_host_list( $input['dns_prefetch_hosts'] ?? '' ); return $out; } /** * Gespeicherte Schluessel, die diese Variante nicht kennt (die * PRO-Einstellungen, wenn gerade FREE laeuft), bleiben beim Speichern * unangetastet -- sonst gingen sie bei einem Wechsel von PRO auf FREE mit * dem ersten Speichern verloren. */ public static function save( array $input ) { $settings = self::sanitize( $input ); $stored = get_option( self::OPTION_KEY, array() ); $unknown = is_array( $stored ) ? array_diff_key( $stored, $settings ) : array(); update_option( self::OPTION_KEY, array_merge( $unknown, $settings ) ); return $settings; } private static function clamp_int( $value, $min, $max, $fallback ) { if ( ! is_numeric( $value ) ) { return $fallback; } return max( $min, min( $max, (int) $value ) ); } /** Leerzeichen-getrennte Liste (z. B. Skript-Handles) -- nur erlaubte Handle-Zeichen. */ private static function sanitize_token_list( $value ) { $tokens = preg_split( '/\s+/', trim( (string) $value ) ); $tokens = array_filter( array_map( function ( $token ) { return preg_replace( '/[^A-Za-z0-9_\-.]/', '', $token ); }, $tokens ) ); return implode( ' ', array_unique( $tokens ) ); } /** Zeilenweise Hostnamen (Preconnect/DNS-Prefetch). */ private static function sanitize_host_list( $value ) { $lines = preg_split( '/[\r\n]+/', trim( (string) $value ) ); $hosts = array_filter( array_map( function ( $line ) { $line = trim( $line ); $line = preg_replace( '#^https?://#i', '', $line ); $line = rtrim( $line, '/' ); return preg_match( '/^[A-Za-z0-9.\-]+$/', $line ) ? strtolower( $line ) : ''; }, $lines ) ); return implode( "\n", array_unique( $hosts ) ); } }