> */ public static function alle(): array { return Database::fetchAll( 'SELECT * FROM berichte WHERE benutzer_id = ? ORDER BY sortierung, name', [Mandant::id()] ); } /** * Alle Berichte nach Gruppe, in der Reihenfolge der Übersicht. Berichte ohne * Gruppe stehen unter dem Schlüssel 0. * * @return array|null, berichte: list>}> */ public static function nachGruppe(): array { $gruppen = []; foreach (Berichtsgruppe::alle() as $gruppe) { $gruppen[(int)$gruppe['id']] = ['gruppe' => $gruppe, 'berichte' => []]; } foreach (self::alle() as $bericht) { $id = $bericht['gruppe_id'] === null ? 0 : (int)$bericht['gruppe_id']; // Eine gelöschte Gruppe kann noch in keinem Eintrag stehen; der // Bericht landet dann bei „Nicht gruppiert“ statt zu verschwinden. if (!isset($gruppen[$id])) { $gruppen[$id] = ['gruppe' => null, 'berichte' => []]; } $gruppen[$id]['berichte'][] = $bericht; } // Leere Gruppen bleiben stehen – sie sind angelegt worden, um befüllt zu // werden, und ohne Kachel gäbe es keinen Ort, an den ein Bericht könnte. return $gruppen; } public static function find(int $id): ?array { $zeile = Database::fetchOne( 'SELECT * FROM berichte WHERE id = ? AND benutzer_id = ?', [$id, Mandant::id()] ); return $zeile === false ? null : $zeile; } public static function findeNachName(string $name): ?array { $zeile = Database::fetchOne( 'SELECT * FROM berichte WHERE name = ? AND benutzer_id = ?', [trim($name), Mandant::id()] ); return $zeile === false ? null : $zeile; } /** * Die zuletzt geöffneten Berichte – das Menü „Letzte Berichte“. * * @return list> */ public static function letzte(int $anzahl = 5): array { return Database::fetchAll( 'SELECT * FROM berichte WHERE benutzer_id = ? AND zuletzt_am IS NOT NULL ORDER BY zuletzt_am DESC LIMIT ' . max(1, $anzahl), [Mandant::id()] ); } /** @param array $filter */ public static function anlegen(string $name, array $filter, ?int $gruppeId = null): int { $name = self::pruefeName($name); $filter = Auswertung::normalisiere($filter); if (self::findeNachName($name) !== null) { throw new \RuntimeException('Den Bericht „' . $name . '“ gibt es bereits.'); } Database::execute( 'INSERT INTO berichte (benutzer_id, gruppe_id, name, typ, filter) VALUES (?, ?, ?, ?, ?)', [Mandant::id(), self::gruppe($gruppeId), $name, $filter['typ'], self::alsJson($filter)] ); return Database::lastInsertId(); } /** @param array $filter */ public static function speichern(int $id, string $name, array $filter, ?int $gruppeId = null): void { $name = self::pruefeName($name); $filter = Auswertung::normalisiere($filter); $andere = self::findeNachName($name); if ($andere !== null && (int)$andere['id'] !== $id) { throw new \RuntimeException('Den Bericht „' . $name . '“ gibt es bereits.'); } Database::execute( 'UPDATE berichte SET gruppe_id = ?, name = ?, typ = ?, filter = ? WHERE id = ? AND benutzer_id = ?', [self::gruppe($gruppeId), $name, $filter['typ'], self::alsJson($filter), $id, Mandant::id()] ); } public static function loeschen(int $id): void { Database::execute('DELETE FROM berichte WHERE id = ? AND benutzer_id = ?', [$id, Mandant::id()]); } /** Merkt sich das Öffnen für die Liste „Letzte Berichte“. */ public static function benutzt(int $id): void { Database::execute( 'UPDATE berichte SET zuletzt_am = NOW() WHERE id = ? AND benutzer_id = ?', [$id, Mandant::id()] ); } /** * Der geprüfte Filter eines gespeicherten Berichts. * * @param array $bericht * @return array */ public static function filter(array $bericht): array { $roh = json_decode((string)($bericht['filter'] ?? ''), true); return Auswertung::normalisiere( (is_array($roh) ? $roh : []) + ['typ' => (string)($bericht['typ'] ?? '')] ); } public static function anzahl(): int { return (int)Database::fetchValue( 'SELECT COUNT(*) FROM berichte WHERE benutzer_id = ?', [Mandant::id()], 0 ); } /** Prüft, dass die Gruppe dem Benutzer gehört – sonst gilt „nicht gruppiert“. */ private static function gruppe(?int $gruppeId): ?int { if ($gruppeId === null || $gruppeId === 0) { return null; } return Berichtsgruppe::find($gruppeId) === null ? null : $gruppeId; } /** @param array $filter */ private static function alsJson(array $filter): string { return (string)json_encode($filter, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); } private static function pruefeName(string $name): string { $name = trim($name); if ($name === '') { throw new \InvalidArgumentException('Der Bericht braucht einen Namen.'); } return mb_substr($name, 0, 120); } }