Snippets

If you are a developer here you can find a bunch of snippets provided by the Members plugin. Not a developer? The free WPCode plugin lets you add any of these without editing theme files.

  • Checking if the current user has a capability
  • Checking if a user has a role
  • Need the old user levels system?
  • Registering capabilities
  • Registering cap groups
  • Protecting new posts by default
  • Hide protected posts from search and archives
  • Working with content permissions in code
  • Changing a user’s roles in code

Checking if the current user has a capability

In plugins and your theme template files, you might sometimes need to check if the currently logged in user has permission to do something. We do this by using the WordPress function current_user_can(). The basic format looks like this:

<?php if ( current_user_can( 'capability_name' ) ) echo 'This user can do something'; ?>

For a more practical situation, let’s say you created a new capability called read_pages. Well, you might want to hide the content within your page.php template by adding this:

<?php if ( current_user_can( 'read_pages' ) ) : ?>
  <?php the_content(); ?>
<?php endif; ?>

Only users with a role that has the read_pages capability will be able to see the content.

Checking if a user has a role

Before beginning, I want to note that you really shouldn’t do this. It’s better to check against capabilities. However, for those times when you need to break the rules, you can do so like:

if ( members_user_has_role( $user_id, $role ) )

Or, you can check against the current user:

if ( members_current_user_has_role( $role ) )

Need the old user levels system?

Some plugins and themes might rely on the old user level system in WordPress. These were deprecated in WordPress version 2.1 and should not be used at all. WordPress still has minimal legacy support for these, but I highly suggest contacting your theme/plugin author if user levels are being used.

By default, the levels aren’t shown. They still exist, but are tucked away behind the scenes. While not recommended, if you need to control who has what level (levels are just capabilities), add this to your plugin or your theme’s functions.php:

add_filter( 'members_remove_old_levels', '__return_false' );

Registering capabilities

If you’re a plugin developer with custom capabilities, beginning with version 2.0.0 of Members, you can register your capabilities with Members. Essentially, this allows users to see your capabilities in a nicely-formatted, human-readable form (e.g., Publish Posts instead of publish_posts). This also means that it can be translated so that it’s easier to understand for users who do not read English.

add_action( 'members_register_caps', 'th_register_caps' );

function th_register_caps() {
  members_register_cap( 'your_cap_name', array(
    'label' => __( 'Your Capability Label', 'example-textdomain' ),
    'group' => 'example',
  ) );
}

The group argument is not required, but will allow you to assign the capability to a cap group.

Registering cap groups

Members groups capabilities so that users can more easily find them when editing roles. If your plugin has multiple capabilities, you should consider creating a custom cap group.

add_action( 'members_register_cap_groups', 'th_register_cap_groups' );

function th_register_cap_groups() {
  members_register_cap_group( 'your_group_name', array(
    'label'    => __( 'Your Group Label', 'example-textdomain' ),
    'caps'     => array(),
    'icon'     => 'dashicons-admin-generic',
    'priority' => 10,
  ) );
}

The arguments for the array are:

  • label – An internationalized text label for your group.
  • caps – An array of initial capabilities to add to your group.
  • icon – The name of one of core WP’s dashicons or a custom class (would need to be styled by your plugin in this case).
  • priority – The priority of your group compared to other groups. 10 is the default.

Note that custom post types are automatically registered as groups with Members. So, if you want to do something custom with that, you simply need to unregister the group before registering your own.

members_unregister_cap_group( "type-{$post_type}" );

Protecting new posts by default

If you want new posts and pages to start out restricted, so nothing is published to the public by accident, you can pre-select roles in Content Permissions. This example selects every role:

add_filter( 'members_default_post_roles', function() {
    return array_keys( wp_roles()->role_names );
} );

To select only some roles, return their slugs instead, like array( 'subscriber', 'customer' ).

This only affects new posts. Existing posts keep their current settings, and you can still change the roles on any post before saving. Roles you add later aren’t added to posts that were already saved.

To protect only one post type, check the post ID the filter receives. This example protects new events and leaves everything else alone:

add_filter( 'members_default_post_roles', function( $roles, $post_id ) {
    if ( 'tribe_events' === get_post_type( $post_id ) ) {
        return array( 'subscriber' );
    }

    return $roles;
}, 10, 2 );

Hide protected posts from search and archives

Content Permissions hides a post’s content, but its title still shows in search results, archives, and your blog page. This snippet leaves protected posts out of those lists for visitors who can’t view them:

add_action( 'pre_get_posts', function( $query ) {
    if ( is_admin() || ! $query->is_main_query() ) {
        return;
    }

    if ( ! ( $query->is_search() || $query->is_archive() || $query->is_home() ) ) {
        return;
    }

    $protected = get_posts( array(
        'post_type'      => 'any',
        'posts_per_page' => -1,
        'fields'         => 'ids',
        'meta_key'       => '_members_access_role',
    ) );

    $hidden = array_filter( $protected, function( $post_id ) {
        return ! members_can_current_user_view_post( $post_id );
    } );

    if ( $hidden ) {
        $query->set( 'post__not_in', array_merge( (array) $query->get( 'post__not_in' ), $hidden ) );
    }
} );

It only changes your theme’s main list of posts on those pages. Other post lists, like a “Latest Posts” block, aren’t affected. On sites with thousands of protected posts, this extra lookup on every search and archive page can add up.

Working with content permissions in code

Content Permissions stores each allowed role as its own _members_access_role post meta row. Use these functions instead of writing the meta yourself:

// The roles allowed to view a post (an array of role slugs).
$roles = members_get_post_roles( $post_id );

// Can the current user (or a specific user) view a post?
members_can_current_user_view_post( $post_id );
members_can_user_view_post( $user_id, $post_id );

// Replace a post's roles, or add and remove one at a time.
members_set_post_roles( $post_id, array( 'editor', 'subscriber' ) );
members_add_post_role( $post_id, 'subscriber' );
members_remove_post_role( $post_id, 'subscriber' );

If you import posts, don’t save the roles as a single serialized array; add one _members_access_role row per role, or call members_set_post_roles() after the import.

Developers can also change the result of any view check with the members_can_user_view_post filter, which receives $can_view, $user_id, and $post_id.

Changing a user’s roles in code

Members uses WordPress’ own role functions, so use them directly:

$user = new WP_User( $user_id );

$user->set_role( 'subscriber' );  // Replace all roles with one.
$user->add_role( 'editor' );      // Add a role.
$user->remove_role( 'editor' );   // Remove a role.

To check a user’s roles, use members_user_has_role( $user_id, $role ) or members_current_user_has_role( $role ), described above.