Skip to content

Commit

Permalink
Merge pull request #3512 from 10up/fix/issue-3509
Browse files Browse the repository at this point in the history
Fix and expand the orderby clause with meta fields
  • Loading branch information
felipeelia committed Jul 4, 2023
2 parents ec4a380 + f99bbc3 commit 65c8878
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 14 deletions.
57 changes: 43 additions & 14 deletions includes/classes/Indexable/Post/Post.php
Original file line number Diff line number Diff line change
Expand Up @@ -1290,6 +1290,12 @@ protected function parse_orderby_meta_fields( $orderby_clause, $args ) {
'unsigned' => 'long',
];

// Code is targeting Elasticsearch directly
if ( preg_match( '/^meta\.(.*?)\.(.*)/', $orderby_clause, $match_meta ) ) {
return $orderby_clause;
}

// WordPress meta_value_* compatibility
if ( preg_match( '/^meta_value_?(.*)/', $orderby_clause, $match_type ) ) {
$meta_type = $from_to_metatypes[ strtolower( $match_type[1] ) ] ?? 'value.sortable';
}
Expand All @@ -1298,25 +1304,48 @@ protected function parse_orderby_meta_fields( $orderby_clause, $args ) {
$meta_field = $args['meta_key'];
}

if ( ( ! isset( $meta_type ) || ! isset( $meta_field ) ) && ! empty( $args['meta_query'] ) ) {
$meta_query = new \WP_Meta_Query( $args['meta_query'] );
// Calling get_sql() to populate the WP_Meta_Query->clauses attribute
$meta_query->get_sql( 'post', $wpdb->posts, 'ID' );
// Already have everything needed
if ( isset( $meta_type ) && isset( $meta_field ) ) {
return "meta.{$meta_field}.{$meta_type}";
}

// Don't have any other ways to guess
if ( empty( $args['meta_query'] ) ) {
return $orderby_clause;
}

$meta_query = new \WP_Meta_Query( $args['meta_query'] );
// Calling get_sql() to populate the WP_Meta_Query->clauses attribute
$meta_query->get_sql( 'post', $wpdb->posts, 'ID' );

$clauses = $meta_query->get_clauses();
$clauses = $meta_query->get_clauses();

if ( ! empty( $clauses[ $orderby_clause ] ) ) {
$meta_field = $clauses[ $orderby_clause ]['key'];
$clause_meta_type = strtolower( $clauses[ $orderby_clause ]['type'] ?? $clauses[ $orderby_clause ]['cast'] );
// If it refers to a named meta_query clause
if ( ! empty( $clauses[ $orderby_clause ] ) ) {
$meta_field = $clauses[ $orderby_clause ]['key'];
$clause_meta_type = strtolower( $clauses[ $orderby_clause ]['type'] ?? $clauses[ $orderby_clause ]['cast'] );
} else {
/**
* At this point we:
* 1. Try to find the meta key in any meta_query clause and use the type WP found
* 2. If ordering by `meta_value*`, use the first meta_query clause
* 3. Give up and use the orderby clause as is (code could be capturing it later on)
*/
$meta_keys_and_types = wp_list_pluck( $clauses, 'cast', 'key' );
if ( isset( $meta_keys_and_types[ $orderby_clause ] ) ) {
$meta_field = $orderby_clause;
$clause_meta_type = strtolower( $meta_keys_and_types[ $orderby_clause ] ?? $meta_keys_and_types[ $orderby_clause ] );
} elseif ( isset( $meta_type ) ) {
$primary_clause = reset( $clauses );
$meta_field = $primary_clause['key'];
} else {
$primary_clause = reset( $clauses );
$meta_field = $primary_clause['key'];
$clause_meta_type = strtolower( $primary_clause['type'] ?? $primary_clause['cast'] );
unset( $meta_type );
unset( $meta_field );
}
}

if ( ! isset( $meta_type ) ) {
$meta_type = $from_to_metatypes[ $clause_meta_type ] ?? 'value.sortable';
}
if ( ! isset( $meta_type ) && isset( $clause_meta_type ) ) {
$meta_type = $from_to_metatypes[ $clause_meta_type ] ?? 'value.sortable';
}

if ( isset( $meta_type ) && isset( $meta_field ) ) {
Expand Down
49 changes: 49 additions & 0 deletions tests/php/indexables/TestPost.php
Original file line number Diff line number Diff line change
Expand Up @@ -6867,6 +6867,55 @@ public function testParseOrderbyMetaQueryTypes( $meta_value_type, $es_type ) {
$this->assertGreaterThanOrEqual( 1, did_filter( 'ep_formatted_args' ) );
}

/**
* Test the parse_orderby_meta_fields() method when dealing with multiple meta fields
*
* @see https://github.com/10up/ElasticPress/issues/3509
* @since 4.6.1
* @group post
*/
public function testParseOrderbyMetaMultiple() {
$method_executed = false;

$query_args = [
'ep_integrate' => true,
'orderby' => [
'meta_field1' => 'desc',
'meta.meta_field3.double' => 'asc',
'meta.meta_field2.double' => 'asc',
],
'meta_query' => [
'date_clause' => [
'key' => 'meta_field2',
'value' => '20230622',
'compare' => '>=',
],
],
];

$assert_callback = function( $args ) use ( &$method_executed ) {
$method_executed = true;

$expected_sort = [
[ 'meta_field1' => [ 'order' => 'desc' ] ],
[ 'meta.meta_field3.double' => [ 'order' => 'asc' ] ],
[ 'meta.meta_field2.double' => [ 'order' => 'asc' ] ],
];

$this->assertSame( $expected_sort, $args['sort'] );

return $args;
};

// Run the tests.
add_filter( 'ep_formatted_args', $assert_callback );
$query = new \WP_Query( $query_args );
remove_filter( 'ep_formatted_args', $assert_callback );

$this->assertTrue( $method_executed );
$this->assertGreaterThanOrEqual( 1, did_filter( 'ep_formatted_args' ) );
}

/**
* Tests additional nested tax queries in parse_tax_query().
*
Expand Down

0 comments on commit 65c8878

Please sign in to comment.