Update modified date when a metadata is saved for HPOS. (#39911)

This commit is contained in:
nigeljamesstevenson 2023-08-29 11:18:17 +01:00 committed by GitHub
commit f53e5f744d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 107 additions and 21 deletions

View File

@ -0,0 +1,4 @@
Significance: patch
Type: fix
Update modified date when a metadata is saved for HPOS.

View File

@ -1858,8 +1858,8 @@ FROM $order_meta_table
if ( $row ) { if ( $row ) {
$result[] = array( $result[] = array(
'table' => self::get_orders_table_name(), 'table' => self::get_orders_table_name(),
'data' => array_merge( $row['data'], array( 'id' => $order->get_id() ) ), 'data' => array_merge( $row['data'], array( 'id' => $order->get_id(), 'type' => $order->get_type() ) ),
'format' => array_merge( $row['format'], array( 'id' => '%d' ) ), 'format' => array_merge( $row['format'], array( 'id' => '%d', 'type' => '%s' ) ),
); );
} }
@ -1928,8 +1928,6 @@ FROM $order_meta_table
protected function get_db_row_from_order( $order, $column_mapping, $only_changes = false ) { protected function get_db_row_from_order( $order, $column_mapping, $only_changes = false ) {
$changes = $only_changes ? $order->get_changes() : array_merge( $order->get_data(), $order->get_changes() ); $changes = $only_changes ? $order->get_changes() : array_merge( $order->get_data(), $order->get_changes() );
$changes['type'] = $order->get_type();
// Make sure 'status' is correctly prefixed. // Make sure 'status' is correctly prefixed.
if ( array_key_exists( 'status', $column_mapping ) && array_key_exists( 'status', $changes ) ) { if ( array_key_exists( 'status', $column_mapping ) && array_key_exists( 'status', $changes ) ) {
$changes['status'] = $this->get_post_status( $order ); $changes['status'] = $this->get_post_status( $order );
@ -2163,16 +2161,6 @@ FROM $order_meta_table
'_wp_trash_meta_time' => time(), '_wp_trash_meta_time' => time(),
); );
foreach ( $trash_metadata as $meta_key => $meta_value ) {
$this->add_meta(
$order,
(object) array(
'key' => $meta_key,
'value' => $meta_value,
)
);
}
$wpdb->update( $wpdb->update(
self::get_orders_table_name(), self::get_orders_table_name(),
array( array(
@ -2186,6 +2174,16 @@ FROM $order_meta_table
$order->set_status( 'trash' ); $order->set_status( 'trash' );
foreach ( $trash_metadata as $meta_key => $meta_value ) {
$this->add_meta(
$order,
(object) array(
'key' => $meta_key,
'value' => $meta_value,
)
);
}
$data_synchronizer = wc_get_container()->get( DataSynchronizer::class ); $data_synchronizer = wc_get_container()->get( DataSynchronizer::class );
if ( $data_synchronizer->data_sync_is_enabled() ) { if ( $data_synchronizer->data_sync_is_enabled() ) {
wp_trash_post( $order->get_id() ); wp_trash_post( $order->get_id() );
@ -2788,12 +2786,13 @@ CREATE TABLE $meta_table (
* Deletes meta based on meta ID. * Deletes meta based on meta ID.
* *
* @param WC_Data $object WC_Data object. * @param WC_Data $object WC_Data object.
* @param stdClass $meta (containing at least ->id). * @param \stdClass $meta (containing at least ->id).
* *
* @return bool * @return bool
*/ */
public function delete_meta( &$object, $meta ) { public function delete_meta( &$object, $meta ) {
$delete_meta = $this->data_store_meta->delete_meta( $object, $meta ); $delete_meta = $this->data_store_meta->delete_meta( $object, $meta );
$this->after_meta_change( $object, $meta );
if ( $object instanceof WC_Abstract_Order && $this->should_backfill_post_record() ) { if ( $object instanceof WC_Abstract_Order && $this->should_backfill_post_record() ) {
self::$backfilling_order_ids[] = $object->get_id(); self::$backfilling_order_ids[] = $object->get_id();
@ -2808,12 +2807,13 @@ CREATE TABLE $meta_table (
* Add new piece of meta. * Add new piece of meta.
* *
* @param WC_Data $object WC_Data object. * @param WC_Data $object WC_Data object.
* @param stdClass $meta (containing ->key and ->value). * @param \stdClass $meta (containing ->key and ->value).
* *
* @return int|bool meta ID or false on failure * @return int|bool meta ID or false on failure
*/ */
public function add_meta( &$object, $meta ) { public function add_meta( &$object, $meta ) {
$add_meta = $this->data_store_meta->add_meta( $object, $meta ); $add_meta = $this->data_store_meta->add_meta( $object, $meta );
$this->after_meta_change( $object, $meta );
if ( $object instanceof WC_Abstract_Order && $this->should_backfill_post_record() ) { if ( $object instanceof WC_Abstract_Order && $this->should_backfill_post_record() ) {
self::$backfilling_order_ids[] = $object->get_id(); self::$backfilling_order_ids[] = $object->get_id();
@ -2828,12 +2828,13 @@ CREATE TABLE $meta_table (
* Update meta. * Update meta.
* *
* @param WC_Data $object WC_Data object. * @param WC_Data $object WC_Data object.
* @param stdClass $meta (containing ->id, ->key and ->value). * @param \stdClass $meta (containing ->id, ->key and ->value).
* *
* @return bool * @return
*/ */
public function update_meta( &$object, $meta ) { public function update_meta( &$object, $meta ) {
$update_meta = $this->data_store_meta->update_meta( $object, $meta ); $update_meta = $this->data_store_meta->update_meta( $object, $meta );
$this->after_meta_change( $object, $meta );
if ( $object instanceof WC_Abstract_Order && $this->should_backfill_post_record() ) { if ( $object instanceof WC_Abstract_Order && $this->should_backfill_post_record() ) {
self::$backfilling_order_ids[] = $object->get_id(); self::$backfilling_order_ids[] = $object->get_id();
@ -2843,4 +2844,22 @@ CREATE TABLE $meta_table (
return $update_meta; return $update_meta;
} }
/**
* Perform after meta change operations, including updating the date_modified field, clearing caches and applying changes.
*
* @param WC_Abstract_Order $order Order object.
* @param \WC_Meta_Data $meta Metadata object.
*/
protected function after_meta_change( &$order, $meta ) {
$current_date_time = new \WC_DateTime( current_time( 'mysql', 1 ), new \DateTimeZone( 'GMT' ) );
method_exists( $meta, 'apply_changes' ) && $meta->apply_changes();
$this->clear_caches( $order );
// Prevent this happening multiple time in same request.
if ( $order->get_date_modified() < $current_date_time && empty( $order->get_changes() ) ) {
$order->set_date_modified( current_time( 'mysql' ) );
$order->save();
}
}
} }

View File

@ -2740,5 +2740,68 @@ class OrdersTableDataStoreTests extends HposTestCase {
remove_action( 'woocommerce_update_order', $callback ); remove_action( 'woocommerce_update_order', $callback );
} }
/**
* @testDox Stale data is not read when sync is off, but then switched on again after a while.
* @testWith [true]
* [false]
*
* @param bool $different_request Whether to simulate different requests (as much as we can in a unit test)
*/
public function test_stale_data_is_not_read_sync_off_on( $different_request ) {
$this->toggle_cot_authoritative( true );
$this->enable_cot_sync();
$cot_store = wc_get_container()->get( OrdersTableDataStore::class );
$order = OrderHelper::create_order();
$order->set_customer_id( 1 ); // Change a custom table column.
$order->set_billing_address_1( 'test' ); // Change an address column and a meta row.
$order->set_download_permissions_granted( true ); // Change an operational data column.
$order->save();
$different_request && $this->reset_order_data_store_state( $cot_store );
$order->add_meta_data( 'test_key', 'test_value' );
$order->save_meta_data();
$different_request && $this->reset_order_data_store_state( $cot_store );
$r_order = wc_get_order( $order->get_id() );
$this->assertEquals( 1, $r_order->get_customer_id() );
$this->assertEquals( 'test', $r_order->get_billing_address_1() );
$this->assertTrue( $order->get_download_permissions_granted() );
$this->assertEquals( 'test_value', $r_order->get_meta( 'test_key', true ) );
$different_request && $this->reset_order_data_store_state( $cot_store );
sleep(2);
$this->disable_cot_sync();
$r_order->update_meta_data( 'test_key', 'test_value_updated' );
$r_order->add_meta_data( 'test_key2', 'test_value2' );
$r_order->save_meta_data();
$different_request && $this->reset_order_data_store_state( $cot_store );
$this->enable_cot_sync();
$r_order = wc_get_order( $order->get_id() );
$this->assertEquals( 1, $r_order->get_customer_id() );
$this->assertEquals( 'test', $r_order->get_billing_address_1() );
$this->assertTrue( $order->get_download_permissions_granted() );
$this->assertEquals( 'test_value_updated', $r_order->get_meta( 'test_key', true ) );
$this->assertEquals( 'test_value2', $r_order->get_meta( 'test_key2', true ) );
}
/**
* Helper method to reset order data store state (to help simulate multiple requests).
*
* @param OrdersTableDataStore $sut System under test.
*/
private function reset_order_data_store_state( $sut ) {
$reset_state = function () use ( $sut ) {
self::$backfilling_order_ids = [];
self::$reading_order_ids = [];
};
$reset_state->call( $sut );
wp_cache_flush();
}
} }