Add backfill method to support update post and postmeta data.

This commit is contained in:
vedanshujain 2022-05-03 16:21:20 +05:30
parent 22f81c9693
commit 253e8424ea
3 changed files with 315 additions and 77 deletions

View File

@ -76,6 +76,28 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
'_order_stock_reduced',
);
/**
* Getters for internal key in data stores.
*
* @var string[]
*/
protected $internal_data_store_key_getters = array(
'_download_permissions_granted' => 'download_permissions_granted',
'_recorded_sales' => 'recorded_sales',
'_recorded_coupon_usage_counts' => 'recorded_coupon_usage_counts',
'_order_stock_reduced' => 'stock_reduced',
'_new_order_email_sent' => 'email_sent',
);
/**
* Return internal key getters name.
*
* @return string[]
*/
public function get_internal_data_store_key_getters() {
return $this->internal_data_store_key_getters;
}
/**
* Method to create a new order in the database.
*
@ -297,6 +319,57 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
do_action( 'woocommerce_order_object_updated_props', $order, $updated_props );
}
/**
* Given an initialized order object, update the post/postmeta records.
*
* @param WC_Order $order Order object.
*
* @return bool Whether the order was updated.
*/
public function update_order_from_object( $order ) {
if ( ! $order->get_id() ) {
return false;
}
$this->update_order_meta_from_object( $order );
return wp_update_post(
array(
'ID' => $order->get_id(),
'post_date' => gmdate( 'Y-m-d H:i:s', $order->get_date_created( 'edit' )->getOffsetTimestamp() ),
'post_date_gmt' => gmdate( 'Y-m-d H:i:s', $order->get_date_created( 'edit' )->getTimestamp() ),
'post_status' => $this->get_post_status( $order ),
'post_parent' => $order->get_parent_id(),
'post_excerpt' => $this->get_post_excerpt( $order ),
'post_type' => 'shop_order',
)
);
}
/**
* Helper method to update order metadata from intialized order object.
*
* @param WC_Order $order Order object.
*/
private function update_order_meta_from_object( $order ) {
if ( is_null( $order->get_meta() ) ) {
return;
}
$existing_meta_data = get_post_meta( $order->get_id() );
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 ) {
continue;
}
delete_post_meta( $order->get_id(), $meta_data->key );
unset( $existing_meta_data[ $meta_data->key ] );
}
add_post_meta( $order->get_id(), $meta_data->key, $meta_data->value, false );
}
$this->update_post_meta( $order );
}
/**
* Excerpt for post.
*
@ -630,6 +703,29 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
update_post_meta( $order_id, '_recorded_coupon_usage_counts', wc_bool_to_string( $set ) );
}
/**
* Whether email have been sent for this order.
*
* @param WC_Order|int $order Order ID or order object.
*
* @return bool Whether email is sent.
*/
public function get_email_sent( $order ) {
$order_id = WC_Order_Factory::get_order_id( $order );
return wc_string_to_bool( get_post_meta( $order_id, '_new_order_email_sent', true ) );
}
/**
* Stores information about whether email was sent.
*
* @param WC_Order|int $order Order ID or order object.
* @param bool $set True or false.
*/
public function set_email_sent( $order, $set ) {
$order_id = WC_Order_Factory::get_order_id( $order );
update_post_meta( $order_id, '_new_order_email_sent', wc_bool_to_string( $set ) );
}
/**
* Return array of coupon_code => meta_key for coupon which have usage limit and have tentative keys.
* Pass $coupon_id if key for only one of the coupon is needed.
@ -874,7 +970,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
} else {
update_post_caches( $query->posts ); // We already fetching posts, might as well hydrate some caches.
$order_ids = wp_list_pluck( $query->posts, 'ID' );
$orders = $this->compile_orders( $order_ids, $query_vars, $query );
$orders = $this->compile_orders( $order_ids, $query_vars, $query );
}
if ( isset( $query_vars['paginate'] ) && $query_vars['paginate'] ) {
@ -942,7 +1038,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
$cache_keys_mapping[ $order_id ] = WC_Cache_Helper::get_cache_prefix( 'orders' ) . 'refunds' . $order_id;
}
$non_cached_ids = array();
$cache_values = wc_cache_get_multiple( array_values( $cache_keys_mapping ), 'orders' );
$cache_values = wc_cache_get_multiple( array_values( $cache_keys_mapping ), 'orders' );
foreach ( $order_ids as $order_id ) {
if ( false === $cache_values[ $cache_keys_mapping[ $order_id ] ] ) {
$non_cached_ids[] = $order_id;
@ -952,11 +1048,11 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
return;
}
$refunds = wc_get_orders(
$refunds = wc_get_orders(
array(
'type' => 'shop_order_refund',
'type' => 'shop_order_refund',
'post_parent__in' => $non_cached_ids,
'limit' => - 1,
'limit' => - 1,
)
);
$order_refunds = array_reduce(
@ -1002,13 +1098,13 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
return;
}
}
$cache_keys = array_map(
$cache_keys = array_map(
function ( $order_id ) {
return 'order-items-' . $order_id;
},
$order_ids
);
$cache_values = wc_cache_get_multiple( $cache_keys, 'orders' );
$cache_values = wc_cache_get_multiple( $cache_keys, 'orders' );
$non_cached_ids = array();
foreach ( $order_ids as $order_id ) {
if ( false === $cache_values[ 'order-items-' . $order_id ] ) {
@ -1019,9 +1115,9 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
return;
}
$non_cached_ids = esc_sql( $non_cached_ids );
$non_cached_ids = esc_sql( $non_cached_ids );
$non_cached_ids_string = implode( ',', $non_cached_ids );
$order_items = $wpdb->get_results(
$order_items = $wpdb->get_results(
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
"SELECT order_item_type, order_item_id, order_id, order_item_name FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id in ( $non_cached_ids_string ) ORDER BY order_item_id;"
);
@ -1068,7 +1164,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
foreach ( $order_ids as $order_id ) {
$cache_keys_mapping[ $order_id ] = WC_Order::generate_meta_cache_key( $order_id, 'orders' );
}
$cache_values = wc_cache_get_multiple( array_values( $cache_keys_mapping ), 'orders' );
$cache_values = wc_cache_get_multiple( array_values( $cache_keys_mapping ), 'orders' );
$non_cached_ids = array();
foreach ( $order_ids as $order_id ) {
if ( false === $cache_values[ $cache_keys_mapping[ $order_id ] ] ) {
@ -1078,8 +1174,8 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
if ( empty( $non_cached_ids ) ) {
return;
}
$order_ids = esc_sql( $non_cached_ids );
$order_ids_in = "'" . implode( "', '", $order_ids ) . "'";
$order_ids = esc_sql( $non_cached_ids );
$order_ids_in = "'" . implode( "', '", $order_ids ) . "'";
$raw_meta_data_array = $wpdb->get_results(
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
"SELECT post_id as object_id, meta_id, meta_key, meta_value

View File

@ -24,32 +24,6 @@ class MigrationHelper {
'bool' => '%d',
);
/**
* Get insert clause for appropriate switch.
*
* @param string $switch Name of the switch to use.
*
* @return string Insert clause.
*/
public static function get_insert_switch( string $switch ): string {
switch ( $switch ) {
case 'insert_ignore':
$insert_query = 'INSERT IGNORE';
break;
case 'replace': // delete and then insert.
$insert_query = 'REPLACE';
break;
case 'update':
$insert_query = 'UPDATE';
break;
case 'insert':
default:
$insert_query = 'INSERT';
}
return $insert_query;
}
/**
* Helper method to escape backtick in various schema fields.
*

View File

@ -265,18 +265,30 @@ class OrdersTableDataStore extends \Abstract_WC_Order_Data_Store_CPT implements
'type' => 'string',
'name' => 'prices_include_tax',
),
'coupon_usages_are_counted' => array( 'type' => 'bool' ),
'download_permission_granted' => array( 'type' => 'bool' ),
'coupon_usages_are_counted' => array(
'type' => 'bool',
'name' => 'recorded_coupon_usage_counts',
),
'download_permission_granted' => array(
'type' => 'bool',
'name' => 'download_permissions_granted',
),
'cart_hash' => array(
'type' => 'string',
'name' => 'cart_hash',
),
'new_order_email_sent' => array( 'type' => 'string' ),
'new_order_email_sent' => array(
'type' => 'string',
'name' => 'new_order_email_sent',
),
'order_key' => array(
'type' => 'string',
'name' => 'order_key',
),
'order_stock_reduced' => array( 'type' => 'bool' ),
'order_stock_reduced' => array(
'type' => 'bool',
'name' => 'stock_reduced',
),
'date_paid_gmt' => array(
'type' => 'date',
'name' => 'date_paid',
@ -329,6 +341,162 @@ class OrdersTableDataStore extends \Abstract_WC_Order_Data_Store_CPT implements
return $this->all_order_column_mapping;
}
/**
* Backfills order details in to WP_Post DB. Uses WC_Order_Data_store_CPT.
*
* @param \WC_Order $order Order object to backfill.
*/
public function backfill_post_record( $order ) {
$cpt_data_store = new \WC_Order_Data_Store_CPT();
$cpt_data_store->update_order_from_object( $order );
foreach ( $cpt_data_store->get_internal_data_store_key_getters() as $key => $getter_name ) {
if (
is_callable( array( $cpt_data_store, "set_$getter_name" ) ) &&
is_callable( array( $this, "get_$getter_name" ) )
) {
call_user_func_array(
array(
$cpt_data_store,
"set_$getter_name",
),
array(
$order,
$this->{"get_$getter_name"}( $order ),
)
);
}
}
}
/**
* Get information about whether permissions are granted yet.
*
* @param \WC_Order $order Order object.
*
* @return bool Whether permissions are granted.
*/
public function get_download_permissions_granted( $order ) {
return wc_string_to_bool( $order->get_meta( '_download_permissions_granted', true ) );
}
/**
* Stores information about whether permissions were generated yet.
*
* @param \WC_Order $order Order ID or order object.
* @param bool $set True or false.
*/
public function set_download_permissions_granted( $order, $set ) {
return $order->update_meta_data( '_download_permissions_granted', wc_bool_to_string( $set ) );
}
/**
* Gets information about whether sales were recorded.
*
* @param \WC_Order $order Order object.
*
* @return bool Whether sales are recorded.
*/
public function get_recorded_sales( $order ) {
return wc_string_to_bool( $order->get_meta( '_recorded_sales', true ) );
}
/**
* Stores information about whether sales were recorded.
*
* @param \WC_Order $order Order object.
* @param bool $set True or false.
*/
public function set_recorded_sales( $order, $set ) {
return $order->update_meta_data( '_recorded_sales', wc_bool_to_string( $set ) );
}
/**
* Gets information about whether coupon counts were updated.
*
* @param \WC_Order $order Order object.
*
* @return bool Whether coupon counts were updated.
*/
public function get_recorded_coupon_usage_counts( $order ) {
return wc_string_to_bool( $order->get_meta( '_recorded_coupon_usage_counts', true ) );
}
/**
* Stores information about whether coupon counts were updated.
*
* @param \WC_Order $order Order object.
* @param bool $set True or false.
*/
public function set_recorded_coupon_usage_counts( $order, $set ) {
return $order->update_meta_data( '_recorded_coupon_usage_counts', wc_bool_to_string( $set ) );
}
/**
* Whether email have been sent for this order.
*
* @param \WC_Order|int $order Order object.
*
* @return bool Whether email is sent.
*/
public function get_email_sent( $order ) {
return wc_string_to_bool( $order->get_meta( '_new_order_email_sent', true ) );
}
/**
* Stores information about whether email was sent.
*
* @param \WC_Order $order Order object.
*
* @param bool $set True or false.
*/
public function set_email_sent( $order, $set ) {
return $order->update_meta_data( '_new_order_email_sent', wc_string_to_bool( $set ) );
}
/**
* Helper setter for email_sent.
*
* @param \WC_Order $order Order object.
*
* @return bool Whether email was sent.
*/
private function get_new_order_email_sent( $order ) {
return $this->get_email_sent( $order );
}
/**
* Helper setter for new order email sent.
*
* @param \WC_Order $order Order object.
* @param bool $set True or false.
*
* @return bool Whether email was sent.
*/
private function set_new_order_email_sent( $order, $set ) {
return $this->set_email_sent( $order, $set );
}
/**
* Gets information about whether stock was reduced.
*
* @param \WC_Order $order Order object.
*
* @return bool Whether stock was reduced.
*/
public function get_stock_reduced( $order ) {
return wc_string_to_bool( $order->get_meta( '_order_stock_reduced', true ) );
}
/**
* Stores information about whether stock was reduced.
*
* @param \WC_Order $order Order ID or order object.
* @param bool $set True or false.
*/
public function set_stock_reduced( $order, $set ) {
return $order->update_meta_data( '_order_stock_reduced', wc_string_to_bool( $set ) );
}
//phpcs:disable Squiz.Commenting, Generic.Commenting
// TODO: Add methods for other table names as appropriate.
@ -372,33 +540,6 @@ class OrdersTableDataStore extends \Abstract_WC_Order_Data_Store_CPT implements
return array();
}
public function get_download_permissions_granted( $order ) {
// TODO: Implement get_download_permissions_granted() method.
false;
}
public function set_download_permissions_granted( $order, $set ) {
// TODO: Implement set_download_permissions_granted() method.
}
public function get_recorded_sales( $order ) {
// TODO: Implement get_recorded_sales() method.
return false;
}
public function set_recorded_sales( $order, $set ) {
// TODO: Implement set_recorded_sales() method.
}
public function get_recorded_coupon_usage_counts( $order ) {
// TODO: Implement get_recorded_coupon_usage_counts() method.
return false;
}
public function set_recorded_coupon_usage_counts( $order, $set ) {
// TODO: Implement set_recorded_coupon_usage_counts() method.
}
public function get_order_type( $order_id ) {
// TODO: Implement get_order_type() method.
return 'shop_order';
@ -418,6 +559,10 @@ class OrdersTableDataStore extends \Abstract_WC_Order_Data_Store_CPT implements
if ( ! $order->get_id() ) {
throw new \Exception( __( 'ID must be set for an order to be read', 'woocommerce' ) );
}
$meta_data = $this->read_meta( $order );
foreach ( $meta_data as $row ) {
$order->add_meta_data( $row->meta_key, $row->meta_value, false );
}
$order_data = $this->get_order_data_for_id( $order->get_id() );
foreach ( $this->get_all_order_column_mappings() as $table_name => $column_mapping ) {
foreach ( $column_mapping as $column_name => $prop_details ) {
@ -427,6 +572,8 @@ class OrdersTableDataStore extends \Abstract_WC_Order_Data_Store_CPT implements
$prop_setter_function_name = "set_{$prop_details['name']}";
if ( is_callable( array( $order, $prop_setter_function_name ) ) ) {
$order->{$prop_setter_function_name}( $order_data->{$prop_details['name']} );
} elseif ( is_callable( array( $this, $prop_setter_function_name ) ) ) {
$this->{$prop_setter_function_name}( $order, $order_data->{$prop_details['name']} );
}
}
}
@ -434,6 +581,33 @@ class OrdersTableDataStore extends \Abstract_WC_Order_Data_Store_CPT implements
$order->set_object_read();
}
/**
* Read metadata directly from database.
*
* @param \WC_Order $order Order object.
*
* @return array Metadata array.
*/
public function read_meta( &$order ) {
global $wpdb;
$meta_table = $this::get_meta_table_name();
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- $meta_table is hardcoded.
$raw_meta_data = $wpdb->get_results(
$wpdb->prepare(
"
SELECT id, meta_key, meta_value
FROM $meta_table
WHERE order_id = %d
ORDER BY id;
",
$order->get_id()
)
);
// phpcs:enable
return $this->filter_raw_meta_data( $order, $raw_meta_data );
}
/**
* Return order data for a single order ID.
*
@ -537,6 +711,7 @@ LEFT JOIN {$operational_data_clauses['join']}
"{$clauses['join']} AND $address_table_alias.address_type = %s",
$address_type
);
// phpcs:enable
return array(
'select' => $clauses['select'],
@ -603,6 +778,7 @@ LEFT JOIN {$operational_data_clauses['join']}
//phpcs:disable Squiz.Commenting, Generic.Commenting
/**
* @param \WC_Order $order
*/
@ -630,14 +806,6 @@ LEFT JOIN {$operational_data_clauses['join']}
throw new \Exception( 'Unimplemented' );
}
public function get_stock_reduced( $order ) {
return false;
}
public function set_stock_reduced( $order, $set ) {
throw new \Exception( 'Unimplemented' );
}
public function query( $query_vars ) {
return array();
}