Add hook to exclude certain properties from HPOS sync/verification (#43123)

Certain order properties (or metadata) are not relevant for HPOS verification. For example, `_edit_lock` which is an ephemeral key. So far we've been hardcoding these keys in various places. This provides a new API to access these keys. It also introduces hook `woocommerce_hpos_sync_ignored_order_props` which allows 3rd party code to add new keys to be ignored by sync/verification code.

Fixes #41907
This commit is contained in:
Jorge A. Torres 2023-12-28 18:40:02 +00:00 committed by GitHub
parent eabb27c72b
commit 9ce04dc807
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 65 additions and 10 deletions

View File

@ -0,0 +1,4 @@
Significance: minor
Type: tweak
Add hook 'woocommerce_hpos_sync_ignored_order_props' to allow keys to be ignored during HPOS sync/verification.

View File

@ -583,11 +583,7 @@ class CLIRunner {
* @return array Failed IDs with meta details.
*/
private function verify_meta_data( array $order_ids, array $failed_ids ) : array {
$meta_keys_to_ignore = array(
'_paid_date', // This has been deprecated and replaced by '_date_paid' in the CPT datastore.
'_completed_date', // This has been deprecated and replaced by '_date_completed' in the CPT datastore.
'_edit_lock',
);
$meta_keys_to_ignore = $this->synchronizer->get_ignored_order_props();
global $wpdb;
if ( ! count( $order_ids ) ) {

View File

@ -5,9 +5,9 @@
namespace Automattic\WooCommerce\Internal\DataStores\Orders;
use Automattic\WooCommerce\Caches\OrderCache;
use Automattic\WooCommerce\Caches\OrderCacheController;
use Automattic\WooCommerce\Database\Migrations\CustomOrderTable\PostsToOrdersMigrationController;
use Automattic\WooCommerce\Internal\Admin\Orders\EditLock;
use Automattic\WooCommerce\Internal\BatchProcessing\{ BatchProcessingController, BatchProcessorInterface };
use Automattic\WooCommerce\Internal\Features\FeaturesController;
use Automattic\WooCommerce\Internal\Traits\AccessiblePrivateMethods;
@ -335,6 +335,33 @@ class DataSynchronizer implements BatchProcessorInterface {
return $interval;
}
/**
* Keys that can be ignored during synchronization or verification.
*
* @since 8.6.0
*
* @return string[]
*/
public function get_ignored_order_props() {
/**
* Allows modifying the list of order properties that are ignored during HPOS synchronization or verification.
*
* @param string[] List of order properties or meta keys.
* @since 8.6.0
*/
$ignored_props = apply_filters( 'woocommerce_hpos_sync_ignored_order_props', array() );
$ignored_props = array_filter( array_map( 'trim', array_filter( $ignored_props, 'is_string' ) ) );
return array_merge(
$ignored_props,
array(
'_paid_date', // This has been deprecated and replaced by '_date_paid' in the CPT datastore.
'_completed_date', // This has been deprecated and replaced by '_date_completed' in the CPT datastore.
EditLock::META_KEY_NAME,
)
);
}
/**
* Schedule an event to run background sync when the mode is set to interval.
*

View File

@ -97,6 +97,15 @@ class OrdersTableDataStore extends \Abstract_WC_Order_Data_Store_CPT implements
'_new_order_email_sent',
);
/**
* Meta keys that are considered ephemereal and do not trigger a full save (updating modified date) when changed.
*
* @var string[]
*/
protected $ephemeral_meta_keys = array(
EditLock::META_KEY_NAME,
);
/**
* Handles custom metadata in the wc_orders_meta table.
*
@ -2964,9 +2973,7 @@ CREATE TABLE $meta_table (
private function should_save_after_meta_change( $order, $meta = null ) {
$current_time = $this->legacy_proxy->call_function( 'current_time', 'mysql', 1 );
$current_date_time = new \WC_DateTime( $current_time, new \DateTimeZone( 'GMT' ) );
$skip_for = array(
EditLock::META_KEY_NAME,
);
return $order->get_date_modified() < $current_date_time && empty( $order->get_changes() ) && ( ! is_object( $meta ) || ! in_array( $meta->key, $skip_for, true ) );
return $order->get_date_modified() < $current_date_time && empty( $order->get_changes() ) && ( ! is_object( $meta ) || ! in_array( $meta->key, $this->ephemeral_meta_keys, true ) );
}
}

View File

@ -3239,4 +3239,25 @@ class OrdersTableDataStoreTests extends HposTestCase {
$this->assertContains( 'user@woo.test', $coupon->get_used_by( 'edit' ) );
}
/**
* Tests that changes to certain keys don't trigger full order updates.
*/
public function test_ephemeral_meta_updates() {
$this->toggle_cot_authoritative( true );
// Set order in the past so that we can accurately compare dates.
$order = WC_Helper_Order::create_order();
$order->set_date_modified( time() - DAY_IN_SECONDS );
$order->save();
$date_modified = $order->get_date_modified();
$order->update_meta_data( '_edit_lock', 'whatever' );
$order->save_meta_data();
$this->assertEquals( $date_modified, $order->get_date_modified() );
$order->update_meta_data( 'other_meta', 'whatever' );
$order->save_meta_data();
$this->assertNotEquals( $date_modified, $order->get_date_modified() );
}
}