How to show a category post to a specific registered user

I’m working a private blog and I’d like to know if this can be done with any other plugin or any other way:
Lets say we have 3 categories: CA, CB and CC, and 3 users, UA, UB and UC, all of them can post but only in a particular category, UA in CA and so on. Now when one of them login to see the blog, this will only shows the post category which he was allowed to for that user.
Any suggestion?

PD: Allow Categories Plugin was supposed to do that but it does not work at all in wp 3.4.2 and it has not been updated long time ago.

Related posts

Leave a Reply

2 comments

  1. This is awesome material for a plugin. This answer will also include how to associate the user with the category (it’s hard to give you a solution without knowing that).

    Before we get started, the real meat is in step four (way at the bottom). Skip to that if you don’t need a way to associate categories with users.

    So first off, let’s wrap everything up in a class. Our class with a static init method that adds actions and such as well as a few class constants.

    <?php
    WPSE65959_User_One_Cat::init();
    
    class WPSE65959_User_One_Cat
    {
        /**
         * Nonce name.
         *
         */
        const NONCE = 'wpse65959_nonce';
    
        /**
         * The user meta key we'll use
         *
         */
        const KEY = 'wpse65959_category';
    
        /**
         * The taxonomy we'll use.  Just 'category' in this case.
         *
         */
        const TAX = 'category';
    
        public static function init()
        {
            // add actions here
        }
    }
    

    Step One: Add a Field to the User Edit Page

    We’ll hook into edit_user_profile which will only show when editing other users profiles. You’ll never see it when editing your own profile, but you will see it when editing other users. Our field will grab all the current categories and put them in a drop down menu. We’ll also output a nonce field that we’ll check later on saving the user.

    <?php
    class WPSE65959_User_One_Cat
    {
        // snip snip
    
        public static function init()
        {
            add_action(
                'edit_user_profile',
                array(__CLASS__, 'show_field')
            );
        }
    
        public static function show_field($user)
        {
            $terms = get_terms(self::TAX, array('hide_empty' => false));
    
            wp_nonce_field(self::NONCE . $user->ID, self::NONCE, false);
    
            echo '<h4>';
            esc_html_e('User Category', 'wpse65959');
            echo '</h4>';
    
            printf('<select name="%1$s" id="%1$s">', esc_attr(self::KEY));
            echo '<option value="">----</option>';
            foreach($terms as $t)
            {
                printf(
                    '<option value="%1$s" %2$s>%3$s</option>',
                    esc_attr($t->term_id),
                    selected(get_user_meta($user->ID, self::KEY, true), $t->term_id, false),
                    esc_html($t->name)
                );
            }
            echo '</select>';
        }
    }
    

    The other side of that field is that we need to save it. Do do that, hook into edit_user_profile_update. The function will verify the nonce and make sure the current user has permission to edit the user.

    <?php
    class WPSE65959_User_One_Cat
    {
        // snip snip
    
        public static function init()
        {
            // snip snip
    
            add_action(
                'edit_user_profile_update',
                array(__CLASS__, 'save')
            );
        }
    
    
        public static function save($user_id)
        {
            if(
                !isset($_POST[self::NONCE]) ||
                !wp_verify_nonce($_POST[self::NONCE], self::NONCE . $user_id)
            ) return;
    
            if(!current_user_can('edit_user', $user_id))
                return;
    
            if(isset($_POST[self::KEY]) && $_POST[self::KEY])
                update_user_meta($user_id, self::KEY, absint($_POST[self::KEY]));
            else
                delete_user_meta($user_id, self::KEY);
        }
    }
    

    We now have a way to associate a user with a category.

    Step Two: Remove the category meta box

    Hook into add_meta_boxes_post. If the user is not an admin, remove the category box so authors can’t change category.

    <?php
    class WPSE65959_User_One_Cat
    {
        // snip snip
    
        public static function init()
        {
            // snip snip
    
            add_action(
                'add_meta_boxes_post',
                array(__CLASS__, 'remove_metabox')
            );
        }
    
        public static function remove_metabox()
        {
            if(current_user_can('manage_options'))
                return; // this is an admin.  Admins can do what they want.
    
            remove_meta_box(
                'categorydiv',
                'post',
                'side'
            );
        }
    }
    

    Step Three: Change the Default Category for Non-Admins

    If the user isn’t an admin, they won’t see the category meta box, so we need to make sure that their posts go in the right category. Hook into pre_option_default_category to accomplish that.

    <?php
    class WPSE65959_User_One_Cat
    {
        // snip snip
    
        public static function init()
        {
            // snip snip
    
            add_filter(
                'pre_option_default_category',
                array(__CLASS__, 'default_cat')
            );
        }
    
        public static function default_cat($false)
        {
            if(current_user_can('manage_options'))
                return $false; // don't change default category for admins
    
            if($cat = get_user_meta(wp_get_current_user()->ID, self::KEY, true))
                return $cat; // we have a default category for this user.
    
            return $false; // no default category, return the original value
        }
    }
    

    Step Four: Alter the Query

    With a way to associate users with a category, we can now alter the query to show only the posts in their category.

    Hook into request. Check if the user is an admin, and alter the query to include only their category if not.

    <?php
    class WPSE65959_User_One_Cat
    {
        // snip snip
    
        public static function init()
        {
            // snip snip
    
            add_filter(
                'request',
                array(__CLASS__, 'request')
            );
        }
    
        public static function request($vars)
        {
            if(current_user_can('manage_options'))
                return $vars; // admins can view whatever
    
            // if the user has a default category, make sure they only see that category
            if($cat = get_user_meta(wp_get_current_user()->ID, self::KEY, true))
                $vars['cat'] = $cat;
    
            // handle not having a category associated with them here
    
            return $vars;
        }
    }
    

    All of the above as a plugin

  2. That’s actually pretty easy with WP on board functions and the »Template Hierarchy«.

    You can – depending on your needs – target the single.php and category-*.php templates.

    Toolkit: Needed data

    First, we need to wp_get_current_user(). Then we can do several checks, depending on whatever you want to check against. For details, do a var_dump( wp_get_current_user() ); and compare your users to see what data is available and what you can check against reliable. Hint: The user ID and the user_login are always required and can’t be changed.

    Lock-Out effect and reroute

    Then, you just need to do the check on top of your template, right below the call to get_header(); for example.

    // redirect all users, except the one with the ID of 5 to the index.php page
    if ( 5 != wp_get_current_user()->ID )
    {
        wp_redirect( home_url( '/' ) );
        exit;
    }
    

    You could also redirect him to his author page and list all his allowed categories there.

    Alter the query

    Another option would be to intercept the query, right before posts get fetched from the DB with a check for the user ID – see details in other questions using posts_clauses-filter.

    Different template for different user

    You could also simply intercept the template_redirect hook, like explained in this answer.