diff --git a/CHANGELOG.md b/CHANGELOG.md
index 809d29f..e47b91d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,7 +7,8 @@ Versioning: [Semantic Versioning](https://semver.org/).
## [2.5.1] - 2026-06-17
### Fixed
-- PHP 8.3 `TypeError` on Articles admin page: `number_format()` rejects the numeric string returned by `$wpdb->get_var()`. Cast `$total` to `(int)` at point of assignment in `admin/partials/articles-list.php` (#31).
+- PHP 8.3 `TypeError` on Articles admin page: `number_format()` rejects the numeric string returned by `$wpdb->get_var()`. Cast `$total` to `(int)` at point of assignment in `admin/partials/articles-list.php` (#32).
+- PHP 8.3 `TypeError` on Analytics Dashboard page: `number_format()` rejects SUM aggregate strings returned by `$wpdb->get_results()`. Cast `$article->total_clicks` and `$article->total_unique` to `(int)` inline in `admin/partials/dashboard.php` (same-class fix, no PR number — follow-on to #32).
## [2.5.0] — 2026-06-16
diff --git a/admin/partials/dashboard.php b/admin/partials/dashboard.php
index c79f5ad..395cc2f 100755
--- a/admin/partials/dashboard.php
+++ b/admin/partials/dashboard.php
@@ -105,8 +105,8 @@ $total_articles = count( $top_articles );
title ); ?> |
source ); ?> |
categories ); ?> |
- total_clicks ) ); ?> |
- total_unique ) ); ?> |
+ total_clicks ) ); ?> |
+ total_unique ) ); ?> |
diff --git a/tests/unit/DashboardTopArticlesCastTest.php b/tests/unit/DashboardTopArticlesCastTest.php
new file mode 100644
index 0000000..10ff37f
--- /dev/null
+++ b/tests/unit/DashboardTopArticlesCastTest.php
@@ -0,0 +1,41 @@
+get_results() do not
+ * cause a TypeError in number_format() (PHP 8.3 strict typing).
+ * Mirrors the fix in admin/partials/dashboard.php lines 108-109.
+ */
+ public function test_total_clicks_cast_prevents_type_error() {
+ $article = (object) array(
+ 'total_clicks' => '1234', // numeric string from $wpdb->get_results()
+ 'total_unique' => '987',
+ );
+ // Simulate the inline cast applied in dashboard.php
+ $formatted_clicks = number_format( (int) $article->total_clicks );
+ $formatted_unique = number_format( (int) $article->total_unique );
+ $this->assertSame( '1,234', $formatted_clicks );
+ $this->assertSame( '987', $formatted_unique );
+ }
+
+ /**
+ * Verify NULL SUM() (no rows) results in 0, not a TypeError.
+ */
+ public function test_null_sum_cast_to_zero() {
+ $article = (object) array(
+ 'total_clicks' => null,
+ 'total_unique' => null,
+ );
+ $formatted_clicks = number_format( (int) $article->total_clicks );
+ $formatted_unique = number_format( (int) $article->total_unique );
+ $this->assertSame( '0', $formatted_clicks );
+ $this->assertSame( '0', $formatted_unique );
+ }
+}