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, ]; } }