Automatically select categories on new post based on GET value

If you start to edit a new post, already a post with the status auto-draft is created. Actually, what you see is this post. So you can hook into the transition filter new_to_auto-draft and add a category to this post:

add_action( 'new_to_auto-draft', function(  $post ) {
    // Bail out, if not in admin editor.
    if ( ! strpos( $_SERVER['REQUEST_URI'], 'wp-admin/post-new.php' ) ) {
        return;
    }

    // Bail out, it no category set in $_GET.
    if ( empty( $_GET['cat'] ) ) {
        return;
    }

    $cat = wp_unslash( $_GET['cat'] );

    // Bail out, if category does not exist.
    if ( false === ( $cat = get_category_by_slug( $cat ) ) ) {
        return;
    }

    wp_set_post_categories( $post->ID, array( $cat->term_id ) );

} );

Explanation

As I’ve said, a post is created in the moment, you open the editor. wp_insert_post() is calling wp_transition_post_status( $new_status, $old_status, $post ) where the $new_status is auto-draft and the old “status” is new. wp_transition_post_status() basically fires three action hooks:

I am using {$old_status}_to_{$new_status} (new_to_auto-draft) because it is the most precise for what you are trying to accomplish.

In the function, where we get the post object as parameter ($post), we bail out if we are not in the correct location or the $_GET['cat'] is not found. With wp_unslash() we remove ‘\’ and stuff from $_GET['cat']. Another possibility would be to use sanitize_key(), maybe it is even more appropriate.

We now load the category object with get_category_by_slug() since we will need the ID of the category to attach the post to the category in wp_set_post_categories(). If the category was not found get_category_by_slug() will return false and we bail out. Another idea would be to create a category with this slug, if the category was not found.

For Custom Post Types and Custom Taxonomies

In response to

This does not seem to work on a custom post type/taxonomy

The above example works explicitly on the post type post and the taxonomy category. If you want to use it with a custom post type and a custom taxononmy, you will need to use get_term_by() instead of get_category_by_slug() and you will need to use wp_set_object_terms() instead of wp_set_post_categories().

The example below registers a post type, a taxonomy and shows the process:

add_action( 'new_to_auto-draft', function(  $post ) {
    // Bail out, if not in admin editor.
    if ( ! strpos( $_SERVER['REQUEST_URI'], 'wp-admin/post-new.php' ) ) {
        return;
    }

    // Bail out, it no category set in $_GET.
    if ( empty( $_GET['post_type'] ) || 'post_slug' !== wp_unslash( $_GET['post_type'] ) ) {
        return;
    }

    // Bail out, it no category set in $_GET.
    if ( empty( $_GET['cat'] ) ) {
        return;
    }

    $cat = wp_unslash( $_GET['cat'] );

    // Bail out, if category does not exist.
    if ( false === ( $cat = get_term_by( 'slug', $cat, 'tax' ) ) ) {
        return;
    }

    wp_set_object_terms( $post->ID, array( $cat->term_id ), 'tax' );

} );
add_action ( 'init', function() {
    $args['label'] = 'Test';
    $args['public'] = TRUE;
    register_post_type( 'post_slug', $args );

    $args['label'] = 'Taxonomy';
    register_taxonomy( 'tax', 'post_slug', $args );
});

Leave a Comment