How to enable comments for pending and draft posts?

I have a custom post type with comments enabled. The comments metabox in the admin only appears when the post is published. I’m wanting to use the comments system as more of a discussion between certain authors (it will be hidden on the front end) so I would like the commenting system to be active when the posts are draft, pending or published. Is this possible?

I should note that I have tried the edit flow plugin which has the “editorial comments” feature, however it introduces more issues with capabilities etc and doesn’t suit what I am trying to achieve.

Related posts

Leave a Reply

1 comment

  1. The following enables the default meta box for draft and pending posts (in the portfolio post_type):

    add_action( 'admin_init', 'wpse_74018_enable_draft_comments' );
    
    /**
     * Add Comments Meta Box if CPT is 'draft' or 'pending'
     */
    function wpse_74018_enable_draft_comments()
    {
        if( isset( $_GET['post'] ) ) 
        {
            $post_id = absint( $_GET['post'] ); 
            $post = get_post( $post_id ); 
            if ( 'draft' == $post->post_status || 'pending' == $post->post_status )
                add_meta_box(
                    'commentsdiv', 
                    __('Comments'), 
                    'post_comment_meta_box', 
                    'portfolio', // CHANGE FOR YOUR CPT
                    'normal', 
                    'core'
                );
        }
    }
    

    But, we cannot comment…
    error commenting in draft post

    The error is produced in /wp-admin/includes/ajax-actions.php, line 736:


    To correct this, the Ajax call must be intercepted with:

    add_action( 'admin_init', 'wpse_74018_enable_custom_ajax_comments' );
    
    function wpse_74018_enable_custom_ajax_comments()
    {
        add_action( 'wp_ajax_replyto-comment', 'wpse_74018_custom_callback', 0 );
    }
    
    /**
     * Copy of wp_ajax_replyto_comment()
     * /wp-admin/includes/ajax-actions.php
     *
     * Adjust the CPT that defines $diff_status   
     */
    function wpse_74018_custom_callback( $action ) {
        global $wp_list_table, $wpdb;
        if ( empty( $action ) )
            $action = 'replyto-comment';
    
        check_ajax_referer( $action, '_ajax_nonce-replyto-comment' );
    
        set_current_screen( 'edit-comments' );
    
        $comment_post_ID = (int) $_POST['comment_post_ID'];
        if ( !current_user_can( 'edit_post', $comment_post_ID ) )
            wp_die( -1 );
    
        $status = $wpdb->get_var( $wpdb->prepare("SELECT post_status FROM $wpdb->posts WHERE ID = %d", $comment_post_ID) );
    
        if( 'portfolio' == get_post_type( $comment_post_ID ) )
            $diff_status = array('trash');
        else
            $diff_status = array('draft','pending','trash');
        
        if ( empty($status) )
            wp_die( 1 );
        elseif ( in_array($status, $diff_status ) )
            wp_die( __('ERROR: you are replying to a comment on a draft post.') );
    
        $user = wp_get_current_user();
        if ( $user->exists() ) {
            $user_ID = $user->ID;
            $comment_author       = $wpdb->escape($user->display_name);
            $comment_author_email = $wpdb->escape($user->user_email);
            $comment_author_url   = $wpdb->escape($user->user_url);
            $comment_content      = trim($_POST['content']);
            if ( current_user_can( 'unfiltered_html' ) ) {
                if ( wp_create_nonce( 'unfiltered-html-comment' ) != $_POST['_wp_unfiltered_html_comment'] ) {
                    kses_remove_filters(); // start with a clean slate
                    kses_init_filters(); // set up the filters
                }
            }
        } else {
            wp_die( __( 'Sorry, you must be logged in to reply to a comment.' ) );
        }
    
        if ( '' == $comment_content )
            wp_die( __( 'ERROR: please type a comment.' ) );
    
        $comment_parent = absint($_POST['comment_ID']);
        $comment_auto_approved = false;
        $commentdata = compact('comment_post_ID', 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_content', 'comment_type', 'comment_parent', 'user_ID');
    
        $comment_id = wp_new_comment( $commentdata );
        $comment = get_comment($comment_id);
        if ( ! $comment ) wp_die( 1 );
    
        $position = ( isset($_POST['position']) && (int) $_POST['position'] ) ? (int) $_POST['position'] : '-1';
    
        // automatically approve parent comment
        if ( !empty($_POST['approve_parent']) ) {
            $parent = get_comment( $comment_parent );
    
            if ( $parent && $parent->comment_approved === '0' && $parent->comment_post_ID == $comment_post_ID ) {
                if ( wp_set_comment_status( $parent->comment_ID, 'approve' ) )
                    $comment_auto_approved = true;
            }
        }
    
        ob_start();
            if ( 'dashboard' == $_REQUEST['mode'] ) {
                require_once( ABSPATH . 'wp-admin/includes/dashboard.php' );
                _wp_dashboard_recent_comments_row( $comment );
            } else {
                if ( 'single' == $_REQUEST['mode'] ) {
                    $wp_list_table = _get_list_table('WP_Post_Comments_List_Table');
                } else {
                    $wp_list_table = _get_list_table('WP_Comments_List_Table');
                }
                $wp_list_table->single_row( $comment );
            }
            $comment_list_item = ob_get_contents();
        ob_end_clean();
    
        $response =  array(
            'what' => 'comment',
            'id' => $comment->comment_ID,
            'data' => $comment_list_item,
            'position' => $position
        );
    
        if ( $comment_auto_approved )
            $response['supplemental'] = array( 'parent_approved' => $parent->comment_ID );
    
        $x = new WP_Ajax_Response();
        $x->add( $response );
        $x->send();
    }
    

    Alternatives

    Editorially, I understand that the comments system and interface would be much better. An alternative is to create a custom meta box with repeatable fields, where messages can be left within the post.

    Basic implementation:

    Plugins of interest:


    Further developments

    I went ahead and made a plugin with more features.
    Kudos @toscho, that pointed an entry point in the Ajax query.