' . self::e($info) . ''; } return '
' . $button . $inner . '
'; } public static function pill(string $tone, string $text, string $title = ''): string { return '' . self::e($text) . ''; } /** * Ring gauge, 0..1, with a short text in the middle. */ public static function ring(float $fraction, string $tone, string $center, int $size = 76): string { $c = 2 * M_PI * 40; $offset = $c * (1 - max(0.0, min(1.0, $fraction))); return '
' . '' . '' . self::e($center) . '
'; } /** * Same labels and tones as the purge timeline in the module. * * @return array{0: string, 1: string, 2: string} [label, tone, user] */ public static function trigger(string $source): array { $who = ''; if (str_contains($source, ':')) { [$source, $who] = explode(':', $source, 2); } return match ($source) { 'module' => ['manual', 'orange', $who], 'contextmenu' => ['context menu', 'navy', $who], 'editor-save', 'editor-command' => ['auto-purge', 'ok', $who], 'switch-on' => ['switch-on', 'warn', $who], default => [$source, 'sky', $who], }; } /** * Availability strip of the last 24 hours, 96 windows of 15 minutes, * from the health log (cron vitec:ssr-health every 5 minutes). * * @return array{html: string, uptime: ?float, slow: int, down: int, samples: int} */ public static function strip(ConnectionPool $pool): array { $slot = 900; $end = intdiv(time(), $slot) * $slot + $slot; $windows = array_fill(0, 96, null); $ok = 0; $n = 0; try { $rows = $pool->getConnectionForTable('tx_vitec_ssrhealthlog')->executeQuery( 'SELECT crdate, ok, response_ms FROM tx_vitec_ssrhealthlog WHERE crdate > ?', [$end - 96 * $slot] )->fetchAllAssociative(); } catch (\Throwable) { $rows = []; } foreach ($rows as $r) { $i = 95 - intdiv($end - 1 - (int)$r['crdate'], $slot); if ($i < 0 || $i > 95) { continue; } $n++; $isOk = (int)$r['ok'] === 1; $ok += $isOk ? 1 : 0; $state = !$isOk ? 2 : ((int)$r['response_ms'] > 400 ? 1 : 0); if ($windows[$i] === null || $state > $windows[$i]['s']) { $windows[$i] = ['s' => $state, 'ms' => (int)$r['response_ms']]; } } $slow = 0; $down = 0; $html = '
' . date('H:i', $end - 96 * $slot) . '' . date('H:i', $end - 48 * $slot) . 'now
'; return [ 'html' => $html, 'uptime' => $n > 0 ? round($ok / $n * 100, 1) : null, 'slow' => $slow, 'down' => $down, 'samples' => $n, ]; } public static function moduleLink(string $label = 'Open the SSR cockpit'): string { try { $uri = (string)GeneralUtility::makeInstance(UriBuilder::class)->buildUriFromRoute('web_vitecssr'); } catch (\Throwable) { return ''; } return '' . self::e($label) . ' →'; } }