Use correct datastore when backfilling orders. (#35176)

* Use correct datastore when backfilling orders.

* Fix some unit tests and simplify calls.
This commit is contained in:
Vedanshu Jain 2022-10-20 13:22:22 +05:30 committed by GitHub
parent 3d78fd24ee
commit 80cbb9dcdc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 87 additions and 26 deletions

View File

@ -0,0 +1,4 @@
Significance: patch
Type: fix
Use correct datastore when backfilling orders.

View File

@ -539,6 +539,18 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
return wc_string_to_bool( $this->get_prop( 'recorded_coupon_usage_counts', $context ) );
}
/**
* Get basic order data in array format.
*
* @return array
*/
public function get_base_data() {
return array_merge(
array( 'id' => $this->get_id() ),
$this->data
);
}
/*
|--------------------------------------------------------------------------
| Setters

View File

@ -187,7 +187,7 @@ class WC_Order_Factory {
*
* @return array Array of order_id => class_name.
*/
private static function get_class_names_for_order_ids( $order_ids ) {
public static function get_class_names_for_order_ids( $order_ids ) {
$order_data_store = WC_Data_Store::load( 'order' );
if ( $order_data_store->has_callable( 'get_orders_type' ) ) {
$order_types = $order_data_store->get_orders_type( $order_ids );

View File

@ -497,9 +497,9 @@ class OrdersTableDataStore extends \Abstract_WC_Order_Data_Store_CPT implements
*
* @return \WC_Order_Data_Store_CPT Data store instance.
*/
private function get_cpt_data_store_instance() {
public function get_cpt_data_store_instance() {
if ( ! isset( $this->cpt_data_store ) ) {
$this->cpt_data_store = new \WC_Order_Data_Store_CPT();
$this->cpt_data_store = $this->get_post_data_store_for_backfill();
}
return $this->cpt_data_store;
}
@ -985,7 +985,7 @@ WHERE
$data_sync_enabled = $data_synchronizer->data_sync_is_enabled() && 0 === $data_synchronizer->get_current_orders_pending_sync_count_cached();
$load_posts_for = array_diff( $order_ids, self::$reading_order_ids );
$post_orders = $data_sync_enabled ? $this->get_post_orders_for_ids( $load_posts_for ) : array();
$post_orders = $data_sync_enabled ? $this->get_post_orders_for_ids( array_intersect_key( $orders, array_flip( $load_posts_for ) ) ) : array();
foreach ( $data as $order_data ) {
$order_id = absint( $order_data->id );
@ -1084,31 +1084,46 @@ WHERE
/**
* Helper function to get posts data for an order in bullk. We use to this to compute posts object in bulk so that we can compare it with COT data.
*
* @param array $order_ids List of order IDs.
* @param array $orders List of orders mapped by $order_id.
*
* @return array List of posts.
*/
private function get_post_orders_for_ids( array $order_ids ): array {
$cpt_data_store = $this->get_cpt_data_store_instance();
private function get_post_orders_for_ids( array $orders ): array {
$order_ids = array_keys( $orders );
// We have to bust meta cache, otherwise we will just get the meta cached by OrderTableDataStore.
foreach ( $order_ids as $order_id ) {
wp_cache_delete( WC_Order::generate_meta_cache_key( $order_id, 'orders' ), 'orders' );
}
$query_vars = array(
'include' => $order_ids,
'type' => wc_get_order_types(),
'status' => 'any',
'limit' => count( $order_ids ),
);
$cpt_data_store->prime_caches_for_orders( $order_ids, $query_vars );
$orders = array();
foreach ( $order_ids as $order_id ) {
$order = new WC_Order();
$order->set_id( $order_id );
$cpt_data_store->read( $order );
$orders[ $order_id ] = $order;
$cpt_stores = array();
$cpt_store_orders = array();
foreach ( $orders as $order_id => $order ) {
$table_data_store = $order->get_data_store();
$cpt_data_store = $table_data_store->get_cpt_data_store_instance();
$cpt_store_class_name = get_class( $cpt_data_store );
if ( ! isset( $cpt_stores[ $cpt_store_class_name ] ) ) {
$cpt_stores[ $cpt_store_class_name ] = $cpt_data_store;
$cpt_store_orders[ $cpt_store_class_name ] = array();
}
$cpt_store_orders[ $cpt_store_class_name ][ $order_id ] = $order;
}
return $orders;
$cpt_orders = array();
foreach ( $cpt_stores as $cpt_store_name => $cpt_store ) {
// Prime caches if we can.
if ( method_exists( $cpt_store, 'prime_caches_for_orders' ) ) {
$cpt_store->prime_caches_for_orders( array_keys( $cpt_store_orders[ $cpt_store_name ] ), array() );
}
foreach ( $cpt_store_orders[ $cpt_store_name ] as $order_id => $order ) {
$cpt_order_class_name = wc_get_order_type( $order->get_type() )['class_name'];
$cpt_order = new $cpt_order_class_name();
$cpt_order->set_id( $order_id );
$cpt_store->read( $cpt_order );
$cpt_orders[ $order_id ] = $cpt_order;
}
}
return $cpt_orders;
}
/**
@ -1221,12 +1236,12 @@ WHERE
/**
* Migrate post record from a given order object.
*
* @param \WC_Order $order Order object.
* @param \WC_Order $post_order Order object read from posts.
* @param \WC_Abstract_Order $order Order object.
* @param \WC_Abstract_Order $post_order Order object read from posts.
*
* @return void
*/
private function migrate_post_record( \WC_Order &$order, \WC_Order $post_order ): void {
private function migrate_post_record( \WC_Abstract_Order &$order, \WC_Abstract_Order $post_order ): void {
$this->migrate_meta_data_from_post_order( $order, $post_order );
$post_order_base_data = $post_order->get_base_data();
foreach ( $post_order_base_data as $key => $value ) {

View File

@ -1120,7 +1120,7 @@ class OrdersTableDataStoreTests extends WC_Unit_Test_Case {
$this->enable_cot_sync();
$order = $this->create_complex_cot_order();
$post_order_comparison_closure = function ( $order ) {
$post_order = $this->get_post_orders_for_ids( array( $order->get_id() ) )[ $order->get_id() ];
$post_order = $this->get_post_orders_for_ids( array( $order->get_id() => $order ) )[ $order->get_id() ];
return $this->is_post_different_from_order( $order, $post_order );
};
@ -1135,6 +1135,7 @@ class OrdersTableDataStoreTests extends WC_Unit_Test_Case {
$r_order = new WC_Order();
$r_order->set_id( $order->get_id() );
$this->switch_data_store( $r_order, $this->sut );
// Reading again will make a call to migrate_post_record.
$this->sut->read( $r_order );
$this->assertFalse( $post_order_comparison_closure->call( $this->sut, $r_order ) );
@ -1806,6 +1807,8 @@ class OrdersTableDataStoreTests extends WC_Unit_Test_Case {
* @testDox Test that multiple calls to read don't try to sync again.
*/
public function test_read_multiple_dont_sync_again_for_same_order() {
$this->toggle_cot( true );
$this->enable_cot_sync();
$order = $this->create_complex_cot_order();
$order_id = $order->get_id();
@ -1814,7 +1817,6 @@ class OrdersTableDataStoreTests extends WC_Unit_Test_Case {
return $this->should_sync_order( $order );
};
$this->enable_cot_sync();
$order = new WC_Order();
$order->set_id( $order_id );
$orders = array( $order_id => $order );

View File

@ -12,6 +12,7 @@ use Automattic\WooCommerce\RestApi\UnitTests\Helpers\OrderHelper;
* Class OrdersTableRefundDataStoreTests.
*/
class OrdersTableRefundDataStoreTests extends WC_Unit_Test_Case {
use \Automattic\WooCommerce\RestApi\UnitTests\HPOSToggleTrait;
/**
* @var PostsToOrdersMigrationController
@ -73,4 +74,31 @@ class OrdersTableRefundDataStoreTests extends WC_Unit_Test_Case {
$this->assertEquals( 'Test', $refreshed_refund->get_reason() );
}
/**
* @testDox Test that refunds can be backfilled correctly.
*/
public function test_refunds_backfill() {
$this->enable_cot_sync();
$this->toggle_cot( true );
$order = OrderHelper::create_complex_data_store_order( $this->order_data_store );
$refund = wc_create_refund(
array(
'order_id' => $order->get_id(),
'amount' => 10,
'reason' => 'Test',
)
);
$refund->save();
$this->assertTrue( $refund->get_id() > 0 );
// Check that data was saved.
$refreshed_refund = new WC_Order_Refund();
$cpt_store = $this->sut->get_cpt_data_store_instance();
$refreshed_refund->set_id( $refund->get_id() );
$cpt_store->read( $refreshed_refund );
$this->assertEquals( $refund->get_id(), $refreshed_refund->get_id() );
$this->assertEquals( 10, $refreshed_refund->get_amount() );
$this->assertEquals( 'Test', $refreshed_refund->get_reason() );
}
}