fix: PHP 8.3 TypeError in dashboard top-articles SUM casts + CHANGELOG (#32)
- admin/partials/dashboard.php lines 108-109: cast $article->total_clicks and $article->total_unique to (int) before number_format(). Both are SUM() aggregate columns from $wpdb->get_results() returned as strings; same PHP 8.3 TypeError vector as the articles-list fix. - tests/unit/DashboardTopArticlesCastTest.php: two unit tests mirroring the ArticlesListTotalCastTest pattern (numeric string + null cases). - CHANGELOG [2.5.1]: fix (# 31) typo -> (#32); add dashboard fix entry. - $topic['total_clicks'] at line 137 is safe (already cast to int in Peptide_News_Analytics_Reports::get_popular_topics() at assignment). - $total_clicks/$total_unique at lines 48/52 are safe (array_sum coerces). Agent-Session: engineer-infra-dashboard-cast-fix-20260617
This commit is contained in:
@@ -7,7 +7,8 @@ Versioning: [Semantic Versioning](https://semver.org/).
|
|||||||
## [2.5.1] - 2026-06-17
|
## [2.5.1] - 2026-06-17
|
||||||
|
|
||||||
### Fixed
|
### 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
|
## [2.5.0] — 2026-06-16
|
||||||
|
|
||||||
|
|||||||
@@ -105,8 +105,8 @@ $total_articles = count( $top_articles );
|
|||||||
<td><a href="<?php echo esc_url( $article->source_url ); ?>" target="_blank" rel="noopener"><?php echo esc_html( $article->title ); ?></a></td>
|
<td><a href="<?php echo esc_url( $article->source_url ); ?>" target="_blank" rel="noopener"><?php echo esc_html( $article->title ); ?></a></td>
|
||||||
<td><?php echo esc_html( $article->source ); ?></td>
|
<td><?php echo esc_html( $article->source ); ?></td>
|
||||||
<td><?php echo esc_html( $article->categories ); ?></td>
|
<td><?php echo esc_html( $article->categories ); ?></td>
|
||||||
<td><strong><?php echo esc_html( number_format( $article->total_clicks ) ); ?></strong></td>
|
<td><strong><?php echo esc_html( number_format( (int) $article->total_clicks ) ); ?></strong></td>
|
||||||
<td><?php echo esc_html( number_format( $article->total_unique ) ); ?></td>
|
<td><?php echo esc_html( number_format( (int) $article->total_unique ) ); ?></td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|||||||
41
tests/unit/DashboardTopArticlesCastTest.php
Normal file
41
tests/unit/DashboardTopArticlesCastTest.php
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Test that dashboard top-articles SUM columns are cast to int before number_format().
|
||||||
|
*
|
||||||
|
* @package Peptide_News
|
||||||
|
*/
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class DashboardTopArticlesCastTest extends TestCase {
|
||||||
|
/**
|
||||||
|
* Verify that SUM() aggregate strings from $wpdb->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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user