function pmpro_changeMembershipLevel($level, $user_id = NULL, $old_level_status = 'inactive')
{
    global $wpdb;
    global $current_user, $pmpro_error;
    if (empty($user_id)) {
        $user_id = $current_user->ID;
    }
    if (empty($user_id)) {
        $pmpro_error = __("User ID not found.", "pmpro");
        return false;
    }
    //make sure user id is int for security
    $user_id = intval($user_id);
    if (empty($level)) {
        $level = 0;
    } else {
        if (is_array($level)) {
            //custom level
        } else {
            $level_obj = pmpro_getLevel($level);
            if (empty($level_obj)) {
                $pmpro_error = __("Invalid level.", "pmpro");
                return false;
            }
            $level = $level_obj->id;
        }
    }
    //if it's a custom level, they're changing
    if (!is_array($level)) {
        //are they even changing?
        if (pmpro_hasMembershipLevel($level, $user_id)) {
            $pmpro_error = __("not changing?", "pmpro");
            return false;
            //not changing
        }
    }
    //get all active membershipships for this user
    $old_levels = pmpro_getMembershipLevelsForUser($user_id);
    //deactivate old memberships based on the old_level_status passed in (updates pmpro_memberships_users table)
    if ($old_levels) {
        foreach ($old_levels as $old_level) {
            $sql = "UPDATE {$wpdb->pmpro_memberships_users} SET `status`='{$old_level_status}', `enddate`='" . current_time('mysql') . "' WHERE `id`=" . $old_level->subscription_id;
            if (!$wpdb->query($sql)) {
                $pmpro_error = __("Error interacting with database", "pmpro") . ": " . (mysql_errno() ? mysql_error() : 'unavailable');
                return false;
            }
        }
    }
    //should we cancel their gateway subscriptions?
    $pmpro_cancel_previous_subscriptions = true;
    if (isset($_REQUEST['cancel_membership']) && $_REQUEST['cancel_membership'] == false) {
        $pmpro_cancel_previous_subscriptions = false;
    }
    $pmpro_cancel_previous_subscriptions = apply_filters("pmpro_cancel_previous_subscriptions", $pmpro_cancel_previous_subscriptions);
    //cancel any other subscriptions they have (updates pmpro_membership_orders table)
    if ($pmpro_cancel_previous_subscriptions) {
        $other_order_ids = $wpdb->get_col("SELECT id FROM {$wpdb->pmpro_membership_orders} WHERE user_id = '" . $user_id . "' AND status = 'success' ORDER BY id DESC");
        foreach ($other_order_ids as $order_id) {
            $c_order = new MemberOrder($order_id);
            $c_order->cancel();
            if (!empty($c_order->error)) {
                $pmpro_error = $c_order->error;
            }
        }
    }
    //insert current membership
    if (!empty($level)) {
        if (is_array($level)) {
            //make sure the dates are in good formats
            if ($level['startdate'] != current_time('mysql') && $level['startdate'] != "NULL" && substr($level['startdate'], 0, 1) != "'") {
                $level['startdate'] = "'" . $level['startdate'] . "'";
            }
            if ($level['enddate'] != current_time('mysql') && $level['enddate'] != "NULL" && substr($level['enddate'], 0, 1) != "'") {
                $level['enddate'] = "'" . $level['enddate'] . "'";
            }
            //Better support mySQL Strict Mode by passing  a proper enum value for cycle_period
            if ($level['cycle_period'] == '') {
                $level['cycle_period'] = 0;
            }
            $sql = "INSERT INTO {$wpdb->pmpro_memberships_users} (user_id, membership_id, code_id, initial_payment, billing_amount, cycle_number, cycle_period, billing_limit, trial_amount, trial_limit, startdate, enddate)\n\t\t\t\t\tVALUES('" . $level['user_id'] . "',\n\t\t\t\t\t'" . $level['membership_id'] . "',\n\t\t\t\t\t'" . intval($level['code_id']) . "',\n\t\t\t\t\t'" . $level['initial_payment'] . "',\n\t\t\t\t\t'" . $level['billing_amount'] . "',\n\t\t\t\t\t'" . $level['cycle_number'] . "',\n\t\t\t\t\t'" . $level['cycle_period'] . "',\n\t\t\t\t\t'" . $level['billing_limit'] . "',\n\t\t\t\t\t'" . $level['trial_amount'] . "',\n\t\t\t\t\t'" . $level['trial_limit'] . "',\n\t\t\t\t\t" . $level['startdate'] . ",\n\t\t\t\t\t" . $level['enddate'] . ")";
            if (!$wpdb->query($sql)) {
                $pmpro_error = __("Error interacting with database", "pmpro") . ": " . (mysql_errno() ? mysql_error() : 'unavailable');
                return false;
            }
        } else {
            $sql = "INSERT INTO {$wpdb->pmpro_memberships_users} (user_id, membership_id, code_id, initial_payment, billing_amount, cycle_number, cycle_period, billing_limit, trial_amount, trial_limit, startdate, enddate)\n\t\t\t    VALUES (\n\t\t\t    '" . $user_id . "',\n\t\t\t    '" . $level . "',\n\t\t\t    '0',\n\t\t\t    '0',\n\t\t\t    '0',\n\t\t\t    '0',\n\t\t\t    '0',\n\t\t\t    '0',\n\t\t\t    '0',\n\t\t\t    '0',\n\t\t\t    '" . current_time('mysql') . "',\n                \t    '0000-00-00 00:00:00'\n                \t    )";
            if (!$wpdb->query($sql)) {
                $pmpro_error = __("Error interacting with database", "pmpro") . ": " . (mysql_errno() ? mysql_error() : 'unavailable');
                return false;
            }
        }
    }
    //get level id
    if (is_array($level)) {
        $level_id = $level['membership_id'];
    } else {
        $level_id = $level;
    }
    //just id
    //remove cached level
    global $all_membership_levels;
    unset($all_membership_levels[$user_id]);
    //update user data and call action
    pmpro_set_current_user();
    do_action("pmpro_after_change_membership_level", $level_id, $user_id);
    //$level is the $level_id here
    return true;
}
/**
 * Create, add, remove or updates the membership level of the given user to the given level.
 *
 * $level may either be the ID or name of the desired membership_level.
 * If $user_id is omitted, the value will be retrieved from $current_user.
 *
 * @param int $level ID of level to set as new level, use 0 to cancel membership
 * @param int $user_id ID of the user to change levels for
 * @param string $old_level_status The status to set for the row in the memberships users table. (e.g. inactive, cancelled, admin_cancelled, expired) Defaults to 'inactive'.
 * $param int $cancel_level If set cancel just this one level instead of all active levels (to support Multiple Memberships per User)
 *
 * Return values:
 *		Success returns boolean true.
 *		Failure returns boolean false.
 */
function pmpro_changeMembershipLevel($level, $user_id = NULL, $old_level_status = 'inactive', $cancel_level = NULL)
{
    global $wpdb;
    global $current_user, $pmpro_error;
    if (empty($user_id)) {
        $user_id = $current_user->ID;
    }
    if (empty($user_id)) {
        $pmpro_error = __("User ID not found.", "pmpro");
        return false;
    }
    //make sure user id is int for security
    $user_id = intval($user_id);
    if (empty($level)) {
        $level = 0;
    } else {
        if (is_array($level)) {
            //custom level
        } else {
            $level_obj = pmpro_getLevel($level);
            if (empty($level_obj)) {
                $pmpro_error = __("Invalid level.", "pmpro");
                return false;
            }
            $level = $level_obj->id;
        }
    }
    //if it's a custom level, they're changing
    if (!is_array($level)) {
        //are they even changing?
        if (pmpro_hasMembershipLevel($level, $user_id)) {
            $pmpro_error = __("not changing?", "pmpro");
            return false;
            //not changing
        }
    }
    //get all active membershipships for this user
    $old_levels = pmpro_getMembershipLevelsForUser($user_id);
    //get level id
    if (is_array($level)) {
        $level_id = $level['membership_id'];
    } else {
        $level_id = $level;
    }
    //just id
    /**
     * Action to run before the membership level changes.
     *
     * @param int $level_id ID of the level changed to.
     * @param int $user_id ID of the user changed.
     * @param array $old_levels array of prior levels the user belonged to.
     * $param int $cancel_level ID of the level being cancelled if specified
     */
    do_action("pmpro_before_change_membership_level", $level_id, $user_id, $old_levels, $cancel_level);
    //deactivate old memberships based on the old_level_status passed in (updates pmpro_memberships_users table)
    $pmpro_deactivate_old_levels = true;
    /**
     * Filter whether old levels should be deactivated or not. This supports the MMPU addon.
     * Typically you'll want to hook into pmpro_before_change_membership_level 
     * or pmpro_after_change_membership_level later to run your own deactivation logic.
     * 
     * @since  1.8.11
     * @var $pmpro_deactivate_old_levels bool True or false if levels should be deactivated. Defaults to true.
     */
    $pmpro_deactivate_old_levels = apply_filters("pmpro_deactivate_old_levels", $pmpro_deactivate_old_levels);
    //make sure we deactivate the specified level if it's passed in
    if (!empty($cancel_level)) {
        $pmpro_deactivate_old_levels = true;
        $new_old_levels = array();
        foreach ($old_levels as $key => $old_level) {
            if ($old_level->id == $cancel_level) {
                $new_old_levels[] = $old_levels[$key];
                break;
            }
        }
        $old_levels = $new_old_levels;
    }
    if ($old_levels && $pmpro_deactivate_old_levels) {
        foreach ($old_levels as $old_level) {
            $sql = "UPDATE {$wpdb->pmpro_memberships_users} SET `status`='{$old_level_status}', `enddate`='" . current_time('mysql') . "' WHERE `id`=" . $old_level->subscription_id;
            if (!$wpdb->query($sql)) {
                $pmpro_error = __("Error interacting with database", "pmpro") . ": " . ($wpdb->last_error ? $wpdb->last_error : 'unavailable');
                return false;
            }
        }
    }
    //should we cancel their gateway subscriptions?
    if (!empty($cancel_level)) {
        $pmpro_cancel_previous_subscriptions = true;
        //don't filter cause we're doing just the one
        $other_order_ids = $wpdb->get_col("SELECT id FROM {$wpdb->pmpro_membership_orders} WHERE user_id = '" . $user_id . "' AND status = 'success' AND membership_id = '" . esc_sql($cancel_level) . "' ORDER BY id DESC");
    } else {
        $pmpro_cancel_previous_subscriptions = true;
        if (isset($_REQUEST['cancel_membership']) && $_REQUEST['cancel_membership'] == false) {
            $pmpro_cancel_previous_subscriptions = false;
        }
        $pmpro_cancel_previous_subscriptions = apply_filters("pmpro_cancel_previous_subscriptions", $pmpro_cancel_previous_subscriptions);
        $other_order_ids = $wpdb->get_col("SELECT id FROM {$wpdb->pmpro_membership_orders} WHERE user_id = '" . $user_id . "' AND status = 'success' ORDER BY id DESC");
    }
    //cancel any other subscriptions they have (updates pmpro_membership_orders table)
    if ($pmpro_cancel_previous_subscriptions && !empty($other_order_ids)) {
        foreach ($other_order_ids as $order_id) {
            $c_order = new MemberOrder($order_id);
            $c_order->cancel();
            if (!empty($c_order->error)) {
                $pmpro_error = $c_order->error;
            }
        }
    }
    //insert current membership
    if (!empty($level)) {
        //make sure the dates are in good formats
        if (is_array($level)) {
            //Better support mySQL Strict Mode by passing  a proper enum value for cycle_period
            if ($level['cycle_period'] == '') {
                $level['cycle_period'] = 0;
            }
            // clean up date formatting (string/not string)
            $level['startdate'] = preg_replace('/\'/', '', $level['startdate']);
            $level['enddate'] = preg_replace('/\'/', '', $level['enddate']);
            $sql = $wpdb->prepare("\r\n\t\t\t\t\tINSERT INTO {$wpdb->pmpro_memberships_users}\r\n\t\t\t\t\t(`user_id`, `membership_id`, `code_id`, `initial_payment`, `billing_amount`, `cycle_number`, `cycle_period`, `billing_limit`, `trial_amount`, `trial_limit`, `startdate`, `enddate`)\r\n\t\t\t\t\tVALUES\r\n\t\t\t\t\t( %d, %d, %d, %s, %s, %d, %s, %d, %s, %d, %s, %s )", $level['user_id'], $level['membership_id'], $level['code_id'], $level['initial_payment'], $level['billing_amount'], $level['cycle_number'], $level['cycle_period'], $level['billing_limit'], $level['trial_amount'], $level['trial_limit'], $level['startdate'], $level['enddate']);
        } else {
            $sql = $wpdb->prepare("\r\n\t\t\t\tINSERT INTO {$wpdb->pmpro_memberships_users}\r\n\t\t\t\t( `user_id`, `membership_id`, `code_id`, `initial_payment`, `billing_amount`, `cycle_number`, `cycle_period`, `billing_limit`, `trial_amount`, `trial_limit`, `startdate`, `enddate`)\r\n\t\t\t\t\tVALUES \r\n\t\t\t\t\t( %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %s, %s )", $user_id, $level_id, '0', '0', '0', '0', '0', '0', '0', '0', current_time('mysql'), '0000-00-00 00:00:00');
        }
        if (false === $wpdb->query($sql)) {
            $pmpro_error = sprintf(__("Error interacting with database: %s", "pmpro"), !empty($wpdb->last_error) ? $wpdb->last_error : 'unavailable');
            return false;
        }
    }
    //remove cached level
    global $all_membership_levels;
    unset($all_membership_levels[$user_id]);
    //update user data and call action
    pmpro_set_current_user();
    /**
     * Action to run after the membership level changes.
     *
     * @param int $level_id ID of the level changed to.
     * @param int $user_id ID of the user changed.
     * $param int $cancel_level ID of the level being cancelled if specified.
     */
    do_action("pmpro_after_change_membership_level", $level_id, $user_id, $cancel_level);
    return true;
}
     $morder->Email = $bemail;
     $morder->gateway = "free";
 }
 //add an item to the history table, cancel old subscriptions
 if (!empty($morder)) {
     $morder->user_id = $user_id;
     $morder->membership_id = $pmpro_level->id;
     $morder->saveOrder();
 }
 //update the current user
 global $current_user;
 if (!$current_user->ID && $user->ID) {
     $current_user = $user;
 }
 //in case the user just signed up
 pmpro_set_current_user();
 //add discount code use
 if ($discount_code && $use_discount_code) {
     if (!empty($morder->id)) {
         $code_order_id = $morder->id;
     } else {
         $code_order_id = "";
     }
     $wpdb->query("INSERT INTO {$wpdb->pmpro_discount_codes_uses} (code_id, user_id, order_id, timestamp) VALUES('" . $discount_code_id . "', '" . $user_id . "', '" . intval($code_order_id) . "', '" . current_time("mysql") . "')");
 }
 //save billing info ect, as user meta
 $meta_keys = array("pmpro_bfirstname", "pmpro_blastname", "pmpro_baddress1", "pmpro_baddress2", "pmpro_bcity", "pmpro_bstate", "pmpro_bzipcode", "pmpro_bcountry", "pmpro_bphone", "pmpro_bemail", "pmpro_CardType", "pmpro_AccountNumber", "pmpro_ExpirationMonth", "pmpro_ExpirationYear");
 $meta_values = array($bfirstname, $blastname, $baddress1, $baddress2, $bcity, $bstate, $bzipcode, $bcountry, $bphone, $bemail, $CardType, hideCardNumber($AccountNumber), $ExpirationMonth, $ExpirationYear);
 pmpro_replaceUserMeta($user_id, $meta_keys, $meta_values);
 //save first and last name fields
 if (!empty($bfirstname)) {
Example #4
0
	function pmpro_changeMembershipLevel($level, $user_id = NULL)
	{
		global $wpdb;
		global $current_user, $pmpro_error;

		if(empty($user_id))
		{
			$user_id = $current_user->ID;
		}

		if(empty($user_id))
		{
			$pmpro_error = "User ID not found.";
			return false;
		}

		if(empty($level)) //cancelling membership
		{
			$level = 0;
		}
		else if(is_array($level))
		{
			//custom level
		}
		else
		{
			$level_obj = pmpro_getLevel($level);
			if(empty($level_obj))
			{
				$pmpro_error = "Invalid level.";
				return false;
			}
			$level = $level_obj->id;
		}
		

		//if it's a custom level, they're changing
		if(!is_array($level))
		{
			//are they even changing?
			if(pmpro_hasMembershipLevel($level, $user_id)) {
				$pmpro_error = "not is changing?";
				return false; //not changing
			}
		}

		$old_levels = pmpro_getMembershipLevelsForUser($user_id);
					
		$pmpro_cancel_previous_subscriptions = apply_filters("pmpro_cancel_previous_subscriptions", true);
		if($pmpro_cancel_previous_subscriptions)
		{
			//deactivate old memberships (updates pmpro_memberships_users table)
			if(!empty($old_levels))
			{
				foreach($old_levels as $old_level) {
					$sql = "UPDATE $wpdb->pmpro_memberships_users SET `status`='inactive', `enddate`=NOW() WHERE `id`=".$old_level->subscription_id;				
					if(!$wpdb->query($sql))
					{
						$pmpro_error = "Error interacting with database: ".(mysql_errno()?mysql_error():'unavailable');
						return false;
					}										
				}
			}

			//cancel any other subscriptions they have (updates pmpro_membership_orders table)
			$other_order_ids = $wpdb->get_col("SELECT id FROM $wpdb->pmpro_membership_orders WHERE user_id = '" . $user_id . "' AND status = 'success' ORDER BY id DESC");
			foreach($other_order_ids as $order_id)
			{
				$c_order = new MemberOrder($order_id);
				$c_order->cancel();
			}
		}

		//insert current membership
		if(!empty($level)) //are we getting a new one or just cancelling the old ones
		{
			if(is_array($level))
			{
				//make sure the dates are in good formats				
				if($level['startdate'] != "NOW()" && $level['startdate'] != "NULL" && substr($level['startdate'], 0, 1) != "'")
					$level['startdate'] = "'" . $level['startdate'] . "'";
								
				if($level['enddate'] != "NOW()" && $level['enddate'] != "NULL" && substr($level['enddate'], 0, 1) != "'")
					$level['enddate'] = "'" . $level['enddate'] . "'";
											
				$sql = "INSERT INTO $wpdb->pmpro_memberships_users (user_id, membership_id, code_id, initial_payment, billing_amount, cycle_number, cycle_period, billing_limit, trial_amount, trial_limit, startdate, enddate)
						VALUES('" . $level['user_id'] . "',
						'" . $level['membership_id'] . "',
						'" . intval($level['code_id']) . "',
						'" . $level['initial_payment'] . "',
						'" . $level['billing_amount'] . "',
						'" . $level['cycle_number'] . "',
						'" . $level['cycle_period'] . "',
						'" . $level['billing_limit'] . "',
						'" . $level['trial_amount'] . "',
						'" . $level['trial_limit'] . "',
						" . $level['startdate'] . ",
						" . $level['enddate'] . ")";
								
				if(!$wpdb->query($sql))
				{
					$pmpro_error = "Error interacting with database: ".(mysql_errno()?mysql_error():'unavailable');
					return false;
				}
			}
			else
			{
				$sql = "INSERT INTO $wpdb->pmpro_memberships_users (`membership_id`,`user_id`) VALUES ('" . $level . "','" . $user_id . "')";
				if(!$wpdb->query($sql))
				{
					$pmpro_error = "Error interacting with database: ".(mysql_errno()?mysql_error():'unavailable');
					return false;
				}
			}
		}

		//get level id
		if(is_array($level))
			$level_id = $level['membership_id'];	//custom level
		else
			$level_id = $level;	//just id
		
		//update user data and call action
		pmpro_set_current_user();
		do_action("pmpro_after_change_membership_level", $level_id, $user_id);	//$level is the $level_id here
		return true;
	}