Exclude A Category From Turn Off Comments Automatically

Thanks to our post New Ideas For 2010? Now It’s Your Turn! we got an email form one of our loyal sponsors Chris Coyier.

Hey WP Engineer folks!

I have a little issue I’m trying to resolve on CSS-Tricks, regarding comments. In my discussion settings, I have it set to automatically turn off comments on everything after one-month. However, on certain things, specifically the snippets pages which all share a common page template, I want the comments to be left on forever.
This seems like the job for some fancy functions.php work that you guys are the masters at 🙂

Ok Chris, here is our solution (copy the code in your functions.php and change the $cat values):

/**
 * Close comments on an old post.  Hooked to comments_open and pings_open.
 * small modifications on the default functions of WordPress
 *
 * @param bool $open Comments open or closed
 * @param int $post_id Post ID
 * @param int $cat Category ID (cat_ID), set '' or empty for all categories
 * @param int $days_old Days to close comments, set '' for use value from settings
 * @return bool $open
 */
function wpe_close_comments_for_old_post( $open, $post_id, $cat = array(1, 4), $days_old = '' ) {
	if ( !$open )
		return $open;
	
	if ( in_category($cat) )
		return $open;
	
	if ( '' === $days_old )
		$days_old = (int) get_option('close_comments_days_old');

	if ( !$days_old )
		return $open;
	
	$post = get_post($post_id);
	
	if ( time() - strtotime( $post->post_date_gmt ) > ( $days_old * 24 * 60 * 60 ) )
		return false;
	
	return $open;
}
add_filter( 'comments_open', 'wpe_close_comments_for_old_post', 10, 2 );
add_filter( 'pings_open',    'wpe_close_comments_for_old_post', 10, 2 );

Thanks Chris for your idea and please send us an email if you also have a nice idea how we could make WordPress even better.


Posted

in

by

Comments

17 responses to “Exclude A Category From Turn Off Comments Automatically”

  1. Chris Coyier Avatar

    Nice! You guys rock =)

    I was just slightly unclear though. In my particular situation, it’s a *page template* that I’d like to leave comments on eternally for, not a category. Could I change this:

    if ( in_category($cat) )

    to this?

    if ( is_page_template($cat) )

    and then pass in the file name for the page template as a param?

  2. Michael Avatar

    Hey Chis, change it to


    function wpe_close_comments_for_old_post( $open, $post_id, $pageid = 45, $days_old = '' ) // where 45 is the ID of snippets-page

    and than replace the category line with

    if ( is_page($pageid )
    return $open;

    That should work.

  3. Alphawolf Avatar

    @Chris Coyier: If you’d like to use is_page_template() passing a page template ID won’t work. Instead, pass the page template filename as a parameter, like so:

    if ( is_page_template(‘your-page-template.php’) )

    where your-page-template.php is located in your active theme’s folder. 🙂

  4. Chris Coyier Avatar

    This was my attempt at alteration:

    function wpe_close_comments_for_old_post( $open, $post_id, $template = 'page-snippet.php', $days_old = '' ) {
    if ( !$open )
    return $open;

    if ( is_page_template($template) )
    return $open;

    … rest the same

    but no dice.

  5. Alphawolf Avatar

    @Chris Coyier: Try

    if ( basename( get_page_template() ) == $template )

    instead.

    *keeps his fingers cross* 🙂

  6. Chris Coyier Avatar

    Thanks for the update, but unfortunately no, still nothing.

    My test:

    function wpe_close_comments_for_old_post( $open, $post_id, $template = 'page-snippet.php', $days_old = '' ) {
    if ( !$open )
    return $open;
    if ( basename( get_page_template() ) == $template )
    return $open;
    if ( '' === $days_old )
    $days_old = (int) get_option('close_comments_days_old');
    if ( !$days_old )
    return $open;
    $post = get_post($post_id);
    if ( time() - strtotime( $post->post_date_gmt ) > ( $days_old * 24 * 60 * 60 ) )
    return false;
    return $open;
    }
    add_filter( 'comments_open', 'wpe_close_comments_for_old_post', 10, 2 );
    add_filter( 'pings_open', 'wpe_close_comments_for_old_post', 10, 2 );

    Example of page I’m trying to leave comments open on:
    http://css-tricks.com/snippets/css/quality-abbreviations/

  7. Michael Avatar

    Chris, css is a subpage of snippets and quality-abbreviations a subpage of css, right?

  8. Michael Avatar

    Chris: Alphawolf and me working hard :p

    if ( get_post_meta($post_id, '_wp_page_template', true) == $template ) return open;

  9. Chris Coyier Avatar

    I gave it a shot but it’s a no-go. Thanks for all the work on this though guys. I’m sure it works great for categories =) It probably isn’t destined to be for me.

  10. Chris Coyier Avatar

    As a test, I made the function just “return true;”, and indeed that did activate comments on all older content, so at least we can be sure the functions.php file is working and the filter is being applied properly. My theory is that the is_page_template and get_post_meta functions dont run properly in this context?

  11. Michael Avatar

    Here is the final working code for Chris Coyier’s solution:

    function wpe_close_comments_for_old_post( $open, $post_id, $template = 'page-snippet.php', $days_old = '' ) {
    global $wp_query;

    if( !$post_id )
    $post_id = $wp_query->post->ID;

    if ( get_post_meta($post_id, '_wp_page_template', true) == $template && get_option('close_comments_for_old_posts') ) {
    return !$open;
    }

    if ( !$open )
    return $open;

    if ( '' === $days_old )
    $days_old = (int) get_option('close_comments_days_old');

    if ( !$days_old )
    return $open;

    $post = get_post($post_id);

    if ( (time() - strtotime( $post->post_date_gmt )) > ( $days_old * 24 * 60 * 60 ) )
    return false;

    return $open;
    }
    add_filter( 'comments_open', 'wpe_close_comments_for_old_post', 10, 2 );
    add_filter( 'pings_open', 'wpe_close_comments_for_old_post', 10, 2 );

    Thanks to Alphawolf for the final idea!

  12. Chris Coyier Avatar

    Yep that did the trick. I think it was pulling in that

    global $wp_query;

    that got the get_post_meta working.

    Excellent work guys, thanks!

  13. ahmad Avatar
    ahmad

    Hi,

    I loved the post very much.
    I have a small blog and what I want is to allow comments Meta Tag on some categories and totally make the comments link or the comments box invisible in some categories.

    Say I have 4 categories Google, Microsoft , yahoo, and Amazon. what I want is to remove comments box and link fully for category google & keep it visible for yahoo and others.

    Looking for your help

    Kind Regards,
    Ahmad

  14. […] neat posts: Build a WordPress 2.8 Widget With the New Widget API Exclude a Category From “Turn Off Comments” Automatically. Display the Total Number of Registered Users RSS | […]

  15. phocean Avatar
    phocean

    Hi,

    I copied the code above in functions.php of my them, created a new template and affected it to the page where I want the comment to stay open.
    Of course I updated the template name inside the function call.

    But it does not work. Any suggestion please ? Is there any change that my theme ignore functions.php ?

  16. Ralph Avatar

    I’m trying to get this to work for allowing comments permanently on two categories, and not having success. I’m confused on where you sub the $cat value – is it in the array definition or down in the add_filter function? Either way, comments stay off. How can I best troubleshoot this?

  17. Dan Avatar
    Dan

    Hey, this looks great and should do exactly what I need it to. One question though, whenever I place it in my ‘functions.php’ I get a parse error…?

    Is there somewhere in particular where I should be placing it?