Category: Snippets
This article also touches on: Admin metaboxes, Using post_meta
Members Only
Recently, I was tasked with coding a ‘members only’ site which required a login to view all but a few pages. This turned out to be a surprisingly simple task, so I thought I’d share the code here. The job broke down into three tasks:
- Allow anyone who’s logged in or else redirect to the Login page.
- Otherwise, allow if the current page is authorized for public view.
- Add a metabox that enables admin to grant public access to any page / post.
The site was also using the extraordinarily well-engineered WooCommerce plugin (if you’re looking into any other e-commerce solution, stop now!). So you’ll see a couple of helper functions which you can omit or replace easily.
1. Allow anyone who’s logged in / redirect to the Login page.
I put this at the top of my ‘header.php’ file. I could get away with this because all my display templates use the same header. I suppose you could wrap this in a function, then hook that function into the ‘init’ action; the important thing is: it must occur before any output has been sent to the browser.
if (!is_user_logged_in() && !wpcx_can_access_nologin($post->ID)) { $account_pageid = get_option( 'woocommerce_myaccount_page_id' ); if ($account_pageid) { wp_redirect( get_permalink($account_pageid)); exit; } }
This calls the function defined in the next block (wpcx_can_access_nologin) and runs if the user isn’t logged in and the page isn’t public.
Also, get_option( 'woocommerce_myaccount_page_id' is the WooCommerce login page ID. Replace this with your own page ID if you’re not using WooCommerce.
2. Check if the page is public.
Stick this in your ‘functions.php’ file somewhere:
function wpcx_can_access_nologin($post_id) { // frontpage and all account pages are exceptions if ( is_front_page() || is_home() ) return true; if ( function_exists('is_account_page') && is_account_page() ) return true; global $post; // now check for 'wpcx_nologin_allowed' meta key if ( get_post_meta($post->ID,'wpcx_nologin_allowed',true) ) return true; return false; }
The one line containing is_account_page() is another WooCommerce reference, which you can replace with some boolean check to see if the current page is indeed the login page. This function simply looks for a meta value which tells us if the page is public or not (defined in the next step).
3. Add a metabox that grants public access to any page / post.
We’re hooking into some admin actions here, so we need three functions: one that checks if it’s appropriate to make this page / post public, another that presents the checkbox, and a third which saves the checkbox value when submitted. All these go in your ‘functions.php’ file.
Incidentally, this is pretty good general code for adding any kind of checkbox to a particular kind of admin panel, which can be acted upon by your frontend display code. This might be worth close examination, so I’ll explain in detail in the next section.
add_action( 'add_meta_boxes', 'my_meta_boxes' ); function my_meta_boxes() { switch( get_post_type() ): case 'page': case 'post': case 'attachment': add_meta_box('nologin_allowed','Permit Access Without Login?','add_nologin_allowed',get_post_type(),'side'); break; endswitch; }
We enable public access only to Pages, Posts and Attachments. As you may know, WordPress organizes lots of other things, and permits customization, using the ‘post’ class. So this hooked function ensures our metabox only appears on the appropriate panel — otherwise, it might appear on the ‘Menu Item’ admin panel, for instance, or some other customized panel.
Next, the metabox:
function add_nologin_allowed($post) { $meta = get_post_meta($post->ID,'nologin_allowed',true); wp_nonce_field( plugin_basename( __FILE__ ), 'nologin_nonce' ); ?><input type="checkbox" checked="checked" name="nologin_allowed" value="1" /> <label for="nologin_allowed">Allow visitors to view this page without logging in.</label> <?php }
Simply a checkbox. I’ve arbitrarily given it a value of ’1′ but you could assign any value you like, then check that value in your frontend display code.
Finally, the save code:
function save_my_meta_boxes($postid) { if ( !current_user_can( 'edit_post', $post_id ) ) return; if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return; if ( !wp_verify_nonce( $_POST['nologin_nonce'], plugin_basename( __FILE__ ) ) ) return; if ( $_POST['nologin_allowed']) { update_post_meta($postid,'nologin_allowed',$_POST['nologin_allowed']); } else { delete_post_meta($postid, 'nologin_allowed'); } }