$meta->id = $add_meta; $changes_applied = $this->after_meta_change( $object, $meta ); if ( ! $changes_applied && $object instanceof WC_Abstract_Order && $this->should_backfill_post_record() ) { self::$backfilling_order_ids[] = $object->get_id(); add_post_meta( $object->get_id(), $meta->key, $meta->value ); self::$backfilling_order_ids = array_diff( self::$backfilling_order_ids, array( $object->get_id() ) ); } return $add_meta; } /** * Update meta. * * @param WC_Data $object WC_Data object. * @param \stdClass $meta (containing ->id, ->key and ->value). * * @return bool The number of rows updated, or false on error. */ public function update_meta( &$object, $meta ) { $update_meta = $this->data_store_meta->update_meta( $object, $meta ); $changes_applied = $this->after_meta_change( $object, $meta ); if ( ! $changes_applied && $object instanceof WC_Abstract_Order && $this->should_backfill_post_record() ) { self::$backfilling_order_ids[] = $object->get_id(); update_post_meta( $object->get_id(), $meta->key, $meta->value ); self::$backfilling_order_ids = array_diff( self::$backfilling_order_ids, array( $object->get_id() ) ); } 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. * * @return bool True if changes were applied, false otherwise. */ protected function after_meta_change( &$order, $meta ) { method_exists( $meta, 'apply_changes' ) && $meta->apply_changes(); // Prevent this happening multiple time in same request. if ( $this->should_save_after_meta_change( $order, $meta ) ) { $order->set_date_modified( current_time( 'mysql' ) ); $order->save(); return true; } else { $order_cache = wc_get_container()->get( OrderCache::class ); $order_cache->remove( $order->get_id() ); } return false; } /** * Helper function to check whether the modified date needs to be updated after a meta save. * * This method prevents order->save() call multiple times in the same request after any meta update by checking if: * 1. Order modified date is already the current date, no updates needed in this case. * 2. If there are changes already queued for order object, then we don't need to update the modified date as it will be updated ina subsequent save() call. * * @param WC_Order $order Order object. * @param \WC_Meta_Data|null $meta Metadata object. * * @return bool Whether the modified date needs to be updated. */ 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 ) ); } }