[HPOS] Fix regression in supporting nested date query arguments (#37827)
This commit is contained in:
commit
8ac3c29937
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: fix
|
||||
|
||||
Fix regression in supporting nested date query arguments in HPOS.
|
|
@ -270,15 +270,6 @@ class OrdersTableQuery {
|
|||
$this->args['meta_query'] = array( $shortcut_meta_query ); // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
|
||||
}
|
||||
}
|
||||
|
||||
// Date query.
|
||||
if ( isset( $this->args['date_query'] ) && is_array( $this->args['date_query'] ) ) {
|
||||
foreach ( $this->args['date_query'] as $index => $query ) {
|
||||
if ( isset( $query['column'] ) && isset( $mapping[ $query['column'] ] ) ) {
|
||||
$this->args['date_query'][ $index ]['column'] = $mapping[ $query['column'] ];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -325,6 +316,11 @@ class OrdersTableQuery {
|
|||
* @throws \Exception When date args are invalid.
|
||||
*/
|
||||
private function process_date_args(): void {
|
||||
if ( $this->arg_isset( 'date_query' ) ) {
|
||||
// Process already passed date queries args.
|
||||
$this->args['date_query'] = $this->map_gmt_and_post_keys_to_hpos_keys( $this->args['date_query'] );
|
||||
}
|
||||
|
||||
$valid_operators = array( '>', '>=', '=', '<=', '<', '...' );
|
||||
$date_queries = array();
|
||||
$local_to_gmt_date_keys = array(
|
||||
|
@ -333,30 +329,13 @@ class OrdersTableQuery {
|
|||
'date_paid' => 'date_paid_gmt',
|
||||
'date_completed' => 'date_completed_gmt',
|
||||
);
|
||||
$gmt_date_keys = array_values( $local_to_gmt_date_keys );
|
||||
$local_date_keys = array_keys( $local_to_gmt_date_keys );
|
||||
|
||||
$gmt_date_keys = array_values( $local_to_gmt_date_keys );
|
||||
$local_date_keys = array_keys( $local_to_gmt_date_keys );
|
||||
|
||||
$valid_date_keys = array_merge( $gmt_date_keys, $local_date_keys );
|
||||
$date_keys = array_filter( $valid_date_keys, array( $this, 'arg_isset' ) );
|
||||
|
||||
// Process already passed date queries args.
|
||||
if ( $this->arg_isset( 'date_query' ) && is_array( $this->args['date_query'] ) ) {
|
||||
foreach ( $this->args['date_query'] as $index => $query ) {
|
||||
if ( ! isset( $query['column'] ) || ! in_array( $query['column'], $valid_date_keys, true ) ) {
|
||||
unset( $this->args['date_query'][ $index ] );
|
||||
continue;
|
||||
}
|
||||
// Convert any local dates to GMT.
|
||||
if ( isset( $local_to_gmt_date_keys[ $query['column'] ] ) ) {
|
||||
$this->args['date_query'][ $index ]['column'] = $local_to_gmt_date_keys[ $query['column'] ];
|
||||
$op = isset( $query['after'] ) ? 'after' : 'before';
|
||||
$date_value_local = $query[ $op ];
|
||||
$date_value_gmt = wc_string_to_timestamp( get_gmt_from_date( wc_string_to_datetime( $date_value_local ) ) );
|
||||
$this->args['date_query'][ $index ][ $op ] = $this->date_to_date_query_arg( $date_value_gmt, 'UTC' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( $date_keys as $date_key ) {
|
||||
$date_value = $this->args[ $date_key ];
|
||||
$operator = '=';
|
||||
|
@ -430,6 +409,63 @@ class OrdersTableQuery {
|
|||
$this->process_date_query_columns();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to map posts and gmt based keys to HPOS keys.
|
||||
*
|
||||
* @param array $query Date query argument.
|
||||
*
|
||||
* @return array|mixed Date query argument with modified keys.
|
||||
*/
|
||||
private function map_gmt_and_post_keys_to_hpos_keys( $query ) {
|
||||
if ( ! is_array( $query ) ) {
|
||||
return $query;
|
||||
}
|
||||
|
||||
$post_to_hpos_mappings = array(
|
||||
'post_date' => 'date_created',
|
||||
'post_date_gmt' => 'date_created_gmt',
|
||||
'post_modified' => 'date_updated',
|
||||
'post_modified_gmt' => 'date_updated_gmt',
|
||||
'_date_completed' => 'date_completed',
|
||||
'_date_paid' => 'date_paid',
|
||||
'date_modified' => 'date_updated',
|
||||
'date_modified_gmt' => 'date_updated_gmt',
|
||||
);
|
||||
|
||||
$local_to_gmt_date_keys = array(
|
||||
'date_created' => 'date_created_gmt',
|
||||
'date_updated' => 'date_updated_gmt',
|
||||
'date_paid' => 'date_paid_gmt',
|
||||
'date_completed' => 'date_completed_gmt',
|
||||
);
|
||||
|
||||
array_walk(
|
||||
$query,
|
||||
function ( &$sub_query ) {
|
||||
$sub_query = $this->map_gmt_and_post_keys_to_hpos_keys( $sub_query );
|
||||
}
|
||||
);
|
||||
|
||||
if ( ! isset( $query['column'] ) ) {
|
||||
return $query;
|
||||
}
|
||||
|
||||
if ( isset( $post_to_hpos_mappings[ $query['column'] ] ) ) {
|
||||
$query['column'] = $post_to_hpos_mappings[ $query['column'] ];
|
||||
}
|
||||
|
||||
// Convert any local dates to GMT.
|
||||
if ( isset( $local_to_gmt_date_keys[ $query['column'] ] ) ) {
|
||||
$query['column'] = $local_to_gmt_date_keys[ $query['column'] ];
|
||||
$op = isset( $query['after'] ) ? 'after' : 'before';
|
||||
$date_value_local = $query[ $op ];
|
||||
$date_value_gmt = wc_string_to_timestamp( get_gmt_from_date( wc_string_to_datetime( $date_value_local ) ) );
|
||||
$query[ $op ] = $this->date_to_date_query_arg( $date_value_gmt, 'UTC' );
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure all 'date_query' columns are correctly prefixed and their respective tables are being JOIN'ed.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
<?php
|
||||
|
||||
use Automattic\WooCommerce\RestApi\UnitTests\Helpers\OrderHelper;
|
||||
use Automattic\WooCommerce\RestApi\UnitTests\HPOSToggleTrait;
|
||||
use Automattic\WooCommerce\Utilities\OrderUtil;
|
||||
|
||||
/**
|
||||
* Class OrdersTableQueryTests.
|
||||
*/
|
||||
class OrdersTableQueryTests extends WC_Unit_Test_Case {
|
||||
use HPOSToggleTrait;
|
||||
|
||||
/**
|
||||
* Stores the original COT state.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $cot_state;
|
||||
|
||||
/**
|
||||
* Setup - enable COT.
|
||||
*/
|
||||
public function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->setup_cot();
|
||||
$this->cot_state = OrderUtil::custom_orders_table_usage_is_enabled();
|
||||
$this->toggle_cot( true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the original COT state.
|
||||
*/
|
||||
public function tearDown(): void {
|
||||
$this->toggle_cot( $this->cot_state );
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to create different orders with different dates for testing.
|
||||
*
|
||||
* @return array Array of WC_Order objects.
|
||||
*/
|
||||
private function create_orders_with_different_dates() {
|
||||
$order1 = OrderHelper::create_order();
|
||||
$order2 = OrderHelper::create_order();
|
||||
$order3 = OrderHelper::create_order();
|
||||
|
||||
$order1->set_date_created( '2000-01-01T10:00:00' );
|
||||
$order1->set_date_modified( '2001-02-01T10:00:00' );
|
||||
$order1->set_date_paid( '2002-03-01T10:00:00' );
|
||||
$order1->save();
|
||||
|
||||
$order2->set_date_created( '2000-02-01T10:00:00' );
|
||||
$order2->set_date_modified( '2001-01-01T10:00:00' );
|
||||
$order2->set_date_paid( '2002-03-01T10:00:00' );
|
||||
$order2->save();
|
||||
|
||||
$order3->set_date_created( '2001-01-01T10:00:00' );
|
||||
$order3->set_date_modified( '2001-02-01T10:00:00' );
|
||||
$order3->set_date_paid( '2002-03-01T10:00:00' );
|
||||
$order3->save();
|
||||
|
||||
return array( $order1, $order2, $order3 );
|
||||
}
|
||||
|
||||
/**
|
||||
* @testDox Nested date queries works as expected.
|
||||
*/
|
||||
public function test_nested_date_queries_single() {
|
||||
$orders = $this->create_orders_with_different_dates();
|
||||
|
||||
$date_query_created_in_2000 = array(
|
||||
array(
|
||||
'relation' => 'AND',
|
||||
array(
|
||||
'column' => 'date_created',
|
||||
'inclusive' => true,
|
||||
'after' => '2000-01-01T00:00:00',
|
||||
),
|
||||
array(
|
||||
'column' => 'date_created',
|
||||
'inclusive' => false,
|
||||
'before' => '2001-01-01T10:00:00',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$queried_orders = wc_get_orders(
|
||||
array(
|
||||
'return' => 'ids',
|
||||
'date_query' => $date_query_created_in_2000,
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertEquals( 2, count( $queried_orders ) );
|
||||
$this->assertContains( $orders[0]->get_id(), $queried_orders );
|
||||
$this->assertContains( $orders[1]->get_id(), $queried_orders );
|
||||
}
|
||||
|
||||
/**
|
||||
* @testDox Multiple nested date queries works as expected.
|
||||
*/
|
||||
public function test_nested_date_queries_multi() {
|
||||
$orders = $this->create_orders_with_different_dates();
|
||||
|
||||
$date_query_created_in_2000_and_modified_in_2001 = array(
|
||||
array(
|
||||
'relation' => 'AND',
|
||||
array(
|
||||
'column' => 'date_created',
|
||||
'inclusive' => true,
|
||||
'after' => '2000-01-01T00:00:00',
|
||||
),
|
||||
array(
|
||||
'column' => 'post_date',
|
||||
'inclusive' => false,
|
||||
'before' => '2001-01-01T10:00:00',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'column' => 'date_modified',
|
||||
'before' => '2001-01-02T10:00:00',
|
||||
),
|
||||
);
|
||||
|
||||
$queried_orders = wc_get_orders(
|
||||
array(
|
||||
'return' => 'ids',
|
||||
'date_query' => $date_query_created_in_2000_and_modified_in_2001,
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertEquals( 1, count( $queried_orders ) );
|
||||
$this->assertContains( $orders[1]->get_id(), $queried_orders );
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue