beginTransaction(); try { $stmt = $pdo->prepare('SELECT view_count FROM public_page_views WHERE view_date = CURRENT_DATE AND page_key = ?'); $stmt->execute(['landing']); $before = (int)($stmt->fetchColumn() ?: 0); $_SERVER['REQUEST_METHOD'] = 'GET'; app_record_public_page_view('landing', $pdo); $stmt->execute(['landing']); $afterGet = (int)($stmt->fetchColumn() ?: 0); $assert('Ein GET erhöht den aggregierten Tageszähler genau einmal', $afterGet === $before + 1); $_SERVER['REQUEST_METHOD'] = 'POST'; app_record_public_page_view('landing', $pdo); $stmt->execute(['landing']); $afterPost = (int)($stmt->fetchColumn() ?: 0); $assert('Ein POST wird nicht als Seitenaufruf gezählt', $afterPost === $afterGet); $_SERVER['REQUEST_METHOD'] = 'GET'; try { app_record_public_page_view('token-aus-einer-url', $pdo); $assert('Unbekannte Seitenschlüssel werden abgewiesen', false); } catch (InvalidArgumentException) { $assert('Unbekannte Seitenschlüssel werden abgewiesen', true); } $summary = app_public_page_view_summary($pdo); $landingRows = array_values(array_filter( $summary['pages'], static fn(array $row): bool => $row['page_key'] === 'landing' )); $assert('Back-Office-Zusammenfassung enthält den aktuellen Zähler', $summary['totals']['today'] >= $afterGet && count($landingRows) === 1 && $landingRows[0]['today'] === $afterGet); $columns = $pdo->query('SHOW COLUMNS FROM public_page_views')->fetchAll(PDO::FETCH_COLUMN); sort($columns); $assert('Statistiktabelle enthält nur Datum, Seitenschlüssel und Anzahl', $columns === ['page_key', 'view_count', 'view_date']); $counterSource = file_get_contents(__DIR__ . '/../app/public-page-views.php') ?: ''; $assert('Zähler liest keine IP-, User-Agent- oder URL-Daten', !str_contains($counterSource, 'REMOTE_ADDR') && !str_contains($counterSource, 'HTTP_USER_AGENT') && !str_contains($counterSource, 'REQUEST_URI')); foreach ([ 'landing.php' => 'landing', 'preise.php' => 'prices', 'register.php' => 'register', 'login.php' => 'login', 'datenschutz.php' => 'privacy', 'impressum.php' => 'imprint', 'agb.php' => 'terms', 'avv.php' => 'dpa', 'widerruf.php' => 'withdrawal_information', ] as $template => $pageKey) { $templateSource = file_get_contents(APP_ROOT . '/' . $template) ?: ''; $assert("{$template} zählt den festen Seitenschlüssel {$pageKey}", str_contains($templateSource, "app_record_public_page_view('{$pageKey}')")); } $privacy = app_legal_document_text('privacy_notice'); $assert('Datenschutzerklärung grenzt den anonymen Zähler von Matomo ab', str_contains($privacy, 'anonyme Aufrufzahlen') && str_contains($privacy, 'weder die Ermittlung eindeutiger Besucher noch die Bildung von Nutzungsprofilen')); } finally { if ($pdo->inTransaction()) { $pdo->rollBack(); } if ($previousMethod === null) { unset($_SERVER['REQUEST_METHOD']); } else { $_SERVER['REQUEST_METHOD'] = $previousMethod; } } if ($failures > 0) { echo "\n{$failures} Seitenzähler-Prüfung(en) fehlgeschlagen.\n"; exit(1); } echo "\nAnonymer Seitenzähler: alle Prüfungen bestanden.\n";