new WC_Shipping_Flat_Rate(), 'woocommerce_international_delivery_flat_rates' => new WC_Shipping_International_Delivery() ); foreach ( $shipping_methods as $flat_rate_option_key => $shipping_method ) { // Stop this running more than once if routine is repeated if ( version_compare( $shipping_method->get_option( 'version', 0 ), '2.4.0', '<' ) ) { $has_classes = sizeof( WC()->shipping->get_shipping_classes() ) > 0; $cost_key = $has_classes ? 'no_class_cost' : 'cost'; $min_fee = $shipping_method->get_option( 'minimum_fee' ); $math_cost_strings = array( 'cost' => array(), 'no_class_cost' => array() ); $math_cost_strings[ $cost_key ][] = $shipping_method->get_option( 'cost' ); if ( $fee = $shipping_method->get_option( 'fee' ) ) { $math_cost_strings[ $cost_key ][] = strstr( $fee, '%' ) ? '[fee percent="' . str_replace( '%', '', $fee ) . '" min="' . esc_attr( $min_fee ) . '"]' : $fee; } foreach ( WC()->shipping->get_shipping_classes() as $shipping_class ) { $rate_key = 'class_cost_' . $shipping_class->slug; $math_cost_strings[ $rate_key ] = $math_cost_strings[ 'no_class_cost' ]; } if ( $flat_rates = array_filter( (array) get_option( $flat_rate_option_key, array() ) ) ) { foreach ( $flat_rates as $shipping_class => $rate ) { $rate_key = 'class_cost_' . $shipping_class; if ( $rate['cost'] || $rate['fee'] ) { $math_cost_strings[ $rate_key ][] = $rate['cost']; $math_cost_strings[ $rate_key ][] = strstr( $rate['fee'], '%' ) ? '[fee percent="' . str_replace( '%', '', $rate['fee'] ) . '" min="' . esc_attr( $min_fee ) . '"]' : $rate['fee']; } } } if ( 'item' === $shipping_method->type ) { foreach ( $math_cost_strings as $key => $math_cost_string ) { $math_cost_strings[ $key ] = array_filter( array_map( 'trim', $math_cost_strings[ $key ] ) ); if ( ! empty( $math_cost_strings[ $key ] ) ) { $last_key = max( 0, sizeof( $math_cost_strings[ $key ] ) - 1 ); $math_cost_strings[ $key ][0] = '( ' . $math_cost_strings[ $key ][0]; $math_cost_strings[ $key ][ $last_key ] .= ' ) * [qty]'; } } } $math_cost_strings[ 'cost' ][] = $shipping_method->get_option( 'cost_per_order' ); // Save settings foreach ( $math_cost_strings as $option_id => $math_cost_string ) { $shipping_method->settings[ $option_id ] = implode( ' + ', array_filter( $math_cost_string ) ); } $shipping_method->settings['version'] = '2.4.0'; $shipping_method->settings['type'] = 'item' === $shipping_method->settings['type'] ? 'class' : $shipping_method->settings['type']; update_option( $shipping_method->plugin_id . $shipping_method->id . '_settings', $shipping_method->settings ); } } /** * Update the old user API keys to the new Apps keys. */ $api_users = $wpdb->get_results( "SELECT user_id FROM $wpdb->usermeta WHERE meta_key = 'woocommerce_api_consumer_key'" ); $apps_keys = array(); // Get user data foreach ( $api_users as $_user ) { $user = get_userdata( $_user->user_id ); $apps_keys[] = array( 'user_id' => $user->ID, 'permissions' => $user->woocommerce_api_key_permissions, 'consumer_key' => wc_api_hash( $user->woocommerce_api_consumer_key ), 'consumer_secret' => $user->woocommerce_api_consumer_secret, 'truncated_key' => substr( $user->woocommerce_api_consumer_secret, -7 ) ); } if ( ! empty( $apps_keys ) ) { // Create new apps foreach ( $apps_keys as $app ) { $wpdb->insert( $wpdb->prefix . 'woocommerce_api_keys', $app, array( '%d', '%s', '%s', '%s', '%s' ) ); } // Delete old user keys from usermeta foreach ( $api_users as $_user ) { $user_id = intval( $_user->user_id ); delete_user_meta( $user_id, 'woocommerce_api_consumer_key' ); delete_user_meta( $user_id, 'woocommerce_api_consumer_secret' ); delete_user_meta( $user_id, 'woocommerce_api_key_permissions' ); } } /** * Webhooks. * Make sure order.update webhooks get the woocommerce_order_edit_status hook. */ $order_update_webhooks = get_posts( array( 'posts_per_page' => -1, 'post_type' => 'shop_webhook', 'meta_key' => '_topic', 'meta_value' => 'order.updated' ) ); foreach ( $order_update_webhooks as $order_update_webhook ) { $webhook = new WC_Webhook( $order_update_webhook->ID ); $webhook->set_topic( 'order.updated' ); } /** * Refunds for full refunded orders. * Update fully refunded orders to ensure they have a refund line item so reports add up. */ $refunded_orders = get_posts( array( 'posts_per_page' => -1, 'post_type' => 'shop_order', 'post_status' => array( 'wc-refunded' ) ) ); // Ensure emails are disabled during this update routine remove_all_actions( 'woocommerce_order_status_refunded_notification' ); remove_all_actions( 'woocommerce_order_partially_refunded_notification' ); remove_action( 'woocommerce_order_status_refunded', array( 'WC_Emails', 'send_transactional_email' ) ); remove_action( 'woocommerce_order_partially_refunded', array( 'WC_Emails', 'send_transactional_email' ) ); foreach ( $refunded_orders as $refunded_order ) { $order_total = get_post_meta( $refunded_order->ID, '_order_total', true ); $refunded_total = $wpdb->get_var( $wpdb->prepare( " SELECT SUM( postmeta.meta_value ) FROM $wpdb->postmeta AS postmeta INNER JOIN $wpdb->posts AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d ) WHERE postmeta.meta_key = '_refund_amount' AND postmeta.post_id = posts.ID ", $refunded_order->ID ) ); if ( $order_total > $refunded_total ) { $refund = wc_create_refund( array( 'amount' => $order_total - $refunded_total, 'reason' => __( 'Order Fully Refunded', 'woocommerce' ), 'order_id' => $refunded_order->ID, 'line_items' => array(), 'date' => $refunded_order->post_modified ) ); } } wc_delete_shop_order_transients();