Redirection to taxonomy posts list after post submit.

First of all note that a post can have more than one category, also posts can have no category, what you’ll do in that cases?

And what about post update?

That said, if you look at the url when in edit.php and select a category by clicking on its name, you’ll notice that the only thing that change in the url is that the param category_name is appended to url.
You can easily do that by get the category using get_the_category and appending the url argument using add_query_arg.

I’m assuming that:

  • if post has more than one category, use the first one.
  • if the post has no category, redirect to edit.php without any category filter.
  • if the post status is ‘draft’ does not trigger the redirect.
  • if the post is deleted, redirect to trash.
  • if the post is updated you will act in the same way

So:

add_action( 'wp_insert_post', function( $post_ID, $post, $update ) {
  if ( defined('DOING_AJAX') && DOING_AJAX ) return;
  if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) return;
  if ( $post->post_type !== 'post' ) return;
  if ( in_array($post->post_status, array('draft','auto-draft','inherit') ) ) return;
  $url = add_query_arg( array( 'post_type'=>'post' ), admin_url('edit.php') );
  if ( $post->post_status === 'trash' ) {
    $args = array('post_status' => 'trash', 'trashed' => '1', 'ids' => $post_ID );
    $redirect = add_query_arg( $args, $url );
    wp_safe_redirect( $redirect );
    exit();
  }
  $url = add_query_arg( array( 'pid' => $post_ID ), $url );
  // uncomment following line to avoid redirect on post update
  // if ($update) return;
  $cats = get_the_category( $post_ID );
  if ( empty( $cats ) ) {
    wp_safe_redirect( $url );
    exit();
  }
  $cat = array_shift( $cats );
  $args = array( 'category_name' => $cat->slug, 'msg' => 'updated' );
  $redirect = add_query_arg( $args, $url );
  wp_safe_redirect( $redirect );
  exit();

}, PHP_INT_MAX, 3);

I’ve used 'wp_insert_post' with the highest priority because it’s the last hook fired when a post is saved. In this way code for saving custom metaboxes, that normally runs on save_post, should work with no problems because that hook is fired first.

However, the issues with this are:

  • you don’t see the “post updated” message anymore
  • when, after redirect, you show only one category in edit.php the filter is not very evident at first glance and this can confuse users

For these reasons, I want to share a way to proper show messages making the edit page more clear after redirect:

add_action('admin_notices', function() {
  $screen = get_current_screen();
  if ( $screen->id !== 'edit-post' ) return; 
  $pid = (int) filter_input( INPUT_GET, 'pid', FILTER_SANITIZE_NUMBER_INT );
  if ( ! $pid > 0 ) return;
  $msg = filter_input( INPUT_GET, 'msg', FILTER_SANITIZE_STRING );
  if ( $msg === 'updated' ) {
    echo '<div class="updated"><p>';
    printf(
      __('Post updated. <a href="https://wordpress.stackexchange.com/questions/140448/%s">View post</a>'), esc_url( get_permalink($pid) )
    );
    echo '</p></div>';
  }
  $cat = filter_input( INPUT_GET, 'category_name', FILTER_SANITIZE_STRING );
  if( ! empty($cat) ) {
    $term = get_term_by( 'slug', $cat, 'category' );
    if ( empty( $term ) ) return;
    $c = get_taxonomy( 'category' );
    $cname = esc_html( $c->labels->singular_name );
    echo '<div class="updated"><p>';
    $all = add_query_arg( array( 'post_type'=>'post' ), admin_url('edit.php') );
    $f="%s <strong>&quot;%s&quot;</strong>. <a href="https://wordpress.stackexchange.com/questions/140448/%s">%s</a>";
    printf( $f, $cname, esc_html($term->name), esc_url($all), __('All Posts') );
    echo '</p></div>';
  }
});