# xspeed/1.1.4/includes/class-settings.php

xSpeed Cache: AI-Powered Performance Hub with MCP, Caching &amp; CDN, version 1.1.4. 130 lines.

- Page: https://pluginprobe.com/plugins/xspeed/1.1.4/code/includes/class-settings.php
- Raw: https://pluginprobe.com/plugins/xspeed/1.1.4/raw/includes/class-settings.php
- Modified: 2026-08-05T12:06:42+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/xspeed/1.1.4/code/includes/class-settings.php#L10-L20`.

```php
<?php
/**
 * Settings handling.
 *
 * @package XSpeed
 */

namespace XSpeed;

defined( 'ABSPATH' ) || exit;

class Settings {

	const OPTION_KEY = 'xspeed_options';

	public static function defaults() {
		// Migrated out of this legacy blob (now per-module storage):
		//   - minify_html / minify_css / minify_js → xspeed_module_minify
		//   - gzip_enabled                         → xspeed_module_gzip
		//   - cache_expiry / excluded_urls         → xspeed_module_cache
		// Still here (intentionally, drop-in lifecycle):
		//   - cache_enabled (Cache::toggle owns the .htaccess/wp-config edit)
		return array(
			'cache_enabled' => false,
		);
	}

	public static function get() {
		$saved = get_option( self::OPTION_KEY, array() );
		return wp_parse_args( $saved, self::defaults() );
	}

	public static function update( array $input ) {
		$current = self::get();
		$clean   = $current;

		// Every former field is now in per-module storage:
		//   - minify_* → MinifyModule, gzip_enabled → GzipModule,
		//     cache_expiry / excluded_urls → CacheModule.
		// Only cache_enabled lives on here, owned by Cache::toggle's
		// drop-in lifecycle. All other writes are silently ignored to
		// keep duplicate sources from re-forming.
		if ( isset( $input['cache_enabled'] ) ) {
			$clean['cache_enabled'] = (bool) $input['cache_enabled'];
		}

		update_option( self::OPTION_KEY, $clean );
		return $clean;
	}

	public static function set_defaults() {
		if ( false === get_option( self::OPTION_KEY ) ) {
			add_option( self::OPTION_KEY, self::defaults() );
			// Only a genuinely fresh install reaches this branch — the
			// option survives deactivation, so an upgrade (deactivate →
			// wipe → install → activate) always finds it present.
			self::seed_recommended_modules();
		}
	}

	/**
	 * Settings a fresh install starts with, beyond each module's schema
	 * default. Mirrors the wizard's "Balanced" preset — the profile the
	 * product already labels "Recommended for most sites".
	 *
	 * Why this exists: the wizard is skippable, and a WP-CLI or bulk
	 * activation never shows it at all. Those users fell through to the raw
	 * schema defaults, which are more conservative than what we recommend to
	 * the very same site — so whether a site compressed its responses came
	 * down to whether someone clicked through a wizard. Measured on a real
	 * install: gzip off, browser-cache headers off, no minification, while
	 * lazy-load and resource hints (schema default `true`) were on.
	 *
	 * Deliberately excluded: `minify_js`, `defer_js`, `combine_css`,
	 * `combine_js`, `delay_js`. Each can break a theme, and a default that
	 * breaks the site is worse than a default that is merely slow. They stay
	 * opt-in via the wizard's Aggressive preset or the dashboard.
	 *
	 * @return array<string,array<string,bool>> module slug => settings
	 */
	private static function recommended_module_settings(): array {
		return array(
			// Compression — the single largest byte win, and inert until a
			// server actually supports it (GzipModule writes .htaccess only
			// where supports_htaccess() is true, and emits a snippet
			// otherwise).
			'gzip'          => array( 'gzip_enabled' => true ),
			// Far-future caching for static assets. Only ever affects
			// css/js/images/fonts; HTML keeps its own short TTL.
			'browser-cache' => array( 'enabled' => true ),
			// HTML + CSS minification. Both are whitespace/comment-level
			// and do not reorder or combine anything, so they carry none of
			// the cascade risk that combine_css does.
			'minify'        => array(
				'minify_html' => true,
				'minify_css'  => true,
			),
		);
	}

	/**
	 * Write the recommended defaults for a fresh install, without ever
	 * overwriting a value the user has already chosen.
	 *
	 * Each key is written only when it is absent from stored settings, so
	 * this stays safe if it is ever reached on a site that has some — but
	 * not all — module options saved.
	 */
	private static function seed_recommended_modules(): void {
		foreach ( self::recommended_module_settings() as $slug => $values ) {
			$key    = 'xspeed_module_' . $slug;
			$stored = get_option( $key, null );
			$stored = is_array( $stored ) ? $stored : array();

			$next = $stored;
			foreach ( $values as $setting => $value ) {
				if ( ! array_key_exists( $setting, $stored ) ) {
					$next[ $setting ] = $value;
				}
			}
			if ( $next !== $stored ) {
				update_option( $key, $next, false );
			}
		}
	}

	// sanitize_urls() removed — excluded_urls now owned by CacheModule
	// and validated by Settings_Manager's typed schema (list / item_type).
}

```
