fix(boundary): 核心不得無守衛呼叫 AddOn 的 TMDO_Listing_Stats

實機渲染時 Dashboard 分頁 fatal:"Class TMDO_Listing_Stats not found"。
該類別住在 hivepress-addon,核心有 6 處直呼,沒裝 AddOn 的站台會炸掉
Dashboard 與兩個 REST 端點(GET /listing/{id}、POST /listing/{id}/view)。

- TMDO_Zone_Warm 新增 VIEW_KEY / VIEW_TTL 常數(值與 AddOn 的
  TMDO_Listing_Stats::VIEW_KEY 完全相同的 'wpdo_views',指向同一批列,
  無資料遷移)
- CLI benchmark 改用核心常數
- REST 兩個 handler 改走新的 read_view_count() / bump_view_count():
  AddOn 在場時仍委派過去(保留 hp_view_count postmeta fallback),
  否則核心自己讀寫 warm 列
- wp tmdo cleanup --archive-expired 加守衛,AddOn 缺席時印 warning 並跳過
This commit is contained in:
2026-07-31 10:34:40 +08:00
parent b63ab46f54
commit 6751c69bc2
3 changed files with 61 additions and 10 deletions
+36 -3
View File
@@ -646,7 +646,7 @@ class TMDO_REST_API {
return $err;
}
$views = TMDO_Listing_Stats::get_view_count( $post_id );
$views = self::read_view_count( $post_id );
return new WP_REST_Response(
array(
@@ -730,8 +730,8 @@ class TMDO_REST_API {
// Mark as counted for this IP/session.
set_transient( $rl_key, 1, HOUR_IN_SECONDS );
TMDO_Listing_Stats::increment_view( $post_id );
$views = TMDO_Listing_Stats::get_view_count( $post_id );
self::bump_view_count( $post_id );
$views = self::read_view_count( $post_id );
$response = new WP_REST_Response(
array(
@@ -1642,4 +1642,37 @@ class TMDO_REST_API {
$result = TMDO_Migration_Orchestrator::resume();
return new WP_REST_Response( $result, ! empty( $result['ok'] ) ? 200 : 409 );
}
/**
* Read a post's view counter.
*
* Delegates to the HivePress AddOn when it is active, because that class
* adds an hp_view_count postmeta fallback for listings migrated before the
* warm zone existed. Without the AddOn — the normal case for a plain
* install — core reads its own warm row directly. Calling the AddOn class
* unconditionally used to fatal these endpoints on any site without it.
*
* @param int $post_id Post ID.
* @return int
*/
private static function read_view_count( int $post_id ): int {
if ( class_exists( 'TMDO_Listing_Stats' ) ) {
return (int) TMDO_Listing_Stats::get_view_count( $post_id );
}
return (int) ( TMDO_Zone_Warm::get( $post_id, TMDO_Zone_Warm::VIEW_KEY ) ?? 0 );
}
/**
* Increment a post's view counter.
*
* @param int $post_id Post ID.
* @return void
*/
private static function bump_view_count( int $post_id ): void {
if ( class_exists( 'TMDO_Listing_Stats' ) ) {
TMDO_Listing_Stats::increment_view( $post_id );
return;
}
TMDO_Zone_Warm::increment( $post_id, TMDO_Zone_Warm::VIEW_KEY, 1, TMDO_Zone_Warm::VIEW_TTL );
}
}
+13
View File
@@ -24,6 +24,19 @@ if ( ! defined( 'ABSPATH' ) ) {
*/
class TMDO_Zone_Warm {
/**
* Warm key used for per-post view counters.
*
* Owned by core because the row lives in this zone's table and core's admin,
* CLI and REST layers all read it. The HivePress AddOn's
* TMDO_Listing_Stats::VIEW_KEY carries the identical literal, so the two
* address the same rows — nothing to migrate either way.
*/
const VIEW_KEY = 'wpdo_views';
/** TTL applied when core increments the view counter itself. */
const VIEW_TTL = DAY_IN_SECONDS;
/**
* Get the warm table name.
*/