fix(hivepress): detector active-plugin 偵測 + 4 個 interceptor 改繼承核心基底(F2/F3/F4)
F3 detector(A v3.4.5):HivePress addon 不暴露任何 per-addon class/const,
它們是透過 add_filter('hivepress/v1/extensions') 註冊目錄,所以原本的
class_exists / defined 偵測永遠只認得 core → 反 EAV 覆蓋率卡在 1/13。
改以 get_option('active_plugins') 為第一級訊號(新增 active_plugin_files()),
version_for() 對 addon 改讀其主檔 Version: header。覆蓋率回到 7/13。
F2 interceptor:reviews / messages / memberships / requests 改繼承核心的
TMDO_Standard_Post_Interceptor,573 → 344 行。FIELD_MAP 由 private
提升為 public(late static binding 從基底讀取)。
bootstrap 的 require 迴圈加核心版本守衛:這 4 個檔案在舊核心下會於
parse 階段就 fatal,class_exists 守衛來不及。
F4 listing-stats:view 計數改用 Zone_Warm::increment() 原子遞增,
flush 改原子 UPDATE,消除 get()+set() 的 lost-update race。
F5:主檔補 TablePrefix header(打包終檢 §10 schema drift 主路徑)。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TbG1keQQ7XBa7qMQY16KCY
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
/**
|
||||
* Listing stats integration for Zone B view counting.
|
||||
*
|
||||
* @package WP_Data_Optimizer
|
||||
* @package TMDO
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
@@ -93,8 +93,7 @@ class TMDO_Listing_Stats {
|
||||
* @param int $post_id Listing post ID.
|
||||
*/
|
||||
public static function increment_view( int $post_id ): void {
|
||||
$current = (int) TMDO_Zone_Warm::get( $post_id, self::VIEW_KEY );
|
||||
TMDO_Zone_Warm::set( $post_id, self::VIEW_KEY, (string) ( $current + 1 ), self::VIEW_TTL );
|
||||
TMDO_Zone_Warm::increment( $post_id, self::VIEW_KEY, 1, self::VIEW_TTL );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,29 +135,26 @@ class TMDO_Listing_Stats {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Batch-fetch existing hp_view_count for all post IDs in one query.
|
||||
$post_ids = array_map( 'intval', array_column( $rows, 'post_id' ) );
|
||||
$placeholders = implode( ',', array_fill( 0, count( $post_ids ), '%d' ) );
|
||||
$existing_rows = $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
"SELECT post_id, meta_value FROM {$wpdb->postmeta} WHERE meta_key = 'hp_view_count' AND post_id IN ({$placeholders})", // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare -- $wpdb->postmeta is core. phpcs:ignore WPDO.AntiEAV.no-direct-postmeta-select -- Listing Stats: Zone B → postmeta view-count sync path.
|
||||
...$post_ids
|
||||
),
|
||||
ARRAY_A
|
||||
);
|
||||
$existing_map = array();
|
||||
foreach ( $existing_rows as $er ) {
|
||||
$existing_map[ (int) $er['post_id'] ] = (int) $er['meta_value'];
|
||||
}
|
||||
|
||||
$flushed = 0;
|
||||
foreach ( $rows as $row ) {
|
||||
$post_id = (int) $row['post_id'];
|
||||
$new_views = (int) $row['meta_value'];
|
||||
|
||||
// Add to existing postmeta total.
|
||||
$existing = $existing_map[ $post_id ] ?? 0;
|
||||
update_post_meta( $post_id, 'hp_view_count', $existing + $new_views );
|
||||
// Atomic increment: avoids the read-modify-write race that could lose
|
||||
// concurrent view increments arriving between our batch-read and the write.
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- WPDO.AntiEAV.no-direct-postmeta-update: view-count sync, no meta API equivalent for atomic add.
|
||||
$updated = $wpdb->query(
|
||||
$wpdb->prepare(
|
||||
"UPDATE `{$wpdb->postmeta}` SET meta_value = meta_value + %d WHERE post_id = %d AND meta_key = 'hp_view_count'",
|
||||
$new_views,
|
||||
$post_id
|
||||
)
|
||||
);
|
||||
|
||||
// Seed the key when it does not exist yet.
|
||||
if ( ! $updated ) {
|
||||
add_post_meta( $post_id, 'hp_view_count', $new_views, true );
|
||||
}
|
||||
|
||||
// Remove the warm entry after flush.
|
||||
TMDO_Zone_Warm::delete( $post_id, self::VIEW_KEY );
|
||||
|
||||
Reference in New Issue
Block a user