PluginProbe
EasyFonts – Host Google Fonts Locally, Fast & Auto-Optimize, GDPR Compliant / trunk
EasyFonts – Host Google Fonts Locally, Fast & Auto-Optimize, GDPR Compliant vtrunk
2.0.3 2.0.2 2.0.1 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.2 1.3 2.0.0
easyfonts / src / Settings.php

Settings.php in EasyFonts – Host Google Fonts Locally, Fast & Auto-Optimize, GDPR Compliant trunk, at src/Settings.php

158 lines 3.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Settings accessor.
4 *
5 * @package EasyFonts
6 */
7
8 namespace EasyFonts;
9
10 use EasyFonts\Database\Migrator;
11
12 defined( 'ABSPATH' ) || exit;
13
14 /**
15 * Thin, cached wrapper around the single settings option.
16 */
17 class Settings {
18
19 const OPTION = 'easyfonts_settings';
20
21 /**
22 * Per-request cache.
23 *
24 * @var array<string,mixed>|null
25 */
26 private static ?array $cache = null;
27
28 /**
29 * Get all settings (merged over defaults).
30 *
31 * @return array<string,mixed>
32 */
33 public static function all(): array {
34 if ( null === self::$cache ) {
35 $stored = get_option( self::OPTION, array() );
36 self::$cache = is_array( $stored )
37 ? array_merge( Migrator::default_settings(), $stored )
38 : Migrator::default_settings();
39 }
40
41 return self::$cache;
42 }
43
44 /**
45 * Get a single setting.
46 *
47 * @param string $key Setting key.
48 * @param mixed $default Fallback.
49 * @return mixed
50 */
51 public static function get( string $key, $default = null ) {
52 $all = self::all();
53
54 return $all[ $key ] ?? $default;
55 }
56
57 /**
58 * Persist the full settings array.
59 *
60 * @param array<string,mixed> $settings Settings.
61 */
62 public static function save( array $settings ): void {
63 update_option( self::OPTION, $settings, false );
64 self::$cache = null;
65 }
66
67 /**
68 * Flush the cache (after external writes).
69 */
70 public static function flush(): void {
71 self::$cache = null;
72 }
73
74 /**
75 * Has a detector been learned as "active" for this site?
76 *
77 * @param string $detector Detector id.
78 * @return bool
79 */
80 public static function detector_active( string $detector ): bool {
81 $detectors = (array) self::get( 'detectors', array() );
82
83 return in_array( $detector, $detectors, true );
84 }
85
86 /**
87 * Mark a detector active (Auto-Config self-learning). Persists only on change.
88 *
89 * @param string $detector Detector id.
90 */
91 public static function learn_detector( string $detector ): void {
92 // Respect the Auto-Config toggle: when off, freeze the learned set.
93 if ( ! self::get( 'auto_config', 1 ) ) {
94 return;
95 }
96
97 $all = self::all();
98 $detectors = (array) ( $all['detectors'] ?? array() );
99
100 if ( in_array( $detector, $detectors, true ) ) {
101 return;
102 }
103
104 $detectors[] = $detector;
105 $all['detectors'] = array_values( array_unique( $detectors ) );
106 self::save( $all );
107 }
108
109 /**
110 * Current cache-buster timestamp (appended to served URLs).
111 *
112 * @return int
113 */
114 public static function buster(): int {
115 return (int) get_option( 'easyfonts_cache_buster', 0 );
116 }
117
118 /**
119 * Secret key authorising background cache-warming loopback requests.
120 * Generated lazily and stored autoloaded. Lets an unauthenticated self-request
121 * (?easyfonts_probe=KEY) be trusted to perform downloads, without wp-cron.
122 *
123 * @return string
124 */
125 public static function warm_key(): string {
126 $key = (string) get_option( 'easyfonts_warm_key', '' );
127
128 if ( '' === $key ) {
129 $key = wp_generate_password( 40, false, false );
130 update_option( 'easyfonts_warm_key', $key, true );
131 }
132
133 return $key;
134 }
135
136 /**
137 * Cache-safe token authorising the public beacon endpoints.
138 *
139 * REST nonces expire (~24h), so a nonce baked into a page-cached HTML copy
140 * eventually 403s every beacon on exactly the cached, high-traffic sites
141 * this plugin targets. This site-secret-derived token doesn't expire, so
142 * cached pages keep reporting. It grants only what the endpoints already
143 * allowed anonymously (throttled, capped measurement ingest) — no more.
144 *
145 * @return string
146 */
147 public static function beacon_token(): string {
148 return hash_hmac( 'sha256', 'easyfonts-beacon-v1', wp_salt( 'nonce' ) );
149 }
150
151 /**
152 * Bump the cache-buster (after re-optimisation / purge).
153 */
154 public static function bump_buster(): void {
155 update_option( 'easyfonts_cache_buster', time(), false );
156 }
157 }
158