get_blog_prefix() . 'woocommerce_subscriptions'; $order_items_table = $wpdb->get_blog_prefix() . 'woocommerce_order_items'; $order_item_meta_table = $wpdb->get_blog_prefix() . 'woocommerce_order_itemmeta'; // Get the IDs of all users who have a subscription $users_to_upgrade = get_users( array( 'meta_key' => $subscriptions_meta_key, 'fields' => 'ID', 'orderby' => 'ID', ) ); $users_to_upgrade = array_filter( $users_to_upgrade, __CLASS__ . '::is_user_upgraded' ); foreach ( $users_to_upgrade as $user_to_upgrade ) { // Can't use WC_Subscriptions_Manager::get_users_subscriptions() because it relies on the new structure $users_old_subscriptions = get_user_option( $subscriptions_meta_key, $user_to_upgrade ); foreach ( $users_old_subscriptions as $subscription_key => $subscription ) { if ( ! isset( $subscription['order_id'] ) ) { // Subscription created incorrectly with v1.1.2 continue; } $order_item_id = WC_Subscriptions_Order::get_item_id_by_subscription_key( $subscription_key ); if ( empty( $order_item_id ) ) { // Subscription created incorrectly with v1.1.2 continue; } if ( ! isset( $subscription['trial_expiry_date'] ) ) { $subscription['trial_expiry_date'] = ''; } // Set defaults $failed_payments = isset( $subscription['failed_payments'] ) ? $subscription['failed_payments'] : 0; $completed_payments = isset( $subscription['completed_payments'] ) ? $subscription['completed_payments'] : array(); $suspension_count = isset( $subscription['suspension_count'] ) ? $subscription['suspension_count'] : 0; $trial_expiry_date = isset( $subscription['trial_expiry_date'] ) ? $subscription['trial_expiry_date'] : ''; $wpdb->query( $wpdb->prepare( "INSERT INTO $order_item_meta_table (order_item_id, meta_key, meta_value) VALUES (%d,%s,%s), (%d,%s,%s), (%d,%s,%s), (%d,%s,%s), (%d,%s,%s), (%d,%s,%s), (%d,%s,%s), (%d,%s,%s)", $order_item_id, '_subscription_status', $subscription['status'], $order_item_id, '_subscription_start_date', $subscription['start_date'], $order_item_id, '_subscription_expiry_date', $subscription['expiry_date'], $order_item_id, '_subscription_end_date', $subscription['end_date'], $order_item_id, '_subscription_trial_expiry_date', $trial_expiry_date, $order_item_id, '_subscription_failed_payments', $failed_payments, $order_item_id, '_subscription_completed_payments', serialize( $completed_payments ), $order_item_id, '_subscription_suspension_count', $suspension_count ) ); } update_option( 'wcs_1_4_last_upgraded_user_id', $user_to_upgrade ); self::$last_upgraded_user_id = $user_to_upgrade; } // Add an underscore prefix to usermeta key to deprecate, but not delete, subscriptions in user meta $wpdb->update( $wpdb->usermeta, array( 'meta_key' => '_' . $subscriptions_meta_key ), array( 'meta_key' => $subscriptions_meta_key ) ); // Now set the recurring shipping & payment method on all subscription orders $wpdb->query( "INSERT INTO $wpdb->postmeta (`post_id`, `meta_key`, `meta_value`) SELECT `post_id`, CONCAT('_recurring',`meta_key`), `meta_value` FROM $wpdb->postmeta WHERE `meta_key` IN ('_shipping_method','_shipping_method_title','_payment_method','_payment_method_title') AND `post_id` IN ( SELECT `post_id` FROM $wpdb->postmeta WHERE `meta_key` = '_order_recurring_total' )" ); // Set the recurring shipping total on all subscription orders $wpdb->query( "INSERT INTO $wpdb->postmeta (`post_id`, `meta_key`, `meta_value`) SELECT `post_id`, '_order_recurring_shipping_total', `meta_value` FROM $wpdb->postmeta WHERE `meta_key` = '_order_shipping' AND `post_id` IN ( SELECT `post_id` FROM $wpdb->postmeta WHERE `meta_key` = '_order_recurring_total' )" ); // Get the ID of all orders for a subscription with a free trial and no sign-up fee $order_ids = $wpdb->get_col( "SELECT order_items.order_id FROM $order_items_table AS order_items LEFT JOIN $order_item_meta_table AS itemmeta USING (order_item_id) LEFT JOIN $order_item_meta_table AS itemmeta2 USING (order_item_id) WHERE itemmeta.meta_key = '_subscription_trial_length' AND itemmeta.meta_value > 0 AND itemmeta2.meta_key = '_subscription_sign_up_fee' AND itemmeta2.meta_value > 0" ); $order_ids = implode( ',', array_map( 'absint', array_unique( $order_ids ) ) ); // Now set the order totals to $0 (can't use $wpdb->update as it only allows joining WHERE clauses with AND) if ( ! empty( $order_ids ) ) { $wpdb->query( "UPDATE $wpdb->postmeta SET `meta_value` = 0 WHERE `meta_key` IN ( '_order_total', '_order_tax', '_order_shipping_tax', '_order_shipping', '_order_discount', '_cart_discount' ) AND `post_id` IN ( $order_ids )" ); // Now set the line totals to $0 $wpdb->query( "UPDATE $order_item_meta_table SET `meta_value` = 0 WHERE `meta_key` IN ( '_line_subtotal', '_line_subtotal_tax', '_line_total', '_line_tax', 'tax_amount', 'shipping_tax_amount' ) AND `order_item_id` IN ( SELECT `order_item_id` FROM $order_items_table WHERE `order_item_type` IN ('tax','line_item') AND `order_id` IN ( $order_ids ) )" ); } update_option( 'wcs_1_4_upgraded_order_ids', explode( ',', $order_ids ) ); } /** * Used to check if a user ID is greater than the last user upgraded to version 1.4. * * Needs to be a separate function so that it can use a static variable (and therefore avoid calling get_option() thousands * of times when iterating over thousands of users). * * @since 1.4 */ public static function is_user_upgraded( $user_id ) { if ( false === self::$last_upgraded_user_id ) { self::$last_upgraded_user_id = get_option( 'wcs_1_4_last_upgraded_user_id', 0 ); } return ( $user_id > self::$last_upgraded_user_id ) ? true : false; } } WCS_Upgrade_1_4::init();