> $checks */ public static function forChecks(array $checks): string { $tuples = []; foreach ($checks as $check) { if (! is_array($check)) { continue; } $key = self::normalizeKey($check['key'] ?? null); $status = self::normalizeEnumString($check['status'] ?? null); $reasonCode = self::normalizeEnumString($check['reason_code'] ?? null); $blocking = is_bool($check['blocking'] ?? null) ? (bool) $check['blocking'] : false; $severity = $check['severity'] ?? null; $severity = is_string($severity) ? trim($severity) : ''; if ($severity === '') { $severity = ''; } else { $severity = strtolower($severity); } $tuples[] = [ 'key' => $key, 'tuple' => implode('|', [ $key, $status, $blocking ? '1' : '0', $reasonCode, $severity, ]), ]; } usort($tuples, static function (array $a, array $b): int { $keyComparison = $a['key'] <=> $b['key']; if ($keyComparison !== 0) { return $keyComparison; } return $a['tuple'] <=> $b['tuple']; }); $payload = implode("\n", array_map(static fn (array $item): string => (string) $item['tuple'], $tuples)); return hash('sha256', $payload); } /** * @param array $report */ public static function forReport(array $report): string { $checks = $report['checks'] ?? null; $checks = is_array($checks) ? $checks : []; /** @var array> $checks */ return self::forChecks($checks); } private static function normalizeKey(mixed $value): string { if (! is_string($value)) { return ''; } $value = trim($value); return $value === '' ? '' : $value; } private static function normalizeEnumString(mixed $value): string { if (! is_string($value)) { return ''; } $value = trim($value); return $value === '' ? '' : strtolower($value); } }