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 trying to add a delisting feature to my WordPress network. Posts which are delisted would not appear in post lists, but would still be visible if accessed directly.

I've written a plugin that helps editors delist entries with custom meta values on authors and posts. So there are two meta values that I need to check before displaying each post in public listings: the delist-post post meta value and the delist-author user meta value.

I was hoping to register a pre_get_posts filter that limits the return of get_posts() by setting the query's meta_query property. Is it possible to check a user meta value with a posts meta_query? If not, can you think of a better way to do this without adding conditional statements in theme files (i.e. not if (!get_post_meta(...) && !get_user_meta(...)) in the_loop)?

share|improve this question

3 Answers 3

If you're using WP_Query to do your loop it should be as simple as getting all the post IDs and then setting them as negative in the p parameter.

For example:

$unwanted_posts = array(); // you must generate this
$unwanted_posts_str = '-'.implode( ',-', $unwanted_posts );

$args = array(
    'p' => $unwanted_posts_str
);

You can also set this on an existing query using the set() method.

share|improve this answer
    
The list could be thousands of IDs long. (Edited to remove first sentence ;) –  weberwithoneb May 22 '12 at 18:43
up vote 1 down vote accepted

Shortly after writing my question, The Theme Foundry wrote a blog entry that answered my question. The solution is to add_actions for both posts_join and posts_where. These each take clauses as arguments, which you append with your own conditions and return the appended clause.

In my case, I just had to limit the join in the posts_join callback:

$join .= " 
            LEFT JOIN    " . $wpdb->postmeta . " AS pm 
            ON           (" . $wpdb->posts . ".ID = pm.post_id AND 
                        pm.meta_key = 'post_meta_key_here') 
            LEFT JOIN    " . $wpdb->usermeta . " AS um 
            ON           (" . $wpdb->posts . ".post_author = um.user_id AND 
                        um.meta_key = 'author_meta_key_here') "

... and the where clause in the posts_where callback...

$where .= " 
                AND ((pm.meta_key = 'post_meta_key_here' AND pm.meta_value = 0)
                    OR pm.meta_id IS NULL) 
                AND ((um.meta_key = 'author_meta_key_here' AND um.meta_value = 0)
                    OR um.umeta_id IS NULL) ";

Please see the blog post for more information.

share|improve this answer

I would use pre_get_posts:

<?php
function wpse52961_filter_delisted_posts( $query ) {
    // Only modify the main query
    // NOTE: You'll need to change this if
    // you intend to target a specific secondary query
    if ( $query->is_main_query() ) {
        // Define meta query
        $filtered_posts_meta_query = array(
            'relation' => 'OR',
            array(
                'meta_key' => 'delist-post',
                'meta_value' => true
            ),
            array(
                'meta_key' => 'delist-author',
                'meta_value' => true
            )

        );
        // Add the meta query args to the query
        $query->set( 'meta_query', $filtered_posts_meta_query );
    }
}
add_action( 'pre_get_posts', 'wpse52961_filter_delisted_posts' );
?>

I've made some assumptions about the meta key values, and the desired relationship between delist-post and delist-author.

share|improve this answer
    
The meta entries must exist or the post will be omitted. In a future version of WordPress, we will have an "exists/does not exist" criteria (core.trac.wordpress.org/ticket/18158). Also, delist-author must be attached to the user meta table, not posts meta, otherwise other posts by that author won't be delisted. –  weberwithoneb May 24 '12 at 17:06

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.