From 4a34410e21b9e23bff742d63644532c1ab07fbab Mon Sep 17 00:00:00 2001 From: agnes Date: Sun, 20 Sep 2026 19:34:58 +0000 Subject: [PATCH] Add pureblog-stats.php --- pureblog-stats.php | 251 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 251 insertions(+) create mode 100644 pureblog-stats.php diff --git a/pureblog-stats.php b/pureblog-stats.php new file mode 100644 index 0000000..49aacb2 --- /dev/null +++ b/pureblog-stats.php @@ -0,0 +1,251 @@ + null]); + +?> + +
+

Stats

+ ($post['status'] ?? 'draft') === 'published')); +$publishedCount = count($publishedPosts); +$tz = site_timezone_object($config); +$now = new DateTimeImmutable('now', $tz); +$currentYear = (int) $now->format('Y'); + +$publishedThisYear = 0; +$totalWordsThisYear = 0; +$tagCounts = []; +$tagCountsThisYear = []; +$tagDisplayNames = []; +$totalWords = 0; +$allTimeMonthCounts = array_fill(1, 12, 0); +$allTimeDayCounts = array_fill(1, 7, 0); // 1=Mon … 7=Sun (ISO 8601) +$yearCounts = []; + +// Build rolling 12-month chart slots (oldest first) +$chartMonths = []; +$firstOfMonth = new DateTimeImmutable($now->format('Y-m-01'), $tz); +for ($i = 11; $i >= 0; $i--) { +$dt = $firstOfMonth->modify("-{$i} months"); +$month = (int) $dt->format('n'); +$chartMonths[] = [ +'year' => (int) $dt->format('Y'), +'month' => $month, +'label' => t('date.months_short.' . ($month - 1)), +'count' => 0, +]; +} +$chartIndex = []; +foreach ($chartMonths as $idx => $cm) { +$chartIndex[$cm['year'] . '-' . $cm['month']] = $idx; +} +$recentCutoff = $firstOfMonth->modify('-11 months')->getTimestamp(); + +foreach ($publishedPosts as $post) { +$content = (string) ($post['content'] ?? ''); +$totalWords += str_word_count($content); + +$timestamp = (int) ($post['timestamp'] ?? 0); +if ($timestamp > 0) { +$dt = (new DateTimeImmutable('@' . $timestamp))->setTimezone($tz); +$postYear = (int) $dt->format('Y'); +$postMon = (int) $dt->format('n'); +$postDay = (int) $dt->format('N'); // 1=Mon … 7=Sun + +$chartKey = $postYear . '-' . $postMon; +if (isset($chartIndex[$chartKey])) { +$chartMonths[$chartIndex[$chartKey]]['count']++; +} + +if ($timestamp >= $recentCutoff) { +$publishedThisYear++; +$totalWordsThisYear += str_word_count($content); +} + +$allTimeMonthCounts[$postMon]++; +$allTimeDayCounts[$postDay]++; +$yearCounts[$postYear] = ($yearCounts[$postYear] ?? 0) + 1; +} + +$tags = $post['tags'] ?? []; +if (!is_array($tags)) { +continue; +} +foreach ($tags as $tag) { +$name = trim((string) $tag); +if ($name !== '') { +$slug = normalize_tag($name); +$tagDisplayNames[$slug] ??= $name; +$tagCounts[$slug] = ($tagCounts[$slug] ?? 0) + 1; +if ($timestamp >= $recentCutoff) { +$tagCountsThisYear[$slug] = ($tagCountsThisYear[$slug] ?? 0) + 1; +} +} +} +} + +ksort($yearCounts); +$maxYearCount = !empty($yearCounts) ? max($yearCounts) : 1; + +$avgWordsAllTime = $publishedCount > 0 ? (int) round($totalWords / $publishedCount) : 0; +$avgWordsThisYear = $publishedThisYear > 0 ? (int) round($totalWordsThisYear / $publishedThisYear) : 0; +$booksEquivalent = $totalWords > 0 ? round($totalWords / 80000, 1) : 0; +$booksThisYear = $totalWordsThisYear > 0 ? round($totalWordsThisYear / 80000, 1) : 0; + +// Last published time +$lastTimestamp = 0; +foreach ($publishedPosts as $post) { +$ts = (int) ($post['timestamp'] ?? 0); +if ($ts > $lastTimestamp) { +$lastTimestamp = $ts; +} +} +$lastPublishedAgo = $lastTimestamp > 0 ? relative_time($lastTimestamp) : t('admin.dashboard.no_posts_yet'); + +?> +
+ null]); ?> + + + +pj@laptop5:~/pureblog$ sudo docker compose up -d --force-recreate + + +pj@laptop5:~/pureblog$ sudo docker compose up -d --force-recreate +[+] up 1/1 + + +pj@laptop5:~/pureblog$ sudo docker compose up -d --force-recreate +[+] up 1/1 + + + +pj@laptop5:~/pureblog$ sudo docker compose up -d --force-recreate +pj@laptop5:~/pureblog$ +pj@laptop5:~/pureblog$ sudo docker compose up -d --force-recreate +pj@laptop5:~/pureblog$ sudo cat content/includes/stats.php + null]); + +?> + +
+

Stats

+ ($post['status'] ?? 'draft') === 'published')); +$publishedCount = count($publishedPosts); +$tz = site_timezone_object($config); +$now = new DateTimeImmutable('now', $tz); +$currentYear = (int) $now->format('Y'); + +$publishedThisYear = 0; +$totalWordsThisYear = 0; +$tagCounts = []; +$tagCountsThisYear = []; +$tagDisplayNames = []; +$totalWords = 0; +$allTimeMonthCounts = array_fill(1, 12, 0); +$allTimeDayCounts = array_fill(1, 7, 0); // 1=Mon … 7=Sun (ISO 8601) +$yearCounts = []; + +// Build rolling 12-month chart slots (oldest first) +$chartMonths = []; +$firstOfMonth = new DateTimeImmutable($now->format('Y-m-01'), $tz); +for ($i = 11; $i >= 0; $i--) { +$dt = $firstOfMonth->modify("-{$i} months"); +$month = (int) $dt->format('n'); +$chartMonths[] = [ +'year' => (int) $dt->format('Y'), +'month' => $month, +'label' => t('date.months_short.' . ($month - 1)), +'count' => 0, +]; +} +$chartIndex = []; +foreach ($chartMonths as $idx => $cm) { +$chartIndex[$cm['year'] . '-' . $cm['month']] = $idx; +} +$recentCutoff = $firstOfMonth->modify('-11 months')->getTimestamp(); + +foreach ($publishedPosts as $post) { +$content = (string) ($post['content'] ?? ''); +$totalWords += str_word_count($content); + +$timestamp = (int) ($post['timestamp'] ?? 0); +if ($timestamp > 0) { +$dt = (new DateTimeImmutable('@' . $timestamp))->setTimezone($tz); +$postYear = (int) $dt->format('Y'); +$postMon = (int) $dt->format('n'); +$postDay = (int) $dt->format('N'); // 1=Mon … 7=Sun + +$chartKey = $postYear . '-' . $postMon; +if (isset($chartIndex[$chartKey])) { +$chartMonths[$chartIndex[$chartKey]]['count']++; +} + +if ($timestamp >= $recentCutoff) { +$publishedThisYear++; +$totalWordsThisYear += str_word_count($content); +} + +$allTimeMonthCounts[$postMon]++; +$allTimeDayCounts[$postDay]++; +$yearCounts[$postYear] = ($yearCounts[$postYear] ?? 0) + 1; +} + +$tags = $post['tags'] ?? []; +if (!is_array($tags)) { +continue; +} +foreach ($tags as $tag) { +$name = trim((string) $tag); +if ($name !== '') { +$slug = normalize_tag($name); +$tagDisplayNames[$slug] ??= $name; +$tagCounts[$slug] = ($tagCounts[$slug] ?? 0) + 1; +if ($timestamp >= $recentCutoff) { +$tagCountsThisYear[$slug] = ($tagCountsThisYear[$slug] ?? 0) + 1; +} +} +} +} + +ksort($yearCounts); +$maxYearCount = !empty($yearCounts) ? max($yearCounts) : 1; + +$avgWordsAllTime = $publishedCount > 0 ? (int) round($totalWords / $publishedCount) : 0; +$avgWordsThisYear = $publishedThisYear > 0 ? (int) round($totalWordsThisYear / $publishedThisYear) : 0; +$booksEquivalent = $totalWords > 0 ? round($totalWords / 80000, 1) : 0; +$booksThisYear = $totalWordsThisYear > 0 ? round($totalWordsThisYear / 80000, 1) : 0; + +// Last published time +$lastTimestamp = 0; +foreach ($publishedPosts as $post) { +$ts = (int) ($post['timestamp'] ?? 0); +if ($ts > $lastTimestamp) { +$lastTimestamp = $ts; +} +} +$lastPublishedAgo = $lastTimestamp > 0 ? relative_time($lastTimestamp) : t('admin.dashboard.no_posts_yet'); + +?> +
+ +

Published posts:


+ +

Total words:


+
+

Average words per post:

+

Book equivalents (base 80,000):


+

Last published:

+
+
+ null]); ?> + + \ No newline at end of file