WC 2.2 order statuses: plugin compatibility

Orders can have several statuses in WooCommerce; completed, processing, on-hold, pending to name a few.

In WooCommerce 2.1, statuses were associated with orders via a taxonomy called shop_order_status. The shop_order_status taxonomy is no more in 2.2.

Instead, 2.2 uses post_status for the order status. In terms of usage, this makes more sense – regular post statuses are of little use for orders (since when did you have a non-published order?). For performance, using post status has several benefits, particulary to queries and reporting which can now contain less table joins.

How does this affect developers? If you query shop_order posts via a get_posts() function, or DB query, you will need to modify your code to fully support 2.2. Otherwise you’ll either get a notice, or no results.

If you are calling get_posts() for the shop_order post type

Here is an example of a 2.1 order query:

$orders = get_posts( array(
        'post_type'   => 'shop_order',
        'post_status' => 'publish',
        'tax_query'   => array( array(
                'taxonomy' => 'shop_order_status',
                'field'           => 'slug',
                'terms'         => array( 'processing', 'completed' )
        ) )
) );

This query uses shop_order_status which will no longer work in 2.2 without throwing a notice. For 2.2 you’d change this to be:

$orders = get_posts( array(
        'post_type'   => 'shop_order',
        'post_status' => array( 'wc-processing', 'wc-completed' )
) );

If you wanted to get all orders, of any status, 2.2 has a function wc_get_order_statuses() which returns all registered order statuses:

$orders = get_posts( array(
        'post_type'   => 'shop_order',
        'post_status' => array_keys( wc_get_order_statuses() )
) );

If you are doing $wpdb queries on shop_order posts

Like above, you’ll need to change the taxonomy part of your query. Here is an example from 2.1:

$sales = $wpdb->get_var( "SELECT ID FROM {$wpdb->posts} as posts
            LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID=rel.object_ID
            LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
            LEFT JOIN {$wpdb->terms} AS term USING( term_id )
            WHERE   posts.post_type     = 'shop_order'
            AND     posts.post_status   = 'publish'
            AND     tax.taxonomy        = 'shop_order_status'
            AND     term.slug           IN ( '" . implode( "','", array( 'completed', 'processing', 'on-hold' ) ) . "' )
        " );

In 2.2, this becomes:

$sales = $wpdb->get_var( "SELECT ID FROM {$wpdb->posts} as posts
            WHERE   posts.post_type     = 'shop_order'
            AND     posts.post_status   IN ( '" . implode( "','", array( 'wc-completed', 'wc-processing', 'wc-on-hold' ) ) . "' )
        " );

Direct queries on the database will need to be updated, or no results will be returned.


7 responses to “WC 2.2 order statuses: plugin compatibility”

  1. Another use case that needs updating – using get_posts() without specifying a post_status.

    The default WP_Query value for post_status is ‘publish’, so when no post_status value is specified, WordPress will fall back to 'publish' and that’s not a valid order status.

  2. It would be nice to have a helper function to handle the list of new statuses. I assume they will change in the future or plugins will need to add custom ones in the future.

    A helper wc_order_statuses() or similar will make any future changes simpler.

    1. wc_get_order_statuses()

  3. David Woodthorpe Avatar
    David Woodthorpe

    Will the update automatically alter previous orders to use the new post status?

  4. David Villalpando Avatar
    David Villalpando

    Is it possible to translate this statuses with this new post_status usage? I can’t find where to do that.

  5. How the woocommerce_reports_order_statuses filter been changed to still allow developers to add custom order statuses? I noticed after upgrading a dev site that any added this way were no longer listed on orders. Is using WordPress’ register_post_status the only way forward to do this?

  6. I’m not quite a devoloper, but I was wondering how I could update the following function to be compatible with 2.2 (I would like to display the slug (like ‘Completed’, ‘Pending’, etc.):

    If (@$product_id_db->meta_value == $product_id) {
    $terms = wp_get_object_terms($order->post_id, ‘shop_order_status’, array(
    ‘fields’ => ‘names’));

    $order_status = isset($terms[0]) ? $terms[0] : ‘pending’;

Leave a Reply

Your email address will not be published. Required fields are marked *