prepare("SELECT setting_value, setting_type FROM settings WHERE setting_key = ?"); $stmt->execute([$key]); $row = $stmt->fetch(PDO::FETCH_ASSOC); if ($row) { $value = self::castValue($row['setting_value'], $row['setting_type']); self::$cache[$key] = $value; return $value; } } catch (PDOException $e) { error_log("Error getting setting '{$key}': " . $e->getMessage()); } return $default; } /** * Set or update a setting value. * * @param string $key The setting key. * @param mixed $value The setting value. * @param string $type The type of the setting (e.g., 'text', 'checkbox', 'number'). * @param mixed $defaultValue The default value for the setting. * @param string|null $validationRules JSON string of validation rules. * @param string|null $description A description for the setting. * @return bool True on success, false on failure. */ public static function set( string $key, $value, string $type = 'text', $defaultValue = null, ?string $validationRules = null, ?string $description = null ): bool { try { $pdo = db(); // Check if setting exists $stmt = $pdo->prepare("SELECT COUNT(*) FROM settings WHERE setting_key = ?"); $stmt->execute([$key]); $exists = $stmt->fetchColumn(); $stringValue = self::valueToString($value); $defaultValue = self::valueToString($defaultValue); if ($exists) { $stmt = $pdo->prepare("UPDATE settings SET setting_value = ?, setting_type = ?, default_value = ?, validation_rules = ?, description = ?, updated_at = NOW() WHERE setting_key = ?"); $stmt->execute([$stringValue, $type, $defaultValue, $validationRules, $description, $key]); } else { $stmt = $pdo->prepare("INSERT INTO settings (setting_key, setting_value, setting_type, default_value, validation_rules, description) VALUES (?, ?, ?, ?, ?, ?)"); $stmt->execute([$key, $stringValue, $type, $defaultValue, $validationRules, $description]); } // Clear cache for this key unset(self::$cache[$key]); return true; } catch (PDOException $e) { error_log("Error setting '{$key}': " . $e->getMessage()); return false; } } /** * Casts a string value to its appropriate PHP type based on the setting type. * * @param string $value The string value from the database. * @param string $type The declared type of the setting. * @return mixed The type-casted value. */ private static function castValue(string $value, string $type) { switch ($type) { case 'boolean': case 'checkbox': return (bool)$value; case 'integer': case 'number': return (int)$value; case 'float': return (float)$value; case 'json': return json_decode($value, true); case 'array': // Simple comma-separated array return explode(',', $value); default: return $value; } } /** * Converts a PHP value to its string representation for storage. * * @param mixed $value The PHP value. * @return string The string representation. */ private static function valueToString($value): string { if (is_bool($value)) { return $value ? '1' : '0'; } elseif (is_array($value) || is_object($value)) { return json_encode($value); } else { return (string)$value; } } /** * Clears the entire settings cache. */ public static function clearCache(): void { self::$cache = []; } /** * Fetches all settings from the database. * * @return array An associative array of all settings. */ public static function getAll(): array { try { $pdo = db(); $stmt = $pdo->query("SELECT setting_key, setting_value, setting_type FROM settings"); $allSettings = $stmt->fetchAll(PDO::FETCH_ASSOC); $result = []; foreach ($allSettings as $setting) { $result[$setting['setting_key']] = self::castValue($setting['setting_value'], $setting['setting_type']); } return $result; } catch (PDOException $e) { error_log("Error getting all settings: " . $e->getMessage()); return []; } } /** * Fetches all settings with their metadata from the database. * * @return array An associative array of all settings including metadata. */ public static function getAllWithMetadata(): array { try { $pdo = db(); $stmt = $pdo->query("SELECT * FROM settings"); return $stmt->fetchAll(PDO::FETCH_ASSOC); } catch (PDOException $e) { error_log("Error getting all settings with metadata: " . $e->getMessage()); return []; } } }