designtopack/public/site/plugins/analytics/classes/AnalyticsStore.php

162 lines
5.1 KiB
PHP
Raw Normal View History

<?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 (top 10 pages)
$topPages = array_keys(array_slice($visitsByPage, 0, 10, true));
$visitsByDayByPage = [];
foreach ($visits as $visit) {
$page = $visit->pageName ?: $visit->pageUrl;
if (!in_array($page, $topPages)) continue;
$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,
];
}
}