Co-authored-by: tg95 <tg95@noreply.localhost> Co-authored-by: Taarly <lownslow.music@gmail.com> Co-authored-by: taarly <lownslow.music@gmail.com> Co-authored-by: ViperioN1339 <stezel1989@outlook.de> Co-authored-by: MuchenTuchen31 <yasin.mine31@gmail.com> Reviewed-on: https://git.eckertplayground.de/taarly/PHP_AdminTool_Projekt/pulls/28 Co-authored-by: blaerf <blaerf@gmx.de> Co-committed-by: blaerf <blaerf@gmx.de>
164 lines
7.7 KiB
PHP
164 lines
7.7 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* Log Viewer (Ansicht).
|
|
*
|
|
* Erwartete Variablen:
|
|
* @var array<int, array{name:string, size:int, mtime:int}> $files
|
|
* @var string $selectedFile
|
|
* @var array{name:string, size:int, mtime:int}|null $fileMeta
|
|
* @var array<int, array{ts:string|null, level:string|null, message:string, context:array<string,mixed>|null, raw:string}> $entries
|
|
* @var string $filterLevel
|
|
* @var string $searchQuery
|
|
* @var int $lines
|
|
* @var string|null $error
|
|
*/
|
|
?>
|
|
|
|
<div class="d-sm-flex align-items-center justify-content-between mb-4">
|
|
<h1 class="h3 mb-0 text-gray-800">Log Viewer</h1>
|
|
</div>
|
|
|
|
<?php if (!empty($error)) : ?>
|
|
<div class="alert alert-danger" role="alert">
|
|
<?php echo htmlspecialchars((string)$error, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<div class="card shadow mb-4">
|
|
<div class="card-header py-3">
|
|
<h6 class="m-0 font-weight-bold text-primary">Filter</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<form method="get" action="../index.php">
|
|
<input type="hidden" name="route" value="logs">
|
|
|
|
<div class="form-row">
|
|
<div class="form-group col-md-4">
|
|
<label for="file">Log-Datei</label>
|
|
<select class="form-control" id="file" name="file">
|
|
<?php foreach (($files ?? []) as $f) : ?>
|
|
<?php $name = (string)($f['name'] ?? ''); ?>
|
|
<option value="<?php echo htmlspecialchars($name, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?>"
|
|
<?php echo ($name === (string)$selectedFile) ? 'selected' : ''; ?>>
|
|
<?php echo htmlspecialchars($name, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="form-group col-md-2">
|
|
<label for="level">Level</label>
|
|
<select class="form-control" id="level" name="level">
|
|
<?php
|
|
$levels = ['', 'ERROR', 'WARNING', 'INFO', 'DEBUG'];
|
|
foreach ($levels as $lvl) :
|
|
$label = ($lvl === '') ? 'Alle' : $lvl;
|
|
?>
|
|
<option value="<?php echo htmlspecialchars($lvl, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?>"
|
|
<?php echo ((string)$filterLevel === (string)$lvl) ? 'selected' : ''; ?>>
|
|
<?php echo htmlspecialchars($label, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="form-group col-md-3">
|
|
<label for="q">Suche</label>
|
|
<input type="text" class="form-control" id="q" name="q"
|
|
value="<?php echo htmlspecialchars((string)$searchQuery, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?>"
|
|
placeholder="Text in message/context">
|
|
</div>
|
|
|
|
<div class="form-group col-md-2">
|
|
<label for="lines">Zeilen</label>
|
|
<input type="number" class="form-control" id="lines" name="lines"
|
|
value="<?php echo (int)$lines; ?>" min="1" max="2000">
|
|
</div>
|
|
|
|
<div class="form-group col-md-1 d-flex align-items-end">
|
|
<button type="submit" class="btn btn-primary btn-block">
|
|
Anzeigen
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<?php if (is_array($fileMeta)) : ?>
|
|
<div class="small text-gray-600">
|
|
Datei: <strong><?php echo htmlspecialchars((string)$fileMeta['name'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></strong>
|
|
· Größe: <?php echo number_format((int)$fileMeta['size'], 0, ',', '.'); ?> Bytes
|
|
· Stand: <?php echo ($fileMeta['mtime'] ?? 0) > 0 ? date('d.m.Y H:i:s', (int)$fileMeta['mtime']) : 'n/a'; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card shadow mb-4">
|
|
<div class="card-header py-3 d-flex align-items-center justify-content-between">
|
|
<h6 class="m-0 font-weight-bold text-primary">Einträge (neueste unten)</h6>
|
|
<a class="btn btn-sm btn-outline-secondary"
|
|
href="../index.php?route=logs&file=<?php echo urlencode((string)$selectedFile); ?>&level=<?php echo urlencode((string)$filterLevel); ?>&q=<?php echo urlencode((string)$searchQuery); ?>&lines=<?php echo (int)$lines; ?>">
|
|
Refresh
|
|
</a>
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
<?php if (empty($entries)) : ?>
|
|
<div class="text-gray-600">Keine Einträge gefunden.</div>
|
|
<?php else : ?>
|
|
<div class="table-responsive">
|
|
<table class="table table-bordered table-sm" width="100%" cellspacing="0">
|
|
<thead>
|
|
<tr>
|
|
<th style="width: 170px;">Zeit</th>
|
|
<th style="width: 110px;">Level</th>
|
|
<th>Message</th>
|
|
<th style="width: 35%;">Context</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($entries as $e) : ?>
|
|
<?php
|
|
$lvl = strtoupper((string)($e['level'] ?? ''));
|
|
$badge = 'badge-secondary';
|
|
if ($lvl === 'ERROR') { $badge = 'badge-danger'; }
|
|
if ($lvl === 'WARNING') { $badge = 'badge-warning'; }
|
|
if ($lvl === 'INFO') { $badge = 'badge-info'; }
|
|
if ($lvl === 'DEBUG') { $badge = 'badge-light'; }
|
|
|
|
$ctx = $e['context'] ?? null;
|
|
$ctxPretty = '';
|
|
if (is_array($ctx)) {
|
|
$ctxPretty = (string)json_encode($ctx, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
|
}
|
|
?>
|
|
<tr>
|
|
<td><?php echo htmlspecialchars((string)($e['ts'] ?? ''), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></td>
|
|
<td>
|
|
<span class="badge <?php echo $badge; ?>">
|
|
<?php echo htmlspecialchars($lvl, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?>
|
|
</span>
|
|
</td>
|
|
<td><?php echo htmlspecialchars((string)($e['message'] ?? ''), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></td>
|
|
<td>
|
|
<?php if ($ctxPretty !== '') : ?>
|
|
<pre class="mb-0" style="white-space: pre-wrap;"><?php echo htmlspecialchars($ctxPretty, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></pre>
|
|
<?php else : ?>
|
|
<span class="text-gray-600">-</span>
|
|
<?php endif; ?>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="small text-gray-600">
|
|
Hinweis: Dieser Viewer lädt bewusst nur die letzten Zeilen (Tail), damit große Logfiles die Oberfläche nicht killen.
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|