From 5cea473d1708266a49f5116f5bcc5ca9f146f5ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9drix?= Date: Fri, 15 May 2026 20:08:24 +0200 Subject: [PATCH] feat : "Meilleures audiences" + admin/stats pages via flux RSS XML (v1.6.6) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - post_list.php : section AJAX qui lit /trending?period=1h en XML (DOMParser) — plus de rendu PHP - admin_stats.php : colonne "Pages les plus visitées" chargée en AJAX depuis /trending?period=14d XML - index.php/stats : suppression de topGrouped pour /post/ ; seuls /book/ et ASN restent côté serveur Co-Authored-By: Claude Sonnet 4.6 --- CHANGELOG.md | 9 ++++ public/index.php | 13 ++---- public/version.txt | 2 +- templates/admin_stats.php | 89 ++++++++++++++++++++++----------------- templates/post_list.php | 56 ++++++++++++++++++++---- 5 files changed, 112 insertions(+), 57 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d8ba47f..8f0d92d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,15 @@ Format : [Keep a Changelog](https://keepachangelog.com/fr/1.0.0/) — versionnag --- +## [1.6.6] - 2026-05-15 + +### Modifié +- Page d'accueil "Meilleures audiences" : chargement AJAX depuis le flux RSS XML `/trending?period=1h` (DOMParser côté client, plus de rendu PHP) +- `/admin/stats` section "Pages les plus visitées" : chargement AJAX depuis le flux RSS XML `/trending?period=14d` — plus de parsing de logs direct pour cette colonne +- `/admin/stats` : suppression de `topGrouped` pour les pages ; seuls les livres (`/book/`) et l'ASN conservent le parsing log côté serveur + +--- + ## [1.6.5] - 2026-05-15 ### Modifié diff --git a/public/index.php b/public/index.php index 41e71df..183f740 100644 --- a/public/index.php +++ b/public/index.php @@ -2559,25 +2559,20 @@ switch ($action) { $statsRaw = json_decode((string) file_get_contents($statsCacheFile), true) ?: null; } if ($statsRaw === null) { - $cutoff14 = strtotime('-14 days midnight') ?: (time() - 14 * 86400); - $tParser = new TrendingParser('/var/log/apache2', apacheAccessLog()); - $grouped = $tParser->topGrouped($cutoff14, ['/post/' => 30, '/book/' => 20]); - - // IPs pour le lookup ASN (AccessLogParser conserve le comptage brut par IP) + $cutoff14 = strtotime('-14 days midnight') ?: (time() - 14 * 86400); + $tParser = new TrendingParser('/var/log/apache2', apacheAccessLog()); $accessParser = new AccessLogParser('/var/log/apache2', apacheAccessLog()); $topIps = array_slice($accessParser->stats()['ips'], 0, 200, true); $asnMap = (new AsnLookup())->batchLookup(array_keys($topIps)); $statsRaw = [ - 'readable' => $tParser->isReadable(), - 'pages' => $grouped['/post/'], - 'books' => $grouped['/book/'], + 'readable' => $accessParser->isReadable(), + 'books' => $tParser->top($cutoff14, 20, ['/book/']), 'as' => AsnLookup::aggregateByAs($topIps, $asnMap), ]; @file_put_contents($statsCacheFile, json_encode($statsRaw)); } $adminData['stats_readable'] = $statsRaw['readable']; - $adminData['stats_pages'] = $statsRaw['pages']; $adminData['stats_books'] = $statsRaw['books']; $adminData['stats_as'] = $statsRaw['as']; $adminData['stats_as_groups'] = AsnLookup::applyGroups($statsRaw['as'], asGroups()); diff --git a/public/version.txt b/public/version.txt index 9f05f9f..ec70f75 100644 --- a/public/version.txt +++ b/public/version.txt @@ -1 +1 @@ -1.6.5 +1.6.6 diff --git a/templates/admin_stats.php b/templates/admin_stats.php index cfaf90b..8dca9e0 100644 --- a/templates/admin_stats.php +++ b/templates/admin_stats.php @@ -2,7 +2,6 @@ $_statsSaved = isset($_GET['saved']); $_statsError = ($_GET['error'] ?? '') === 'write'; $_readable = $adminData['stats_readable'] ?? false; -$_pages = $adminData['stats_pages'] ?? []; $_books = $adminData['stats_books'] ?? []; $_asList = $adminData['stats_as'] ?? []; $_asGroups = $adminData['stats_as_groups'] ?? []; @@ -23,51 +22,19 @@ $_activeGroup = trim($_GET['group'] ?? ''); -

14 derniers jours · visiteurs uniques · cache 60 s

+

14 derniers jours · visiteurs uniques · flux RSS XML

- +
Pages les plus visitées - URLs +
-
- -

Aucune donnée.

- -
- - - $hits): - $rankP++; - $slug = rawurldecode(substr($url, 6)); - $pct = round($hits / $maxP * 100); - ?> - - - - - - - -
- - - -
-
-
-
vis.
-
- +
+

Chargement…

@@ -238,4 +205,50 @@ document.getElementById('as-groups-list').addEventListener('click', e => { e.target.closest('.as-group-row').remove(); } }); + +// ── Chargement des pages via le flux RSS XML ────────────────────────────────── +(function(){ + var container = document.getElementById('stats-pages-container'); + var badge = document.getElementById('stats-pages-count'); + if (!container) return; + function esc(s){ return String(s).replace(/&/g,'&').replace(//g,'>').replace(/"/g,'"'); } + fetch('/trending?period=14d') + .then(function(r){ return r.ok ? r.text() : Promise.reject(); }) + .then(function(xml){ + var doc = new DOMParser().parseFromString(xml, 'application/xml'); + var items = Array.from(doc.querySelectorAll('item')); + if (!items.length) { + container.innerHTML = '

Aucune donnée.

'; + return; + } + var rows = items.map(function(item){ + var raw = (item.querySelector('title') || {textContent:''}).textContent; + var link = ((item.querySelector('link') || {}).textContent || '').trim(); + var m = raw.match(/\((\d+)\s+visiteurs?\)$/); + var vis = m ? parseInt(m[1], 10) : 0; + var title = raw.replace(/\s*\(\d+\s+visiteurs?\)$/, ''); + var slug = decodeURIComponent(link.replace(/.*\/post\//, '')); + return {title: title, link: link, slug: slug, vis: vis}; + }); + var maxV = Math.max.apply(null, rows.map(function(r){ return r.vis; })) || 1; + var html = '
'; + rows.forEach(function(row, i){ + var pct = Math.round(row.vis / maxV * 100); + var vis = row.vis.toLocaleString('fr-FR'); + html += '' + + '' + + '' + + '' + + ''; + }); + html += '
' + (i+1) + '' + + esc(row.title || row.slug) + '' + + '
' + vis + ' vis.
'; + if (badge) badge.textContent = rows.length + ' URLs'; + container.innerHTML = html; + }) + .catch(function(){ + container.innerHTML = '

Impossible de charger le flux.

'; + }); +})(); diff --git a/templates/post_list.php b/templates/post_list.php index 10be95d..1401cba 100644 --- a/templates/post_list.php +++ b/templates/post_list.php @@ -155,19 +155,57 @@ function _renderCard(array $post, array $privateCats, array $allCats, \Parsedown - - -
+ + - +