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 am attempting to alter the query of pages where the post meta value of _members_access_role does not meet that of the currently logged-in user. Here is what I have so far:

// Get all posts with the access level of 'Member'
function members_get_member_posts() {
    $post_ids = array();
    $args=array(
        'post_type' => array('post','tribe_events','document'),
        'meta_key' => '_members_access_role',
        'meta_value' => 'member',
        'post_status' => array('publish','private')
    );
    $protected_posts = get_posts($args);
    if($protected_posts) {
        foreach($protected_posts as $p) {
            $post_ids[] = $p->ID;
        }
    }
    // return an array of paid post IDs
    return $post_ids;
}

// Hide all posts from users who are not logged-in or are not administrators or members
function members_hide_member_posts($query) {
    $current_user = wp_get_current_user();
    if(empty($current_user) || ($current_user->roles[0] != 'member' && $current_user->roles[0] != 'administrator') && (false == $query->query_vars['suppress_filters'])) {
        $protected_posts = members_get_member_posts();
        if($protected_posts)
            $query->set('post__not_in', $protected_posts);
    }
    return $query;
}
add_filter('pre_get_posts', 'members_hide_member_posts');

If I do a quick print_r(members_get_member_posts()) I am seeing the array of post IDs correctly - but on the front-end, posts are still showing up when they should not be (since I am feeding in that returned function value to posts__not_in).

For example, if a public user visits the site, they can still see the Member (role) posts. Was also having a bit of trouble bringing in global $current_user object -- as it would not check if $current_user->ID was empty or not without the page producing a fatal error about memory limits (even after I set the php.ini file to 256M for the hell of it), so a possible memory leak? Thanks!

Update While not documented, I did double-check that you can use an array() value for post_type in get_posts as of 3.3 (I believe). Also tried without it and returns just posts as it should - so the data is returning, just not "filtering out" that data.

share|improve this question
    
what is the suppress filters check for? –  Stephen Harris Aug 14 '12 at 7:46

1 Answer 1

up vote 2 down vote accepted
+50

Try this version:

// Get all posts with the access level of 'Member'
function members_get_member_posts() {

    $post_ids = wp_cache_get( 'wpse61487_members_posts' );
    if ( false === $post_ids ) {

        $post_ids = array();
        $args=array(
            'post_type' => 'any',
            'meta_key' => '_members_access_role',
            'meta_value' => 'member',
            'post_status' => array('publish','private')
        );

        $protected_posts = get_posts($args);
        if($protected_posts) {
            $post_ids = wp_list_pluck( $protected_posts, 'ID' );
        }

        wp_cache_set( 'wpse61487_members_posts', $post_ids );
     }

     // return an array of paid post IDs
     return $post_ids;
}

// Hide all posts from users who are not logged-in or are not administrators or members
function members_hide_member_posts($query) {

    if( !$query->is_main_query() )
        return;

    $current_user = wp_get_current_user();
    if(empty($current_user) || ($current_user->roles[0] != 'member' && $current_user->roles[0] != 'administrator') && (false === $query->query_vars['suppress_filters'])) {
        $protected_posts = members_get_member_posts();
        if( !empty( $protected_posts ) )
            $query->set('post__not_in', $protected_posts);
    }
}
add_action('pre_get_posts', 'members_hide_member_posts');
share|improve this answer
    
Aha! So it was running this on every query on the page that was causing the memory issue - awesome! I adjusted the pre_get_posts() action slightly (as it wasn't checking if a user was logged-in or not correctly pastebin.com/x0mkzaTE -- my bad), but this also bring up one minor detail I left out. If I did in-fact want this pre_get_posts() action to effect a widget that would have recent posts (for example), any recommendations on that? Thanks again! –  Zach Aug 13 '12 at 14:52
    
Do you only want to target that one widget or also target the widget? –  Pippin Aug 13 '12 at 21:52
    
Hey Pippin - Also target widgets. Seeing how to specifically target widgets would be very interesting too. Thanks! –  Zach Aug 14 '12 at 0:20
    
To target all queries, just remove if( !$query->is_main_query() ) return; –  Pippin Aug 14 '12 at 0:59
1  
Great place to use caching as well! –  Stephen Harris Aug 14 '12 at 7:47

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.