0, 'error' => 1, 'warning' => 2, 'info' => 3, ]; /** * @param list> $meldungen * @return array */ public static function erstellen( string $installationID, int $managerID, string $rolle, bool $managerAktiv, array $meldungen, ?int $zeitpunkt = null ): array { if (preg_match( '/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i', $installationID ) !== 1) { throw new InvalidArgumentException('Die Installations-ID muss eine UUIDv4 sein.'); } if ($managerID <= 0) { throw new InvalidArgumentException('Die Manager-ID muss positiv sein.'); } if (!in_array($rolle, ['standalone', 'main', 'submanager'], true)) { throw new InvalidArgumentException('Die Managerrolle ist ungueltig.'); } $eindeutig = []; foreach ($meldungen as $meldung) { $normalisiert = self::normalisiereMeldung($meldung); $schluessel = $normalisiert['sourceId'] . "\0" . $normalisiert['code']; $eindeutig[$schluessel] = $normalisiert; } $meldungen = array_values($eindeutig); usort($meldungen, static function (array $links, array $rechts): int { $schweregrad = self::SCHWEREGRADE[$links['severity']] <=> self::SCHWEREGRADE[$rechts['severity']]; if ($schweregrad !== 0) { return $schweregrad; } return [$links['sourceName'], $links['code']] <=> [$rechts['sourceName'], $rechts['code']]; }); // Das Portal akzeptiert hoechstens 100 Meldungen; die hoechste Prioritaet bleibt erhalten. $meldungen = array_slice($meldungen, 0, 100); return [ 'version' => self::VERSION, 'installationId' => strtolower($installationID), 'capturedAt' => gmdate('Y-m-d\TH:i:s\Z', $zeitpunkt ?? time()), 'manager' => [ 'instanceId' => $managerID, 'role' => $rolle, 'active' => $managerAktiv, ], 'faults' => $meldungen, ]; } /** @param array $snapshot */ public static function zustandHash(array $snapshot): string { unset($snapshot['capturedAt']); return hash('sha256', json_encode( $snapshot, JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES )); } /** * @param array $meldung * @return array */ private static function normalisiereMeldung(array $meldung): array { $felder = ['sourceType', 'sourceId', 'sourceName', 'code', 'severity', 'message']; if (array_diff($felder, array_keys($meldung)) !== [] || array_diff(array_keys($meldung), $felder) !== [] ) { throw new InvalidArgumentException('Eine Stoerungsmeldung hat ungueltige Felder.'); } $normalisiert = []; foreach ($felder as $feld) { if (!is_string($meldung[$feld])) { throw new InvalidArgumentException('Stoerungsfelder muessen Texte sein.'); } $normalisiert[$feld] = trim((string) preg_replace('/\s+/', ' ', $meldung[$feld])); } if ($normalisiert['sourceType'] === '' || $normalisiert['sourceId'] === '' || $normalisiert['sourceName'] === '' || $normalisiert['code'] === '' || $normalisiert['message'] === '' ) { throw new InvalidArgumentException('Stoerungsfelder duerfen nicht leer sein.'); } if (!array_key_exists($normalisiert['severity'], self::SCHWEREGRADE)) { throw new InvalidArgumentException('Der Stoerungsschweregrad ist ungueltig.'); } if (strlen($normalisiert['sourceType']) > 40 || strlen($normalisiert['sourceId']) > 120 || strlen($normalisiert['sourceName']) > 160 || strlen($normalisiert['code']) > 120 || strlen($normalisiert['message']) > 500 ) { throw new InvalidArgumentException('Mindestens ein Stoerungsfeld ist zu lang.'); } return $normalisiert; } }