Force category choice before creating new post?

How can I force the user to first choose a category before continuing to the editor when creating a new post? I want to set some default content, but this is based on the category, so I need to know that before showing the editor (unless I do some fancy Ajax stuff, but in this case I don’t want to do that).

Related posts

Leave a Reply

1 comment

  1. I solved this by hooking into post-new.php, and checking for a category_id request parameter. If it does not exist, I display a form with a category dropdown that submits back to this page, and then call exit() so the regular post form does not display. If it exists, I set up a hook for wp_insert_post that will add the category. This works because a new post is already created in the database via the get_default_post_to_edit() function, and we can add categories, tags, or other (meta) content. The form is rendered after this with the “fresh” new content.

    add_filter( 'load-post-new.php', 'wpse14403_load_post_new' );
    function wpse14403_load_post_new()
    {
        $post_type = 'post';
        if ( isset( $_REQUEST['post_type'] ) ) {
            $post_type = $_REQUEST['post_type'];
        }
    
        // Only do this for posts
        if ( 'post' != $post_type ) {
            return;
        }
    
        if ( array_key_exists( 'category_id', $_REQUEST ) ) {
            add_action( 'wp_insert_post', 'wpse14403_wp_insert_post' );
            return;
        }
    
        // Show intermediate screen
        extract( $GLOBALS );
        $post_type_object = get_post_type_object( $post_type );
        $title = $post_type_object->labels->add_new_item;
    
        include( ABSPATH . 'wp-admin/admin-header.php' );
    
        $dropdown = wp_dropdown_categories( array(
            'name' => 'category_id[]',
            'hide_empty' => false,
            'echo' => false,
        ) );
    
        $category_label = __( 'Category:' );
        $continue_label = __( 'Continue' );
        echo <<<HTML
    <div class="wrap">
        <h2>{$title}</h2>
    
        <form method="get">
            <table class="form-table">
                <tbody>
                    <tr valign="top">
                        <th scope="row">{$category_label}</th>
                        <td>{$dropdown}</td>
                    </tr>
                    <tr>
                        <td></td>
                        <th><input name="continue" type="submit" class="button-primary" value="{$continue_label}" /></th>
                </tbody>
            </table>
            <input type="hidden" name="post_type" value="{$post_type}" />
        </form>
    </div>
    HTML;
        include( ABSPATH . 'wp-admin/admin-footer.php' );
        exit();
    }
    
    // This function will only be called when creating an empty post,
    // via `get_default_post_to_edit()`, called in post-new.php
    function wpse14403_wp_insert_post( $post_id )
    {
        wp_set_post_categories( $post_id, $_REQUEST['category_id'] );
    }