$defaults */ public static function registerDefaults(array $defaults): void { self::$defaults = array_merge(self::$defaults, $defaults); } /** * @return array */ public static function defaults(): array { return self::$defaults; } public static function get(string $key, $default = null) { $optionKey = SOFTMINAL_CACHE_TABLE_PREFIX . $key; $value = get_option($optionKey, null); if ($value === null) { return $default ?? (self::$defaults[$key] ?? null); } return $value; } public static function set(string $key, $value): bool { if (self::isSameValue(self::get($key), $value)) { return true; } $optionKey = SOFTMINAL_CACHE_TABLE_PREFIX . $key; $result = update_option($optionKey, $value); if ($result === false) { // update_option() also returns false when nothing changed. return self::isSameValue(get_option($optionKey), $value); } return true; } /** * Whether a stored value and a new value are the same setting, allowing for * how WordPress round-trips scalars (true -> '1', false -> ''). */ private static function isSameValue($stored, $new): bool { // Arrays/objects: compare contents, never their string form. if (is_array($stored) || is_array($new) || is_object($stored) || is_object($new)) { return gettype($stored) === gettype($new) && $stored == $new; } // An empty value equals only another empty value or false (which // WordPress stores as ''). It is not the same as '0'. $storedBlank = $stored === '' || $stored === null; $newBlank = $new === '' || $new === null; if ($storedBlank || $newBlank) { return ($storedBlank || $stored === false) && ($newBlank || $new === false); } return self::normalizeScalar($stored) === self::normalizeScalar($new); } private static function normalizeScalar($value): string { if (is_bool($value)) { return $value ? '1' : '0'; } return (string) $value; } public static function all(): array { $settings = []; foreach (self::$defaults as $key => $default) { $settings[$key] = self::get($key); } return $settings; } /** * Update several registered settings at once. Keys that were not * registered with registerDefaults() are ignored; returns false when a * non-empty input contained no registered key at all. */ public static function update(array $settings): bool { $allSuccess = true; $updatedCount = 0; $knownCount = 0; foreach ($settings as $key => $value) { if (array_key_exists($key, self::$defaults)) { $knownCount++; if (self::set($key, $value)) { $updatedCount++; } else { $allSuccess = false; } } } if ($knownCount === 0) { return empty($settings); } return $allSuccess || $updatedCount > 0; } }