diff options
| author | winter | 2025-01-26 15:25:17 +0000 |
|---|---|---|
| committer | winter | 2025-01-26 15:25:17 +0000 |
| commit | 890dad24d6c095c41e6358b2a6cb61f1b6c2f6ad (patch) | |
| tree | a662dfd61585b755054075cd93121a9c70a48983 /Digitigrade/UserSettings.php | |
| parent | 5841d6550936e1fc34f1fbdf4325b1e27ff79230 (diff) | |
add user settings / preferences
Diffstat (limited to 'Digitigrade/UserSettings.php')
| -rw-r--r-- | Digitigrade/UserSettings.php | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/Digitigrade/UserSettings.php b/Digitigrade/UserSettings.php new file mode 100644 index 0000000..4a27014 --- /dev/null +++ b/Digitigrade/UserSettings.php @@ -0,0 +1,169 @@ +<?php +namespace Digitigrade; + +use Digitigrade\Model\UserAccount; + +class UserSettings { + private const DEFINITIONS_INI_PATH = __DIR__ . '/../settings.user.ini'; + + private \PDO $db; + private array $info; + private UserAccount $user; + + public function __construct(UserAccount $user) { + $this->user = $user; + $this->db = Db::getInstance()->getPdo(); + if (!$this->get('settings.initialised')) { + $this->resetAll(); + } + } + + /** + * Gets a setting's value. + * @param string $key which setting to get + * @return ?string the value, or null if not set + */ + public function get(string $key): ?string { + $stmt = $this->db->prepare('SELECT value FROM user_setting WHERE name = ? AND user_id = ?'); + $stmt->execute([$key, $this->user->id]); + return $stmt->fetchColumn(0) ?: null; + } + + /** + * Gets a boolean setting's value. + * @param string $key which setting to get + * @return ?bool the value, or null if not set + */ + public function getBool(string $key): ?bool { + return match ($this->get($key)) { + '', 'false' => false, + '1', 'true' => true, + default => null + }; + } + + /** + * Sets the value of a setting. + * @param string $key which setting to modify + * @param string $value the new value + * @return void + */ + public function set(string $key, string $value) { + $stmt = $this->db->prepare(<<<END + INSERT INTO user_setting(user_id, name, value) VALUES (?, ?, ?) + ON CONFLICT (user_id, name) DO UPDATE SET value = EXCLUDED.value + END); + $stmt->execute([$this->user->id, $key, $value]); + } + + public function setBool(string $key, bool $value) { + $this->set($key, $value ? 'true' : 'false'); + } + + /** + * Checks whether a setting is set. + * @param string $key which setting to check + * @return bool if it's set (has a value) or not + */ + public function isset(string $key): bool { + $stmt = $this->db->prepare('SELECT count(*) FROM user_setting WHERE name = ? AND user_id = ?'); + $stmt->execute([$key, $this->user->id]); + return $stmt->fetchColumn(0) > 0; + } + + /** + * Unsets a setting. + * @param string $key which setting to remove + * @return void + */ + public function unset(string $key) { + $stmt = $this->db->prepare('DELETE FROM user_setting WHERE name = ? AND user_id = ?'); + $stmt->execute([$key, $this->user->id]); + } + + /** + * Gets a list of all currently-set settings. + * @return array{key: string, value: string} array of keys to values + */ + public function getAll(): array { + $stmt = $this->db->prepare('SELECT name, value FROM user_setting WHERE user_id = ?'); + $stmt->execute([$this->user->id]); + $items = $stmt->fetchAll(); + $result = []; + foreach ($items as $row) { + $result[$row['name']] = $row['value']; + } + return $result; + } + + /** + * Gets a list of all settings in a given prefix. + * @param string $prefix prefix to look in (not including the trailing dot) + * @return array{key: string, value: string} array of keys to values + */ + public function getAllInPrefix(string $prefix): array { + $stmt = $this->db->prepare('SELECT name, value FROM user_setting WHERE name ^@ ? AND user_id = ?'); + $stmt->execute(["$prefix.", $this->user->id]); + $items = $stmt->fetchAll(); + $result = []; + foreach ($items as $row) { + $result[$row['name']] = $row['value']; + } + return $result; + } + + /** + * Gets a list of all first-level prefixes. + * @return string[] + */ + public function getAllPrefixes(): array { + return array_unique(array_map( + fn($x) => explode('.', $x, 2)[0], + array_keys($this->getAll()) + )); + } + + /** + * Gets information (name, description, default value) for a given setting. + * @param string $key which setting to look up + * @return ?array{item: string, value: string} associative array of info, + * or null if none is available + */ + public function getInfo(string $key): ?array { + $this->loadDefinitions(); + return $this->info[$key] ?? null; + } + + /** + * Merges new keys from the settings definition file into the settings + * without overwriting existing values. + * @return void + */ + public function mergeUpdates() { + $this->initialise(false); + } + + /** + * Sets all defined settings back to their default values. + * @return void + */ + public function resetAll() { + $this->initialise(true); + } + + private function loadDefinitions() { + if (!isset($this->info)) { + $this->info = parse_ini_file(self::DEFINITIONS_INI_PATH, process_sections: true); + } + } + + private function initialise(bool $overwriteExisting) { + $this->loadDefinitions(); + foreach ($this->info as $key => $setting) { + if ($overwriteExisting || !$this->isset($key)) { + $this->set($key, $setting['default']); + } + } + $this->set('settings.initialised', true); + } +}
\ No newline at end of file |
