Restrict all pages except

We are using s2Member Pro for a newsletter web site.

The newsletter features two or three articles per issue that are available for free to subscribers, and on a pay per article basis for nonsubscribers. To do this we duplicated the content and split it into two sites:
http://passingbucks.com/newsletter/
and
http://passingbucks.com/newsletter/premium/

This has been working great with all pages and posts on the premium site protected except, of course, the membership page.

As long as we were only using PayPal for subscriptions, everything worked fine. Adding the capability to accept Stripe has proven to be a huge pain.

Putting the page with the Stripe form on the premium site makes it unavailable unless someone already has a subscription, which is useless.

I thought I would be clever and put the page with the Stripe form on the newsletter site, but it has to be on the premium site, or the subscription gets entered into the database on the newsletter site, which is also useless.

Of course, I could, in theory, simply remove the all restriction from pages on the premium site and enter each restricted page ID individually. I could also, in theory, empty an Olympic size swimming pool using a thimble. Ok, it may not be quite that bad, but you get the idea.

Researching the problem I came across a solution that involved modifying page.php for the theme. Ok. Sounds good. Except, both the newsletter and premium sites use the same theme.

What I really need is a way to restrict all pages on the premium site except the membership page and the two Stripe form pages (one for a six moth subscription, the other for a year).

Or if there were a way to handle the Stripe payment offsite the way PayPal payments are handled, that would be great.

Any suggestions???

Try this. Put this code in an mu-plugin or your (child) theme’s functions.php file:

function kts_list_page_ids() {
	$pages = get_all_page_ids();
	echo '<pre>';
	echo json_encode( $pages );
	echo '</pre>';
}
add_shortcode( 'list-page-ids', 'kts_list_page_ids' );

Then put the shortcode [list-page-ids] on a page, save and look at it on the front-end. Copy and paste the results into a plain text program and do a search and replace to remove all the ".

Now you have a perfectly formatted list of all the IDs of your pages. Just remove the IDs of the pages where you want to put your Stripe forms (or do this before you create those pages) and then post the list into the relevant field in s2Member.

Then remove the code and shortcode.

This empties the pool for the time being, but it doesn’t really solve the problem since the pool is being continually refilled. I will still have to manually add every new page to the list.

I need a way to to either:

  1. create an exception to restrict all, or
  2. process Stripe payments outside of the site the way PayPal payments are processed.

As many times as I have seen other people post requests for exceptions to restrict all, it seems like something that should be added to s2Member Pro.

We also sell books from the site and have set up Stripe to take payments using a form not on the site. If I could integrate that with s2Member it would solve the problem.

A simpler way to temporarily empty the pool is to:

  • Use the Show IDs plugin.
  • Go to Pages>>All Pages
  • Copy each page of pages and paste the results to an Excel spreadsheet.
  • Once all of the pages are copied and pasted, copy the ID column and paste it into a new Word document. It will paste as a list with an extra line between each number.
  • In Word find “^p^p” and replace with “,” (do not use the " marks).
  • Copy and replace the results to s2Member Pro>>Restriction Options>>Page Access Restrictions>>Pages That Require Level #1 Or Higher:

This is a workaround, but does not solve the problem.

Both methods are possible, but not without custom code.

As for constantly refilling the pool, I would still do it the way I have suggested. Then I’d write a function to handle each new page as it’s added.

That will be much more efficient than running a function on every page load that will have to check a list of all pages, substract a couple, and then ensure that the relevant ones are protected. In fact, I wouldn’t be at all surprised if that’s the reason such a method is not included in s2Member. It wouldn’t scale at all. And then users would be complaining that their sites are really slow or keep crashing.

If you think that’s simpler, fine. It’s your site.

I considered it (though I’d use the Reveal IDs plugin: it’s much faster) but I’d much prefer to do it the way I suggested.

“Both methods are possible, but not without custom code.”

As many times as I have seen this problem come up in WP Sharks, and its predecessor, the ability to restrict all except should be standard.

You say:
“That will be much more efficient than running a function on every page load that will have to check a list of all pages, substract a couple, and then ensure that the relevant ones are protected. In fact, I wouldn’t be at all surprised if that’s the reason such a method is not included in s2Member. It wouldn’t scale at all. And then users would be complaining that their sites are really slow or keep crashing.”

Is it really much more efficient to read through a list of a hundred or so pages every time to see if the page is protected than to read through a list of three to see if it is not protected? That is another reason that the ability to restrict all except should be standard.

That would work, I agree. But what it would also mean is that s2Member would have to utilize two methods of storing protections: either a list of protected pages or a list of unprotected pages. While that can certainly be coded, years on this and other forums tell me exactly where that would lead: to far more questions about why the protections aren’t working as expected because users would get confused about which option does what.

To get what you want without the accompanying support nightmare, I suspect that what is really needed is a filter to override a protection. That way, protections could be set to ALL (one entry, not a list) and then the filter would let you override that protection for specific pages. (You can already do that for individual users, but it won’t overcome the protection if someone is not logged in.) Whether that would run into problems with WP’s nonce system I don’t know.

Here’s the filter (to be placed in an mu-plugin):

<?php
function kts_update_page_options( $options ) {
	// choose the pages that you don't want protected
	if ( !is_home() && !is_front_page() && !is_page( array( 31, 7407 ) ) ) {
		return $options;
	}
	unset( $options['level0_pages'] ); // or
	// unset( $options['level1_pages'] ); //choose which you need
	return $options;
}
function kts_options_init() {
	add_filter( 'option_ws_plugin__s2member_options', 'kts_update_page_options' );
}
add_action( 'parse_query', 'kts_options_init' );

I have tested it quite a bit now, and I haven’t found any problems with nonces or cookies or anything else. And, because it’s filtering the options table, it’s also extremely fast.