/**
  * Register groups for a product.
  * @param int $post_id product ID
  * @param object $post product
  */
 public static function process_product_meta($post_id, $post)
 {
     global $wpdb;
     $is_subscription = class_exists('WC_Subscriptions_Product') && WC_Subscriptions_Product::is_subscription($post_id);
     $is_external = false;
     if ($product = groups_ws_get_product($post_id)) {
         $is_external = $product->is_type('external');
         unset($product);
     }
     // refresh groups, clear all, then assign checked
     delete_post_meta($post_id, '_groups_groups');
     delete_post_meta($post_id, '_groups_groups_remove');
     // set group assignments for supported product types
     if (!$is_external) {
         if (!empty($_POST['_groups_groups']) && is_array($_POST['_groups_groups'])) {
             foreach ($_POST['_groups_groups'] as $group_id) {
                 if ($group = Groups_Group::read($group_id)) {
                     add_post_meta($post_id, '_groups_groups', $group->group_id);
                 }
             }
         }
         if (!empty($_POST['_groups_groups_remove']) && is_array($_POST['_groups_groups_remove'])) {
             foreach ($_POST['_groups_groups_remove'] as $group_id) {
                 if ($group = Groups_Group::read($group_id)) {
                     add_post_meta($post_id, '_groups_groups_remove', $group->group_id);
                 }
             }
         }
     }
     // duration
     delete_post_meta($post_id, '_groups_duration');
     delete_post_meta($post_id, '_groups_duration_uom');
     // store duration settings for supported product types
     if (!$is_external && !$is_subscription) {
         $duration = !empty($_POST['_groups_duration']) ? intval($_POST['_groups_duration']) : null;
         if ($duration <= 0) {
             $duration = null;
         }
         if ($duration !== null) {
             $duration_uom = !empty($_POST['_groups_duration_uom']) ? $_POST['_groups_duration_uom'] : null;
             switch ($duration_uom) {
                 case 'second':
                 case 'minute':
                 case 'hour':
                 case 'day':
                 case 'week':
                 case 'year':
                     break;
                 default:
                     $duration_uom = 'month';
             }
             add_post_meta($post_id, '_groups_duration', $duration);
             add_post_meta($post_id, '_groups_duration_uom', $duration_uom);
         }
     }
     // variations
     $variation_post_ids = isset($_POST['variable_post_id']) ? $_POST['variable_post_id'] : null;
     if ($variation_post_ids !== null && is_array($variation_post_ids)) {
         foreach ($variation_post_ids as $variation_post_id) {
             $variation_post_id = intval($variation_post_id);
             delete_post_meta($variation_post_id, '_groups_variation_groups');
             delete_post_meta($variation_post_id, '_groups_variation_groups_remove');
             if (!empty($_POST['_groups_variation_groups']) && is_array($_POST['_groups_variation_groups'])) {
                 if (!empty($_POST['_groups_variation_groups'][$variation_post_id]) && is_array($_POST['_groups_variation_groups'][$variation_post_id])) {
                     foreach ($_POST['_groups_variation_groups'][$variation_post_id] as $group_id) {
                         if ($group = Groups_Group::read($group_id)) {
                             add_post_meta($variation_post_id, '_groups_variation_groups', $group->group_id);
                         }
                     }
                 }
             }
             if (!empty($_POST['_groups_variation_groups_remove']) && is_array($_POST['_groups_variation_groups_remove'])) {
                 if (!empty($_POST['_groups_variation_groups_remove'][$variation_post_id]) && is_array($_POST['_groups_variation_groups_remove'][$variation_post_id])) {
                     foreach ($_POST['_groups_variation_groups_remove'][$variation_post_id] as $group_id) {
                         if ($group = Groups_Group::read($group_id)) {
                             add_post_meta($variation_post_id, '_groups_variation_groups_remove', $group->group_id);
                         }
                     }
                 }
             }
         }
     }
 }
 /**
  * Handle group assignment : assign the user to the groups related to the subscription's product.
  * @param int $user_id
  * @param string $subscription_key
  */
 public static function activated_subscription($user_id, $subscription_key)
 {
     $subscription = self::get_subscription_by_subscription_key($subscription_key);
     if (isset($subscription['product_id']) && isset($subscription['order_id'])) {
         $product_id = $subscription['product_id'];
         $order_id = $subscription['order_id'];
         // Leasving this here for reference, it can be assumed that normally,
         // if the product's groups are modified, a reactivation should take its
         // data from the current product, not from its previous state.
         // See if the subscription was activated before and try to get subscription's groups.
         // If there are any, use these instead of those from the product.
         // This is necessary when a subscription has been cancelled and re-activated and the
         // original product groups were modified since and we do NOT want to make group
         // assignments based on the current state of the product.
         $done = false;
         //$groups_product_groups = get_user_meta( $user_id, '_groups_product_groups', true );
         //if ( isset( $groups_product_groups[$order_id] ) && isset( $groups_product_groups[$order_id][$product_id] ) &&
         //	 isset( $groups_product_groups[$order_id][$product_id]['groups'] ) &&
         //	 isset( $groups_product_groups[$order_id][$product_id]['subscription_key'] ) &&
         //	( $groups_product_groups[$order_id][$product_id]['subscription_key'] === $subscription_key )
         //) {
         //	foreach( $groups_product_groups[$order_id][$product_id]['groups'] as $group_id ) {
         //		Groups_User_Group::create( $user_id, $group_id );
         //	}
         //	$done = true;
         //}
         // maybe unschedule pending expiration
         wp_clear_scheduled_hook('groups_ws_subscription_expired', array('user_id' => $user_id, 'subscription_key' => $subscription_key));
         if (!$done) {
             // get the product from the subscription
             $product = groups_ws_get_product($product_id);
             if ($product->exists()) {
                 // get the groups related to the product
                 $product_groups = get_post_meta($product_id, '_groups_groups', false);
                 if (isset($subscription['variation_id'])) {
                     if ($variation_product_groups = get_post_meta($subscription['variation_id'], '_groups_variation_groups', false)) {
                         $product_groups = array_merge($product_groups, $variation_product_groups);
                     }
                 }
                 if ($product_groups) {
                     if (count($product_groups) > 0) {
                         // add the groups to the subscription (in case the product is changed later on, the subscription is still valid)
                         $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]['version'] = GROUPS_WS_VERSION;
                         $groups_product_groups[$order_id][$product_id]['start'] = time();
                         $groups_product_groups[$order_id][$product_id]['groups'] = $product_groups;
                         $groups_product_groups[$order_id][$product_id]['subscription_key'] = $subscription_key;
                         update_user_meta($user_id, '_groups_product_groups', $groups_product_groups);
                         // add the user to the groups
                         foreach ($product_groups as $group_id) {
                             Groups_User_Group::create(array('user_id' => $user_id, 'group_id' => $group_id));
                         }
                         Groups_WS_Terminator::mark_as_eternal($user_id, $group_id);
                     }
                 }
                 // remove from groups
                 $product_groups_remove = get_post_meta($product_id, '_groups_groups_remove', false);
                 if (isset($subscription['variation_id'])) {
                     if ($variation_product_groups_remove = get_post_meta($subscription['variation_id'], '_groups_variation_groups_remove', false)) {
                         $product_groups_remove = array_merge($product_groups_remove, $variation_product_groups_remove);
                     }
                 }
                 if ($product_groups_remove) {
                     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) {
                             self::maybe_delete($user_id, $group_id, $order_id);
                         }
                     }
                 }
             }
         }
     }
 }