For a system I was buliding recently I needed the following functionality:

  • Allow accounts to be created with a custom role
  • Limit the custom role to only be able to see a custom post type
  • Stop users with the custom role being able to see other peoples posts when they log in
  • Stop users with the custom role being taken to the profile page by default. I didn’t want the profile to be visible to these users.

Why did I want all this? The system needed to be able to allow affiliates to log in to WordPress and see nothing but the pages they set up. I needed it to be as simple as possible as many of the users would not be familiar with WordPress or any CMS for that matter. That means nothing in the admin area apart from a custom post type (which comprised of a bunch of custom fields) which enabled them to add, edit and delete the posts.

Setting Up Custom Roles and Capabilities in WordPress

This bit was straight forward thanks to the great members plugin by Justin Tadlock. The plugin makes it really easy to create new roles and capabilities. To associate a role with a custom post type in WordPress you need to make use of ‘capability_type’ parameter when you register a custom post type. In my code it looked like this:

register_post_type('affiliate',
    array(
        'labels' => $post_labels,
        'public' => true,
        'supports' => array('title'),
        'capability_type' => 'affiliate'
    )
);

With the members plugin installed and my custom post ready, I needed to setup the roles. The members plugin adds some new links to the users menu; ‘roles’ and ‘add new roles’. I gave the role the name ‘affiliate’ and saved it. I then needed to create custom capabilities for my affiliate post so I created the following capabilities:

  • publish_affiliates
  • delete_affiliate
  • edit_affiliate
  • read_affiliate
  • read_affiliate

Along with these custom capabilities I added the following default capability:

  • read

Removing the Profile Page in WordPress

The next step was to remove the profile page for my custom users. This code does that nicely:

function remove_profile_menu() {
    // Only the Admin can see the profile menu
    if ( !current_user_can('update_core') ) {
        remove_submenu_page('users.php', 'profile.php');
        remove_menu_page('profile.php');
    }
}

add_action('admin_init', 'remove_profile_menu');

Redirecting the User After Login in WordPress

Annoyingly, even with the page removed, users are still redirected to the profile page when they log in so I needed to redirect them somewhere else on login. This bit was easy enough:

function redirect_default_login_page(){
    return site_url() . '/wp-admin';
}

add_filter('login_redirect', 'redirect_default_login_page');

I now had almost everything I needed. The only issue I had left now was that when my users with custom roles logged in, they could see a list of others users affiliate posts. This is no good if you need this information to be private for each account. With thanks to Mark who provided a this great answer I was able to fix this easily enough. Thanks to Mark for the code below:

function posts_for_current_author($query) {
	global $user_level;

	if($query->is_admin && $user_level < 5) {
		global $user_ID;
		$query->set('author',  $user_ID);
		unset($user_ID);
	}
	unset($user_level);

	return $query;
}
add_filter('pre_get_posts', 'posts_for_current_author');