hardening 2.0: 2meet-data-optimizer (staged rollout, dev22 first) #3

Merged
wpdev merged 30 commits from hardening/2.0 into main 2026-09-26 10:20:24 +08:00
2 changed files with 38 additions and 246 deletions
Showing only changes of commit 07db7734cf - Show all commits
+4 -246
View File
@@ -31,31 +31,10 @@ class TMDO_Core {
// Fire the schema registry hook so integrations can register their fields.
$registry = TMDO_Schema_Registry::instance();
// v2.0.x: Pre-register the 7 partner plugin integrations BEFORE firing the
// `wpdo_register_fields` and `wpdo_register_custom_tables` hooks. Each
// `register()` is a thin `add_action()` wrapper guarded by a partner-plugin
// `class_exists()` probe (TMDO_Infocards / Bookings / Quotation / Events /
// Mobile_Bridge / Collab / Playlist). Without this, partner add_actions
// arrive too late and the do_action below misses them — observed via
// 2meet-infocards 9 hp_vendor meta keys never landing in Schema Registry.
// register() is side-effect-free aside from add_action(), so pre-registering
// is provably safe (no hidden dependency on later-state global init).
// v2.1.3 R1 (B step): TMDO_Events removed — 2meet-events now self-registers
// via its own bridge class. Other partners still pre-registered here pending
// their own decentralized migrations (R1 continuation in v2.2.x).
$partner_integrations = array(
'TMDO_Infocards',
'TMDO_Bookings',
'TMDO_Quotation',
'TMDO_Mobile_Bridge',
'TMDO_Collab',
'TMDO_Playlist',
'TMDO_WooCommerce',
'TMDO_Member_Fields',
'TMDO_Post_Fields',
'TMDO_Hivepress_Term_Comment_Fields',
);
foreach ( $partner_integrations as $cls ) {
// Core-owned field providers register before `wpdo_register_fields` fires.
// AddOns wire their own integrations from their bootstraps
// (plugins_loaded:3 or :6), so core does not probe for them here.
foreach ( array( 'TMDO_Member_Fields', 'TMDO_Post_Fields' ) as $cls ) {
if ( class_exists( $cls ) ) {
call_user_func( array( $cls, 'register' ) );
}
@@ -74,7 +53,6 @@ class TMDO_Core {
// AFTER plugins_loaded:4 (e.g., partners loaded by HP modules at plugins_loaded:5+,
// or lazy-loaded modules booted on init:0). Schema_Registry::register() has
// internal dedup, so re-firing is idempotent — same partner calls won't double-register.
// This deprecates the need for the TMDO_Core hardcoded partner pre-registration list above.
//
// v2.1.6: also re-fire `wpdo_register_entity_fields` so partner plugins booting on
// plugins_loaded:20 (e.g. 2meet-spoke-sso) can register entity-based user/term/comment
@@ -116,12 +94,6 @@ class TMDO_Core {
$this->register_hpct_interceptors();
}
// v2.1.2 fix: WC commission interceptor is independent of HPCT — writes
// to its own wp_wpdo_wc_commissions table. Register whenever WC is active.
if ( class_exists( 'TMDO_WooCommerce' ) && TMDO_WooCommerce::is_active() && class_exists( 'TMDO_WC_Orders_Interceptor' ) ) {
( new TMDO_WC_Orders_Interceptor() )->register_hooks();
}
// Zone interceptors are always safe to register.
if ( TMDO_Compatibility::can_register_zone_hooks() ) {
$this->register_zone_hooks();
@@ -149,10 +121,6 @@ class TMDO_Core {
TMDO_Conflict_Monitor::register_hooks();
}
// v2.0.x: partner plugin integrations have been pre-registered earlier
// (see top of run() before the wpdo_register_fields do_action). Removing
// the duplicate late-binding block — see commit log for time-ordering bug.
// Schedule cron events.
$this->schedule_cron();
@@ -182,14 +150,6 @@ class TMDO_Core {
add_action( TMDO_Comment_Stress_Tester::CRON_HOOK, array( __CLASS__, 'run_comment_stress_test_batch' ) );
}
// v2.11.5: HivePress per-post transient cache → wp_options reroute.
// Filters registered on `init` so HivePress's own bootstrap (plugins_loaded:5)
// runs first and our filter chain catches the actual cache writes happening
// during save_post and term-cache rebuilds.
if ( class_exists( 'TMDO_Hivepress_Transient_Filter' ) ) {
add_action( 'init', array( 'TMDO_Hivepress_Transient_Filter', 'init' ), 5 );
}
// v2.12.1: Term + Comment garbage write-time filter
// (silent-drop _wxr_import_* / _2meet_demo_* / orphan post-meta keys).
if ( class_exists( 'TMDO_Term_Comment_Garbage_Filter' ) ) {
@@ -282,208 +242,6 @@ class TMDO_Core {
do_action( 'wpdo_register_entity_fields', TMDO_Entity_Registry::class );
}
/**
* Register default HivePress field mappings.
*
* These are the known HivePress meta_keys and their zone classifications.
*
* @param TMDO_Schema_Registry $registry The schema registry instance.
* @return void
*/
private function register_hivepress_defaults( TMDO_Schema_Registry $registry ): void {
// Zone A (Hot) — Listing search/filter fields.
$registry->register_many(
'hivepress',
array(
array(
'post_type' => 'hp_listing',
'meta_key' => 'hp_price',
'zone' => 'hot',
'data_type' => 'decimal(10,2) NOT NULL DEFAULT 0',
'column' => 'hp_price',
'indexed' => true,
),
array(
'post_type' => 'hp_listing',
'meta_key' => 'hp_featured',
'zone' => 'hot',
'data_type' => 'tinyint(1) NOT NULL DEFAULT 0',
'column' => 'hp_featured',
'indexed' => true,
),
array(
'post_type' => 'hp_listing',
'meta_key' => 'hp_verified',
'zone' => 'hot',
'data_type' => 'tinyint(1) NOT NULL DEFAULT 0',
'column' => 'hp_verified',
'indexed' => true,
),
array(
'post_type' => 'hp_listing',
'meta_key' => 'hp_expired_time',
'zone' => 'hot',
'data_type' => 'bigint(20) NOT NULL DEFAULT 0',
'column' => 'hp_expired_time',
),
array(
'post_type' => 'hp_listing',
'meta_key' => 'hp_featured_time',
'zone' => 'hot',
'data_type' => 'bigint(20) NOT NULL DEFAULT 0',
'column' => 'hp_featured_time',
),
// Vendor hot fields.
array(
'post_type' => 'hp_vendor',
'meta_key' => 'hp_verified',
'zone' => 'hot',
'data_type' => 'tinyint(1) NOT NULL DEFAULT 0',
'column' => 'hp_verified',
'indexed' => true,
),
array(
'post_type' => 'hp_vendor',
'meta_key' => 'hp_hourly_rate',
'zone' => 'hot',
'data_type' => 'decimal(10,2) NOT NULL DEFAULT 0',
'column' => 'hp_hourly_rate',
'indexed' => true,
),
array(
'post_type' => 'hp_vendor',
'meta_key' => 'hp_rating_count',
'zone' => 'hot',
'data_type' => 'int(11) NOT NULL DEFAULT 0',
'column' => 'hp_rating_count',
'indexed' => false,
),
)
);
// Zone C (Cold) — Profile/display fields.
$registry->register_many(
'hivepress',
array(
array(
'post_type' => 'hp_vendor',
'meta_key' => 'hp_description',
'zone' => 'cold',
'cache_group' => 'wpdo_cold_hp_vendor',
'cache_ttl' => HOUR_IN_SECONDS,
),
array(
'post_type' => 'hp_listing',
'meta_key' => 'hp_description',
'zone' => 'cold',
'cache_group' => 'wpdo_cold_hp_listing',
'cache_ttl' => HOUR_IN_SECONDS,
),
)
);
// ── HivePress extension fields (filled the 47% → 94% coverage gap) ──
// Reviews extension (hp_review post type).
$registry->register_many(
'hivepress-reviews',
array(
array(
'post_type' => 'hp_review',
'meta_key' => 'hp_rating',
'zone' => 'hot',
'data_type' => 'tinyint(1) NOT NULL DEFAULT 0',
'column' => 'hp_rating',
'indexed' => true,
),
array(
'post_type' => 'hp_vendor',
'meta_key' => 'hp_rating',
'zone' => 'hot',
'data_type' => 'decimal(3,2) NOT NULL DEFAULT 0',
'column' => 'hp_rating',
'indexed' => true,
),
array(
'post_type' => 'hp_review',
'meta_key' => 'hp_text',
'zone' => 'cold',
'cache_group' => 'wpdo_cold_hp_review',
'cache_ttl' => HOUR_IN_SECONDS,
),
)
);
// Bookings extension (hp_booking post type).
$registry->register_many(
'hivepress-bookings',
array(
array(
'post_type' => 'hp_booking',
'meta_key' => 'hp_start_time',
'zone' => 'hot',
'data_type' => 'bigint(20) NOT NULL DEFAULT 0',
'column' => 'hp_start_time',
'indexed' => true,
),
array(
'post_type' => 'hp_booking',
'meta_key' => 'hp_end_time',
'zone' => 'hot',
'data_type' => 'bigint(20) NOT NULL DEFAULT 0',
'column' => 'hp_end_time',
'indexed' => true,
),
array(
'post_type' => 'hp_booking',
'meta_key' => 'hp_status',
'zone' => 'hot',
'data_type' => "varchar(20) NOT NULL DEFAULT ''",
'column' => 'hp_status',
'indexed' => true,
),
array(
'post_type' => 'hp_listing',
'meta_key' => 'hp_booking_enabled',
'zone' => 'hot',
'data_type' => 'tinyint(1) NOT NULL DEFAULT 0',
'column' => 'hp_booking_enabled',
'indexed' => true,
),
)
);
// Marketplace / Requests extension.
$registry->register_many(
'hivepress-marketplace',
array(
array(
'post_type' => 'hp_request',
'meta_key' => 'hp_request_category',
'zone' => 'hot',
'data_type' => 'bigint(20) NOT NULL DEFAULT 0',
'column' => 'hp_request_category',
'indexed' => true,
),
array(
'post_type' => 'hp_offer',
'meta_key' => 'hp_amount',
'zone' => 'hot',
'data_type' => 'decimal(10,2) NOT NULL DEFAULT 0',
'column' => 'hp_amount',
'indexed' => true,
),
array(
'post_type' => 'hp_offer',
'meta_key' => 'hp_request',
'zone' => 'hot',
'data_type' => 'bigint(20) NOT NULL DEFAULT 0',
'column' => 'hp_request',
'indexed' => true,
),
)
);
}
/**
* Register HPCT-inherited module interceptors and query interceptors.
*/
+34
View File
@@ -114,6 +114,40 @@ class CoreBoundaryTest extends TestCase {
);
}
/**
* TMDO_Core::run() fires at plugins_loaded:4, but these AddOn classes load
* at plugins_loaded:6 and wire themselves up in their own bootstrap. Probing
* them from core boot can never hit, so core must not mention them at all.
* (The infocards AddOn loads at :3 and also calls its own register().)
*/
public function test_core_boot_does_not_probe_addons_that_self_register(): void {
$tokens = token_get_all( (string) file_get_contents( dirname( __DIR__, 2 ) . '/includes/class-tmdo-core.php' ) );
$code = '';
foreach ( $tokens as $token ) {
if ( is_array( $token ) && in_array( $token[0], array( T_COMMENT, T_DOC_COMMENT ), true ) ) {
continue;
}
$code .= is_array( $token ) ? $token[1] : $token;
}
$late_addon_names = array(
'TMDO_Infocards',
'TMDO_Bookings',
'TMDO_Quotation',
'TMDO_Mobile_Bridge',
'TMDO_Collab',
'TMDO_Playlist',
'TMDO_WooCommerce',
'TMDO_WC_Orders_Interceptor',
'TMDO_Hivepress_Term_Comment_Fields',
'TMDO_Hivepress_Transient_Filter',
'register_hivepress_defaults',
);
$found = array_values( array_filter( $late_addon_names, static fn( $name ) => str_contains( $code, $name ) ) );
$this->assertSame( array(), $found, 'Dead AddOn probes remain in TMDO_Core: ' . implode( ', ', $found ) );
}
/**
* Remove line comments and string literals so mentions inside them are ignored.
*/