1

WooCommerce 3.0 broke my app and I cannot figure out how to fix it now.

I have an action for when a subscription is added/changed running here:

Inside the function I was getting the order details and finding the line item for a variable subscription to update my custom DB with the option as well as getting custom order meta that I added via woocommerce_form_field:

This no longer works and everything appears protected? How can I update this to work with 3.0?

add_action( 'woocommerce_subscription_status_changed', 'update_subscription', 10, 3 );
function update_subscription( $id, $old_status, $new_status ) {

    $sitelink_db            = new SSLA_DB_Sitelink();
    $order                  = new WC_Order( $id );
    $items                  = $order->get_items();
    $subscription_type  = '';
    $user_id                = $order->get_user_id();
    $sitelink_domain        = get_post_meta( $order->id, 'ssla_sitelink_url', true );

    foreach ($items as $item) {

        if( "SiteLink Subscription" === $item['name'] ) {
            $subscription_type = $item['brand'];
        }

    }

    $customer_data = array(
        'user_id'               => $user_id,
        'subscription_type'     => $subscription_type,
        'domain_referrer'       => $sitelink_domain,
        'active_subscription'   => $new_status,
        'date_modified'         => date( 'Y-m-d H:i:s' ),
        );

    $sitelink_db->add( $customer_data );

}

Basically I need to get that variation name of the subscription to store in my DB, as well as that custom meta field I made. Which does not work anymore either

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
thatryan
  • 1,551
  • 6
  • 21
  • 39
  • The arrays are supposed to be back compatible, but now `get_items()` returns an array of `WC_Order_Item` objects, so you need to use the getter methods to get info. I *think* it gets the order item products by default so the class is probably `WC_Order_Item_Product` which extends `WC_Order_Item`.Take a look at the getters [here](https://github.com/woocommerce/woocommerce/blob/master/includes/class-wc-order-item-product.php#L207) and [here](https://github.com/woocommerce/woocommerce/blob/master/includes/class-wc-order-item.php#L73) – helgatheviking Apr 20 '17 at 18:07
  • I don't recall `brand` ever being an order item array key so that could be part of the problem. You should turn on `WP_DEBUG_LOG` so you can see what is going on. – helgatheviking Apr 20 '17 at 18:09
  • The brand is a custom variation I have in the variable product – thatryan Apr 20 '17 at 18:17
  • updated with full function – thatryan Apr 20 '17 at 18:41
  • Yes, the whole function is much better. `$item` is now the `WC_Order_Item_Product` object and if I had to guess never supported a "brand" key. So brand is a variation attribute? – helgatheviking Apr 20 '17 at 19:18

1 Answers1

1

Here's my best guess. It's impossible to test since I don't have the same setup as you.

Few notes:

  1. The $subscription object is passed to the woocommerce_subscription_status_changed hook so let's use it.
  2. $order->id should be replaced by $order->get_id() in WC3.0, but we're going to use the the $subscription object (the subscription order class extends the order class so it's similar).
  3. getters must be used on the WC_Order_Item_Product object that is returned when looping through get_items() so $item['name'] becomes $item->get_name()

Here's the full code block:

add_action( 'woocommerce_subscription_status_changed', 'update_subscription', 10, 4 );
function update_subscription( $subscription_id, $old_status, $new_status, $subscription ) {

    $match_this_id = 99; // Change this to the product ID of your special subscription

    $sitelink_db            = new SSLA_DB_Sitelink();

    $items                  = $subscription->get_items();
    $subscription_type  = '';
    $user_id                = $subscription->get_user_id();
    $sitelink_domain        = $subscription->get_meta( 'ssla_sitelink_url' );

    foreach ($items as $item) {

        if( $match_this_id === $item->get_product_id() ) {
            $product = $item->get_product();
            if( $product->is_type( 'variation' ) ){
                $subscription_type = $product->get_attribute( 'brand' );
            }
        }

    }

    $customer_data = array(
        'user_id'               => $user_id,
        'subscription_type'     => $subscription_type,
        'domain_referrer'       => $sitelink_domain,
        'active_subscription'   => $new_status,
        'date_modified'         => date( 'Y-m-d H:i:s' ),
        );

    $sitelink_db->add( $customer_data );

}
helgatheviking
  • 25,596
  • 11
  • 95
  • 152
  • Thank you, this is really helpful understanding the different approach needed. How do you know what methods are available, where you used get_name() for example, is there a "get_title()" maybe? Looks like variations choices are now made part of the "name" so not reliable. – thatryan Apr 20 '17 at 23:42
  • 1
    In that case, I would suggest using [`$item->get_product_id()`](https://github.com/woocommerce/woocommerce/blob/master/includes/class-wc-order-item-product.php#L226) and using the product ID as your conditional. You know what methods are available by reading the documentation and/or the code itself, which I'll admit is a lot less transparent than being able to `var_dump()` a variable. – helgatheviking Apr 21 '17 at 00:19
  • Thanks I did wind up using product ID! I found it but yeah the docs are tough on me heh. – thatryan Apr 21 '17 at 00:48
  • Hey @helgatheviking Any chance you could check out my other question on why I cant figure out meta either now in 3.0? http://stackoverflow.com/questions/43532208/add-custom-meta-to-order-woocommerce :) thank you much. – thatryan Apr 21 '17 at 01:02