'7 Tage', 30 => '30 Tage', 90 => '90 Tage', 365 => '1 Jahr']; public function __construct(private Statistics $statistics) { } #[Route('/%kant.admin_path%/statistik', name: 'admin_statistics', methods: ['GET'])] public function index(Request $request): Response { $this->denyAccessUnlessGranted('ROLE_EDITOR'); $range = isset(self::RANGES[$request->query->getInt('tage')]) ? $request->query->getInt('tage') : 30; return $this->render('admin/statistics.html.twig', [ 'stats' => $this->statistics->overview($range), 'ranges' => self::RANGES, 'range' => $range, 'compactAfter' => Statistics::COMPACT_AFTER_DAYS, 'keepDays' => Statistics::KEEP_DAYS, ]); } #[Route('/%kant.admin_path%/statistik.csv', name: 'admin_statistics_csv', methods: ['GET'])] public function csv(Request $request): Response { $this->denyAccessUnlessGranted('ROLE_EDITOR'); $range = isset(self::RANGES[$request->query->getInt('tage')]) ? $request->query->getInt('tage') : 30; // Streamed, because a year of counters is a lot of rows and none of them need to be held // in memory at once. $response = new StreamedResponse(function () use ($range): void { $out = fopen('php://output', 'w'); fputcsv($out, ['tag', 'stunde', 'pfad', 'status', 'verweis-domain', 'anzahl'], ';', '"', ''); foreach ($this->statistics->export($range) as $row) { fputcsv($out, [ $row['day'], -1 === (int) $row['hour'] ? 'ganzer Tag' : $row['hour'], $row['path'], $row['status'], $row['referrer_host'], $row['count'], ], ';', '"', ''); } fclose($out); }); $response->headers->set('Content-Type', 'text/csv; charset=UTF-8'); $response->headers->set('Content-Disposition', sprintf('attachment; filename="kantsites-statistik-%d-tage.csv"', $range)); return $response; } }