latest stable versions: v150827 (changelog)

Old Forums (READ-ONLY): The community now lives at WP Sharks™. If you have an s2Member® Pro question, please use our new Support System.

About: Josh Levinson

Sorry, I've not written a description yet. I'll get to it soon!


Topics I'm Subscribed To

Viewing 5 topics - 1 through 5 (of 5 total)
Topic Count Last Reply
Hooks

By:  Josh Levinson in: Community Forum

voices: 2
replies: 1

3 years, 6 months ago  Bruce

s2Member code problem causes conflict

By:  Josh Levinson in: Community Forum

voices: 2
replies: 6

3 years, 7 months ago  Bruce

Correct Shortcode to use

By:  Josh Levinson in: Community Forum

voices: 2
replies: 12

3 years, 8 months ago  Cristián Lávaque

s2Member shortcode over ajax.

By:  Josh Levinson in: Community Forum

voices: 2
replies: 2

3 years, 8 months ago  Bruce

Testing EOT Behavior for Subscriptions

By:  Josh Levinson in: Community Forum

voices: 2
replies: 2

3 years, 8 months ago  Josh Levinson

Viewing 5 topics - 1 through 5 (of 5 total)

Topics I've Started

Viewing 5 topics - 1 through 5 (of 5 total)
Topic Count Last Reply
Hooks

By:  Josh Levinson in: Community Forum

voices: 2
replies: 1

3 years, 6 months ago  Bruce

s2Member code problem causes conflict

By:  Josh Levinson in: Community Forum

voices: 2
replies: 6

3 years, 7 months ago  Bruce

Correct Shortcode to use

By:  Josh Levinson in: Community Forum

voices: 2
replies: 12

3 years, 8 months ago  Cristián Lávaque

s2Member shortcode over ajax.

By:  Josh Levinson in: Community Forum

voices: 2
replies: 2

3 years, 8 months ago  Bruce

Testing EOT Behavior for Subscriptions

By:  Josh Levinson in: Community Forum

voices: 2
replies: 2

3 years, 8 months ago  Josh Levinson

Viewing 5 topics - 1 through 5 (of 5 total)

My Latest Replies (From Various Topics)

Viewing 15 replies - 1 through 15 (of 15 total)
Author Replies
Author Replies
Posted: Tuesday Jun 11th, 2013 at 8:34 am #51758

I understand the logic you present about needing to track all logins. However, I still disagree with the need to use the wp_signon hook for the redirection. If you need to track user logins, why not hook the wp_signon to perform user login tracking, then perform your redirect logic separately? I feel like performing user tracking, brute force, and ip logging logic should not lie in a function called login_redirect. I suggest something like:

public static function login_redirect ($redirect,$request,$user)
{
	foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;
	do_action ("ws_plugin__s2member_before_login_redirect", get_defined_vars ());
	unset /* Unset defined __refs, __v. */ ($__refs, $__v);
	$username = $user->user_login;
	if (is_string($username) && $username && is_object ($user) && !empty ($user->ID) && ($user_id = $user->ID))
		{

			if (($redirect = apply_filters ("ws_plugin__s2member_login_redirect", (($user->has_cap ("edit_posts")) ? false : true), get_defined_vars ())))
				{
					$obey_redirect_to = apply_filters ("ws_plugin__s2member_obey_login_redirect_to", /* By default, we obey this. */ true, get_defined_vars ());

					if (!$obey_redirect_to || empty ($_REQUEST["redirect_to"]) || !is_string ($_REQUEST["redirect_to"]) || $_REQUEST["redirect_to"] === admin_url () || preg_match ("/^\/?wp-admin\/?$/", $_REQUEST["redirect_to"]))
						{
							foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;
							do_action ("ws_plugin__s2member_during_login_redirect", get_defined_vars ());
							unset /* Unset defined __refs, __v. */ ($__refs, $__v);

							if /* Is this a string? */ ($redirect && is_string ($redirect))
								return /* Dynamic URL introduced by a Filter? */ ($redirect);

							else if ($redirection_url = c_ws_plugin__s2member_login_redirects::login_redirection_url ($user))
								return /* Special Redirection URL configured with s2Member. */ ($redirection_url);

							else // Else we use the Login Welcome Page configured for s2Member.
								return (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"]));

							exit /* Clean exit. */ ();
						}
				}
		}

	foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;
	do_action ("ws_plugin__s2member_after_login_redirect", get_defined_vars ());
	unset /* Unset defined __refs, __v. */ ($__refs, $__v);

	return $redirect /* Return for uniformity. */;
}

public static function user_login_tracking($username,$user){
	do_action ("ws_plugin__s2member_before_user_login_tracking", get_defined_vars ());
	if (is_string($username) && $username && is_object ($user) && !empty ($user->ID) && ($user_id = $user->ID))
		{
			update_user_option ($user_id, "s2member_last_login_time", time());

			if /* Have we got this yet? */ (!get_user_option ("s2member_registration_ip", $user_id))
				update_user_option ($user_id, "s2member_registration_ip", $_SERVER["REMOTE_ADDR"]);

			if (($logins = (int)get_user_option ("s2member_login_counter", $user_id) + 1) >= 1 || ($logins = 1))
				update_user_option ($user_id, "s2member_login_counter", $logins);

			if /* Nag em? */ ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_password"])
				delete_user_setting ("default_password_nag") . update_user_option ($user_id, "default_password_nag", false, true);

			$disable_login_ip_restrictions = apply_filters ("ws_plugin__s2member_disable_login_ip_restrictions", false, get_defined_vars ());

			if (($ok = true) && !is_super_admin ($user_id) && $username !== "demo" && !$disable_login_ip_restrictions)
				$ok = c_ws_plugin__s2member_ip_restrictions::ip_restrictions_ok ($_SERVER["REMOTE_ADDR"], $username);
		}
	do_action ("ws_plugin__s2member_after_user_login_tracking", get_defined_vars ());
	return $user;
}
Posted: Monday Jun 10th, 2013 at 12:20 pm #51718

I have made a few changes to s2Member to fit what I believe is the most appropriate place to redirect a logged in user. The first step was changing the logic from hooking into wp_login to filtering the login_redirect. Since s2Member removes all filters on login_redirect, I also had to modify login-redirects-r.inc.php to add the filter back after all others are removed.

The altered login_redirect function in login-redirects.inc.php:

public static function login_redirect ($redirect,$request,$user)
					{
						foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;
						do_action ("ws_plugin__s2member_before_login_redirect", get_defined_vars ());
						unset /* Unset defined __refs, __v. */ ($__refs, $__v);
						$username = $user->user_login;
						if (is_string($username) && $username && is_object ($user) && !empty ($user->ID) && ($user_id = $user->ID))
							{
								update_user_option ($user_id, "s2member_last_login_time", time());

								if /* Have we got this yet? */ (!get_user_option ("s2member_registration_ip", $user_id))
									update_user_option ($user_id, "s2member_registration_ip", $_SERVER["REMOTE_ADDR"]);

								if (($logins = (int)get_user_option ("s2member_login_counter", $user_id) + 1) >= 1 || ($logins = 1))
									update_user_option ($user_id, "s2member_login_counter", $logins);

								if /* Nag em? */ ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_password"])
									delete_user_setting ("default_password_nag") . update_user_option ($user_id, "default_password_nag", false, true);

								$disable_login_ip_restrictions = apply_filters ("ws_plugin__s2member_disable_login_ip_restrictions", false, get_defined_vars ());

								if (($ok = true) && !is_super_admin ($user_id) && $username !== "demo" && !$disable_login_ip_restrictions)
									$ok = c_ws_plugin__s2member_ip_restrictions::ip_restrictions_ok ($_SERVER["REMOTE_ADDR"], $username);

								if (($redirect = apply_filters ("ws_plugin__s2member_login_redirect", (($user->has_cap ("edit_posts")) ? false : true), get_defined_vars ())))
									{
										$obey_redirect_to = apply_filters ("ws_plugin__s2member_obey_login_redirect_to", /* By default, we obey this. */ true, get_defined_vars ());

										if (!$obey_redirect_to || empty ($_REQUEST["redirect_to"]) || !is_string ($_REQUEST["redirect_to"]) || $_REQUEST["redirect_to"] === admin_url () || preg_match ("/^\/?wp-admin\/?$/", $_REQUEST["redirect_to"]))
											{
												foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;
												do_action ("ws_plugin__s2member_during_login_redirect", get_defined_vars ());
												unset /* Unset defined __refs, __v. */ ($__refs, $__v);

												if /* Is this a string? */ ($redirect && is_string ($redirect))
													return /* Dynamic URL introduced by a Filter? */ ($redirect);

												else if ($redirection_url = c_ws_plugin__s2member_login_redirects::login_redirection_url ($user))
													return /* Special Redirection URL configured with s2Member. */ ($redirection_url);

												else // Else we use the Login Welcome Page configured for s2Member.
													return (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"]));

												exit /* Clean exit. */ ();
											}
									}
							}

						foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;
						do_action ("ws_plugin__s2member_after_login_redirect", get_defined_vars ());
						unset /* Unset defined __refs, __v. */ ($__refs, $__v);

						return /* Return for uniformity. */;
					}

My altered filter in hooks.php (replaces the add_action(‘wp_login’)):

add_filter("login_redirect", "c_ws_plugin__s2member_login_redirects::login_redirect", 20, 3);

My altered remove_login_redirect_filters in login-redirects-r.inc.php:

public static function remove_login_redirect_filters ()
					{
						//if(defined ("DOING_AJAX") || DOING_AJAX) return;
						do_action ("ws_plugin__s2member_before_remove_login_redirect_filters", get_defined_vars ());

						if (!apply_filters ("ws_plugin__s2member_allow_other_login_redirect_filters", false, get_defined_vars ()))
							{
								remove_all_filters /* Removes all `login_redirect` Filters. */("login_redirect");
								add_filter ("login_redirect", "c_ws_plugin__s2member_login_redirects_r::_empty_login_redirect_filter");
								add_filter("login_redirect", "c_ws_plugin__s2member_login_redirects::login_redirect", 20, 3);

								do_action ("ws_plugin__s2member_during_remove_login_redirect_filters", get_defined_vars ());
							}

						do_action ("ws_plugin__s2member_after_remove_login_redirect_filters", get_defined_vars ());

						return /* Return for uniformity. */;
					}

I realize that filtering the login_redirect twice may be redundant, but I will leave that decision up to s2Member’s team.

The summary of my changes are:

  1. Changing the use of wp_login hook to login_redirect filter.
  2. Altering the login_redirect function of s2Member to return the url instead of redirecting to it.
  3. Re-adding the filter after all filters are removed by remove_login_redirect_filters.
Posted: Monday Jun 10th, 2013 at 11:59 am #51716

I know it’s been over a weekend, but I believe this to be a significant issue with the way s2Member is set up. Is there any new information on this?

Posted: Friday Apr 19th, 2013 at 9:00 am #47873

Thanks Cristián! I just tried those and it looks like they’ve worked! the s2_auto_eot_time gets set, as well as s2_eot_notify_date, and the user’s level is s2member_level1!

:)

Posted: Thursday Apr 18th, 2013 at 11:52 am #47792

Marco, the reason I believe Bruce posted that article was to basically (and politely) say that you are responsible for investigating what s2Pro is capable of before purchasing it. You cannot expect a refund when a product does what it explicitly says it CAN do, but not what everything you wish it would do.

If I go and buy a soldering iron that advertises that it can weld solder, I can’t expect a refund because it can’t build me a circuit board without some work.

I appreciate/understand your frustration, but again – it is your responsibility to investigate (read – ask questions in the community forum) before you purchase s2Pro.

Another thing; if you think about it, it is almost impossible to give refunds for premium software purchases – even if I were to get a refund on my soldering iron, the store would at least get their merchandise back. With software, not so. If you were to get a refund now, you could potentially happily continue to use said software – which has basically now become free software – and whomever you may decide to share it with.

Posted: Thursday Apr 18th, 2013 at 8:55 am #47780

Cristián,

I feel like we are going in circles here, sorry that we keep misunderstanding each other :)

Let me try to sum up what I need again:

I need two types of membership:
1. Paid Membership @ $20, NOT recurring, for Level 1.
2. Free Form for the above membership, same rights (level 1).

I need BOTH memberships to set an EOT. Otherwise I fail to see how a user, free or paid, will be demoted as set in my Auto-EOT behavior settings (which demotes them to a free user).

The user also needs an EOT for my notification emails to work correctly (as they are based on a user having an EOT).

I am also confused by the term “trial term”. I don’t need a trial term (I especially don’t want a subscription considering that subscriptions don’t register an EOT). I just need a free version of the paid membership form that will give the user the exact same rights, level, and EOT as a paid member gets.

Posted: Wednesday Apr 17th, 2013 at 7:25 pm #47709

Marco – yes, I was able to do this, but my situation was an edge case – I had a database (outside of s2) of available, one time use vouchers that members could purchase in-store; my code would validate that the inputted voucher was valid and wasn’t taken/used, then would output a free registration form. There is a guide here on the site that I got the idea from, but my solution really doesn’t look anything like it.

You said:

it [s2Member] does not do what I needed to do without customization of the php code

You were correct unfortunately; if you aren’t comfortable doing this you will have to hire someone or find another solution. I didn’t find a solution so I did it myself. I didn’t see where WPMU’s membership plugin supported free coupon codes, but I may have just missed it.

Posted: Wednesday Apr 17th, 2013 at 4:47 pm #47695

Interesting…I wasn’t able to find anything there that s2 doesn’t support. In fact, s2 seems way more powerful than that plugin. Anywho, hope that plugin works well for you!

Posted: Wednesday Apr 17th, 2013 at 4:19 pm #47692

Everything is working great with the paid membership form; the free one however is not working as intended.
Currently the shortcode is:

[s2Member-Pro-AuthNet-Form level=”1″ ccaps=”” custom=”example.com” register=”1″ desc=”$20.00 / One Time (for 1 year access, non-recurring)” cc=”USD” a=”0″ ra=”20.00″ rp=”1″ rt=”Y” rr=”BN” rrt=”” accept=”visa,mastercard,amex,discover” coupon=”” accept_coupons=”0″ default_country_code=”US” captcha=”0″ /]

No EOT is set however. Why is this? I need EOT’s set on users who visit the paid and free form; both need to expire within a year, and both need the EOT for my EOT notification to work.

In addition to the lack of an EOT notification if no EOT is set, how will a user be demoted if their is no EOT?
As the functionality should be the same whether the user registered with the paid or free form, I am using the same shortcode in both scenarios, with the exception of the free form having register=”0″

Posted: Wednesday Apr 17th, 2013 at 3:07 pm #47688

Hey Marco,

I love s2Member for the extreme amount of customization it allows, but I don’t like the fact that 100% discount coupons are not built into core.

With that in mind, I am curious – what product did you end up going with?

Posted: Wednesday Apr 17th, 2013 at 10:02 am #47672

Thanks for your reponse Cristián.

Trials/initial terms are only possible with subscriptions, even if they don’t recur, keep that in mind.

What do you mean by this?

The pro-form coupon codes don’t work for free acess (i.e. no 100% off). See: Knowledge Base » Offering a Free Coupon Code (100% Discount)

I am using my own coupon code system (similar to the one in your response, but much more complex), not s2Member’s. This wasn’t really part of my question (my coupon system is working well for me), just information to help with answering the real question(s) (EOT’s/correct shortcode).

If you sell buy-now for the paid one, yes, right after payment. Not subscriptions, not before it ends.
For the free one, set the time with tp and tt attributes. Dashboard -› s2Member® -› PayPal® Pro Forms -› Shortcode Attributes -> tp, tt

Why/how would I use the tp, tt attributes if it will be a Buy Now form? You said:

Trials/initial terms are only possible with subscriptions, even if they don’t recur, keep that in mind.

P.S. – I’m using Authorize.net (if it makes a difference).

Posted: Tuesday Apr 16th, 2013 at 2:22 pm #47610

Oops! I had some wrong info the first time I posted this topic. My needs are as such:

Customers can visit the site and purchase membership (level 1 @ $20 via authorize.net) that lasts one year. It does NOT auto-renew, but instead demotes them to a free subscriber.

Customers can ALSO visit the site and eventually (through coupon codes) gain access to the SAME membership, but in a free registration form. What is the correct shortcode to use in these scenario? I hate to ask these question, but I feel very confused every time I look at the “Shortcode Attributes Explained” section of s2.

On another related note, are BOTH of these customers, whether through the free/not-free registration form, assigned an EOT? I need a way, as I mentioned, of notifying customers 1 month before their EOT of their upcoming EOT so they can renew.

I plan on using the guide here – http://www.s2member.com/forums/topic/setting-up-eot-notifications/ – to set up the EOT notifications, but need to know if the EOT’s are assigned/occur for both types of customers.

Thanks!

Posted: Monday Apr 15th, 2013 at 10:05 am #47496

Comment added to original question. Please delete this comment.

Posted: Monday Apr 15th, 2013 at 9:34 am #47495

Thank you, I think that should do.

Posted: Monday Apr 15th, 2013 at 9:31 am #47494

Thank you, I think that answers my questions. I should be able to use
Dashboard -› s2Member® -› API/Notifications to send a expiration notice.

Viewing 15 replies - 1 through 15 (of 15 total)

Old Forums (READ-ONLY): The community now lives at WP Sharks™. If you have an s2Member® Pro question, please use our new Support System.

Contacting s2Member: Please use our Support Center for bug reports, pre-sale questions & technical assistance.