This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user