How to show a category post to a specific registered user

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

Leave a Comment