<?phpnamespace App\Chat;/** * The permanent rooms (and their last sentences), kept in one JSON file between two runs. The rest of the chat * (who is connected, the rooms people made) only lives while the server runs, as the original reset it at start. */final class RoomStore{ /** The 22 permanent rooms of the Caramail chat ("22 salons permanents"), "Salon" the room one enters first. */ public const DEFAULT_ROOMS = ['Salon', '10 - 15 ans', '15 - 20 ans', '20 - 25 ans', '25 - 30 ans', '30 - 35 ans', '35 - 40 ans', '40 - 45 ans', '45 - 50 ans', 'plus de 50 ans', 'Belgique', 'Gay', 'Lesbiennes', 'Salon : 2', 'Salon : 3', 'Salon : 4', 'Salon : 5', 'Salon : 6', 'Salon : 7', 'Salon : 8', 'Salon : 9', 'Salon : 10']; public function __construct(private readonly string $file) { } public function file(): string { return $this->file; } /** @return list<Room> */ public function load(): array { $data = is_file($this->file) ? json_decode((string)file_get_contents($this->file), true) : null; if (!is_array($data) || !isset($data['rooms']) || !is_array($data['rooms'])) { return array_map(static fn (string $name) => new Room($name, 0, 'admin', true), self::DEFAULT_ROOMS); } $rooms = []; foreach ($data['rooms'] as $row) { if (!is_array($row) || !isset($row['name']) || trim((string)$row['name']) === '') { continue; } $room = new Room((string)$row['name'], (int)($row['type'] ?? 0), (string)($row['creator'] ?? 'admin'), true, (int)($row['created'] ?? 0)); foreach ((array)($row['history'] ?? []) as $line) { if (is_array($line) && isset($line['id'], $line['nickname'], $line['text'])) { $room->history[] = ['id' => (string)$line['id'], 'nickname' => (string)$line['nickname'], 'text' => (string)$line['text'], 'at' => (int)($line['at'] ?? 0)]; } } $room->history = array_slice($room->history, -Room::HISTORY); $rooms[] = $room; } return $rooms; } /** @param iterable<Room> $rooms only the permanent ones are written */ public function save(iterable $rooms): void { $rows = []; foreach ($rooms as $room) { if ($room->permanent) { $rows[] = ['name' => $room->name, 'type' => $room->type, 'creator' => $room->creator, 'created' => $room->createdAt, 'history' => $room->history]; } } $dir = dirname($this->file); if (!is_dir($dir)) { @mkdir($dir, 0775, true); } $tmp = $this->file . '.tmp'; file_put_contents($tmp, json_encode(['rooms' => $rows], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\n"); rename($tmp, $this->file); } /** Adds (or removes) a permanent room in the file: the `rooms` command, while the server is stopped or before a restart. */ public function edit(string $name, bool $add): bool { $rooms = $this->load(); $key = Room::keyOf($name, 0); $found = false; foreach ($rooms as $i => $room) { if ($room->key() === $key) { $found = true; if (!$add) { unset($rooms[$i]); } } } if ($add && !$found) { $rooms[] = new Room($name, 0, 'admin', true); } $this->save($rooms); return $add ? !$found : $found; }}