chore: initial snapshot of 2meet-data-optimizer v0.1.0

Baseline before backporting wp-data-optimizer v3.0.1-v3.4.6.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TbG1keQQ7XBa7qMQY16KCY
This commit is contained in:
2026-07-31 05:06:36 +08:00
commit d36bb954d1
206 changed files with 66538 additions and 0 deletions
@@ -0,0 +1,320 @@
<?php
/**
* TMDO_Post_Query_Router — Post entity meta_query → flat table JOIN rewriter (v2.10.1).
*
* Companion to legacy TMDO_Query_Router (which targets zone hot tables).
* Independent class — does NOT modify the user side path or the legacy zone
* router. Both routers can coexist on the same WP_Query without conflict
* because they extract clauses on disjoint criteria:
*
* - TMDO_Query_Router → only zone-registered keys with feature_flag query_active
* - TMDO_Post_Query_Router → only entity-registered keys with mode=reads_from_flat
*
* Mode-gated: only rewrites when post mode is `shadow_read` or `aeav_only`.
* In `disabled` / `dual_write` modes the router is a no-op.
*
* Hook order:
* 1. pre_get_posts — strip registered keys from meta_query, store in
* $query->set( 'wpdo_post_clauses', $routed )
* 2. posts_join — LEFT JOIN wp_wpdo_post_<group> per routed post_type
* 3. posts_where — append WHERE conditions targeting flat columns
* 4. posts_groupby — ensure GROUP BY posts.ID to dedup join multiplication
*
* 🔒 v2.9.x → v2.10.x frozen contract: never touches user entity. Routes
* only entity_type='post'.
*
* @package WP_Data_Optimizer
* @since 2.10.1
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Internal query rewriter: table names go through Schema_Manager::sanitize_column_name, column names go through esc_sql, user-controlled values use $wpdb->prepare() in build_condition().
/**
* Rewrites WP_Query meta_query clauses to JOIN against post entity flat tables.
*/
class TMDO_Post_Query_Router {
/** Query var key for capturing routed clauses (consumed by posts_join/where). */
private const QUERY_VAR = 'wpdo_post_clauses';
/**
* Map post_type → entity group (mirror of TMDO_Post_Migration::group_post_type
* but inverted; a post_type may map to multiple groups eventually, currently
* we route to the most-specific *_core group plus the cross-cutting wp_core
* group when the key is in wp_core).
*
* @var array<string,string>
*/
private const POST_TYPE_GROUP_MAP = array(
'product' => 'wc_product',
'hp_listing' => 'hp_listing_core',
'hp_request' => 'hp_request_core',
'hp_vendor' => 'hp_vendor_core',
'attachment' => 'attachment',
'nav_menu_item' => 'nav_menu_item',
);
/**
* Register all WP_Query hooks.
*
* @return void
*/
public function register_hooks(): void {
add_action( 'pre_get_posts', array( $this, 'pre_get_posts' ), 10, 1 );
add_filter( 'posts_join', array( $this, 'posts_join' ), 10, 2 );
add_filter( 'posts_where', array( $this, 'posts_where' ), 10, 2 );
add_filter( 'posts_groupby', array( $this, 'posts_groupby' ), 10, 2 );
}
/**
* Strip Entity-Registry-managed meta_query keys; store routed clauses.
*
* @param \WP_Query $query Current WP_Query.
* @return void
*/
public function pre_get_posts( \WP_Query $query ): void {
// Mode gate: only run when post mode is reads_from_flat.
if ( ! self::is_router_active() ) {
return;
}
// is_admin guard (matches legacy TMDO_Query_Router behavior).
if ( is_admin() && ! wp_doing_ajax() ) {
return;
}
$post_types = (array) $query->get( 'post_type' );
if ( empty( $post_types ) ) {
return;
}
$raw_meta_query = (array) $query->get( 'meta_query' );
if ( empty( $raw_meta_query ) ) {
return;
}
$routed = array(); // Keyed by post_type.
$remaining = array();
foreach ( $raw_meta_query as $k => $clause ) {
if ( 'relation' === $k || ! is_array( $clause ) || ! isset( $clause['key'] ) ) {
$remaining[ $k ] = $clause;
continue;
}
$matched = false;
foreach ( $post_types as $pt ) {
$field = TMDO_Entity_Registry::get_field( 'post', $clause['key'] );
if ( ! $field ) {
continue;
}
// Confirm the field's group is appropriate for this post_type:
// either cross-cutting wp_core (any) or the post_type-specific group.
$group = $field['group'] ?? '';
$expected_grp = self::POST_TYPE_GROUP_MAP[ $pt ] ?? null;
$is_appropriate = ( 'wp_core' === $group ) || ( null !== $expected_grp && $expected_grp === $group );
if ( ! $is_appropriate ) {
continue;
}
$column = TMDO_Schema_Manager::sanitize_column_name( $clause['key'] );
$routed[ $pt ][] = array(
'group' => $group,
'column' => $column,
'value' => $clause['value'] ?? '',
'compare' => strtoupper( trim( (string) ( $clause['compare'] ?? '=' ) ) ),
'type' => strtoupper( trim( (string) ( $clause['type'] ?? 'CHAR' ) ) ),
);
$matched = true;
break;
}
if ( ! $matched ) {
$remaining[ $k ] = $clause;
}
}
if ( empty( $routed ) ) {
return;
}
// Preserve relation if surviving clauses still have it.
if ( isset( $raw_meta_query['relation'] ) && ! isset( $remaining['relation'] ) ) {
$remaining['relation'] = $raw_meta_query['relation'];
}
$query->set( 'meta_query', $remaining );
$query->set( self::QUERY_VAR, $routed );
}
/**
* LEFT JOIN flat tables for each routed post_type.
*
* @param string|null $join Current JOIN SQL.
* @param \WP_Query $query Current WP_Query.
* @return string Modified JOIN SQL.
*/
public function posts_join( ?string $join, \WP_Query $query ): string {
$join = (string) ( $join ?? '' );
$routed = $query->get( self::QUERY_VAR );
if ( empty( $routed ) || ! is_array( $routed ) ) {
return $join;
}
global $wpdb;
foreach ( $routed as $post_type => $clauses ) {
// Each routed clause carries its group; use the first clause's group
// (all clauses for a given post_type currently target one group).
$group = $clauses[0]['group'] ?? '';
if ( '' === $group ) {
continue;
}
$table = $wpdb->prefix . 'wpdo_post_' . sanitize_key( $group );
$alias = self::table_alias( $post_type, $group );
// Don't double-join.
if ( false !== strpos( $join, "`{$alias}`" ) ) {
continue;
}
$join .= " LEFT JOIN `{$table}` AS `{$alias}` "
. "ON (`{$wpdb->posts}`.`ID` = `{$alias}`.`post_id`)";
}
return $join;
}
/**
* Append WHERE conditions for routed clauses.
*
* @param string|null $where Current WHERE SQL.
* @param \WP_Query $query Current WP_Query.
* @return string Modified WHERE SQL.
*/
public function posts_where( ?string $where, \WP_Query $query ): string {
$where = (string) ( $where ?? '' );
$routed = $query->get( self::QUERY_VAR );
if ( empty( $routed ) || ! is_array( $routed ) ) {
return $where;
}
global $wpdb;
foreach ( $routed as $post_type => $clauses ) {
foreach ( $clauses as $clause ) {
$alias = self::table_alias( $post_type, $clause['group'] );
$col = '`' . $alias . '`.`' . esc_sql( $clause['column'] ) . '`';
$compare = self::sanitize_compare( $clause['compare'] );
$value = $clause['value'];
$where .= self::build_condition( $col, $compare, $value );
}
}
return $where;
}
/**
* Ensure GROUP BY posts.ID to deduplicate JOIN-multiplied rows.
*
* @param string|null $groupby Current GROUP BY SQL.
* @param \WP_Query $query Current WP_Query.
* @return string Modified GROUP BY SQL.
*/
public function posts_groupby( ?string $groupby, \WP_Query $query ): string {
$groupby = (string) ( $groupby ?? '' );
$routed = $query->get( self::QUERY_VAR );
if ( empty( $routed ) || ! is_array( $routed ) ) {
return $groupby;
}
global $wpdb;
if ( '' === trim( $groupby ) ) {
$groupby = "`{$wpdb->posts}`.`ID`";
}
return $groupby;
}
// ─────────────────────────────────────────────────────────────────────────
// Helpers
// ─────────────────────────────────────────────────────────────────────────
/**
* Whether the router is mode-active (post mode is shadow_read or aeav_only).
*
* @return bool
*/
public static function is_router_active(): bool {
if ( ! class_exists( 'TMDO_Mode_Manager' ) ) {
return false;
}
return TMDO_Mode_Manager::reads_from_flat( 'post' );
}
/**
* Generate a deterministic JOIN alias for a (post_type, group) pair.
*
* @param string $post_type Post type slug.
* @param string $group Entity group name.
* @return string SQL alias.
*/
private static function table_alias( string $post_type, string $group ): string {
return 'wpdoflat_' . sanitize_key( $post_type ) . '_' . sanitize_key( $group );
}
/**
* Allow-list of comparison operators.
*
* @param string $compare Raw operator from clause.
* @return string Sanitized operator (defaults to '=').
*/
private static function sanitize_compare( string $compare ): string {
$allowed = array( '=', '!=', '<>', '<', '<=', '>', '>=', 'IN', 'NOT IN', 'LIKE', 'NOT LIKE', 'BETWEEN', 'NOT BETWEEN', 'EXISTS', 'NOT EXISTS' );
$compare = strtoupper( trim( $compare ) );
return in_array( $compare, $allowed, true ) ? $compare : '=';
}
/**
* Build a single WHERE condition fragment (always prepended with " AND ").
*
* @param string $col_sql Quoted column reference.
* @param string $compare Sanitized comparison operator.
* @param mixed $value Raw value (scalar or array).
* @return string
*/
private static function build_condition( string $col_sql, string $compare, $value ): string {
global $wpdb;
if ( in_array( $compare, array( 'IN', 'NOT IN' ), true ) ) {
$values = (array) $value;
if ( empty( $values ) ) {
return '';
}
$placeholders = implode( ',', array_fill( 0, count( $values ), '%s' ) );
return ' AND ' . $col_sql . ' ' . $compare . ' (' . $wpdb->prepare( $placeholders, ...$values ) . ')';
}
if ( in_array( $compare, array( 'BETWEEN', 'NOT BETWEEN' ), true ) ) {
$values = (array) $value;
if ( count( $values ) < 2 ) {
return '';
}
return ' AND ' . $col_sql . ' ' . $compare . ' '
. $wpdb->prepare( '%s AND %s', $values[0], $values[1] );
}
if ( in_array( $compare, array( 'EXISTS', 'NOT EXISTS' ), true ) ) {
$op = 'EXISTS' === $compare ? 'IS NOT NULL' : 'IS NULL';
return ' AND ' . $col_sql . ' ' . $op;
}
return ' AND ' . $col_sql . ' ' . $compare . ' ' . $wpdb->prepare( '%s', (string) $value );
}
}