How To Write a Restricted Content Plugin
73There are a lot of sites out there, particularly digital education sites, such as Net Tuts and Blender Cookie, that push out a lot of “premium” content that is only accessible to registered users.
In this tutorial, I’m going to show you some of the basics of writing a WordPress plugin from scratch that will allow you to restrict content on your site to registered users. You will be able to restrict complete pages / posts by clicking a check box or just sections of content using WordPress shortcodes.
Note: I will not be showing how to create a paid membership system, or how to integrate this plugin into a paid membership system, such as aMember. This plugin will deal with choosing which content is restricted, but not how users register. It will use the default WordPress user roles: Administrator, Editor, Author, Subscriber, and None.
1 – Getting Started – The Plugin Basics
WordPress plugin development is very similar to theme development and can employ many of the same tricks to achieve the end goal.
If you are not at all familiar with WordPress plugin development, I recommend you read Writing a WordPress Plugin from the WordPress codex.
2 – The Plugin Header
The first thing to do, once we’re ready to start writing our plugin, is to create a new file called restrict_content.php and to enter all of the plugin’s necessary meta data, such as name, author, description, url, etc.
1 2 3 4 5 6 7 8 9 10 11 | <?php /* Plugin Name: Restrict Content Plugin URI: http://pippinspages.com/freebies/restricted-content-plugin-free/ Description: Restrict Content to registered users only. Version: 1.0 Author: Pippin Williamson Author URL: http://pippinspages.com */ ?> |
If you upload this file to your wp-content/plugins directory and click Activate from the WordPress plugins menu, the plugin will activate fine, though it won’t actually do anything at this time.
3 – Create the Shortcode
Now it’s time to begin really writing the plugin.
First we are going to create a function that will allow us to use WordPress shortcodes to restrict sections of content like this:
[restrict] . . . this is restricted to logged in users . . . [/restrict] |
Paste this below the plugin meta info we entered earlier:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | function restrict_shortcode( $atts, $content = null ) { extract( shortcode_atts( array( 'userlevel' => 'none', ), $atts ) ); if ($userlevel == 'admin' && current_user_can('switch_themes')) { return do_shortcode($content); } if ($userlevel == 'editor' && current_user_can('moderate_comments')) { return do_shortcode($content); } if ($userlevel == 'author' && current_user_can('upload_files')) { return do_shortcode($content); } if ($userlevel == 'subscriber' && current_user_can('read')) { return do_shortcode($content); } if ($userlevel == 'none' && is_user_logged_in) { return do_shortcode($content); } else return '<span style="color: red;">Some content is only viewable by ' . $userlevel . 's</span>'; } add_shortcode('restrict', 'restrict_shortcode'); |
What does this code do?
It first creates a place for us to store options (in the variable $atts), and a place to store the content contained within the shortcode (in the variable $content).
Next, an option is created called userlevel and it is given a default value of none. This option allows us to define which users will be able to see the content inside of the shortcode.
When loading the content, every visitor’s user status must be checked, and only to those whom have sufficient privileges will the content be displayed. This check is done like this:
1 2 3 4 | if ($userlevel == 'admin' && current_user_can('switch_themes')) { return do_shortcode($content); } |
This will check whether the user level is set to admin and if the current user has the ability to switch themes. If both of these are true, the content contained in the shortcode will be displayed. If one of the above checks is not true, then this happens:
1 | else return '<span style="color: red;">Some content is only viewable by ' . $userlevel . 's</span>'; |
Which will display the message: Some content is only viewable by admins
These two checks are done for every user level.
Lastly, we need to make the shortcode available for use by doing this:
1 | add_shortcode('restrict', 'restrict_shortcode'); |
Now we are able to use something like this in our posts / pages:
[restrict userlevel="editor"] . . . this is restricted to logged in users . . . [/restrict] |
The available options are:
- admin
- editor
- author
- subscriber
- none (this is the same as using just [restrict] . . . [/restrict] )
4 – Creating the Meta Box
The next step is to add an option to all posts / pages that will allow us to restrict the entire post / page. This is much better than simply wrapping shortcodes around our entire post / page, even though it would accomplish the same thing.
We will do this by adding a custom meta box to our editor screen. This will be done with multiple functions, all pasted just below the code we already have in our restrict_content.php plugin file.
The first function defines all of the options for our meta box:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | //custom meta boxes $prefix = 'rc'; $meta_box = array( 'id' => 'rcMetaBox', 'title' => 'Restrict this content', 'context' => 'normal', 'priority' => 'high', 'fields' => array( array( 'name' => 'User Level', 'id' => $prefix . 'UserLevel', 'type' => 'select', 'desc' => 'Choose the user level that can see this page / post', 'options' => array('None', 'Administrator', 'Editor', 'Author', 'Subscriber'), 'std' => 'None' ), array( 'name' => 'Hide from Feed?', 'id' => $prefix . 'FeedHide', 'type' => 'checkbox', 'desc' => 'HIde the excerpt of this post / page from the Feed?', 'std' => '' ) ) ); |
We have now created an option for choosing the user level to which we’d like to restrict the content, and an option to hide the content from being displayed (even as an excerpt) in the feed.
Now let’s actually make the meta box display on the editor screen:
1 2 3 4 5 6 7 | // Add meta box function rcAddMetaBoxes() { global $meta_box; foreach (array('post','page') as $type) add_meta_box($meta_box['id'], $meta_box['title'], 'rcShowMetaBox', $type, $meta_box['context'], $meta_box['priority']); } add_action('admin_menu', 'rcAddMetaBoxes'); |
Inside of the add_meta_box command, we are calling all of the options we defined above.
The next step is to make a function that controls how the meta options are displayed. This next function is called by the third variable (rcShowMetaBox) in the above function.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | // Callback function to show fields in meta box function rcShowMetaBox() { global $meta_box, $post; // Use nonce for verification echo '<input type="hidden" name="rcMetaNonce" value="', wp_create_nonce(basename(__FILE__)), '" />'; echo '<table class="form-table">'; foreach ($meta_box['fields'] as $field) { // get current post meta data $meta = get_post_meta($post->ID, $field['id'], true); echo '<tr>', '<th style="width:20%"><label for="', $field['id'], '">', $field['name'], '</label></th>', '<td>'; switch ($field['type']) { case 'select': echo '<select name="', $field['id'], '" id="', $field['id'], '">'; foreach ($field['options'] as $option) { echo '<option', $meta == $option ? ' selected="selected"' : '', '>', $option, '</option>'; } echo '</select>'; break; case 'checkbox': echo '<input type="checkbox" name="', $field['id'], '" id="', $field['id'], '"', $meta ? ' checked="checked"' : '', ' />'; break; } echo '<td>', $field['desc'], '</td><td>', '</tr>'; } echo '</table>'; } |
This will now provide us with a nice layout for our “restrict content” options. At the top of this function we have included a hidden input for the nonce verification. This makes sure that no one edits these options who does not have permission.
Finally, we need to have a function to save our data we have inputed. Once again, copy this into restrict_content.php beneath all of the code you have already entered.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | // Save data from meta box function rcSaveData($post_id) { global $meta_box; // verify nonce if (!wp_verify_nonce($_POST['rcMetaNonce'], basename(__FILE__))) { return $post_id; } // check autosave if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return $post_id; } // check permissions if ('page' == $_POST['post_type']) { if (!current_user_can('edit_page', $post_id)) { return $post_id; } } elseif (!current_user_can('edit_post', $post_id)) { return $post_id; } foreach ($meta_box['fields'] as $field) { $old = get_post_meta($post_id, $field['id'], true); $new = $_POST[$field['id']]; if ($new && $new != $old) { update_post_meta($post_id, $field['id'], $new); } elseif ('' == $new && $old) { delete_post_meta($post_id, $field['id'], $old); } } } add_action('save_post', 'rcSaveData'); |
I’m not going to go into detail about what exactly this code does as it is rather detailed, but essentially it first checks to make sure the updates were made by a person with permission to do so, then checks to make sure that we’ve made changes. If both of these checks come out okay, the data is saved to the database.
That’s it for the meta box.
5 – User Check #1
It is now time to create a series of functions that will each check for whether or not there is a restriction level set and then display the appropriate content (or lack thereof).
These functions are the first of two user checks we will perform.
Let’s first take a look at what one of these functions look like, then we will put them all together.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | function rcMetaDisplaySubscriber($error = ' ') { $custom_meta = get_post_custom($post->ID); $rcUserLevel = $custom_meta['rcUserLevel'][0]; if ($rcUserLevel == 'Administrator' || $rcUserLevel == 'Editor' || $rcUserLevel == 'Author') { echo 'This content is restricted to ' . $rcUserLevel; } else { $error .= ""; return $error; } } |
This function first gets the user level info from the custom meta box we created above and then displays an error message if the user level is set to a value that is above the current user.
Note: the user level of the current user will be determined later.
We need a function like this for each user level, so all together it looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | function rcMetaDisplayEditor($error = ' ') { $custom_meta = get_post_custom($post->ID); $rcUserLevel = $custom_meta['rcUserLevel'][0]; if ($rcUserLevel == 'Administrator') { echo 'This content is restricted to ' . $rcUserLevel; } else { $error .= ""; return $error; } } function rcMetaDisplayAuthor($error = ' ') { $custom_meta = get_post_custom($post->ID); $rcUserLevel = $custom_meta['rcUserLevel'][0]; if ($rcUserLevel == 'Administrator' || $rcUserLevel == 'Editor') { echo 'This content is restricted to ' . $rcUserLevel; } else { $error .= ""; return $error; } } function rcMetaDisplaySubscriber($error = ' ') { $custom_meta = get_post_custom($post->ID); $rcUserLevel = $custom_meta['rcUserLevel'][0]; if ($rcUserLevel == 'Administrator' || $rcUserLevel == 'Editor' || $rcUserLevel == 'Author') { echo 'This content is restricted to ' . $rcUserLevel; } else { $error .= ""; return $error; } } function rcMetaDisplayNone($error = ' ') { $custom_meta = get_post_custom($post->ID); $rcUserLevel = $custom_meta['rcUserLevel'][0]; if (!current_user_can('read') && $rcUserLevel == 'Administrator' || $rcUserLevel == 'Editor' || $rcUserLevel == 'Author' || $rcUserLevel == 'Subscriber') { echo 'This content is restricted to ' . $rcUserLevel; } else { $error .= ""; return $error; } } |
6 – User Check #2
The second user check is the one that is going to run inside of the WordPress loop. Even though I’ve label it User Check #2, it’s actually the first check that is performed. It is run from within the WordPress loop.
Let’s take a look at it, then we will dissect it. Copy the code below into the bottom of your plugin file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | function checkUser() { if (current_user_can('read')) { if (current_user_can('upload_files')) { if (current_user_can('moderate_comments')) { if (current_user_can('switch_themes')) { //do nothing here for admin } else { add_filter('the_content', 'rcMetaDisplayEditor'); } } else { add_filter('the_content', 'rcMetaDisplayAuthor'); } } else { add_filter('the_content', 'rcMetaDisplaySubscriber'); } } else { add_filter('the_content', 'rcMetaDisplayNone'); } } add_action('loop_start', 'checkUser'); |
This is a linear capability check that first tests to see if the logged-in user has the minimum permission level, and if they do, it proceeds onto the second permission level check. At each stage the user either passes or fails.
One of the important things to notice with this user check is that all users, except for administrators, end up having a filter applied to the the_content() function. These filters tie directly into the functions we wrote in the above step with User Check #1.
User Check #2 allows us to determine the permission level of the current user and pass them to the correct function in User Check #1, which will filter the content accordingly.
Now that we have performed both of the user checks, we only have two more functions.
7 – Add Filter to Feed Header
This next function will add a small content filter to the top of all the WordPress feeds that will allow us to hide content from the feed if a post/page is restricted.
At the bottom of your file, put:
1 2 3 4 5 | function rcCheckFeed() { add_filter('the_content', 'rcIsFeed'); } add_action('rss_head', 'rcCheckFeed'); |
8 – Check for “Hide from Feed”
The last thing we need to do to finish up our plugin is to add a small function that will check whether the “Hide from Feed” option is turned on. If it is turned on, we then need to display a message like “This content is restricted to Editors“. If it is not turned on, we do nothing but display the regular content.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | function rcIsFeed($error = ' ') { $custom_meta = get_post_custom($post->ID); $rcUserLevel = $custom_meta['rcUserLevel'][0]; $rcFeedHide = $custom_meta['rcFeedHide'][0]; if (is_feed && $rcFeedHide == 'on') { echo 'This content is restricted to ' . $rcUserLevel . 's'; } else { $error .= ""; return $error; } } |
That’s it! Your Restricted Content plugin is complete!
9 – Going Further
The first thing to do, of course, is to give your new plugin a thorough test run. Next is to extend it to have further capabilities, such as restricted categories.
The complete version of this plugin is available as a free download from my site.
Enjoy!
Enjoy this post? You should follow me on Twitter!
Cool tutorial.
Reference tutorial for me.
Thanks
Useful tutorial, this will also let me learn things like creating meta boxes (am sure there are other tutorials but am too lazy to search ;) ).
And I’m also going over to Pippin’s blog, looks really interesting…
Glad you liked it, Sumesh.
I try to keep things interesting. New update coming later today.
Definitely check it out, plenty more like this to be found! :D
Now it just needs a PayPal subscription plugin that ties in with it. :)
I’ll look into it for the premium version.
thanks for this useful tutorial. Restricting someone is good one and makes me learn to new things from here
Excellent tutorial – I look forward to some info on Paypal integration!
awesome tutorial,
thanks for sharing..
Almost all members access plugins are paid only, it’s great as it’s free.
Thanks for this great tutorial mate!
A very info for creating or editing the plug ins and this will defiantly help a lot in many ways as its going to be the very important factor .We can allow ,disallow and many ways this could be helpfull.
Informative post. Though at present I don’t need of restricting content to my viewers, it will be useful later I feel. I am going to try it out and see whether it works for me. By the way I have a problem. The comments I post are not getting displayed I think its because my URL is health realted and is treated as spam. Plz check to it.
Sorry about your comments being caught. I usually do go through the spam filter, so even the simple fact you have a Gravatar will help any future comments of yours stand out for me! Sorry again though, hopefully it won’t keep happening now!
I usually do go through the spam filter, so even the simple fact you have a Gravatar
I am going to try this out in my blog today. I will first install it as plugin and see how it is, then then i am going to create it. Helped me to know more in wordpress.
I usually do go through the spam filter, so even the simple fact you have a Gravatar will help any future comments of yours stand out for me
This post has proved helpful to me. Thanks and good job !!
Sweet! Thanks for sharing this. An awesome find and a great post to read.
Useful tutorial,i learn how to make a plugin
useful tutorial..thank you pippin ;)
there are some code where its difficult to understand and edit,so this will defiantly easy to get some good editing out of it…we can change in our manner
I’m looking forward to implementing this myself on a current project of mine for our church website.
Excellent, I hope all goes well for you. Be sure to me know if you have any problems :)
Very good article, keep the good job and tanks to share it
It’s good tips for program a WordPress plugin. Nice
Awesome tutorial Pippin!! Definitely going to give this a try as soon as I get a chance!!!
Thanks.
Great tip, I really needed this
Unbelievable tutorial. Now I half understand how to even begin writing a WordPress plugin. I do agree with one of the comments in that all that is left to do is implement a PayPal subscription option :)
Other than that, pure perfection.
I have looked into it, and it’s possible that it may get the feature sometime down the road.
Excellent tutorial, I am very happy to read a quality tutorial on wordpress plugin creation after a very long time.
This will help us a lot to stop or restrict the entire post from the different users .Its necessary to restrict some of the users if the users are not so trust worthy ,such that we can give them the entire permission for what ever they feel….
Nice post
Great tutorial! Loved it!
Thanks for the tips. How do we make it so that the paid content area can still be crawled by Google and other robots ONLY? Is there a simple plugin for that?
thanks for such a good tutorials!
I am very glad to see such information which I was searching for a long time.
Thanks Pippin. Good stuff as usual.
Good stuff mate :) Thnx a lot :)
thanks for such a good tutorials!
Thanks for the heads up and information about this, that is the encourage that I need, am so happy to have found this ,Thanks for the article. I liked reading it.
Inchirieri Apartamente Bucuresti
thanks for this great tutorials…its helped me lot in ma previous project…..thanks Pepin
Valuable information and excellent design you got here!
website seo
Thanks for sharing this Pippim, awesome tutorial :)
I never even thought about writing a restricted content plugin, but after reading this cool article I might think about it.
Great tutorial for me.. I need this tutorial to restric area on my blog.. Thanks
Informative post. Though at present I don’t need of restricting content to my viewers, it will be useful later I feel.
Hey Pippin,
Dude, you really rock these tutorials. One question: are you writing (or providing tutorials) on object-oriented plugin development? Especially with WP 3.0+ and PHP 5.3+.
I’m trying to learn the latest best practices, and most of the tutorials I find are either PHP 4, or don’t use the class/ __construct object-oriented model.
Love to get your thoughts.
I very rarely work with classes, simply because my PHP skills are not great. I’m still learning it, and classes are one of those things I haven’t fully gotten into yet.
I always do my best to keep up on current trends and best practices, so if you have any questions or would like assistance on anything, please feel free to contact me anytime via email at pippin(at)pippinspages(dot)com.
I feel you Pippin. Same thing I’m going through with the learning PHP thing. And the jQuery thing. Oh, and the tinymce thing. ;-)
Only reason I got into all this is because I grabbed a plugin from a tutorial that works fine as is, but when I modify just the variables to match my desired use, it doesn’t work at all. I’m trying to write a plugin that puts a button in the tinymce visual editor that launches a dialogue and creates a catalog entry with lightbox-able thumbnails.
By the way, please forgive me if my comment about best practices sounded negative in any way. I should’ve said, from all the hours of research through many conflicting tutorials, it SEEMS as though using object-oriented plugins is becoming a recommended methodology so I’m trying to learn it, but I am still essentially a newbie and haven’t found anything I can understand in lay terms.
I can try and help you out with it if you want.
No worries, wasn’t taken negative at all :)
Hi,
this is a great plugin. I’ll featured it on WordPress Channel soon.
I edited this to add another role and it works fine.
Do you plan to make it translatable with Poedit ? If you do so, please contact me to get the French version. ;)
Thanks! Glad you like it!
I would like to update it with Poedit, but I have a hard time finding enough time to make the updates. If you’re interested in helping out, I’d be more than happy to work with you. Contact me via email: pippin(at)pippinspages(dot)com
Hi,
I could make the french translation but I’m not able to update the plugin to make it compatible with Poedit (don’t have skills in this domain).
But email me with if you do so or anyone, to let me do the fr translation. ;)
Send me an email and I will see what I can do.
This is really cool – I never thought I’d be able to write a WP plugin but this actually looks doable (and useful). Thanks!
Never know until you try :)
Great Plugin cause it’s just doing what you need to restrict access and not so overfunctionalized like UAM or Role Scoper.
But there’s something I couldn’t figure out (maybe because I never played with add_filter or something like that):
Is there a way to alter the code, so that in archives the restricted content isn’t outputted at all? I have an archive page where I call the_post_thumbnail, the_permalink and the_excerpt inside the loop, and want that completely hidden for not-logged-in users.
I guess there’s an easy way to do this like add_filter(‘the_content’, ‘removeeverythingfromthispost’); :)
You could do that by altering each of the filter functions to something like this:
function rcMetaDisplayNone($error = ' ')
{
$custom_meta = get_post_custom($post->ID);
$rcUserLevel = $custom_meta['rcUserLevel'][0];
if (!current_user_can('read') && $rcUserLevel == 'Administrator' || $rcUserLevel == 'Editor' || $rcUserLevel == 'Author' || $rcUserLevel == 'Subscriber')
{
if (is_archive()) {} else {
echo 'This content is restricted to ' . $rcUserLevel;
}
}
else
{
$error .= "";
return $error;
}
Thanx mate, a really useful tutorial.
I need to build a restricted area for a project and this is the best solution I’ve found.
BTW all your tutorials are amazing.
Informative post. Though at present I don’t need of restricting content to my viewers, it will be useful later I feel.
I learned a lot with this tutorial. Looking forward for future free tutorials.
thanks for the great tutorial.will help us a lot to stop. This is really cool – I never thought
Is there a way that i can display content of a page to a user that is logged in using username?
Example:
On the same page there are 5 lines of text:
Line 1 with text
Line 2 with text
Line 3 with text
Line 4 with text
Line 5 with text
Line 1 must only display if user 1 is logged in
Line 2 must only display if user 2 us logged in
Line 3 must only display if lune 3 is logged in
ect.
Mvg,
Avinash Bhageloe
See my comment below
Yes, do it like this:
// gets the current user
global $current_user;
get_currentuserinfo();
if($current_user->ID == 1) {
// display content for user ID 1
}
Pippin,
I am using WordPress as a CMS. In the backand i can only use Wysiwyg and HTML. Is there a way that i can implement the code in the backand? Or must i place the code in the page.php file?
Mvg,
Avinash Bhageloe
Pippin,
I am using WordPress as a CMS. In the backand i can only use Wysiwyg and HTML. Is there a way that i can implement the code in the backand? Or must i place the code in the page.php file?
The easiest way for you to do this will be to use a plugin that allows you to run PHP from inside of the post content. 5 Sec Run PHP is a great one.
Pippin,
Thanx a lot for ur help :)
I used another free version of PHP in the backenf of wordpress and it’s working great.
Thanx a lot my friend :)
Nice tips for WorldPress. I love it. Thanks.
This is a very useful tutorial, greatly illustrated and well explained. Thanks.
This is a really great and useful tutorial ! Thanks Pippin
Pro Blog Design, may be its new idea, am using WordPress as a CMS. In the backand i can only use word press, But try to learn pro blog design..