Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

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.

share|improve this question
add comment

2 Answers

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.

share|improve this answer
    
Ah, but that doesn't solve the "UA can only post in category CA" problem. –  chrisguitarguy Sep 22 '12 at 15:45
1  
@chrisguitarguy That's a second/different question. I answered the main question here (see OPs title). From the OPs question: »all of them can post but only in a particular category« –  kaiser Sep 22 '12 at 16:19
add comment

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

share|improve this answer
    
+1 (as always) One Note: Currently (just read the code), every user could choose his own category, right? This would also mean, that the user could temp. switch to another cat, edit/view other users posts and then switch back again. I'd wrap that profile field into a manage_options cap.-check. –  kaiser Sep 22 '12 at 17:14
    
Nope. edit_user_profile will not show up when you view your own profile. So users won't see it. Only the admin will see it when editing other's profiles. :) Same story for edit_user_profile_update only fires when updating another's profile. –  chrisguitarguy Sep 22 '12 at 17:21
1  
Ah, damn. Mixed the profile/edit filters ... again :) –  kaiser Sep 22 '12 at 17:32
    
Hi in this case the users are created by the admin and they will only be allowed to post to a specific category assigned by the admin too, then they can see the post in the private blog but only its own category. For categories assigned to users I used a couple of plugins: Restrict Category and Author Category so that they are force to publish in that particular category. Unfortunally I'm not a coder so I have to rely on plugins, may be modify if I'm clear where to do it. For example in step four I'm not sure where to insert the code. Or the way to implement the user-one-cat.php as a plugin. –  miguelalas Sep 22 '12 at 17:48
    
So, you can right click here and "Save Link As" to get a PHP file. Upload that to your wp-content/plugins directory and activate it in the WordPress admin. That's how you would install it. If you want to use the step four code somewhere outside the plugin, you'll have to modify it. But you could stick it into the theme's functions.php file or a plugin of its own. –  chrisguitarguy Sep 22 '12 at 18:09
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.