Auf Shared Hosting gibt es keine Kommandozeile - ohne Anzeige laesst sich dort nicht feststellen, ob etwa gd fehlt, die PHP-Version zu alt ist oder data/ nicht beschreibbar ist. Der Setup-Assistent prueft das jetzt und listet es auf; im Dashboard meldet sich die Pruefung spaeter nur noch, wenn etwas nicht stimmt. Fehlende Pflichtbausteine sind Fehler, fehlende Kuer (intl, imagick, cURL) nur Hinweise mit Angabe, was dadurch entfaellt. build-release.sh erzeugt das Upload-Paket: Abhaengigkeiten ohne Entwicklungspakete, ohne Tests und Docker-Dateien. Dabei faellt eine 16 MB grosse Schriftart aus endroid/qr-code weg, die ausschliesslich fuer Beschriftungen unter dem QR-Code gebraucht wird - die erzeugt diese Anwendung nicht. Das Paket schrumpft damit von 18 MB auf 1 MB. Sollte spaeter doch eine Beschriftung dazukommen, erkennt das Skript das und behaelt die Datei. Die Variante ohne eigenen Webroot (alles liegt im Domainverzeichnis, die .htaccess im Stammverzeichnis leitet nach public/ um) war bisher gebaut, aber nie erprobt. Sie ist jetzt gegen eine Hoster-Simulation getestet: Ersteinrichtung, Kurzlinks, Weiterleitung, QR-Codes, Statistik und die Sperren fuer src/, vendor/, data/ und .env.
136 lines
5.8 KiB
PHP
136 lines
5.8 KiB
PHP
<?php
|
||
|
||
/**
|
||
* @var array{links:int,clicks:int,active:int} $summary
|
||
* @var list<array<string,mixed>> $recentLinks
|
||
* @var list<array<string,mixed>> $topLinks
|
||
* @var list<array{date:string,clicks:int}> $series
|
||
* @var int $domainCount
|
||
* @var App\Config $config
|
||
*/
|
||
|
||
use App\Repository\LinkRepository;
|
||
use App\Service\SystemCheck;
|
||
use App\Support\ShortDomain;
|
||
|
||
$fallbackBase = rtrim($config->baseUrl(), '/');
|
||
?>
|
||
<?php if (($systemProblems ?? []) !== []):
|
||
$hatFehler = false;
|
||
foreach ($systemProblems as $problem) {
|
||
if ($problem['status'] === SystemCheck::ERROR) {
|
||
$hatFehler = true;
|
||
}
|
||
}
|
||
?>
|
||
<section class="card check-result check-result--<?= $hatFehler ? 'error' : 'warn' ?>">
|
||
<div class="check-result__head">
|
||
<span class="check-result__icon" aria-hidden="true"><?= $hatFehler ? '×' : '!' ?></span>
|
||
<div>
|
||
<h2>Hinweise zum Server</h2>
|
||
<p class="check-result__summary">
|
||
<?= $hatFehler
|
||
? 'Es fehlt etwas, das die Anwendung braucht.'
|
||
: 'Alles läuft – einzelne Zusatzfunktionen stehen aber nicht zur Verfügung.' ?>
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<ul class="check-list">
|
||
<?php foreach ($systemProblems as $problem): ?>
|
||
<li class="check-list__item check-list__item--<?= $problem['status'] === SystemCheck::ERROR ? 'error' : 'warn' ?>">
|
||
<span class="check-list__icon" aria-hidden="true"><?= $problem['status'] === SystemCheck::ERROR ? '×' : '!' ?></span>
|
||
<span class="check-list__label"><?= $e($problem['label']) ?></span>
|
||
<span class="check-list__text"><?= $e($problem['text']) ?></span>
|
||
</li>
|
||
<?php endforeach; ?>
|
||
</ul>
|
||
</section>
|
||
<?php endif; ?>
|
||
<div class="page-head">
|
||
<div>
|
||
<h1>Übersicht</h1>
|
||
<p class="muted">Alle Kurzlinks und Klicks auf einen Blick.</p>
|
||
</div>
|
||
<a href="<?= $e($url('/admin/links/new')) ?>" class="btn btn--primary">Neuer Kurzlink</a>
|
||
</div>
|
||
|
||
<div class="stats-grid">
|
||
<div class="stat">
|
||
<span class="stat__label">Kurzlinks</span>
|
||
<span class="stat__value"><?= (int) $summary['links'] ?></span>
|
||
</div>
|
||
<div class="stat">
|
||
<span class="stat__label">davon aktiv</span>
|
||
<span class="stat__value"><?= (int) $summary['active'] ?></span>
|
||
</div>
|
||
<div class="stat">
|
||
<span class="stat__label">Klicks gesamt</span>
|
||
<span class="stat__value"><?= number_format((int) $summary['clicks'], 0, ',', '.') ?></span>
|
||
</div>
|
||
<div class="stat">
|
||
<span class="stat__label">Klicks (30 Tage)</span>
|
||
<span class="stat__value"><?= number_format(array_sum(array_column($series, 'clicks')), 0, ',', '.') ?></span>
|
||
</div>
|
||
<div class="stat">
|
||
<span class="stat__label">Domains</span>
|
||
<span class="stat__value">
|
||
<a href="<?= $e($url('/admin/domains')) ?>"><?= (int) $domainCount ?></a>
|
||
</span>
|
||
</div>
|
||
</div>
|
||
|
||
<section class="card">
|
||
<h2>Klicks der letzten 30 Tage</h2>
|
||
<div class="chart" data-chart="line" data-series="<?= $e(json_encode($series, JSON_UNESCAPED_SLASHES)) ?>">
|
||
<canvas height="120" aria-label="Liniendiagramm der Klicks pro Tag"></canvas>
|
||
<noscript><p class="muted">Für das Diagramm wird JavaScript benötigt.</p></noscript>
|
||
</div>
|
||
</section>
|
||
|
||
<div class="grid grid--2">
|
||
<section class="card">
|
||
<h2>Zuletzt angelegt</h2>
|
||
<?php if ($recentLinks === []): ?>
|
||
<p class="muted">Noch keine Kurzlinks vorhanden.
|
||
<a href="<?= $e($url('/admin/links/new')) ?>">Jetzt den ersten anlegen.</a></p>
|
||
<?php else: ?>
|
||
<ul class="list">
|
||
<?php foreach ($recentLinks as $link): ?>
|
||
<li class="list__item">
|
||
<div class="list__main">
|
||
<a class="mono" href="<?= $e($url('/admin/links/' . $link['id'] . '/stats')) ?>"><?php
|
||
if ($domainCount > 1 && $link['domain_base_url'] !== null): ?><span class="linkcopy__domain"><?=
|
||
$e(ShortDomain::displayName((string) $link['domain_base_url'])) ?></span><?php
|
||
endif; ?>/<?= $e($link['slug']) ?></a>
|
||
<span class="muted small truncate"><?= $e($link['target_url']) ?></span>
|
||
</div>
|
||
<span class="badge"><?= (int) $link['click_count'] ?> Klicks</span>
|
||
</li>
|
||
<?php endforeach; ?>
|
||
</ul>
|
||
<?php endif; ?>
|
||
</section>
|
||
|
||
<section class="card">
|
||
<h2>Meistgeklickt</h2>
|
||
<?php if ($topLinks === [] || (int) $summary['clicks'] === 0): ?>
|
||
<p class="muted">Noch keine Klicks erfasst.</p>
|
||
<?php else: ?>
|
||
<ul class="list">
|
||
<?php foreach ($topLinks as $link): ?>
|
||
<li class="list__item">
|
||
<div class="list__main">
|
||
<a class="mono" href="<?= $e($url('/admin/links/' . $link['id'] . '/stats')) ?>"><?php
|
||
if ($domainCount > 1 && $link['domain_base_url'] !== null): ?><span class="linkcopy__domain"><?=
|
||
$e(ShortDomain::displayName((string) $link['domain_base_url'])) ?></span><?php
|
||
endif; ?>/<?= $e($link['slug']) ?></a>
|
||
<span class="muted small truncate"><?= $e($link['target_url']) ?></span>
|
||
</div>
|
||
<span class="badge"><?= (int) $link['click_count'] ?> Klicks</span>
|
||
</li>
|
||
<?php endforeach; ?>
|
||
</ul>
|
||
<?php endif; ?>
|
||
</section>
|
||
</div>
|