Widgets, backend module template and flash messages now match the rest of the backend, which is English. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
118 lines
4.7 KiB
PHP
118 lines
4.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Evomedien\Vitec\Widgets;
|
|
|
|
use Evomedien\Vitec\Service\SsrPurgeService;
|
|
use TYPO3\CMS\Core\Core\Environment;
|
|
use TYPO3\CMS\Core\Database\ConnectionPool;
|
|
use TYPO3\CMS\Core\Http\RequestFactory;
|
|
use TYPO3\CMS\Dashboard\Widgets\WidgetConfigurationInterface;
|
|
use TYPO3\CMS\Dashboard\Widgets\WidgetInterface;
|
|
|
|
/**
|
|
* Dashboard tile: live state of the SSR node on the Solr VPS plus the
|
|
* delivery switch - green/red at a glance after backend login.
|
|
*/
|
|
final class SsrStatusWidget implements WidgetInterface
|
|
{
|
|
public function __construct(
|
|
private readonly WidgetConfigurationInterface $configuration,
|
|
private readonly SsrPurgeService $purgeService,
|
|
private readonly RequestFactory $requestFactory,
|
|
private readonly ConnectionPool $connectionPool,
|
|
) {}
|
|
|
|
public function renderWidgetContent(): string
|
|
{
|
|
$flagOn = file_exists(Environment::getVarPath() . '/vitec-ssr-on.flag');
|
|
$health = $this->fetchHealth();
|
|
$lastPurge = $this->lastPurgeRow();
|
|
|
|
$badge = static function (bool $ok, string $yes, string $no): string {
|
|
return $ok
|
|
? '<span class="badge badge-success">' . htmlspecialchars($yes) . '</span>'
|
|
: '<span class="badge badge-danger">' . htmlspecialchars($no) . '</span>';
|
|
};
|
|
|
|
$rows = [];
|
|
$rows[] = ['SSR delivery', $badge($flagOn, 'ON - pages served from the VPS', 'OFF - SPA as before')];
|
|
if ($health === null) {
|
|
$rows[] = ['SSR server', '<span class="badge badge-danger">NOT REACHABLE</span>'];
|
|
} else {
|
|
$rows[] = ['SSR server', $badge((bool)($health['ok'] ?? false), 'running (' . (int)$health['responseMs'] . ' ms)', 'reports errors')];
|
|
$rows[] = ['Release', htmlspecialchars((string)($health['release']['release'] ?? '?'))
|
|
. ' <small>(commit ' . htmlspecialchars((string)($health['release']['commit'] ?? '?'))
|
|
. ', built ' . htmlspecialchars($this->fmtDate((string)($health['release']['builtAt'] ?? ''))) . ')</small>'];
|
|
$rows[] = ['Page cache', (int)($health['cachedPages'] ?? 0) . ' pages / ' . (int)($health['cacheMB'] ?? 0) . ' MB'];
|
|
}
|
|
if ($lastPurge !== null) {
|
|
$rows[] = ['Last purge', htmlspecialchars(date('m-d H:i', (int)$lastPurge['crdate']))
|
|
. ' <small>(' . htmlspecialchars((string)$lastPurge['trigger_source']) . ', '
|
|
. ($lastPurge['success'] ? 'ok' : 'FAILED') . ', '
|
|
. htmlspecialchars(mb_strimwidth((string)$lastPurge['paths'], 0, 60, '…')) . ')</small>'];
|
|
}
|
|
if (!$this->purgeService->isConfigured()) {
|
|
$rows[] = ['Auto purge', '<span class="badge badge-warning">not configured (var/vitec-ssr-purge.env missing)</span>'];
|
|
}
|
|
|
|
$html = '<table class="table table-striped table-sm"><tbody>';
|
|
foreach ($rows as [$label, $value]) {
|
|
$html .= '<tr><th style="width:38%">' . htmlspecialchars($label) . '</th><td>' . $value . '</td></tr>';
|
|
}
|
|
$html .= '</tbody></table>';
|
|
$html .= '<p class="text-muted" style="font-size:11px">Switch: Site Management › Settings › VITEC. Module "VITEC SSR" for purge & protocol.</p>';
|
|
return $html;
|
|
}
|
|
|
|
public function getOptions(): array
|
|
{
|
|
return [];
|
|
}
|
|
|
|
private function fetchHealth(): ?array
|
|
{
|
|
$endpoint = $this->purgeService->getHealthEndpoint();
|
|
if ($endpoint === '') {
|
|
return null;
|
|
}
|
|
$start = microtime(true);
|
|
try {
|
|
$response = $this->requestFactory->request($endpoint, 'GET', [
|
|
'timeout' => 3, 'connect_timeout' => 2, 'http_errors' => false,
|
|
]);
|
|
if ($response->getStatusCode() !== 200) {
|
|
return null;
|
|
}
|
|
$data = json_decode((string)$response->getBody(), true);
|
|
if (!is_array($data)) {
|
|
return null;
|
|
}
|
|
$data['responseMs'] = (int)round((microtime(true) - $start) * 1000);
|
|
return $data;
|
|
} catch (\Throwable) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private function lastPurgeRow(): ?array
|
|
{
|
|
try {
|
|
$qb = $this->connectionPool->getQueryBuilderForTable('tx_vitec_ssrpurgelog');
|
|
$row = $qb->select('*')->from('tx_vitec_ssrpurgelog')
|
|
->orderBy('uid', 'DESC')->setMaxResults(1)
|
|
->executeQuery()->fetchAssociative();
|
|
return $row ?: null;
|
|
} catch (\Throwable) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private function fmtDate(string $iso): string
|
|
{
|
|
$ts = strtotime($iso);
|
|
return $ts ? date('Y-m-d H:i', $ts) : '?';
|
|
}
|
|
}
|