Allow guests comments on single post

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.

Related posts

Leave a Reply

1 comment

  1. 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