- Ajout toggle Kirby natif au-dessus du graphique - Moyenne : courbe agrégée unique pour toutes les pages - Pages les + visitées : multi-courbes pour le top 10 - Toggle masqué quand un filtre par page est actif - PHP : visitsByDayByPage inclut toutes les pages Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
159 lines
5 KiB
PHP
159 lines
5 KiB
PHP
<?php
|
|
|
|
namespace adrienpayet\analytics;
|
|
|
|
use Kirby\Data\Yaml;
|
|
use Kirby\Toolkit\F;
|
|
|
|
class AnalyticsStore
|
|
{
|
|
private static function getFilePath(): string
|
|
{
|
|
return kirby()->root('content') . '/analytics/visits.yml';
|
|
}
|
|
|
|
private static function ensureFileExists(): void
|
|
{
|
|
$filePath = self::getFilePath();
|
|
$dirPath = dirname($filePath);
|
|
|
|
if (!is_dir($dirPath)) {
|
|
F::mkdir($dirPath, true);
|
|
}
|
|
|
|
if (!F::exists($filePath)) {
|
|
F::write($filePath, Yaml::encode(['visits' => []]));
|
|
}
|
|
}
|
|
|
|
public static function addVisit(Visit $visit): void
|
|
{
|
|
self::ensureFileExists();
|
|
|
|
$filePath = self::getFilePath();
|
|
$data = Yaml::decode(F::read($filePath));
|
|
|
|
$visits = $data['visits'] ?? [];
|
|
$visits[] = $visit->toArray();
|
|
|
|
// Limiter à 10000 visites max
|
|
if (count($visits) > 10000) {
|
|
$visits = array_slice($visits, -10000);
|
|
}
|
|
|
|
$data['visits'] = $visits;
|
|
F::write($filePath, Yaml::encode($data));
|
|
}
|
|
|
|
public static function getVisits(array $filters = []): array
|
|
{
|
|
self::ensureFileExists();
|
|
|
|
$filePath = self::getFilePath();
|
|
$data = Yaml::decode(F::read($filePath));
|
|
$visits = $data['visits'] ?? [];
|
|
|
|
// Convertir en objets Visit
|
|
$visits = array_map(fn($v) => Visit::fromArray($v), $visits);
|
|
|
|
// Filtrer par daterange
|
|
if (!empty($filters['startDate']) || !empty($filters['endDate'])) {
|
|
$visits = array_filter($visits, function($visit) use ($filters) {
|
|
$timestamp = strtotime($visit->timestamp);
|
|
|
|
if (!empty($filters['startDate'])) {
|
|
$startDate = strtotime($filters['startDate'] . ' 00:00:00');
|
|
if ($timestamp < $startDate) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (!empty($filters['endDate'])) {
|
|
$endDate = strtotime($filters['endDate'] . ' 23:59:59');
|
|
if ($timestamp > $endDate) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
});
|
|
}
|
|
|
|
// Filtrer par projet
|
|
if (!empty($filters['project'])) {
|
|
$projectId = $filters['project'];
|
|
$visits = array_filter($visits, function($visit) use ($projectId) {
|
|
return str_contains($visit->pageUrl, "/projects/{$projectId}");
|
|
});
|
|
}
|
|
|
|
// Filtrer par email (permissions)
|
|
if (!empty($filters['emails'])) {
|
|
$allowedEmails = $filters['emails'];
|
|
$visits = array_filter($visits, function($visit) use ($allowedEmails) {
|
|
return in_array($visit->email, $allowedEmails);
|
|
});
|
|
}
|
|
|
|
// Filtrer par nom de page
|
|
if (!empty($filters['pageNames'])) {
|
|
$pageNames = $filters['pageNames'];
|
|
$visits = array_filter($visits, function($visit) use ($pageNames) {
|
|
$name = $visit->pageName ?: $visit->pageUrl;
|
|
return in_array($name, $pageNames);
|
|
});
|
|
}
|
|
|
|
return array_values($visits);
|
|
}
|
|
|
|
public static function getAggregatedData(array $filters = []): array
|
|
{
|
|
self::ensureFileExists();
|
|
|
|
// Visits sans filtre pageNames → pour construire la liste des pages (options)
|
|
$filtersWithoutPages = $filters;
|
|
unset($filtersWithoutPages['pageNames']);
|
|
$allVisits = self::getVisits($filtersWithoutPages);
|
|
|
|
$visitsByPage = [];
|
|
foreach ($allVisits as $visit) {
|
|
$page = $visit->pageName ?: $visit->pageUrl;
|
|
$visitsByPage[$page] = ($visitsByPage[$page] ?? 0) + 1;
|
|
}
|
|
arsort($visitsByPage);
|
|
|
|
// Visits avec tous les filtres → pour les stats affichées
|
|
$visits = !empty($filters['pageNames'])
|
|
? self::getVisits($filters)
|
|
: $allVisits;
|
|
|
|
$visitsByDay = [];
|
|
foreach ($visits as $visit) {
|
|
$day = date('Y-m-d', strtotime($visit->timestamp));
|
|
$visitsByDay[$day] = ($visitsByDay[$day] ?? 0) + 1;
|
|
}
|
|
ksort($visitsByDay);
|
|
|
|
$uniqueSessions = count(array_unique(array_map(fn($v) => $v->sessionId, $visits)));
|
|
|
|
// Visites par jour par page (toutes les pages)
|
|
$visitsByDayByPage = [];
|
|
foreach ($visits as $visit) {
|
|
$page = $visit->pageName ?: $visit->pageUrl;
|
|
$day = date('Y-m-d', strtotime($visit->timestamp));
|
|
$visitsByDayByPage[$page][$day] = ($visitsByDayByPage[$page][$day] ?? 0) + 1;
|
|
}
|
|
foreach ($visitsByDayByPage as &$days) {
|
|
ksort($days);
|
|
}
|
|
|
|
return [
|
|
'totalVisits' => count($visits),
|
|
'uniqueSessions' => $uniqueSessions,
|
|
'visitsByDay' => $visitsByDay,
|
|
'visitsByPage' => array_slice($visitsByPage, 0, 10, true),
|
|
'visitsByDayByPage' => $visitsByDayByPage,
|
|
];
|
|
}
|
|
}
|