Unlocking Pages with Custom User Roles in WordPress

Unlocking Pages with Custom User Roles in WordPress

Hello, fellow WordPress enthusiasts! Have you ever wondered how you can take full control over who gets to see what on your WordPress site? Today, I'm going to share the story of how I created a custom WordPress plugin that allows you to do just that. And guess what? You can easily replicate this functionality on your own website!

The Journey Begins: Why Did I Create This Code?

Once upon a time, I was managing multiple projects with various team members who had different roles within the organization. We used WordPress as the platform for our internal communication and documentation. However, it quickly became a challenge to manage who had access to what. The default user roles in WordPress—like Editor, Author, and Subscriber—were too broad for our specific use case. I thought, "There's got to be a better way!"

And so, armed with my development skills and a cup of coffee, I took it upon myself to solve this issue. I decided to create a custom plugin that would allow me to specify which user roles could access specific pages. It was an exhilarating process, full of coding, debugging, and, well, more debugging.

So, How Does It Work?

Before we dive into the code, let's outline what we want to achieve. We need:

  1. A new meta box in the WordPress Page editor where you can select which user roles have access to the page.

  2. A mechanism to check a user's role when they try to access a page and redirect them if they don't have the required role.

Sounds fun, right? Let's get to it!

Step 1: Add a Meta Box for Role Selection

Firstly, we use WordPress hooks to add a meta box on the page editor screen. This meta box will contain checkboxes for all the available user roles.

// Add meta box for role selection
function add_role_access_metabox() {
    add_meta_box(
        'role_access_metabox', // Meta box ID
        'Role Access', // Title
        'role_access_metabox_callback', // Callback function
        'page', // Post type
        'side' // Context
    );
}
add_action('add_meta_boxes', 'add_role_access_metabox');
  • Meta box ID: A unique identifier for the meta box.

  • Title: The title that appears on the meta box.

  • Callback function: The function that outputs the content of the meta box.

  • Post type: Specifies that this meta box is for 'page'.

  • Context: Specifies that this meta box should appear on the side of the editor.

Step 2: Define What's Inside the Meta Box

The meta box will display checkboxes for each user role. When you select a checkbox, the corresponding role will have access to the page.

// Meta box callback function
function role_access_metabox_callback($post) {
    // ... code ...
    foreach ($all_roles as $role => $details) {
        // ... code ...
    }
}

In the above code, $all_roles holds an array of all user roles. We loop through each role to generate a checkbox. Simple yet effective!

Step 3: Save User Roles as Metadata

After selecting which roles can access the page, we need to save this information.

// Save post meta data
function save_role_access($post_id) {
    // ... code ...
    update_post_meta($post_id, '_custom_allowed_roles', $new_roles);
}
add_action('save_post', 'save_role_access');

Here, we save the selected roles as metadata for the page.

Step 4: Implement Access Control

Lastly, we add a mechanism to check if a user has the required role to view a page.

// Redirect users without access
function check_page_access() {
    // ... code ...
    if (empty($allowed)) {
        wp_redirect(home_url());
        exit;
    }
}
add_action('wp', 'check_page_access');

If a user tries to access a page they don't have permission to view, they are redirected to the home page.

And there you have it, folks! You can now specify which user roles have access to individual WordPress pages.

Conclusion

It's empowering to have complete control over who can access your content. By using this custom plugin, you can fine-tune page visibility to specific user roles, making your WordPress website a more secure and organized space.

Here's the complete code for your perusal:

<?php
/**
 * Plugin Name: Custom Role Access
 * Description: Limit page access by user roles.
 * Version: 1.0
 * Author: Theo van der Sluijs
 */

// Add meta box for role selection
function add_role_access_metabox() {
    add_meta_box(
        'role_access_metabox',
        'Role Access',
        'role_access_metabox_callback',
        'page',
        'side'
    );
}
add_action('add_meta_boxes', 'add_role_access_metabox');

// Meta box callback function
function role_access_metabox_callback($post) {
    $roles = get_option('custom_allowed_roles');
    $roles = is_array($roles) ? $roles : [];

    $all_roles = get_editable_roles();
    $selected_roles = get_post_meta($post->ID, '_custom_allowed_roles', true);
    $selected_roles = is_array($selected_roles) ? $selected_roles : [];

    wp_nonce_field('role_access_metabox', 'role_access_metabox_nonce');
    foreach ($all_roles as $role => $details) {
        $name = translate_user_role($details['name']);
        echo '<input type="checkbox" name="custom_allowed_roles[]" value="' . esc_attr($role) . '"';
        if (in_array($role, $selected_roles)) {
            echo ' checked="checked"';
        }
        echo '> ' . esc_html($name) . '<br>';
    }
}

// Save post meta data
function save_role_access($post_id) {
    if (!isset($_POST['role_access_metabox_nonce']) || !wp_verify_nonce($_POST['role_access_metabox_nonce'], 'role_access_metabox')) {
        return;
    }
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
        return;
    }
    if (isset($_POST['post_type']) && 'page' == $_POST['post_type']) {
        if (!current_user_can('edit_page', $post_id)) {
            return;
        }
    }
    $new_roles = isset($_POST['custom_allowed_roles']) ? $_POST['custom_allowed_roles'] : [];
    update_post_meta($post_id, '_custom_allowed_roles', $new_roles);
}
add_action('save_post', 'save_role_access');

// Redirect users without access
function check_page_access() {
    if (is_page() && !is_user_logged_in()) {
        global $post;
        $selected_roles = get_post_meta($post->ID, '_custom_allowed_roles', true);
        if (is_array($selected_roles) && !empty($selected_roles)) {
            wp_redirect(home_url());
            exit;
        }
    }
    if (is_page() && is_user_logged_in()) {
        global $post, $current_user;
        $selected_roles = get_post_meta($post->ID, '_custom_allowed_roles', true);
        if (is_array($selected_roles) && !empty($selected_roles)) {
            $user_roles = $current_user->roles;
            $allowed = array_intersect($selected_roles, $user_roles);
            if (empty($allowed)) {
                wp_redirect(home_url());
                exit;
            }
        }
    }
}
add_action('wp', 'check_page_access');
?>

I hope you found this tutorial exciting and useful. Do you have any questions or something to add? Feel free to comment below! Until next time, happy coding!

Did you find this article valuable?

Support Theo van der Sluijs by becoming a sponsor. Any amount is appreciated!