CodePress CMS v1.9.0: visitor statistics with SVG world map and GeoIP

- Add GeoIP class with provider chain: local DB-IP Lite, MaxMind .mmdb, external API
- Add built-in pure-PHP MMDBReader so .mmdb works without Composer
- Add cli/geoip-update.php to download DB-IP Lite and build a compact binary index
- Add cli/generate-world-map.php to generate the world map SVG from Natural Earth TopoJSON
- Add Analytics class aggregating stats in admin/storage/stats.json with LOCK_EX
- Add admin statistics page with choropleth world map, country list, top pages,
  daily chart, referrers and a period filter
- Add GeoIP and privacy settings with database update and stats reset buttons
- Add optional IP anonymization and configurable retention period
- Add country field to requests.log (parser accepts 7, 8 or 9 fields)
- Add country column to request log and KPI cards to the dashboard
- Ignore GeoIP binaries and stats.json in Git
- Update TODO.md, guides and version to 1.9.0
This commit is contained in:
2026-07-29 15:40:02 +02:00
parent 8c6b38c2c5
commit 06785e9922
20 changed files with 1804 additions and 11 deletions
+26 -4
View File
@@ -146,24 +146,46 @@ if (!$isAllowedIp) {
// Instantiate CMS instance
$cms = new CodePressCMS($config);
// Analytics & GeoIP settings
$analyticsSettings = $config['analytics'] ?? [];
$geoCountry = null;
if (!empty($analyticsSettings['enabled'])) {
$geoIp = new GeoIP($analyticsSettings);
$geoCountry = $geoIp->lookupCountry($clientIp);
}
// Apply IP anonymization for storage if enabled
$storedIp = !empty($analyticsSettings['anonymize_ip'])
? RequestLogger::anonymizeIp($clientIp)
: $clientIp;
// Log page view (not for media/assets)
if (!str_starts_with($path, '/-media/') && !str_starts_with($path, '/-assets/')) {
if (session_status() === PHP_SESSION_NONE) {
@session_start();
}
$loggedInUser = $_SESSION['admin_user'] ?? 'Gast';
$currentPage = $_GET['page'] ?? $cms->getEffectiveDefaultPage();
$referrer = $_SERVER['HTTP_REFERER'] ?? '';
$requestLogFile = dirname(__DIR__) . '/admin/storage/logs/requests.log';
$logger = new RequestLogger($requestLogFile);
$logger->log(
$_GET['page'] ?? $cms->getEffectiveDefaultPage(),
$clientIp,
$currentPage,
$storedIp,
$userAgent,
$_SERVER['HTTP_REFERER'] ?? '',
$referrer,
$loggedInUser,
$_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? '',
$requestStatus
$requestStatus,
$geoCountry
);
// Record aggregated statistics
if (!empty($analyticsSettings['enabled'])) {
$analytics = new Analytics($analyticsSettings);
$analytics->record($currentPage, $storedIp, $userAgent, $referrer, $geoCountry, $requestStatus);
}
}
// Block request if status is not ok