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 would allow guests comments who are not registered yet to comment only one single post. Other posts have to be commentable just for registered users.

share|improve this question
add comment

1 Answer

up vote 2 down vote accepted

That sounds like a useful feature. To get what you need you have to change three things:

  1. Add a checkbox to enable anonymous comments per post.
  2. Save the checkbox value together with the post.
  3. Filter the checks for the comment registration requirement on the post views to enable the comment form and on the actual comment save action to let them go through.

The checkbox

If you open the Screen Options on a post editor page you can enable the Discussion metabox. We will add our checkbox to that metabox:

enter image description here

We are lucky, there is a hook: 'post_comment_status_meta_box-options'. Let’s use it:

add_action( 'post_comment_status_meta_box-options', 'acpp_checkbox' );
/**
 * Print a checkbox into the comment status metabox.
 *
 * @wp-hook post_comment_status_meta_box-options
 * @param   object $post
 * @return  void
 */
function acpp_checkbox( $post )
{
    $key = '_allow_anonymous_comments';
    $current = get_post_meta( $post->ID, $key, TRUE );

    printf(
        '<br /><label for="%1$s">
        <input type="checkbox" id="%1$s" name="%1$s" class="selectit" %2$s/> %3$s
        </label>',
        $key,
        checked( 1, $current, FALSE ),
        apply_filters( 'acpp_metabox_label', 'Allow anonymous comments.' )
    );
}

As you can see, I invented a new post meta key '_allow_anonymous_comments'. The leading underscore will hide it from the Custom Fields metabox. (Related: How to delete custom field “suggestions” from dropdown list)
If the meta value exists already and if it is equal to 1 we preselect it.

The filter 'acpp_metabox_label' exists to allow theme authors translating that value. I was too lazy to add a language file for just one tiny string …

Save the meta value

To save our value we hook into 'save_post', run some checks and store the result as an integer:

add_action( 'save_post', 'acpp_save' );
/**
 * Save the checkbox value as number
 *
 * @wp-hook save_post
 * @param   int $post_id
 * @param   object $post
 * @return  void
 */
function acpp_save( $post_id, $post )
{
    // AJAX autosave
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
        return;

    // Some other POST request
    if ( ! isset ( $_POST['post_type'] ) )
        return;

    // Missing capability
    if ( ! current_user_can( 'edit_' . $_POST['post_type'], $post_id ) )
        return;

    $key = '_allow_anonymous_comments';

    // Checkbox successfully clicked
    if ( isset ( $_POST[ $key ] ) and 'on' === strtolower( $_POST[ $key ] ) )
        return update_post_meta( $post_id, $key, 1 );

    // Checkbox deselected
    delete_post_meta( $post_id, $key );
}

Filter registration checks

And now we have to use that value on the front-end and change the result for checks on the option comment_registration. We don’t want to change the blog wide value in wp-admin:

enter image description here

That’s why we add a check for is_admin() to that filter. Filtering option checks is actually simple: Hook into 'pre_option_' . $option_name and return any other value than FALSE. Since we do not want to return TRUE either, we trick that check by returning 0.

add_filter( 'pre_option_comment_registration', 'acpp_comment_reg_filter' );
/**
 * Trick the registration checks on front-end
 *
 * Important: If we return FALSE, the filter will be effectively ignored.
 * It has to be any other value.
 *
 * @wp-hook pre_option_comment_registration
 * @return bool|int
 */
function acpp_comment_reg_filter()
{
    if ( is_admin() )
        return FALSE;

    $key     = '_allow_anonymous_comments';
    $post_id = 0;

    // Only available on wp-comments-post.php, not on regular post pages.
    if ( isset( $_POST['comment_post_ID'] ) )
        $post_id = (int) $_POST['comment_post_ID'];

    //
    $post = get_post( $post_id );
    $open = get_post_meta( $post->ID, $key, TRUE );

    if ( 1 == $open )
        return 0;

    return FALSE;
}

This check is used by WordPress for the comment form, the comment reply links on threaded comments and when a comment is saved in wp-comments-post.php.

Plugin

That’s all. You can download the code as a plugin on GitHub:
Plugin Anonymous comments per post

share|improve this answer
    
I can't believe it toscho, you are my saviour!!! I was searching for help and tips, and you gave me the entire perfect plugin!!! i want to cry for happiness!!! ;) By the way, thank you so much for your great help, you resolved the problem brilliantly. I ve tried the plugin and everything is working good. i suggest to propose your work on wordpress repository, you deserve a place there!!! I searched a lot something like that, but nobody has created it...i think it is very useful for a lot of applications! Thanks again ;) –  Amaca Nov 24 '12 at 8:26
    
You’re welcome. :) Don’t forget to click the check mark to show other readers that this answer has solved the problem. –  toscho Nov 24 '12 at 8:31
    
Yup, sadly i can't because i don't have 15 points of reputation yet :( –  Amaca Nov 24 '12 at 8:38
    
You can accept answers already (clicking the little ✔ below the voting buttons). That is not the same as voting. –  toscho Nov 24 '12 at 8:41
    
Done! thanks again, it works like a charm!! –  Amaca Nov 24 '12 at 8:54
add comment

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.