chore: initial snapshot of 2meet-data-optimizer-hivepress-addon 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:
@@ -0,0 +1,236 @@
|
||||
<?php
|
||||
/**
|
||||
* WP_Query interceptor for hp_listing meta queries.
|
||||
*
|
||||
* @package WP_Data_Optimizer
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WP_Query interceptor for hp_listing meta queries.
|
||||
*
|
||||
* The hpct_listing_meta is a key-value table (like wp_postmeta), so each
|
||||
* meta_query condition needs its own JOIN alias with a meta_key condition:
|
||||
*
|
||||
* LEFT JOIN wp_hpct_listing_meta AS wpdo_lm_0
|
||||
* ON (wp_posts.ID = wpdo_lm_0.listing_id AND wpdo_lm_0.meta_key = 'hp_price')
|
||||
* WHERE wpdo_lm_0.meta_value >= 100
|
||||
*
|
||||
* All hp_* and _hp_* meta keys are intercepted. Any other meta keys are
|
||||
* left in the meta_query to be handled by wp_postmeta as usual.
|
||||
*/
|
||||
class TMDO_Listing_Meta_Query extends TMDO_Query_Interceptor_Base {
|
||||
|
||||
/**
|
||||
* Returns the module identifier.
|
||||
*
|
||||
* @return string Module name.
|
||||
*/
|
||||
protected function get_module(): string {
|
||||
return 'listing_meta';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the post types this interceptor handles.
|
||||
*
|
||||
* @return string[] Post type slugs.
|
||||
*/
|
||||
protected function get_post_types(): array {
|
||||
return array( 'hp_listing' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the custom table name.
|
||||
*
|
||||
* @return string Table name without prefix.
|
||||
*/
|
||||
protected function get_table(): string {
|
||||
return 'hpct_listing_meta';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the join column for this KV table.
|
||||
*
|
||||
* @return string Join column name.
|
||||
*/
|
||||
protected function get_join_column(): string {
|
||||
return 'listing_id';
|
||||
}
|
||||
|
||||
/**
|
||||
* Not used — this class overrides pre_get_posts directly.
|
||||
*
|
||||
* @return array Empty array.
|
||||
*/
|
||||
protected function get_meta_key_map(): array {
|
||||
return array();
|
||||
}
|
||||
|
||||
// ── Override pre_get_posts for KV-table pattern ───────────────────────
|
||||
|
||||
/**
|
||||
* Intercepts pre_get_posts to handle KV-table meta_query conditions.
|
||||
*
|
||||
* @param \WP_Query $query The WP_Query object.
|
||||
* @return void
|
||||
*/
|
||||
public function pre_get_posts( \WP_Query $query ): void {
|
||||
if ( ! $this->should_intercept( $query ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$raw_meta_query = (array) $query->get( 'meta_query' );
|
||||
if ( empty( $raw_meta_query ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$our_clauses = array();
|
||||
$remaining = array();
|
||||
|
||||
foreach ( $raw_meta_query as $k => $clause ) {
|
||||
if ( 'relation' === $k || ! is_array( $clause ) || ! isset( $clause['key'] ) ) {
|
||||
$remaining[ $k ] = $clause;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $this->is_hp_key( $clause['key'] ) ) {
|
||||
$our_clauses[] = array(
|
||||
'meta_key' => $clause['key'],
|
||||
'value' => $clause['value'] ?? '',
|
||||
'compare' => strtoupper( trim( $clause['compare'] ?? '=' ) ),
|
||||
'type' => strtoupper( trim( $clause['type'] ?? 'CHAR' ) ),
|
||||
);
|
||||
} else {
|
||||
$remaining[ $k ] = $clause;
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty( $our_clauses ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( isset( $raw_meta_query['relation'] ) && ! isset( $remaining['relation'] ) ) {
|
||||
$remaining['relation'] = $raw_meta_query['relation'];
|
||||
}
|
||||
|
||||
$query->set( 'meta_query', $remaining );
|
||||
$query->set( $this->query_var(), $our_clauses );
|
||||
}
|
||||
|
||||
// ── Override posts_join for KV-table: one JOIN alias per condition ─────
|
||||
|
||||
/**
|
||||
* Appends LEFT JOINs for each KV-table meta_query condition.
|
||||
*
|
||||
* @param string $join Current JOIN SQL.
|
||||
* @param \WP_Query $query The WP_Query object.
|
||||
* @return string Modified JOIN SQL.
|
||||
*/
|
||||
public function posts_join( ?string $join, \WP_Query $query ): string {
|
||||
$join = (string) ( $join ?? '' );
|
||||
$clauses = $this->get_clauses( $query );
|
||||
if ( empty( $clauses ) ) {
|
||||
return $join;
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
$table = TMDO_DB::table( $this->get_table() );
|
||||
$join_col = esc_sql( $this->get_join_column() );
|
||||
|
||||
foreach ( $clauses as $i => $clause ) {
|
||||
$alias = $this->alias_for( $i );
|
||||
$meta_key = $clause['meta_key'];
|
||||
|
||||
if ( false === strpos( $join, "`{$alias}`" ) ) {
|
||||
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- $table from TMDO_DB::table(); $alias and $join_col are sanitize_key()-validated.
|
||||
$join .= $wpdb->prepare(
|
||||
" LEFT JOIN `{$table}` AS `{$alias}`"
|
||||
. " ON (`{$wpdb->posts}`.`ID` = `{$alias}`.`{$join_col}`"
|
||||
. " AND `{$alias}`.`meta_key` = %s)",
|
||||
$meta_key
|
||||
);
|
||||
// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
||||
}
|
||||
}
|
||||
|
||||
return $join;
|
||||
}
|
||||
|
||||
// ── Override posts_where for KV-table ─────────────────────────────────
|
||||
|
||||
/**
|
||||
* Appends WHERE conditions for KV-table meta_value comparisons.
|
||||
*
|
||||
* @param string $where Current WHERE SQL.
|
||||
* @param \WP_Query $query The WP_Query object.
|
||||
* @return string Modified WHERE SQL.
|
||||
*/
|
||||
public function posts_where( ?string $where, \WP_Query $query ): string {
|
||||
$where = (string) ( $where ?? '' );
|
||||
$clauses = $this->get_clauses( $query );
|
||||
if ( empty( $clauses ) ) {
|
||||
return $where;
|
||||
}
|
||||
|
||||
foreach ( $clauses as $i => $clause ) {
|
||||
$alias = $this->alias_for( $i );
|
||||
$col = "`{$alias}`.`meta_value`";
|
||||
$compare = $this->sanitize_compare( $clause['compare'] );
|
||||
$type = $clause['type'];
|
||||
$value = $clause['value'];
|
||||
|
||||
$where .= $this->build_condition( $col, $compare, $type, $value );
|
||||
}
|
||||
|
||||
return $where;
|
||||
}
|
||||
|
||||
// ── Override posts_groupby ─────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Ensures GROUP BY is set when KV-table clauses are active.
|
||||
*
|
||||
* @param string $groupby Current GROUP BY SQL.
|
||||
* @param \WP_Query $query The WP_Query object.
|
||||
* @return string Modified GROUP BY SQL.
|
||||
*/
|
||||
public function posts_groupby( ?string $groupby, \WP_Query $query ): string {
|
||||
$groupby = (string) ( $groupby ?? '' );
|
||||
$clauses = $this->get_clauses( $query );
|
||||
if ( empty( $clauses ) ) {
|
||||
return $groupby;
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
if ( '' === trim( $groupby ) ) {
|
||||
$groupby = "`{$wpdb->posts}`.`ID`";
|
||||
}
|
||||
|
||||
return $groupby;
|
||||
}
|
||||
|
||||
// ── Helpers ───────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Generates a unique SQL alias for a KV-table JOIN at a given index.
|
||||
*
|
||||
* @param int $index Zero-based clause index.
|
||||
* @return string SQL alias string.
|
||||
*/
|
||||
private function alias_for( int $index ): string {
|
||||
return "wpdo_lm_{$index}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a meta key belongs to HivePress (hp_ or _hp_ prefix).
|
||||
*
|
||||
* @param string $meta_key Meta key to check.
|
||||
* @return bool True if the key is an HP key.
|
||||
*/
|
||||
private function is_hp_key( string $meta_key ): bool {
|
||||
return str_starts_with( $meta_key, 'hp_' ) || str_starts_with( $meta_key, '_hp_' );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user