feat : onglet Statistiques — pages, livres, répartition AS avec groupes configurables
- AccessLogParser : parse COMBINED, agrège hits /post/ et /book/, cache 10 min - AsnLookup : batch lookup ip-api.com, cache 30j, agrégation et groupes AS - Onglet Statistiques dans l'admin : top pages, top livres, répartition réseau - Filtrage par groupe AS (badges) + formulaire de configuration des groupes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+46
-1
@@ -43,7 +43,7 @@ $action = $_GET['action'] ?? 'list';
|
||||
$uuid = $_GET['uuid'] ?? '';
|
||||
$slug = $_GET['slug'] ?? '';
|
||||
|
||||
$_noindexActions = ['create', 'edit', 'admin', 'categories', 'diff', 'add_files', 'import_image', 'import_image_step2', 'sources', 'profile', 'delete_file', 'delete_external_link', 'rename_category', 'delete_category', 'toggle_private_category', 'admin_save_site', 'not_found', 'add_feed', 'delete_feed', 'add_link', 'delete_link', 'reorder_links', 'react', 'comment', 'verify_comment', 'comment_moderate', 'comment_delete', 'comment_resend', 'create_tag_type', 'delete_tag_type', 'edit_tags', 'book_save', 'book_delete'];
|
||||
$_noindexActions = ['create', 'edit', 'admin', 'categories', 'diff', 'add_files', 'import_image', 'import_image_step2', 'sources', 'profile', 'delete_file', 'delete_external_link', 'rename_category', 'delete_category', 'toggle_private_category', 'admin_save_site', 'not_found', 'add_feed', 'delete_feed', 'add_link', 'delete_link', 'reorder_links', 'react', 'comment', 'verify_comment', 'comment_moderate', 'comment_delete', 'comment_resend', 'create_tag_type', 'delete_tag_type', 'edit_tags', 'book_save', 'book_delete', 'admin_save_as_groups'];
|
||||
$metaRobots = in_array($action, $_noindexActions, true) ? 'noindex, nofollow' : null;
|
||||
unset($_noindexActions);
|
||||
|
||||
@@ -2542,6 +2542,27 @@ switch ($action) {
|
||||
$adminData['search_log_readable'] = $parser->isReadable();
|
||||
}
|
||||
|
||||
if ($tab === 'stats') {
|
||||
if (!isAdmin()) {
|
||||
http_response_code(403);
|
||||
exit;
|
||||
}
|
||||
require_once BASE_PATH . '/src/AccessLogParser.php';
|
||||
require_once BASE_PATH . '/src/AsnLookup.php';
|
||||
$accessParser = new AccessLogParser('/var/log/apache2', apacheAccessLog());
|
||||
$accessStats = $accessParser->stats();
|
||||
$adminData['stats_readable'] = $accessParser->isReadable();
|
||||
$adminData['stats_pages'] = array_slice($accessStats['pages'], 0, 30, true);
|
||||
$adminData['stats_books'] = array_slice($accessStats['books'], 0, 20, true);
|
||||
// Lookup AS pour les top 200 IPs
|
||||
$topIps = array_slice($accessStats['ips'], 0, 200, true);
|
||||
$asnMap = (new AsnLookup())->batchLookup(array_keys($topIps));
|
||||
$asList = AsnLookup::aggregateByAs($topIps, $asnMap);
|
||||
$adminData['stats_as'] = $asList;
|
||||
$adminData['stats_as_groups'] = AsnLookup::applyGroups($asList, asGroups());
|
||||
$adminData['as_groups'] = asGroups();
|
||||
}
|
||||
|
||||
if ($tab === 'categories') {
|
||||
$adminData['cats'] = $articles->getCategories();
|
||||
$adminData['privateCats'] = $articles->getPrivateCategories();
|
||||
@@ -2820,6 +2841,30 @@ switch ($action) {
|
||||
header('Location: /admin/searches?' . ($ok ? 'saved=1' : 'error=write'));
|
||||
exit;
|
||||
|
||||
case 'admin_save_as_groups':
|
||||
requireAuth();
|
||||
if (!isAdmin() || $_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(403);
|
||||
exit;
|
||||
}
|
||||
$rawLabels = $_POST['as_group_label'] ?? [];
|
||||
$rawPatterns = $_POST['as_group_patterns'] ?? [];
|
||||
$groups = [];
|
||||
foreach ((array) $rawLabels as $i => $label) {
|
||||
$label = trim((string) $label);
|
||||
if ($label === '') {
|
||||
continue;
|
||||
}
|
||||
$patterns = array_values(array_filter(array_map(
|
||||
'trim',
|
||||
explode("\n", (string) ($rawPatterns[$i] ?? ''))
|
||||
)));
|
||||
$groups[] = ['label' => $label, 'patterns' => $patterns];
|
||||
}
|
||||
$ok = saveSiteSettings(['as_groups' => $groups]);
|
||||
header('Location: /admin/stats?' . ($ok ? 'saved=1' : 'error=write'));
|
||||
exit;
|
||||
|
||||
case 'admin_create_role':
|
||||
requireAuth();
|
||||
if (!isAdmin() || $_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
|
||||
Reference in New Issue
Block a user