-3

I have a situation where I need to get an array of all current user roles that are "less than or equal to" a specified role, in order to display certain "assigned" content.

I have created a CPT, with a custom taxonomy called gyo_kb_roleview, so I need to be able to query my CPT based on a meta_query where the content's allowed role is equal to or above the current users role.

So, if I have a role of 'Contributor', only users equal to Contributor or higher should be able to view said content, and anyone under would not be able to view it.

How can I do this?

Display Template:

<?php
// We don't want to allow direct access to this
defined('ABSPATH') OR die('No direct script access allowed');

// Get the theme header
get_header();

// Get the user's role
$_user = wp_get_current_user( );
$_role = 'Anonymous';
if( is_user_logged_in() ){
    $_role = ucfirst( $_user->roles[0] );
}

// Query for our CPT taxonomies, Filter the query based on what articles should show for the allowed roles
$args = array( 'post_type'=>'gyo_kbs', 'posts_per_page'=>-1, 'orderby' => 'menu_order', 'order' => 'ASC', 'meta_query' => array(
        array(
          'key' => 'gyo_kb_roleview',
          'value' => $_role, // i am thinking I need to pass an array of "allowed" roles here and add an 'IN'... i just dont know how to procure said array
        )
      ), );

$the_query = new WP_Query ( $args );
while ( $the_query -> have_posts() ) : $the_query -> the_post();

    echo '<h1>' . $post -> post_title . '</h1>';

endwhile;
wp_reset_query();

?>

<?php

// Get the theme footer
get_footer();
  • 5
    WP doesn't have a less than / more than role relationship, and when you check for a specific role you may not get the results you were expecting. Instead best practice is to check by capability. When you register your post type(s), look into map_meta_cap and you can then assign whatever specific capability you need to whatever roles you need to. For example, you might have a read_cpt capability (replace 'cpt' with your cpt name to be clearer) which you would then assign to whichever roles you want to be able to read those posts. – WebElaine Apr 2 '18 at 18:14
  • While I appreciate the comment Elaine, with this excercise I am not interested in hearing your opinions on "best practice".: prntscr.com/izvf7y – Kevin Apr 2 '18 at 18:26
  • 4
    The numeric values are not reliable, they should not be used at all. As Elaine said, roles are not hierarchical, they are a collection of capabilities. Treat the system as it is, not as you wish it should be. :) – fuxia Apr 2 '18 at 18:37
  • 2
    WordPress roles are not hierarchical. If you want hierarchical roles, you should use a different CMS. – Nathan Johnson Apr 2 '18 at 18:50
  • 2
    @Kevin Stop being a jerk and listen to people who are trying to help you. The idea of a 'lowest access role' is a fundamentally incorrect way of describing this functionality in WordPress. Roles are not hierarchical, so the UI in your screenshot doesn't make sense. If you must have roles it would make more sense to have a multi-select for selecting which roles can or can't have access. – Jacob Peattie Apr 3 '18 at 0:50
1

Create function to give role a numeric value:

function get_user_level($role){

    switch ($role) {

        case 'Contributor':
            return 1;
            );
            break;
        case 'Author':
            return 2;
            );
            break;
        case 'Editor':
            return 4;
            break;
        case 'Administrator':
            return 5;
            break;
        case 'Super Admin':
            return 6;
            break;

        default:
            return 0; // default subscriber or other roles
            break;
    }

}

Now you can do without meta query:

$args = array( 'post_type'=>'gyo_kbs', 'posts_per_page'=>-1, 'orderby' => 'menu_order', 'order' => 'ASC'); // Removed meta query

$the_query = new WP_Query ( $args );
while ( $the_query -> have_posts() ) : $the_query -> the_post();

    $allowed_role = get_post_meta( get_the_ID(), 'gyo_kb_roleview', true ); //get the meta value of allowed role

    if( get_user_level($_role) < get_user_level($allowed_role) ){ // $_role from your question
        continue; // skip post if the user role is less than allowed role
    }

    echo '<h1>' . $post -> post_title . '</h1>';

endwhile;
wp_reset_postdata();

Update: If You can save numeric value for the user role in post meta, Then you can do:

    $args = array( 'post_type'=>'gyo_kbs', 'posts_per_page'=>-1, 'orderby' => 'menu_order', 'order' => 'ASC', 
    'meta_query' => array(
     array(
            'key'     => 'gyo_kb_roleview',
            'value'   => get_user_level($_role),
            'compare' => '>='
        ),
    )
);
  • Looks a tad hacky. Whole point of utilizing the meta_query would be to filter the returned results, albeit resulting in a smaller dataset returned. While normal circumstances would dictate it is perfectly viable, however, in the off chance that I have over 1000 posts, there's no need to filter out the bad stuff after the query is run – Kevin Apr 2 '18 at 18:29
  • this also would break potential article counts... – Kevin Apr 2 '18 at 18:32
  • 1
    If you are using radio button. You should save corresponding numeric value for the role (Keep the same Label ) and then you can easily compare meta value in meta query and use above function to get numeric value of current user role – Bikash Waiba Apr 2 '18 at 18:51
  • Thanks. I am going to go with a spin-off of this so I can use the meta_query – Kevin Apr 2 '18 at 18:58
  • I have updated the code hope it helps. – Bikash Waiba Apr 2 '18 at 19:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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