Grace time not performing required function

Okay, I worked on your test site today.

I didn’t change every level, although they’re all basically the same, only thing that changes is length of time. I did need to free up level 1 for the intermediate demotion, so I moved the level 1 users to level 2.

Using the s2Member user import/export tool, I put all the “current” customers (levels 1 and 2) together in a single role (s2member Level 2), and gave them the custom capabilities “annual” and “triennial” as a label to tell them apart (I could have done the same for “contra”, “life” and “exempt” but didn’t bother, feel free to if you want.) WP Admin > s2Member Pro > Import/Export

I hope that makes sense and I didn’t confuse you.

I renamed Level 1 from “Current Annual” to “Overdue”, and renamed Level 2 from “Current Triennial” to “Current”. WP Admin > s2Member > General > Membership Levels/Labels

I changed the Grace Time in the EOT setting, to just 1 day. WP Admin > s2Member > PayPal Options > Auto EOT Behavior

I added the file s2-hacks.php to your /wp-content/must-use/ plugins folder with this code:

<?php

add_action('ws_plugin__s2member_during_auto_eot_system_during_demote', 's2_custom_eot_demotion_role');
add_action('ws_plugin__s2member_during_paypal_notify_during_subscr_eot_demote', 's2_custom_eot_demotion_role');

function s2_custom_eot_demotion_role(array $vars) {
	$user                 = $vars['user']; // WP_User object instance.
	$role_before_demotion = $vars['existing_role']; // Role ID before demotion by s2Member.

	if ($role_before_demotion === 's2member_level2') {
		// If he was at level 2, demote to 1 and give him 3 months to pay.
		$user->set_role('s2member_level1');
		update_user_option($user->ID, 's2member_auto_eot_time', strtotime('+3 months'));
	} else if ($role_before_demotion === 's2member_level1') {
		// If he didn't pay after 3 months, demote to 0.
		$user->set_role('subscriber'); 
	}
}

I created a test user and gave him the role Current (level 2) and an EOT time in the past, and after a while, wp-cron kicked in and demoted him to Overdue (level 1) with an EOT 3 months ahead. Then I changed his EOT time to the past again, and after a while he got demoted to Subscriber (level 0). So it seems to be behaving as desired.

Please run your own tests, check what I did, and ask me anything you want.

I hope that helps! :slight_smile:

Wow, this looks great, Cristian. Let me have a good look through it overnight and get back to you.

1 Like

So when a new subscriber signs up and they choose either annual or triennial membership, s2Member will assign the correct EOT even though they are signing up to the same level of membership. The custom capabilities will look after that and will identify them in the database with these labels? I performed an export and can see this new field ‘custom capability’. I had no idea that you could use this to differentiate memberships of different lengths.

Also I need to be able to send appropriate reminders to the different members at different times. For example I would want to send a reminder to level 2 members a month before their subscription is due to expire. But with level 1 I would want to send a reminder as soon as it starts, then a month later, then another month later, then just before final demotion. Each of these reminders will contain different content. I haven’t seen where I can send different EOT reminder emails based on the membership level. What do you advise?

I’m just running the same demotion tests that you ran now.

A question that is not directly related to this particular issue.
When one exports the full database from s2Member it comes with a huge amount of information about each user. I am trying to organise for my client to be able to export a list of the database themselves but not to have to wade through all the extra information that is exported. My initial thought was to see if I could get someone to write an Excel macro that would remove extraneous columns and rows and which would convert the UNIX timestamp format of the EOT to something meaningful for the client. Am I on the right track do you think by trying to get a macro written, or do you have any other thoughts?

So when a new subscriber signs up and they choose either annual or triennial membership, s2Member will assign the correct EOT even though they are signing up to the same level of membership.

Correct. The payment details are set by the pro-form shortcode and managed by the payment gateway. The level only manages access to content.

The custom capabilities will look after that and will identify them in the database with these labels? I performed an export and can see this new field ‘custom capability’. I had no idea that you could use this to differentiate memberships of different lengths.

No. Custom capabilities are also to manage access, not payment times. I only gave them those capabiities to use them as labels, so it’d be obvious in the users list the two different groups. Since your client was used to seeing them as separate levels, I thought he might miss that, so I added the custom capabilities. Not required for access in this case, but may make it possible to do fancier things with access if you can tell them apart.

Also I need to be able to send appropriate reminders to the different members at different times. For example I would want to send a reminder to level 2 members a month before their subscription is due to expire. But with level 1 I would want to send a reminder as soon as it starts, then a month later, then another month later, then just before final demotion. Each of these reminders will contain different content. I haven’t seen where I can send different EOT reminder emails based on the membership level. What do you advise?

I’m sorry, the reminders system is general for all, doesn’t filter by level or capabilities… There may be a way to hack it, but I haven’t studied it yet. I agree that it’d be better to have different sequences for each, and I plan to address this in the future, it’s on my list.

I’m just running the same demotion tests that you ran now.

Great :slight_smile:

You’re probably using the Advanced exporter. Try the simper one. it gives less columns. You can also get a more readable export, but keep in mind that it’s not re-importable.

export-1-1000.zip

No, it’s actually from the one you suggest. See attached. This is what gets downloaded when I run the User/Member Exportation, not the advanced one.

My testing worked just as yours did. My level 2 was demoted to level 1 after its EOT was reached and my level 1 was demoted to subscriber when its EOT was reached.

1 Like

Great! :slight_smile:

No, it’s actually from the one you suggest. See attached. This is what gets downloaded when I run the User/Member Exportation, not the advanced one.

Ah ok. Well, you can remove columns from that CSV file after you download it, no problem.

Thought about this some more. I still didn’t find how to have different reminder times depending on the level, but I did remember how you could change the content of those reminders based on the level…

The reminders can handle PHP, so you could add a conditional that gives one content or other to customize the message based on the current level of the user. See: WP Admin > s2Member Pro > PayPal Options > EOT Renewal/Reminder Emails > PHP Code (at the bottom)

So the number of reminders would be the same for both levels, and at the same times, but you could make them say different things depending on the level.

I hope that helps. :slight_smile:

I’m not a PHP programmer but are you saying that I could add this code directly into the EOT reminder email fields:

if ($role_before_demotion === 's2member_level2') {
	echo "this email content for members approaching their regular membership EOT"
	} elseif ($role_before_demotion === 's2member_level1') {
	echo "this email content for members approaching their Overdue EOT"
}

Yes, that can definitely be done, but there are dozens of complex looking columns of data to remove and I would not expect the client to have to, or even to be able to do this each time they wish to generate a report. So I was trying to think of a way to automate this process using an excel macro on the exported spreadsheet. I’ll research this unless you had other suggestions.

1 Like

Yes, you could use something close to that in your email message to customize it.

I’d start by trying what the configuration for new user emails says here: WP Admin > s2Member > General Options > Email Configuration > New User Email Messages > PHP Code

" PHP Code: It is also possible to use PHP tags—optional (for developers). If you use PHP tags, please run a test email with <?php print_r(get_defined_vars()); ?>. This will give you a full list of all PHP variables available to you in this email. The $user variable is the most important one. It’s an instance of the WP_User class (e.g., $user->ID, $user->has_cap(), etc). Please note that all Replacement Codes will be parsed first, and then any PHP tags that you’ve included. Also, please remember that emails are sent in plain text format."

Your conditional will probably be something like this (I haven’t tested it yet, though):

<?php
$user_access_level = c_ws_plugin__s2member_user_access::user_access_level($user);
if ($user_access_level == 's2member_level2') {
   echo 'This email message for members approaching their membership EOT.';
} elseif ($user_access_level == 's2member_level1') {
   echo 'This email message for members approaching their overdue EOT.';
}
?>

Hi Cristian,

Two questions. I want to make a donation as good faith for the assistance you have been giving me. Can you show me how this is best achieved.

Secondly I attempted to use PHP in the EOT reminder fields but when I tried to save them they reverted to the original content i.e. it did not save any of my input.
This is the content that I tried to add to the EOT Renewal/Reminder Subject field:

<?php
$user_access_level = c_ws_plugin__s2member_user_access::user_access_level($user);
if ($user_access_level == 's2member_level2') {
   echo 'Renewal Reminder - Account Expires today';
} elseif ($user_access_level == 's2member_level1') {
   echo 'Final Reminder - Account three months overdue';
}
?>

Then this is the content that I attempted to put in the EOT Renewal/Reminder Message field:

Greetings %%first_name%%,

<?php
$user_access_level = c_ws_plugin__s2member_user_access::user_access_level($user);
if ($user_access_level == 's2member_level2') {
   echo 'It is membership renewal time!
If you have setup an automatic recurring subscription then you can ignore this email!
Otherwise this is a reminder that your account access expires today!';
} elseif ($user_access_level == 's2member_level1') {
   echo 'This is your final reminder to renew your TSAA membership.
After today you will not receive any more reminder emails. Your current membership is now three months overdue.';
}
?>
Fees are $30 per year or $75 for 3 years.

Please log in if you'd like to renew at http://www.tourette.org.au/renewal

TSAA Committee Members are all volunteers working for your interest.
Please show your appreciation by renewing promptly.
Your ongoing support is vital to what we do.

The greater our membership the greater our voice for TS.

This email is auto-generated based on your subscription renewal date. If you have already responded and renewed your subscription please ignore this email.

Not being a PHP programmer I feel like I am flying blind a bit here.

I just tried it in my site and then yours (with the -1 day reminder), and it saved fine. Did you click the “Save All Changes” button at the bottom of the page after the changes?

I want to make a donation as good faith for the assistance you have been giving me. Can you show me how this is best achieved.

Thank you! LIke I said, you don’t have to, but I appreciate if you want to do it anyway. :slight_smile:

The PayPal address is paypal@wpsharks.com.

I had set the day reminder to be zero thinking that the reminder would go out on the day the renewal was actually due. It didn’t like the zero but it didn’t mind the ‘-1’. So I will now test this with a couple of dummy users.

By the way I transferred USD$100 to you for your assistance. You’ve really got me out of a difficult situation and I appreciate it. I also appreciate what you are doing in general to keep s2Member alive. I want a positive relationship with you in case I need to ask you something else!

In fact I do! I have just exported a list of users/members from s2Member on the draftsite and the export csv is significantly reduced from the one that gets exported from the live site. I’m including copies of both as attachments to this post and you will see that the draftsite csv has about 30 columns while the live site csv has nearly 150. This is the first time I have seen this difference and I wonder if it relates to anything you have adjusted. Does it make any sense to you?exports.zip (271.0 KB)

Could be because you probably have the live site’s export tool set to “advanced”, while I changed the draft one to the simpler version. This is what I meant before when I suggested not using the advanced one. Grace time not performing required function

I transferred USD$100 to you for your assistance. You’ve really got me out of a difficult situation and I appreciate it. I also appreciate what you are doing in general to keep s2Member alive. I want a positive relationship with you in case I need to ask you something else!

Thank you very much! :smiley:

I’m very glad I’m being of help. Do keep asking when you need something, I’ll keep trying my best.

You did suggest this before and somehow I must have thought you were referring to something else. My apologies. You are absolutely correct, I did have it set to Advanced. All good.
I’ve setup some test members to see if those EOT reminders get sent out as expected.

1 Like

Great! :smiley:

Let me know how it goes.

By the way, Don, if it’s not too much to ask for, it’d help us a lot if you left us a review over at WordPress. https://wordpress.org/support/plugin/s2member/reviews/?filter=5

Thank you! :smiley: