Synchronize order meta data (between HPOS and CPT stores) (#36593)
This commit is contained in:
commit
627c2bce01
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: fix
|
||||
|
||||
When order meta data is saved via HPOS, it should be backfilled to the CPT data store.
|
|
@ -613,14 +613,28 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
|
|||
foreach ( $order->get_meta_data() as $meta_data ) {
|
||||
if ( isset( $existing_meta_data[ $meta_data->key ] ) ) {
|
||||
if ( $existing_meta_data[ $meta_data->key ] === $meta_data->value ) {
|
||||
unset( $existing_meta_data[ $meta_data->key ] );
|
||||
continue;
|
||||
}
|
||||
delete_post_meta( $order->get_id(), $meta_data->key );
|
||||
|
||||
unset( $existing_meta_data[ $meta_data->key ] );
|
||||
delete_post_meta( $order->get_id(), $meta_data->key );
|
||||
}
|
||||
add_post_meta( $order->get_id(), $meta_data->key, $meta_data->value, false );
|
||||
}
|
||||
|
||||
// Find remaining meta that was deleted from the order but still present in the associated post.
|
||||
// Post meta corresponding to order props is excluded (as it shouldn't be deleted).
|
||||
$keys_to_delete = array_diff(
|
||||
array_keys( $existing_meta_data ),
|
||||
$this->internal_meta_keys,
|
||||
array_keys( $this->get_internal_data_store_key_getters() )
|
||||
);
|
||||
|
||||
foreach ( $keys_to_delete as $meta_key ) {
|
||||
delete_post_meta( $order->get_id(), $meta_key );
|
||||
}
|
||||
|
||||
$this->update_post_meta( $order );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,6 +78,8 @@ abstract class CustomMetaDataStore {
|
|||
*
|
||||
* @param WC_Data $object WC_Data object.
|
||||
* @param stdClass $meta (containing at least ->id).
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function delete_meta( &$object, $meta ) {
|
||||
global $wpdb;
|
||||
|
@ -127,6 +129,8 @@ abstract class CustomMetaDataStore {
|
|||
*
|
||||
* @param WC_Data $object WC_Data object.
|
||||
* @param stdClass $meta (containing ->id, ->key and ->value).
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function update_meta( &$object, $meta ) {
|
||||
global $wpdb;
|
||||
|
|
|
@ -11,6 +11,7 @@ use Automattic\WooCommerce\Internal\Utilities\DatabaseUtil;
|
|||
use Automattic\WooCommerce\Proxies\LegacyProxy;
|
||||
use Automattic\WooCommerce\Utilities\ArrayUtil;
|
||||
use Exception;
|
||||
use WC_Abstract_Order;
|
||||
use WC_Data;
|
||||
use WC_Order;
|
||||
|
||||
|
@ -1963,21 +1964,6 @@ FROM $order_meta_table
|
|||
$order->delete_meta_data( '_wp_trash_meta_comments_status' );
|
||||
$order->save_meta_data();
|
||||
|
||||
$data_synchronizer = wc_get_container()->get( DataSynchronizer::class );
|
||||
if ( $data_synchronizer->data_sync_is_enabled() ) {
|
||||
// The previous $order->save() will have forced a sync to the posts table,
|
||||
// this implies that the post status is not "trash" anymore, and thus
|
||||
// wp_untrash_post would do nothing.
|
||||
wp_update_post(
|
||||
array(
|
||||
'ID' => $id,
|
||||
'post_status' => 'trash',
|
||||
)
|
||||
);
|
||||
|
||||
wp_untrash_post( $id );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2457,9 +2443,17 @@ CREATE TABLE $meta_table (
|
|||
*
|
||||
* @param WC_Data $object WC_Data object.
|
||||
* @param stdClass $meta (containing at least ->id).
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function delete_meta( &$object, $meta ) {
|
||||
return $this->data_store_meta->delete_meta( $object, $meta );
|
||||
$delete_meta = $this->data_store_meta->delete_meta( $object, $meta );
|
||||
|
||||
if ( $object instanceof WC_Abstract_Order ) {
|
||||
$this->maybe_backfill_post_record( $object );
|
||||
}
|
||||
|
||||
return $delete_meta;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2467,10 +2461,17 @@ CREATE TABLE $meta_table (
|
|||
*
|
||||
* @param WC_Data $object WC_Data object.
|
||||
* @param stdClass $meta (containing ->key and ->value).
|
||||
* @return int meta ID
|
||||
*
|
||||
* @return int|bool meta ID or false on failure
|
||||
*/
|
||||
public function add_meta( &$object, $meta ) {
|
||||
return $this->data_store_meta->add_meta( $object, $meta );
|
||||
$add_meta = $this->data_store_meta->add_meta( $object, $meta );
|
||||
|
||||
if ( $object instanceof WC_Abstract_Order ) {
|
||||
$this->maybe_backfill_post_record( $object );
|
||||
}
|
||||
|
||||
return $add_meta;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2478,8 +2479,16 @@ CREATE TABLE $meta_table (
|
|||
*
|
||||
* @param WC_Data $object WC_Data object.
|
||||
* @param stdClass $meta (containing ->id, ->key and ->value).
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function update_meta( &$object, $meta ) {
|
||||
return $this->data_store_meta->update_meta( $object, $meta );
|
||||
$update_meta = $this->data_store_meta->update_meta( $object, $meta );
|
||||
|
||||
if ( $object instanceof WC_Abstract_Order ) {
|
||||
$this->maybe_backfill_post_record( $object );
|
||||
}
|
||||
|
||||
return $update_meta;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -223,4 +223,74 @@ class DataSynchronizerTests extends WC_Unit_Test_Case {
|
|||
'After the COT order record was deleted, the order was also deleted from the posts table.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* When sync is enabled, changes to meta data should propagate from the Custom Orders Table to
|
||||
* the post meta table whenever the order object's save_meta_data() method is called.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function test_meta_data_changes_propagate_from_cot_to_cpt(): void {
|
||||
// Sync enabled and COT authoritative.
|
||||
update_option( $this->sut::ORDERS_DATA_SYNC_ENABLED_OPTION, 'yes' );
|
||||
update_option( CustomOrdersTableController::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION, 'yes' );
|
||||
|
||||
$order = OrderHelper::create_order();
|
||||
$order->add_meta_data( 'foo', 'bar' );
|
||||
$order->add_meta_data( 'bar', 'baz' );
|
||||
$order->save_meta_data();
|
||||
|
||||
$order->delete_meta_data( 'bar' );
|
||||
$order->save_meta_data();
|
||||
|
||||
update_option( CustomOrdersTableController::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION, 'no' );
|
||||
$refreshed_order = wc_get_order( $order->get_id() );
|
||||
|
||||
$this->assertEquals(
|
||||
$refreshed_order->get_meta( 'foo' ),
|
||||
'bar',
|
||||
'Meta data persisted via the HPOS datastore is accessible via the CPT datastore.'
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
$refreshed_order->get_meta( 'bar' ),
|
||||
'',
|
||||
'Meta data deleted from the HPOS datastore should also be deleted from the CPT datastore.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* When sync is enabled, changes to meta data should propagate from the post meta table to
|
||||
* the Custom Orders Table whenever the order object's save_meta_data() method is called.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function test_meta_data_changes_propagate_from_cpt_to_cot(): void {
|
||||
// Sync enabled and CPT authoritative.
|
||||
update_option( $this->sut::ORDERS_DATA_SYNC_ENABLED_OPTION, 'yes' );
|
||||
update_option( CustomOrdersTableController::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION, 'no' );
|
||||
|
||||
$order = OrderHelper::create_order();
|
||||
$order->add_meta_data( 'foo', 'bar' );
|
||||
$order->add_meta_data( 'bar', 'baz' );
|
||||
$order->save_meta_data();
|
||||
|
||||
$order->delete_meta_data( 'bar' );
|
||||
$order->save_meta_data();
|
||||
|
||||
update_option( CustomOrdersTableController::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION, 'yes' );
|
||||
$refreshed_order = wc_get_order( $order->get_id() );
|
||||
|
||||
$this->assertEquals(
|
||||
$refreshed_order->get_meta( 'foo' ),
|
||||
'bar',
|
||||
'Meta data persisted via the CPT datastore is accessible via the HPOS datastore.'
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
$refreshed_order->get_meta( 'bar' ),
|
||||
'',
|
||||
'Meta data deleted from the CPT datastore should also be deleted from the HPOS datastore.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue