132 lines
4.5 KiB
PHP
132 lines
4.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Belevo\EnelixEMS;
|
|
|
|
use InvalidArgumentException;
|
|
|
|
final class StoerungsSnapshot
|
|
{
|
|
public const VERSION = '1.0';
|
|
|
|
private const SCHWEREGRADE = [
|
|
'critical' => 0,
|
|
'error' => 1,
|
|
'warning' => 2,
|
|
'info' => 3,
|
|
];
|
|
|
|
/**
|
|
* @param list<array<string, mixed>> $meldungen
|
|
* @return array<string, mixed>
|
|
*/
|
|
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<string, mixed> $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<string, mixed> $meldung
|
|
* @return array<string, string>
|
|
*/
|
|
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;
|
|
}
|
|
}
|