fix(2meet-data-optimizer): filter REST listings collection by post_status and post_type
- GET /wpdo/v1/listings rejects unregistered or non-viewable post types (400) and joins posts so Zone A only lists published posts of that type - WP_Query fallback now returns only show_in_rest hot columns, matching the Zone A path - Verify: core unit 605 / integration 432 OK (new RestApi tests); 1M bench: page 7ms, total COUNT 0.12s → 1.7s (tracked in PR-030) - PR: PR-015
This commit is contained in:
@@ -530,6 +530,15 @@ class TMDO_REST_API {
|
||||
*/
|
||||
public function get_listings( WP_REST_Request $request ): WP_REST_Response {
|
||||
$post_type = $request->get_param( 'post_type' ) ?? 'hp_listing';
|
||||
if ( ! post_type_exists( $post_type ) || ! is_post_type_viewable( $post_type ) ) {
|
||||
return new WP_REST_Response(
|
||||
array(
|
||||
'code' => 'rest_invalid_post_type',
|
||||
'message' => 'Invalid post type.',
|
||||
),
|
||||
400
|
||||
);
|
||||
}
|
||||
// Defense-in-depth: clamp per_page even if validate_callback in listings_args() fails open.
|
||||
// Filter `wpdo_rest_max_per_page` allows site owners to adjust the upper bound.
|
||||
$max_per_page = (int) apply_filters( 'wpdo_rest_max_per_page', 100 );
|
||||
@@ -1365,6 +1374,10 @@ class TMDO_REST_API {
|
||||
/**
|
||||
* Query Zone A flat table directly.
|
||||
*
|
||||
* Rows are joined to the posts table so only published posts of the
|
||||
* requested type are listed (the hot table also holds drafts, private
|
||||
* and trashed posts).
|
||||
*
|
||||
* @param string $post_type Post type slug.
|
||||
* @param int $per_page Number of items per page.
|
||||
* @param int $offset Database offset.
|
||||
@@ -1396,6 +1409,8 @@ class TMDO_REST_API {
|
||||
}
|
||||
|
||||
$where_sql = $where ? 'WHERE ' . implode( ' AND ', $where ) : '';
|
||||
$join_sql = "INNER JOIN `{$wpdb->posts}` p ON p.ID = t.post_id AND p.post_type = %s AND p.post_status = 'publish'";
|
||||
array_unshift( $params, $post_type );
|
||||
|
||||
// Validate orderby against known columns + post_id.
|
||||
$allowed_orderby = array_merge( array( 'post_id' ), array_keys( $columns ) );
|
||||
@@ -1404,16 +1419,12 @@ class TMDO_REST_API {
|
||||
|
||||
// Count total.
|
||||
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber -- table from TMDO_Zone_Hot::table(); where_sql/orderby_col/order_dir are sanitized/validated.
|
||||
if ( $params ) {
|
||||
$total = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM `{$table}` {$where_sql}", ...$params ) );
|
||||
} else {
|
||||
$total = (int) $wpdb->get_var( "SELECT COUNT(*) FROM `{$table}`" );
|
||||
}
|
||||
$total = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM `{$table}` t {$join_sql} {$where_sql}", ...$params ) );
|
||||
|
||||
// Fetch rows.
|
||||
$rows = $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
"SELECT * FROM `{$table}` {$where_sql} ORDER BY `{$orderby_col}` {$order_dir} LIMIT %d OFFSET %d",
|
||||
"SELECT t.* FROM `{$table}` t {$join_sql} {$where_sql} ORDER BY t.`{$orderby_col}` {$order_dir} LIMIT %d OFFSET %d",
|
||||
...array_merge( $params, array( $per_page, $offset ) )
|
||||
),
|
||||
ARRAY_A
|
||||
@@ -1476,8 +1487,8 @@ class TMDO_REST_API {
|
||||
'id' => $post->ID,
|
||||
'post_type' => $post->post_type,
|
||||
);
|
||||
$cols = TMDO_Schema_Registry::instance()->get_hot_columns( $post_type );
|
||||
foreach ( array_keys( $cols ) as $col ) {
|
||||
// Same show_in_rest restriction as the Zone A path.
|
||||
foreach ( TMDO_Schema_Registry::instance()->get_rest_visible_hot_columns( $post_type ) as $col ) {
|
||||
$item[ $col ] = get_post_meta( $post->ID, $col, true );
|
||||
}
|
||||
$items[] = $item;
|
||||
@@ -1507,7 +1518,7 @@ class TMDO_REST_API {
|
||||
$min = $request->get_param( $col . '_min' );
|
||||
if ( null !== $min && is_numeric( $min ) ) {
|
||||
$filters[] = array(
|
||||
'sql' => "`{$col}` >= %f",
|
||||
'sql' => "t.`{$col}` >= %f",
|
||||
'value' => (float) $min,
|
||||
);
|
||||
}
|
||||
@@ -1515,7 +1526,7 @@ class TMDO_REST_API {
|
||||
$max = $request->get_param( $col . '_max' );
|
||||
if ( null !== $max && is_numeric( $max ) ) {
|
||||
$filters[] = array(
|
||||
'sql' => "`{$col}` <= %f",
|
||||
'sql' => "t.`{$col}` <= %f",
|
||||
'value' => (float) $max,
|
||||
);
|
||||
}
|
||||
@@ -1524,12 +1535,12 @@ class TMDO_REST_API {
|
||||
if ( null !== $exact && '' !== $exact ) {
|
||||
if ( is_numeric( $exact ) ) {
|
||||
$filters[] = array(
|
||||
'sql' => "`{$col}` = %f",
|
||||
'sql' => "t.`{$col}` = %f",
|
||||
'value' => (float) $exact,
|
||||
);
|
||||
} else {
|
||||
$filters[] = array(
|
||||
'sql' => "`{$col}` = %s",
|
||||
'sql' => "t.`{$col}` = %s",
|
||||
'value' => (string) $exact,
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user