Пример #1
0
if ($smcFunc['db_num_rows']($request) == 0) {
    generateSubscriptionError(sprintf($txt['paid_count_not_find_subscription_log'], $member_id, $subscription_id));
}
$subscription_info += $smcFunc['db_fetch_assoc']($request);
$smcFunc['db_free_result']($request);
// Is this a refund etc?
if ($gatewayClass->isRefund()) {
    // If the end time subtracted by current time, is not greater
    // than the duration (ie length of subscription), then we close it.
    if ($subscription_info['end_time'] - time() < $subscription_info['length']) {
        // Delete user subscription.
        removeSubscription($subscription_id, $member_id);
        $subscription_act = time();
        $status = 0;
    } else {
        loadSubscriptions();
        $subscription_act = $subscription_info['end_time'] - $context['subscriptions'][$subscription_id]['num_length'];
        $status = 1;
    }
    // Mark it as complete so we have a record.
    $smcFunc['db_query']('', '
		UPDATE {db_prefix}log_subscribed
		SET end_time = {int:current_time}
		WHERE id_subscribe = {int:current_subscription}
			AND id_member = {int:current_member}
			AND status = {int:status}', array('current_time' => $subscription_act, 'current_subscription' => $subscription_id, 'current_member' => $member_id, 'status' => $status));
    // Receipt?
    if (!empty($modSettings['paid_email']) && $modSettings['paid_email'] == 2) {
        $replacements = array('NAME' => $subscription_info['name'], 'REFUNDNAME' => $member_info['member_name'], 'REFUNDUSER' => $member_info['real_name'], 'PROFILELINK' => $scripturl . '?action=profile;u=' . $member_id, 'DATE' => timeformat(time(), false));
        emailAdmins('paid_subscription_refund', $replacements, $notify_users);
    }
function subscriptions($memID)
{
    global $context, $txt, $sourcedir, $modSettings, $smcFunc, $scripturl;
    // Load the paid template anyway.
    loadTemplate('ManagePaid');
    loadLanguage('ManagePaid');
    // Load all of the subscriptions.
    require_once $sourcedir . '/ManagePaid.php';
    loadSubscriptions();
    $context['member']['id'] = $memID;
    // Remove any invalid ones.
    foreach ($context['subscriptions'] as $id => $sub) {
        // Work out the costs.
        $costs = @unserialize($sub['real_cost']);
        $cost_array = array();
        if ($sub['real_length'] == 'F') {
            foreach ($costs as $duration => $cost) {
                if ($cost != 0) {
                    $cost_array[$duration] = $cost;
                }
            }
        } else {
            $cost_array['fixed'] = $costs['fixed'];
        }
        if (empty($cost_array)) {
            unset($context['subscriptions'][$id]);
        } else {
            $context['subscriptions'][$id]['member'] = 0;
            $context['subscriptions'][$id]['subscribed'] = false;
            $context['subscriptions'][$id]['costs'] = $cost_array;
        }
    }
    // Work out what gateways are enabled.
    $gateways = loadPaymentGateways();
    foreach ($gateways as $id => $gateway) {
        $gateways[$id] = new $gateway['display_class']();
        if (!$gateways[$id]->gatewayEnabled()) {
            unset($gateways[$id]);
        }
    }
    // No gateways yet?
    if (empty($gateways)) {
        fatal_error($txt['paid_admin_not_setup_gateway']);
    }
    // Get the current subscriptions.
    $request = $smcFunc['db_query']('', '
		SELECT id_sublog, id_subscribe, start_time, end_time, status, payments_pending, pending_details
		FROM {db_prefix}log_subscribed
		WHERE id_member = {int:selected_member}', array('selected_member' => $memID));
    $context['current'] = array();
    while ($row = $smcFunc['db_fetch_assoc']($request)) {
        // The subscription must exist!
        if (!isset($context['subscriptions'][$row['id_subscribe']])) {
            continue;
        }
        $context['current'][$row['id_subscribe']] = array('id' => $row['id_sublog'], 'sub_id' => $row['id_subscribe'], 'hide' => $row['status'] == 0 && $row['end_time'] == 0 && $row['payments_pending'] == 0, 'name' => $context['subscriptions'][$row['id_subscribe']]['name'], 'start' => timeformat($row['start_time'], false), 'end' => $row['end_time'] == 0 ? $txt['not_applicable'] : timeformat($row['end_time'], false), 'pending_details' => $row['pending_details'], 'status' => $row['status'], 'status_text' => $row['status'] == 0 ? $row['payments_pending'] ? $txt['paid_pending'] : $txt['paid_finished'] : $txt['paid_active']);
        if ($row['status'] == 1) {
            $context['subscriptions'][$row['id_subscribe']]['subscribed'] = true;
        }
    }
    $smcFunc['db_free_result']($request);
    // Simple "done"?
    if (isset($_GET['done'])) {
        $_GET['sub_id'] = (int) $_GET['sub_id'];
        // Must exist but let's be sure...
        if (isset($context['current'][$_GET['sub_id']])) {
            // What are the details like?
            $current_pending = @unserialize($context['current'][$_GET['sub_id']]['pending_details']);
            if (!empty($current_pending)) {
                $current_pending = array_reverse($current_pending);
                foreach ($current_pending as $id => $sub) {
                    // Just find one and change it.
                    if ($sub[0] == $_GET['sub_id'] && $sub[3] == 'prepay') {
                        $current_pending[$id][3] = 'payback';
                        break;
                    }
                }
                // Save the details back.
                $pending_details = serialize($current_pending);
                $smcFunc['db_query']('', '
					UPDATE {db_prefix}log_subscribed
					SET payments_pending = payments_pending + 1, pending_details = {string:pending_details}
					WHERE id_sublog = {int:current_subscription_id}
						AND id_member = {int:selected_member}', array('current_subscription_id' => $context['current'][$_GET['sub_id']]['id'], 'selected_member' => $memID, 'pending_details' => $pending_details));
            }
        }
        $context['sub_template'] = 'paid_done';
        return;
    }
    // If this is confirmation then it's simpler...
    if (isset($_GET['confirm']) && isset($_POST['sub_id']) && is_array($_POST['sub_id'])) {
        // Hopefully just one.
        foreach ($_POST['sub_id'] as $k => $v) {
            $ID_SUB = (int) $k;
        }
        if (!isset($context['subscriptions'][$ID_SUB]) || $context['subscriptions'][$ID_SUB]['active'] == 0) {
            fatal_lang_error('paid_sub_not_active');
        }
        // Simplify...
        $context['sub'] = $context['subscriptions'][$ID_SUB];
        $period = 'xx';
        if ($context['sub']['flexible']) {
            $period = isset($_POST['cur'][$ID_SUB]) && isset($context['sub']['costs'][$_POST['cur'][$ID_SUB]]) ? $_POST['cur'][$ID_SUB] : 'xx';
        }
        // Check we have a valid cost.
        if ($context['sub']['flexible'] && $period == 'xx') {
            fatal_lang_error('paid_sub_not_active');
        }
        // Sort out the cost/currency.
        $context['currency'] = $modSettings['paid_currency_code'];
        $context['recur'] = $context['sub']['repeatable'];
        if ($context['sub']['flexible']) {
            // Real cost...
            $context['value'] = $context['sub']['costs'][$_POST['cur'][$ID_SUB]];
            $context['cost'] = sprintf($modSettings['paid_currency_symbol'], $context['value']) . '/' . $txt[$_POST['cur'][$ID_SUB]];
            // The period value for paypal.
            $context['paypal_period'] = strtoupper(substr($_POST['cur'][$ID_SUB], 0, 1));
        } else {
            // Real cost...
            $context['value'] = $context['sub']['costs']['fixed'];
            $context['cost'] = sprintf($modSettings['paid_currency_symbol'], $context['value']);
            // Recur?
            preg_match('~(\\d*)(\\w)~', $context['sub']['real_length'], $match);
            $context['paypal_unit'] = $match[1];
            $context['paypal_period'] = $match[2];
        }
        // Setup the gateway context.
        $context['gateways'] = array();
        foreach ($gateways as $id => $gateway) {
            $fields = $gateways[$id]->fetchGatewayFields($context['sub']['id'] . '+' . $memID, $context['sub'], $context['value'], $period, $scripturl . '?action=profile;u=' . $memID . ';area=subscriptions;sub_id=' . $context['sub']['id'] . ';done');
            if (!empty($fields['form'])) {
                $context['gateways'][] = $fields;
            }
        }
        // Bugger?!
        if (empty($context['gateways'])) {
            fatal_error($txt['paid_admin_not_setup_gateway']);
        }
        // Now we are going to assume they want to take this out ;)
        $new_data = array($context['sub']['id'], $context['value'], $period, 'prepay');
        if (isset($context['current'][$context['sub']['id']])) {
            // What are the details like?
            $current_pending = array();
            if ($context['current'][$context['sub']['id']]['pending_details'] != '') {
                $current_pending = @unserialize($context['current'][$context['sub']['id']]['pending_details']);
            }
            // Don't get silly.
            if (count($current_pending) > 9) {
                $current_pending = array();
            }
            $pending_count = 0;
            // Only record real pending payments as will otherwise confuse the admin!
            foreach ($current_pending as $pending) {
                if ($pending[3] == 'payback') {
                    $pending_count++;
                }
            }
            if (!in_array($new_data, $current_pending)) {
                $current_pending[] = $new_data;
                $pending_details = serialize($current_pending);
                $smcFunc['db_query']('', '
					UPDATE {db_prefix}log_subscribed
					SET payments_pending = {int:pending_count}, pending_details = {string:pending_details}
					WHERE id_sublog = {int:current_subscription_item}
						AND id_member = {int:selected_member}', array('pending_count' => $pending_count, 'current_subscription_item' => $context['current'][$context['sub']['id']]['id'], 'selected_member' => $memID, 'pending_details' => $pending_details));
            }
        } else {
            $pending_details = serialize(array($new_data));
            $smcFunc['db_insert']('', '{db_prefix}log_subscribed', array('id_subscribe' => 'int', 'id_member' => 'int', 'status' => 'int', 'payments_pending' => 'int', 'pending_details' => 'string-65534', 'start_time' => 'int', 'vendor_ref' => 'string-255'), array($context['sub']['id'], $memID, 0, 0, $pending_details, time(), ''), array('id_sublog'));
        }
        // Change the template.
        $context['sub_template'] = 'choose_payment';
        // Quit.
        return;
    } else {
        $context['sub_template'] = 'user_subscription';
    }
}
Пример #3
0
function removeSubscription($id_subscribe, $id_member, $delete = false)
{
    global $context, $smcFunc;
    loadSubscriptions();
    // Load the user core bits.
    $request = $smcFunc['db_query']('', '
		SELECT m.id_group, m.additional_groups
		FROM {db_prefix}members AS m
		WHERE m.id_member = {int:current_member}', array('current_member' => $id_member));
    // Just in case of errors.
    if ($smcFunc['db_num_rows']($request) == 0) {
        $smcFunc['db_query']('', '
			DELETE FROM {db_prefix}log_subscribed
			WHERE id_member = {int:current_member}', array('current_member' => $id_member));
        return;
    }
    list($id_group, $additional_groups) = $smcFunc['db_fetch_row']($request);
    $smcFunc['db_free_result']($request);
    // Get all of the subscriptions for this user that are active - it will be necessary!
    $request = $smcFunc['db_query']('', '
		SELECT id_subscribe, old_id_group
		FROM {db_prefix}log_subscribed
		WHERE id_member = {int:current_member}
			AND status = {int:is_active}', array('current_member' => $id_member, 'is_active' => 1));
    // These variables will be handy, honest ;)
    $removals = array();
    $allowed = array();
    $old_id_group = 0;
    $new_id_group = -1;
    while ($row = $smcFunc['db_fetch_assoc']($request)) {
        if (!isset($context['subscriptions'][$row['id_subscribe']])) {
            continue;
        }
        // The one we're removing?
        if ($row['id_subscribe'] == $id_subscribe) {
            $removals = explode(',', $context['subscriptions'][$row['id_subscribe']]['add_groups']);
            if ($context['subscriptions'][$row['id_subscribe']]['prim_group'] != 0) {
                $removals[] = $context['subscriptions'][$row['id_subscribe']]['prim_group'];
            }
            $old_id_group = $row['old_id_group'];
        } else {
            $allowed = array_merge($allowed, explode(',', $context['subscriptions'][$row['id_subscribe']]['add_groups']));
            if ($context['subscriptions'][$row['id_subscribe']]['prim_group'] != 0) {
                $allowed[] = $context['subscriptions'][$row['id_subscribe']]['prim_group'];
                $new_id_group = $context['subscriptions'][$row['id_subscribe']]['prim_group'];
            }
        }
    }
    $smcFunc['db_free_result']($request);
    // Now, for everything we are removing check they defintely are not allowed it.
    $existingGroups = explode(',', $additional_groups);
    foreach ($existingGroups as $key => $group) {
        if (empty($group) || in_array($group, $removals) && !in_array($group, $allowed)) {
            unset($existingGroups[$key]);
        }
    }
    // Finally, do something with the current primary group.
    if (in_array($id_group, $removals)) {
        // If this primary group is actually allowed keep it.
        if (in_array($id_group, $allowed)) {
            $existingGroups[] = $id_group;
        }
        // Either way, change the id_group back.
        if ($new_id_group < 1) {
            // If we revert to the old id-group we need to ensure it wasn't from a subscription.
            foreach ($context['subscriptions'] as $id => $group) {
                // It was? Make them a regular member then!
                if ($group['prim_group'] == $old_id_group) {
                    $old_id_group = 0;
                }
            }
            $id_group = $old_id_group;
        } else {
            $id_group = $new_id_group;
        }
    }
    // Crazy stuff, we seem to have our groups fixed, just make them unique
    $existingGroups = array_unique($existingGroups);
    $existingGroups = implode(',', $existingGroups);
    // Update the member
    $smcFunc['db_query']('', '
		UPDATE {db_prefix}members
		SET id_group = {int:primary_group}, additional_groups = {string:existing_groups}
		WHERE id_member = {int:current_member}', array('primary_group' => $id_group, 'current_member' => $id_member, 'existing_groups' => $existingGroups));
    // Disable the subscription.
    if (!$delete) {
        $smcFunc['db_query']('', '
			UPDATE {db_prefix}log_subscribed
			SET status = {int:not_active}
			WHERE id_member = {int:current_member}
				AND id_subscribe = {int:current_subscription}', array('not_active' => 0, 'current_member' => $id_member, 'current_subscription' => $id_subscribe));
    } else {
        $smcFunc['db_query']('', '
			DELETE FROM {db_prefix}log_subscribed
			WHERE id_member = {int:current_member}
				AND id_subscribe = {int:current_subscription}', array('current_member' => $id_member, 'current_subscription' => $id_subscribe));
    }
}
Пример #4
0
 /**
  * Edit or add a user subscription.
  *
  * - Accessed from ?action=admin;area=paidsubscribe;sa=modifyuser
  */
 public function action_modifyuser()
 {
     global $context, $txt, $modSettings;
     require_once SUBSDIR . '/PaidSubscriptions.subs.php';
     loadSubscriptions();
     $context['log_id'] = isset($_REQUEST['lid']) ? (int) $_REQUEST['lid'] : 0;
     $context['sub_id'] = isset($_REQUEST['sid']) ? (int) $_REQUEST['sid'] : 0;
     $context['action_type'] = $context['log_id'] ? 'edit' : 'add';
     // Setup the template.
     $context['sub_template'] = 'modify_user_subscription';
     $context['page_title'] = $txt[$context['action_type'] . '_subscriber'];
     loadJavascriptFile('suggest.js', array('defer' => true));
     // If we haven't been passed the subscription ID get it.
     if ($context['log_id'] && !$context['sub_id']) {
         $context['sub_id'] = validateSubscriptionID($context['log_id']);
     }
     if (!isset($context['subscriptions'][$context['sub_id']])) {
         fatal_lang_error('no_access', false);
     }
     $context['current_subscription'] = $context['subscriptions'][$context['sub_id']];
     // Searching?
     if (isset($_POST['ssearch'])) {
         return $this->action_viewsub();
     } elseif (isset($_REQUEST['save_sub'])) {
         checkSession();
         // Work out the dates...
         $starttime = mktime($_POST['hour'], $_POST['minute'], 0, $_POST['month'], $_POST['day'], $_POST['year']);
         $endtime = mktime($_POST['hourend'], $_POST['minuteend'], 0, $_POST['monthend'], $_POST['dayend'], $_POST['yearend']);
         // Status.
         $status = $_POST['status'];
         // New one?
         if (empty($context['log_id'])) {
             // Find the user...
             require_once SUBSDIR . '/Members.subs.php';
             $member = getMemberByName($_POST['name']);
             if (empty($member)) {
                 fatal_lang_error('error_member_not_found');
             }
             if (alreadySubscribed($context['sub_id'], $member['id_member'])) {
                 fatal_lang_error('member_already_subscribed');
             }
             // Actually put the subscription in place.
             if ($status == 1) {
                 addSubscription($context['sub_id'], $member['id_member'], 0, $starttime, $endtime);
             } else {
                 $details = array('id_subscribe' => $context['sub_id'], 'id_member' => $member['id_member'], 'id_group' => $member['id_group'], 'start_time' => $starttime, 'end_time' => $endtime, 'status' => $status);
                 logSubscription($details);
             }
         } else {
             $subscription_status = getSubscriptionStatus($context['log_id']);
             // Pick the right permission stuff depending on what the status is changing from/to.
             if ($subscription_status['old_status'] == 1 && $status != 1) {
                 removeSubscription($context['sub_id'], $subscription_status['id_member']);
             } elseif ($status == 1 && $subscription_status['old_status'] != 1) {
                 addSubscription($context['sub_id'], $subscription_status['id_member'], 0, $starttime, $endtime);
             } else {
                 $item = array('start_time' => $starttime, 'end_time' => $endtime, 'status' => $status, 'current_log_item' => $context['log_id']);
                 updateSubscriptionItem($item);
             }
         }
         // Done - redirect...
         redirectexit('action=admin;area=paidsubscribe;sa=viewsub;sid=' . $context['sub_id']);
     } elseif (isset($_REQUEST['delete']) || isset($_REQUEST['finished'])) {
         checkSession();
         // Do the actual deletes!
         if (!empty($_REQUEST['delsub'])) {
             $toDelete = array();
             foreach ($_REQUEST['delsub'] as $id => $dummy) {
                 $toDelete[] = (int) $id;
             }
             $deletes = prepareDeleteSubscriptions($toDelete);
             foreach ($deletes as $id_subscribe => $id_member) {
                 removeSubscription($id_subscribe, $id_member, isset($_REQUEST['delete']));
             }
         }
         redirectexit('action=admin;area=paidsubscribe;sa=viewsub;sid=' . $context['sub_id']);
     }
     // Default attributes.
     if ($context['action_type'] == 'add') {
         $context['sub'] = array('id' => 0, 'start' => array('year' => (int) strftime('%Y', time()), 'month' => (int) strftime('%m', time()), 'day' => (int) strftime('%d', time()), 'hour' => (int) strftime('%H', time()), 'min' => (int) strftime('%M', time()) < 10 ? '0' . (int) strftime('%M', time()) : (int) strftime('%M', time()), 'last_day' => 0), 'end' => array('year' => (int) strftime('%Y', time()), 'month' => (int) strftime('%m', time()), 'day' => (int) strftime('%d', time()), 'hour' => (int) strftime('%H', time()), 'min' => (int) strftime('%M', time()) < 10 ? '0' . (int) strftime('%M', time()) : (int) strftime('%M', time()), 'last_day' => 0), 'status' => 1);
         $context['sub']['start']['last_day'] = (int) strftime('%d', mktime(0, 0, 0, $context['sub']['start']['month'] == 12 ? 1 : $context['sub']['start']['month'] + 1, 0, $context['sub']['start']['month'] == 12 ? $context['sub']['start']['year'] + 1 : $context['sub']['start']['year']));
         $context['sub']['end']['last_day'] = (int) strftime('%d', mktime(0, 0, 0, $context['sub']['end']['month'] == 12 ? 1 : $context['sub']['end']['month'] + 1, 0, $context['sub']['end']['month'] == 12 ? $context['sub']['end']['year'] + 1 : $context['sub']['end']['year']));
         if (isset($_GET['uid'])) {
             require_once SUBSDIR . '/Members.subs.php';
             // Get the latest activated member's display name.
             $result = getBasicMemberData((int) $_GET['uid']);
             $context['sub']['username'] = $result['real_name'];
         } else {
             $context['sub']['username'] = '';
         }
     } else {
         $row = getPendingSubscriptions($context['log_id']);
         if (empty($row)) {
             fatal_lang_error('no_access', false);
         }
         // Any pending payments?
         $context['pending_payments'] = array();
         if (!empty($row['pending_details'])) {
             $pending_details = @unserialize($row['pending_details']);
             foreach ($pending_details as $id => $pending) {
                 // Only this type need be displayed.
                 if ($pending[3] == 'payback') {
                     // Work out what the options were.
                     $costs = @unserialize($context['current_subscription']['real_cost']);
                     if ($context['current_subscription']['real_length'] == 'F') {
                         foreach ($costs as $duration => $cost) {
                             if ($cost != 0 && $cost == $pending[1] && $duration == $pending[2]) {
                                 $context['pending_payments'][$id] = array('desc' => sprintf($modSettings['paid_currency_symbol'], $cost . '/' . $txt[$duration]));
                             }
                         }
                     } elseif ($costs['fixed'] == $pending[1]) {
                         $context['pending_payments'][$id] = array('desc' => sprintf($modSettings['paid_currency_symbol'], $costs['fixed']));
                     }
                 }
             }
             // Check if we are adding/removing any.
             if (isset($_GET['pending'])) {
                 foreach ($pending_details as $id => $pending) {
                     // Found the one to action?
                     if ($_GET['pending'] == $id && $pending[3] == 'payback' && isset($context['pending_payments'][$id])) {
                         // Flexible?
                         if (isset($_GET['accept'])) {
                             addSubscription($context['current_subscription']['id'], $row['id_member'], $context['current_subscription']['real_length'] == 'F' ? strtoupper(substr($pending[2], 0, 1)) : 0);
                         }
                         unset($pending_details[$id]);
                         $new_details = serialize($pending_details);
                         // Update the entry.
                         updatePendingSubscription($context['log_id'], $new_details);
                         // Reload
                         redirectexit('action=admin;area=paidsubscribe;sa=modifyuser;lid=' . $context['log_id']);
                     }
                 }
             }
         }
         $context['sub_id'] = $row['id_subscribe'];
         $context['sub'] = array('id' => 0, 'start' => array('year' => (int) strftime('%Y', $row['start_time']), 'month' => (int) strftime('%m', $row['start_time']), 'day' => (int) strftime('%d', $row['start_time']), 'hour' => (int) strftime('%H', $row['start_time']), 'min' => (int) strftime('%M', $row['start_time']) < 10 ? '0' . (int) strftime('%M', $row['start_time']) : (int) strftime('%M', $row['start_time']), 'last_day' => 0), 'end' => array('year' => (int) strftime('%Y', $row['end_time']), 'month' => (int) strftime('%m', $row['end_time']), 'day' => (int) strftime('%d', $row['end_time']), 'hour' => (int) strftime('%H', $row['end_time']), 'min' => (int) strftime('%M', $row['end_time']) < 10 ? '0' . (int) strftime('%M', $row['end_time']) : (int) strftime('%M', $row['end_time']), 'last_day' => 0), 'status' => $row['status'], 'username' => $row['username']);
         $context['sub']['start']['last_day'] = (int) strftime('%d', mktime(0, 0, 0, $context['sub']['start']['month'] == 12 ? 1 : $context['sub']['start']['month'] + 1, 0, $context['sub']['start']['month'] == 12 ? $context['sub']['start']['year'] + 1 : $context['sub']['start']['year']));
         $context['sub']['end']['last_day'] = (int) strftime('%d', mktime(0, 0, 0, $context['sub']['end']['month'] == 12 ? 1 : $context['sub']['end']['month'] + 1, 0, $context['sub']['end']['month'] == 12 ? $context['sub']['end']['year'] + 1 : $context['sub']['end']['year']));
     }
 }
Пример #5
0
/**
 * Removes a subscription from a user, as in removes the groups.
 *
 * @param int $id_subscribe
 * @param int $id_member
 * @param boolean $delete
 */
function removeSubscription($id_subscribe, $id_member, $delete = false)
{
    global $context;
    $db = database();
    loadSubscriptions();
    // Load the user core bits.
    require_once SUBSDIR . '/Members.subs.php';
    $member_info = getBasicMemberData($id_member, array('moderation' => true));
    // Just in case of errors.
    if (empty($member_info)) {
        $db->query('', '
			DELETE FROM {db_prefix}log_subscribed
			WHERE id_member = {int:current_member}', array('current_member' => $id_member));
        return;
    }
    // Get all of the subscriptions for this user that are active - it will be necessary!
    $request = $db->query('', '
		SELECT
			id_subscribe, old_id_group
		FROM {db_prefix}log_subscribed
		WHERE id_member = {int:current_member}
			AND status = {int:is_active}', array('current_member' => $id_member, 'is_active' => 1));
    // These variables will be handy, honest ;)
    $removals = array();
    $allowed = array();
    $member = array();
    $member['id_group'] = 0;
    $new_id_group = -1;
    while ($row = $db->fetch_assoc($request)) {
        if (!isset($context['subscriptions'][$row['id_subscribe']])) {
            continue;
        }
        // The one we're removing?
        if ($row['id_subscribe'] == $id_subscribe) {
            $removals = explode(',', $context['subscriptions'][$row['id_subscribe']]['add_groups']);
            if ($context['subscriptions'][$row['id_subscribe']]['prim_group'] != 0) {
                $removals[] = $context['subscriptions'][$row['id_subscribe']]['prim_group'];
            }
            $member['id_group'] = $row['old_id_group'];
        } else {
            $allowed = array_merge($allowed, explode(',', $context['subscriptions'][$row['id_subscribe']]['add_groups']));
            if ($context['subscriptions'][$row['id_subscribe']]['prim_group'] != 0) {
                $allowed[] = $context['subscriptions'][$row['id_subscribe']]['prim_group'];
                $new_id_group = $context['subscriptions'][$row['id_subscribe']]['prim_group'];
            }
        }
    }
    $db->free_result($request);
    // Now, for everything we are removing check they defintely are not allowed it.
    $existingGroups = explode(',', $member_info['additional_groups']);
    foreach ($existingGroups as $key => $group) {
        if (empty($group) || in_array($group, $removals) && !in_array($group, $allowed)) {
            unset($existingGroups[$key]);
        }
    }
    // Finally, do something with the current primary group.
    if (in_array($member_info['id_group'], $removals)) {
        // If this primary group is actually allowed keep it.
        if (in_array($member_info['id_group'], $allowed)) {
            $existingGroups[] = $member_info['id_group'];
        }
        // Either way, change the id_group back.
        if ($new_id_group < 1) {
            // If we revert to the old id-group we need to ensure it wasn't from a subscription.
            foreach ($context['subscriptions'] as $id => $group) {
                // It was? Make them a regular member then!
                if ($group['prim_group'] == $member['id_group']) {
                    $member['id_group'] = 0;
                }
            }
            $member_info['id_group'] = $member['id_group'];
        } else {
            $member_info['id_group'] = $new_id_group;
        }
    }
    // Crazy stuff, we seem to have our groups fixed, just make them unique
    $existingGroups = array_unique($existingGroups);
    // Update the member
    assignGroupsToMember($id_member, $member_info['id_group'], $existingGroups);
    // Disable the subscription.
    if (!$delete) {
        $db->query('', '
			UPDATE {db_prefix}log_subscribed
			SET status = {int:not_active}
			WHERE id_member = {int:current_member}
				AND id_subscribe = {int:current_subscription}', array('not_active' => 0, 'current_member' => $id_member, 'current_subscription' => $id_subscribe));
    } else {
        $db->query('', '
			DELETE FROM {db_prefix}log_subscribed
			WHERE id_member = {int:current_member}
				AND id_subscribe = {int:current_subscription}', array('current_member' => $id_member, 'current_subscription' => $id_subscribe));
    }
}
 /**
  * Method for doing all the paid subscription stuff - kinda.
  */
 public function action_subscriptions()
 {
     global $context, $txt;
     // Load the paid template anyway.
     loadTemplate('ManagePaid');
     loadLanguage('ManagePaid');
     $memID = currentMemberID();
     $context['member']['id'] = $memID;
     // Load all of the subscriptions in the system
     require_once SUBSDIR . '/PaidSubscriptions.subs.php';
     loadSubscriptions();
     // Remove any invalid ones, ones not properly set up
     foreach ($context['subscriptions'] as $id => $sub) {
         // Work out the costs.
         $costs = @unserialize($sub['real_cost']);
         $cost_array = array();
         // Flexible cost to time?
         if ($sub['real_length'] == 'F') {
             foreach ($costs as $duration => $cost) {
                 if ($cost != 0) {
                     $cost_array[$duration] = $cost;
                 }
             }
         } else {
             $cost_array['fixed'] = $costs['fixed'];
         }
         // No cost associated with it, then drop it
         if (empty($cost_array)) {
             unset($context['subscriptions'][$id]);
         } else {
             $context['subscriptions'][$id]['member'] = 0;
             $context['subscriptions'][$id]['subscribed'] = false;
             $context['subscriptions'][$id]['costs'] = $cost_array;
         }
     }
     // Work out what payment gateways are enabled.
     $gateways = loadPaymentGateways();
     foreach ($gateways as $id => $gateway) {
         $gateways[$id] = new $gateway['display_class']();
         if (!$gateways[$id]->gatewayEnabled()) {
             unset($gateways[$id]);
         }
     }
     // No gateways yet, no way to pay then!
     if (empty($gateways)) {
         fatal_error($txt['paid_admin_not_setup_gateway']);
     }
     // Get the members current subscriptions.
     $context['current'] = loadMemberSubscriptions($memID, $context['subscriptions']);
     // Find the active subscribed ones
     foreach ($context['current'] as $id => $current) {
         if ($current['status'] == 1) {
             $context['subscriptions'][$id]['subscribed'] = true;
         }
     }
     // Simple "done"?
     if (isset($_GET['done'])) {
         $this->_orderDone($memID);
     } elseif (isset($_GET['confirm']) && isset($_POST['sub_id']) && is_array($_POST['sub_id'])) {
         $this->_confirmOrder($gateways, $memID);
     } else {
         $context['sub_template'] = 'user_subscription';
     }
 }