misc-etc/pureblog-stats.php

251 lines
7.3 KiB
PHP
Raw Normal View History

2026-09-20 19:34:58 +00:00
<?php
require PUREBLOG_BASE_PATH . '/includes/header.php';
render_masthead_layout($config, ['page' => null]);
?>
<main>
<h1> Stats </h1>
<?php
$publishedPosts = array_values(array_filter(get_all_posts(true), static fn(array $post): bool => ($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');
?>
</main>
<?php render_footer_layout($config, ['page' => null]); ?>
</body>
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
<?php 4.0s
require PUREBLOG_BASE_PATH . '/includes/header.php';
render_masthead_layout($config, ['page' => null]);
?>
<main>
<h1> Stats </h1>
<?php
$publishedPosts = array_values(array_filter(get_all_posts(true), static fn(array $post): bool => ($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');
?>
<div class="stats">
<h3> Published posts: </h3> <?= e(number_format($publishedCount)) ?><br>
<h3>Total words:</h3> <?= e(number_format($totalWords)) ?><br>
<br>
<h3>Average words per post:</h3> <?= e(number_format($avgWordsAllTime)) ?>
<br><h3>Book equivalents (base 80,000):</h3> <?= e(number_format($booksEquivalent, 1)) ?><br>
<h3>Last published:</h3> <?= e($lastPublishedAgo) ?></p>
</div>
</main>
<?php render_footer_layout($config, ['page' => null]); ?>
</body>
</html>