Files
Enelix-EMS/libs/Lizenzpruefung.php
T

204 lines
6.5 KiB
PHP

<?php
declare(strict_types=1);
namespace Belevo\EnelixEMS;
use DateTimeImmutable;
use InvalidArgumentException;
use Throwable;
final class Lizenzpruefung
{
public const MANAGER_STANDARD = 'manager_standard';
public const MANAGER_PEAK = 'manager_peak';
public static function normalisiereCode(string $code): string
{
return strtoupper((string) preg_replace('/[^A-Z0-9]/i', '', $code));
}
public static function istLizenzcodeGueltig(string $code): bool
{
return preg_match(
'/^ENX[A-HJ-NP-Z2-9]{16}$/',
self::normalisiereCode($code)
) === 1;
}
/**
* @param array<string, mixed> $lease
*/
public static function pruefeLease(
array $lease,
string $installationID,
int $lastspitzenmodus,
?int $zeitpunkt = null
): void {
if (($lease['status'] ?? null) !== 'active') {
throw new InvalidArgumentException('Die Lizenz ist nicht aktiv.');
}
if (($lease['installationId'] ?? null) !== $installationID) {
throw new InvalidArgumentException('Die Lizenz gehoert zu einer anderen Installation.');
}
if (isset($lease['development']) && !is_bool($lease['development'])) {
throw new InvalidArgumentException('Der Entwicklungsstatus der Lizenz ist ungueltig.');
}
$ausgestelltAm = self::zeitstempel($lease, 'issuedAt');
$erneuernAb = self::zeitstempel($lease, 'refreshAfter');
$offlineBis = self::zeitstempel($lease, 'offlineUntil');
if ($ausgestelltAm > $erneuernAb || $erneuernAb > $offlineBis) {
throw new InvalidArgumentException('Die Lizenzzeitpunkte sind widerspruechlich.');
}
if (($zeitpunkt ?? time()) >= $offlineBis) {
throw new InvalidArgumentException('Die Offline-Freigabe ist abgelaufen.');
}
$berechtigungen = $lease['entitlements'] ?? null;
if (!is_array($berechtigungen)) {
throw new InvalidArgumentException('Die Lizenz enthaelt keine Berechtigungen.');
}
$standard = false;
$peak = false;
foreach ($berechtigungen as $berechtigung) {
if (!is_array($berechtigung)
|| ($berechtigung['status'] ?? null) !== 'active'
|| !is_int($berechtigung['quantity'] ?? null)
|| $berechtigung['quantity'] < 1
) {
continue;
}
$kennung = $berechtigung['catalog_key'] ?? $berechtigung['sku'] ?? null;
$standard = $standard || $kennung === self::MANAGER_STANDARD;
$peak = $peak || $kennung === self::MANAGER_PEAK;
}
if (!$standard && !$peak) {
throw new InvalidArgumentException('Die Manager-Berechtigung fehlt.');
}
if ($lastspitzenmodus !== 0 && !$peak) {
throw new InvalidArgumentException('Peak Shaving ist nicht lizenziert.');
}
}
/**
* Liefert die aufsummierte aktive Berechtigung fuer einen Katalogeintrag.
*
* @param array<string, mixed> $lease
*/
public static function berechtigungsMenge(array $lease, string $kennung): int
{
$berechtigungen = $lease['entitlements'] ?? null;
if (!is_array($berechtigungen)) {
return 0;
}
$menge = 0;
foreach ($berechtigungen as $berechtigung) {
if (!is_array($berechtigung)
|| ($berechtigung['status'] ?? null) !== 'active'
|| !is_int($berechtigung['quantity'] ?? null)
|| $berechtigung['quantity'] < 1
) {
continue;
}
$berechtigungsKennung = $berechtigung['catalog_key']
?? $berechtigung['sku']
?? null;
if ($berechtigungsKennung === $kennung) {
$menge += $berechtigung['quantity'];
}
}
return $menge;
}
/**
* @param array<string, mixed> $lease
* @param array<string, int> $verwendeteMengen
*/
public static function pruefeVerbrauchermengen(array $lease, array $verwendeteMengen): void
{
foreach ($verwendeteMengen as $kennung => $verwendet) {
if ($verwendet < 0) {
throw new InvalidArgumentException(
'Die verwendete Menge fuer ' . $kennung . ' darf nicht negativ sein.'
);
}
$lizenziert = self::berechtigungsMenge($lease, $kennung);
if ($verwendet > $lizenziert) {
throw new InvalidArgumentException(sprintf(
'Lizenzkontingent fuer %s ueberschritten: %d verwendet, %d lizenziert.',
$kennung,
$verwendet,
$lizenziert
));
}
}
}
/**
* @param array<string, mixed> $lease
*/
public static function istLeaseGueltig(
array $lease,
string $installationID,
int $lastspitzenmodus,
?int $zeitpunkt = null
): bool {
try {
self::pruefeLease($lease, $installationID, $lastspitzenmodus, $zeitpunkt);
return true;
} catch (Throwable $fehler) {
return false;
}
}
/**
* @param array<string, mixed> $lease
*/
public static function erneuerungFaellig(array $lease, ?int $zeitpunkt = null): bool
{
try {
return ($zeitpunkt ?? time()) >= self::zeitstempel($lease, 'refreshAfter');
} catch (Throwable $fehler) {
return true;
}
}
/**
* @param array<string, mixed> $lease
*/
public static function offlineBis(array $lease): int
{
return self::zeitstempel($lease, 'offlineUntil');
}
/**
* @param array<string, mixed> $lease
*/
public static function erneuernAb(array $lease): int
{
return self::zeitstempel($lease, 'refreshAfter');
}
/**
* @param array<string, mixed> $lease
*/
private static function zeitstempel(array $lease, string $feld): int
{
$wert = $lease[$feld] ?? null;
if (!is_string($wert) || trim($wert) === '') {
throw new InvalidArgumentException($feld . ' fehlt in der Lizenz.');
}
try {
return (new DateTimeImmutable($wert))->getTimestamp();
} catch (Throwable $fehler) {
throw new InvalidArgumentException($feld . ' ist kein gueltiger ISO-8601-Zeitpunkt.', 0, $fehler);
}
}
}