You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
sessioncommunities.online/php/utils/read-config.php

200 lines
5.2 KiB
PHP

<?php
require_once 'php/utils/logging.php';
require_once 'php/utils/utils.php';
/**
* @var string $CONFIG_ROOT
*/
function config_requiring_type(
mixed $value,
bool $int = false,
bool $string = false,
bool $bool = false,
bool $float = false,
bool $null = true
) {
if (is_int($value) && $int) return $value;
if (is_bool($value) && $bool) return $value;
if (is_string($value) && $string) return $value;
if (is_float($value) && $float) return $value;
if (is_null($value) && $null) return $value;
$realtype = get_debug_type($value);
throw new Error("Unexpected configuration option type: $realtype");
}
function remove_trailing_key_slashes(array $array): array {
return $array;
$newarray = array();
foreach ($array as $key => $value) {
if (str_ends_with($key, "/")) {
$newarray[substring($key, 0, -1)] = $value;
} else $newarray[$key] = $value;
}
return $newarray;
}
/**
* Provides custom configuration values.
*/
class LocalConfig {
private function __construct() {
$room_overrides =
LocalConfig::maybe_parse_ini_file(LocalConfig::ROOM_OVERRIDES_CONFIG)
?? array();
// Sort room overrides last
uksort($room_overrides, function($identifier_a, $identifier_b) {
return str_contains($identifier_b, "+") - str_contains($identifier_a, "+");
});
$this->room_overrides = $room_overrides;
$this->room_overrides_computed = array();
$this->known_servers = remove_trailing_key_slashes(
LocalConfig::maybe_parse_ini_file(LocalConfig::KNOWN_SERVERS_CONFIG)
?? array()
);
}
private static LocalConfig | null $instance = null;
/**
* Get the canonical instance of LocalConfig.
* @return LocalConfig
*/
public static function get_instance(): LocalConfig {
return LocalConfig::$instance ??= LocalConfig::read_from_files();
}
private const ROOM_OVERRIDES_CONFIG = "room-overrides.ini";
private const KNOWN_SERVERS_CONFIG = "known-servers.ini";
private readonly array $room_overrides;
private array $room_overrides_computed;
private readonly array $known_servers;
private static function maybe_parse_ini_file(string $filename): array | null {
global $CONFIG_ROOT;
$file = "$CONFIG_ROOT/$filename";
if (!file_exists($file)) {
log_warning("config file not found: $file");
return null;
}
return parse_ini_file($file, process_sections: true, scanner_mode: INI_SCANNER_TYPED);
}
/**
* Read local config from the filesystem.
*/
private static function read_from_files() {
return new LocalConfig();
}
private function get_room_overrides(CommunityRoom $room): array {
$room_id = $room->get_room_identifier();
if (isset($this->room_overrides_computed[$room_id])) {
return $this->room_overrides_computed[$room_id];
}
$room_overrides = array();
foreach ($this->room_overrides as $identifier => $overrides) {
if ($room->matched_by_identifier($identifier)) {
$room_overrides = [...$room_overrides, ...$overrides];
}
}
return $this->room_overrides_computed[$room_id] = $room_overrides;
}
private function get_server_overrides(CommunityServer $server): array {
$server_base_url = $server->get_base_url();
return $this->known_servers[$server_base_url] ?? array();
}
public function get_room_staff_count_override(CommunityRoom $room): int | null {
return config_requiring_type(
$this->get_room_overrides($room)['staff_count'],
int: true,
);
}
public function get_room_safety_override(CommunityRoom $room): RoomSafety {
return RoomSafety::from_keyword(
$this->get_room_overrides($room)['safety']
);
}
private function get_bool_override_value(CommunityRoom $room, string $override_key) {
return config_requiring_type(
$this->get_room_overrides($room)[$override_key] === true,
bool: true
) === true;
}
public function is_testing_room(CommunityRoom $room): bool {
return $this->get_bool_override_value($room, 'testing');
}
public function is_stickied_room(CommunityRoom $room): bool {
return $this->get_bool_override_value($room, 'stickied');
}
public function is_hidden_room(CommunityRoom $room): bool {
return $this->get_bool_override_value($room, 'hidden');
}
public function get_known_servers(): array {
return $this->known_servers;
}
public function get_server_icon_room(CommunityServer $server): ?string {
return $this->get_server_overrides($server)['icon'] ?? null;
}
}
class RoomSafety {
private function __construct(int $value) {
$this->safety = $value;
}
private readonly int $safety;
private const UNSAFE = -2;
private const NOT_SAFE_FOR_WORK = -1;
private const UNSET = 0;
private const SAFE_FOR_WORK = 1;
public static function from_keyword(string|null $keyword) {
if (null == $keyword) {
return new RoomSafety(RoomSafety::UNSET);
}
switch (mb_strtolower($keyword)) {
case "unsafe":
return new RoomSafety(RoomSafety::UNSAFE);
case "nsfw":
return new RoomSafety(RoomSafety::NOT_SAFE_FOR_WORK);
case "sfw":
return new RoomSafety(RoomSafety::SAFE_FOR_WORK);
default:
throw new Error("Unknown safety class: $keyword");
}
}
private function is_set() {
return $this->safety !== RoomSafety::UNSET;
}
public function rated_nsfw(): bool | null {
if (!$this->is_set()) return null;
return $this->safety <= RoomSafety::NOT_SAFE_FOR_WORK;
}
}
?>