11

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

11

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'] );
}
  • Nice. I'm going to need to do something similar soon and have been wondering how I would do it! – MikeSchinkel Apr 10 '11 at 16:35
  • Sorry, but it ain;t working - I added the text in post-new.php but nothing happens. Any ideas ? Thanks – user6448 Jun 23 '11 at 18:30
  • 1
    @kiro: You should not add this code in post-new.php, but in your theme's functions.php or in a plugin file. – Jan Fabry Jun 23 '11 at 20:39
  • @JanFabry Great solution. Just what I'm looking for. Thanks! – rofflox Jul 24 '12 at 14:16
  • Great bit of code I've been using it in my multisite to help add some default styling to some post categories. I did run into a slight issue when using it on sites with the amazing "adminimize" plugin though, which threw an "invalid post type" error. The plugin author suggested commenting out the "//extract( $GLOBALS );" line & that fixed the issue. – speedypancake Nov 8 '12 at 22:52

Not the answer you're looking for? Browse other questions tagged or ask your own question.