fix(2meet-data-optimizer): route post entity keys by post_type

- Entity groups can declare post_types; get_field() resolves a post's key against its own type's groups first, then unscoped ones (legacy last-wins lookup kept for callers without a post type)
- Hook Bus and the post query router pass the post type, so a listing's hp_rating / hp_status / hp_verified map to hp_listing_core instead of the vendor/request tables; core HP groups declare their post types (schema hashes unchanged)
- Behind tmdo_post_scoped_routing: on for sites without post flat rows, off where rows may sit in the wrong table until PR-034 reconciles them (dry-run: dev20–22 off, dev23/24/30/31/40 on)
- Verify: EntityRegistryScopeTest (8), PostScopedRoutingTest (4); core unit 630 / integration 443, HP 144/49, WC 10/22 OK
- PR: PR-033
This commit is contained in:
2026-09-25 23:55:49 +08:00
parent 1653011f4f
commit 3f4fe52e1b
7 changed files with 340 additions and 14 deletions
+42
View File
@@ -268,6 +268,48 @@ class TMDO_Installer {
self::install();
}
self::maybe_preserve_misc_bucket_default();
self::maybe_init_post_scoped_routing();
}
/**
* One-time default for post_type-scoped entity routing.
*
* Autoloaded because TMDO_Entity_Registry::get_field() reads it per lookup.
*
* @return void
*/
public static function maybe_init_post_scoped_routing(): void {
global $wpdb;
if ( false !== get_option( TMDO_Entity_Registry::SCOPED_ROUTING_OPTION, false ) || ! class_exists( 'TMDO_Mode_Manager' ) ) {
return;
}
$has_rows = false;
$tables = (array) $wpdb->get_col( $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $wpdb->prefix . 'wpdo_post_' ) . '%' ) );
foreach ( $tables as $table ) {
if ( $wpdb->get_var( "SELECT 1 FROM `{$table}` LIMIT 1" ) ) { // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- table name from SHOW TABLES.
$has_rows = true;
break;
}
}
add_option( TMDO_Entity_Registry::SCOPED_ROUTING_OPTION, self::post_scoped_routing_default( TMDO_Mode_Manager::get( 'post' ), $has_rows ), '', true );
}
/**
* Whether post_type-scoped routing can start on right away.
*
* Existing post flat rows were written with legacy routing (a key shared by
* several groups went to the last one registered), so they may sit in
* another post type's table. Scoped lookups stay off there until the rows
* are reconciled; with the post bridge disabled nothing reads them.
*
* @param string $post_mode Current post entity bridge mode.
* @param bool $has_post_flat_rows Whether any wpdo_post_* table has rows.
* @return string '1' to enable, '0' to wait for reconcile.
*/
public static function post_scoped_routing_default( string $post_mode, bool $has_post_flat_rows ): string {
return ( 'disabled' === $post_mode || ! $has_post_flat_rows ) ? '1' : '0';
}
/**