/**
  * Creates group membership for the order.
  * @param int $order_id
  */
 public static function order_status_completed($order_id)
 {
     $unhandled = self::register_order($order_id);
     $order = new WC_Order();
     if ($order->get_order($order_id)) {
         if ($items = $order->get_items()) {
             if ($user_id = $order->user_id) {
                 // not much we can do if there isn't
                 foreach ($items as $item) {
                     if ($product = $order->get_product_from_item($item)) {
                         if ($product_groups = get_post_meta($product->id, '_groups_groups', false)) {
                             // don't act on subscriptions here
                             if (!class_exists('WC_Subscriptions_Product') || !WC_Subscriptions_Product::is_subscription($product->id)) {
                                 if (count($product_groups) > 0) {
                                     // add the groups to the user by order and product so that if the product is changed later on,
                                     // the data is still valid for what has been purchased
                                     $groups_product_groups = get_user_meta($user_id, '_groups_product_groups', true);
                                     if (empty($groups_product_groups)) {
                                         $groups_product_groups = array();
                                     }
                                     $groups_product_groups[$order_id][$product->id]['groups'] = $product_groups;
                                     update_user_meta($user_id, '_groups_product_groups', $groups_product_groups);
                                     global $groups_ws_product_with_duration;
                                     $groups_ws_product_with_duration = Groups_WS_Product::has_duration($product);
                                     // add the user to the groups
                                     foreach ($product_groups as $group_id) {
                                         $result = Groups_User_Group::create(array('user_id' => $user_id, 'group_id' => $group_id));
                                         if ($groups_ws_product_with_duration) {
                                             if ($unhandled) {
                                                 Groups_WS_Terminator::schedule_termination(time() + Groups_WS_Product::get_duration($product), $user_id, $group_id);
                                             }
                                         } else {
                                             Groups_WS_Terminator::mark_as_eternal($user_id, $group_id);
                                         }
                                     }
                                 }
                             }
                         }
                         // remove from groups
                         if ($product_groups_remove = get_post_meta($product->id, '_groups_groups_remove', false)) {
                             if (!class_exists('WC_Subscriptions_Product') || !WC_Subscriptions_Product::is_subscription($product->id)) {
                                 if (count($product_groups_remove) > 0) {
                                     $groups_product_groups_remove = get_user_meta($user_id, '_groups_product_groups_remove', true);
                                     if (empty($groups_product_groups_remove)) {
                                         $groups_product_groups_remove = array();
                                     }
                                     $groups_product_groups_remove[$order_id][$product->id]['groups'] = $product_groups_remove;
                                     update_user_meta($user_id, '_groups_product_groups_remove', $groups_product_groups_remove);
                                     // remove the user from the groups
                                     foreach ($product_groups_remove as $group_id) {
                                         $result = Groups_User_Group::delete($user_id, $group_id);
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
 }
 /**
  * Returns an array of order IDs for valid orders that grant group
  * membership for the given group to the user related to the order.
  * 
  * @param int $user_id
  * @param int $group_id
  * @return array of int, order IDs
  */
 public static function get_valid_order_ids_granting_group_membership_from_order_items($user_id, $group_id)
 {
     $order_ids = array();
     if (!empty($user_id)) {
         $base_statuses = array('processing', 'completed');
         $statuses = array('completed');
         $options = get_option('groups-woocommerce', array());
         $order_status = isset($options[GROUPS_WS_MEMBERSHIP_ORDER_STATUS]) ? $options[GROUPS_WS_MEMBERSHIP_ORDER_STATUS] : GROUPS_WS_DEFAULT_MEMBERSHIP_ORDER_STATUS;
         if ($order_status == 'processing') {
             $statuses[] = 'processing';
         }
         // DO NOT use groups_ws_order_status( $statuses ) for $statuses or $base_statuses here,
         // $order->status doesn't provide the wc- prefix.
         $groups_product_groups = get_user_meta($user_id, '_groups_product_groups', true);
         if (empty($groups_product_groups)) {
             $groups_product_groups = array();
         }
         foreach ($groups_product_groups as $order_id => $product_ids) {
             if ($order = Groups_WS_Helper::get_order($order_id)) {
                 // If this is a completed/processing order, consider group assignments.
                 // We check the order status for non-subscription products below,
                 // for subscriptions the subscription status is checked.
                 if (in_array($order->status, $base_statuses)) {
                     // Note that for orders placed with versions up to 1.4.1, the following won't give the results we might expect if the product group-related information has changed since the order was placed.
                     // As we don't store that information (WC doesn't store the whole lot of the product when purchased, nor does GW) checking the duration based on the product is the best effort at
                     // finding out about the group membership duration we can make.
                     // Use the order items (only existing order items are taken into account).
                     if ($items = $order->get_items()) {
                         foreach ($items as $item) {
                             if ($product = $order->get_product_from_item($item)) {
                                 // Use the groups that were stored for the product when it was ordered,
                                 // this avoids hickups when the product's groups were changed since.
                                 if (isset($product_ids[$product->id]) && isset($product_ids[$product->id]['groups'])) {
                                     $product_groups = $product_ids[$product->id]['groups'];
                                     if (in_array($group_id, $product_groups)) {
                                         // non-subscriptions
                                         if (!class_exists('WC_Subscriptions_Product') || !WC_Subscriptions_Product::is_subscription($product->id)) {
                                             if (in_array($order->status, $statuses)) {
                                                 if (isset($product_ids[$product->id]) && isset($product_ids[$product->id]['version'])) {
                                                     $has_duration = isset($product_ids[$product->id]['duration']) && $product_ids[$product->id]['duration'] && isset($product_ids[$product->id]['duration_uom']);
                                                 } else {
                                                     $has_duration = Groups_WS_Product::has_duration($product);
                                                 }
                                                 // unlimited membership
                                                 if (!$has_duration) {
                                                     if (!in_array($order_id, $order_ids)) {
                                                         $order_ids[] = $order_id;
                                                     }
                                                 } else {
                                                     if (isset($product_ids[$product->id]) && isset($product_ids[$product->id]['version'])) {
                                                         $duration = Groups_WS_Product::calculate_duration($product_ids[$product->id]['duration'], $product_ids[$product->id]['duration_uom']);
                                                     } else {
                                                         // <= 1.4.1
                                                         $duration = Groups_WS_Product::get_duration($product);
                                                     }
                                                     // time-limited membership
                                                     if ($duration) {
                                                         $start_date = $order->order_date;
                                                         if ($paid_date = get_post_meta($order_id, '_paid_date', true)) {
                                                             $start_date = $paid_date;
                                                         }
                                                         $end = strtotime($start_date) + $duration;
                                                         if (time() < $end) {
                                                             if (!in_array($order_id, $order_ids)) {
                                                                 $order_ids[] = $order_id;
                                                             }
                                                         }
                                                     }
                                                 }
                                             }
                                         } else {
                                             // include active subscriptions ( subscriptions >= 2.x )
                                             if (function_exists('wcs_get_subscriptions_for_order')) {
                                                 if ($subscriptions = wcs_get_subscriptions_for_order($order_id)) {
                                                     if (is_array($subscriptions)) {
                                                         foreach ($subscriptions as $subscription) {
                                                             if ($subscription->has_product($product->id)) {
                                                                 $valid = false;
                                                                 if ($subscription->get_status() == 'active') {
                                                                     $valid = true;
                                                                 } else {
                                                                     if ($subscription->get_status() == 'cancelled') {
                                                                         $hook_args = array('subscription_id' => $subscription->id);
                                                                         $end_timestamp = wp_next_scheduled('scheduled_subscription_end_of_prepaid_term', $hook_args);
                                                                         if ($end_timestamp !== false && $end_timestamp > time()) {
                                                                             $valid = true;
                                                                         }
                                                                     }
                                                                 }
                                                                 if ($valid) {
                                                                     if (!in_array($order_id, $order_ids)) {
                                                                         $order_ids[] = $order_id;
                                                                         break;
                                                                     }
                                                                 }
                                                             }
                                                         }
                                                     }
                                                 }
                                             } else {
                                                 $subscription_key = WC_Subscriptions_Manager::get_subscription_key($order_id, $product->id);
                                                 $subscription = WC_Subscriptions_Manager::get_subscription($subscription_key);
                                                 if (isset($subscription['status'])) {
                                                     $valid = false;
                                                     if ($subscription['status'] == 'active') {
                                                         $valid = true;
                                                     } else {
                                                         if ($subscription['status'] == 'cancelled') {
                                                             $hook_args = array('user_id' => (int) $user_id, 'subscription_key' => $subscription_key);
                                                             $end_timestamp = wp_next_scheduled('scheduled_subscription_end_of_prepaid_term', $hook_args);
                                                             if ($end_timestamp !== false && $end_timestamp > time()) {
                                                                 $valid = true;
                                                             }
                                                         }
                                                     }
                                                     if ($valid) {
                                                         if (!in_array($order_id, $order_ids)) {
                                                             $order_ids[] = $order_id;
                                                         }
                                                     }
                                                 }
                                             }
                                         }
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
     return $order_ids;
 }