2

I’ve been using basic user rights functionality on a multi-user WP site for a while and its worked out great, having most user accounts just have access to their own posts but a few “editors” having access to everyone’s posts. This was assisted by the wp-front plugin that allows you to easily define user roles.

However I now have a scenario where I need multiple authors at the same external company and an editor also at the company that will oversee the work of the other individuals.

This new remote editor role is new and problematic as they would need to be able to see their own posts plus any posts created by other editors at the same company. They mustn’t be able to see everyone’s posts though.

Is this possible with wp-front or any other plugin or simply by some hand made solution outside of plugins ?

Ideally a solution would work by adding collections of users to groups of some kind but it doesn't have to.

6
  • As you are talking about a plugin - can you specify which one?
    – kraftner
    Apr 18, 2018 at 7:34
  • Yes apologies I've now clarified this in the question, its wp-front. I'm completely open to not using this though if theres a solution out there without it.
    – AdamJones
    Apr 18, 2018 at 10:48
  • I doubt there is any plugin that can do this out-of-the-box, but you could build a custom solution as long as the posts are somehow marked to belong to a certain company. (Either by cateogory or custom meta field)
    – Swen
    Apr 19, 2018 at 17:13
  • Or if you have authors and editors and different companies, might WordPress multisite network be the answer?
    – Myles
    Apr 19, 2018 at 19:10
  • 1
    plugin recomendations are off topic here Apr 21, 2018 at 7:38

3 Answers 3

4
+25

Here's my approach. Bear in mind that it covers the basic needs you've described but could be easily expanded into more robust solution. Few steps to follow (all code goes to your functions.php):

1. Save company name as user meta

The first thing we need to do is assigning a company name to a user - i'd go with user meta to achieve that. You could add a metabox to edit user screen for easy management, I'm not including code for that here, but I'm sure you get the idea.

For testing you can just add meta to user with update_user_meta( $user_id, 'company', 'Tyrell Corporation' ); (codex)

So in this example I assume that we have a bunch of authors with Tyrell Corporation set as company user meta key and editor with exactly same meta.

2. Add Company meta to posts based on author's user meta

To make things easier and cheaper, I'd keep the reference to Company name also in every post saved by any author with company assigned (that way we can get rid of at least one query to author meta table every time we're checking editor's rights to edit the post later on). To do that, I'm using save_post hook:

function save_company_meta( $post_id, $post, $update ) {
    // get author's company meta
    $company = get_user_meta( $post->post_author, 'company', true );

    if ( ! empty( $author_id ) ) {
        // add meta data to the post
        update_post_meta( $post_id, 'company', true );
    }
}

add_action( 'save_post', 'save_company_meta', 10, 3 );

Now every time a user saves his/her draft, the company name that was assigned to this user is copied to post meta.

3. Map editor's edit_post capability

Finally we can simply map editor's 'edit_post' capability. If the post's company meta data is different than editor's company user meta, we take the capability to edit this particular post away from that particular editor. There are some additional conditions in the code below, for example we don't apply restrictions if the post has no company meta at all or is not a post post type. You can align that to your needs:

function restrict_access_to_company_posts( $caps, $cap, $user_id, $args ) {

    /*
    We're messing with capabilities only if 'edit_post' 
    is currently checked and the current user has editor role
    but is not the administrator
    */

    if ( ! in_array( $cap, [ 'edit_post' ], true ) ) {
        return $caps;
    }

    if ( ! user_can( $user_id, 'editor' ) || user_can( $user_id, 'administrator' ) ) {
        return $caps;
    }

    /*
    $args[0] holds post ID. $args var is a bit enigmatic, it contains
    different stuff depending on the context and there's almost 
    no documentation on that, you've got to trust me on this one :)
    Anyways, if no post ID is set, we bail out and return default capabilities
    */
    if ( empty( $args[0] ) ) {
        return $caps;
    }

    /*
    You can also make sure that you're restricting access 
    to posts only and not pages or other post types
    */
    if ( 'post' !== get_post_type( $args[0] ) ) {
        return $caps;
    }

    $post_company   = get_post_meta( $args[0], 'company', true );
    $editor_company = get_user_meta( $user_id, 'company', true );

    /*
    if no meta data is set or editor is assigned 
    to the same company as the post, we allow normal editing
    */
    if ( empty( $post_company ) || $post_company === $editor_company ) {
        return $caps;
    }

    // finally, in all other cases, we restrict access to this post
    $caps = [ 'do_not_allow' ];

    return $caps;
}

This wouldn't hide the posts completely from admin UI, you can still see them on the list, but editor cannot get into post's edit screen and change it nor see the draft (WordPress will automatically remove all "edit" links for you, also in admin bar on front-end). Once the post is published, the Editor still wouldn't be able to edit posts content.

4. (Optionaly) Remove posts from admin list completely

If above still isn't enough, you can also hook into pre_get_posts (codex) to hide posts from admin list completely:

function query_company_posts_only( $query ) {

    if ( ! is_admin() || empty( get_current_user_id() ) ) {
        return $query;
    }

    $editor_company = get_user_meta( get_current_user_id(), 'company', true );

    if ( empty( $editor_company ) ) {
        return $query;
    }

    $query->set( 'meta_key', 'company' );
    $query->set( 'meta_value', $editor_company );
}

add_action( 'pre_get_posts', 'query_company_posts_only', 10, 1 );

Hope that does the trick, just play around with it and add some improvements here and there.

0
-2

As you now have two roles for the same company I would go for https://wordpress.org/plugins/groups/

Integrates standard WordPress capabilities which can be assigned to groups and users

0
-2

I think this Plugin should do what you´re lookin for:

https://de.wordpress.org/plugins/hide-this/

1
  • This seems to hide front end content conditionally via short codes which isn't related at all to what I am after
    – AdamJones
    Apr 23, 2018 at 13:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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