My goal is to have the URL of uncategorized articles be just the URL and the post name, while articles placed in categories will have the URL, category and post name. This code seems to work as expected, but I was hoping that someone could review it and let me know if there’s anything that could cause problems.
function custom_remove_category_slug( $post_link, $post, $leavename ) {
if ( 'post' != $post->post_type || 'publish' != $post->post_status ) {
return $post_link;
}
$categories = get_the_category( $post->ID );
if ( !empty( $categories ) ) {
foreach ( $categories as $category ) {
if ( $category->slug == 'uncategorized' ) {
// Remove the category slug from the permalink
$post_link = str_replace( '/' . $category->slug, '', $post_link );
break;
}
}
}
return $post_link;
}
add_filter( 'post_link', 'custom_remove_category_slug', 10, 3 );
function custom_uncategorized_rewrite_rules() {
add_rewrite_rule(
'^([^/]+)/?$',
'index.php?name=$matches[1]',
'top'
);
// Prevent access to /uncategorized/post-name URLs
add_rewrite_rule(
'^uncategorized/(.+)/?$',
'index.php?error=404',
'top'
);
}
add_action( 'init', 'custom_uncategorized_rewrite_rules' );
function custom_flush_rewrite_rules() {
custom_uncategorized_rewrite_rules();
flush_rewrite_rules();
}
add_action( 'after_switch_theme', 'custom_flush_rewrite_rules' );
function custom_request_filter( $query_vars ) {
if ( isset( $query_vars['error'] ) && $query_vars['error'] == '404' ) {
// Return 404 if trying to access /uncategorized/post-name
global $wp_query;
$wp_query->set_404();
status_header( 404 );
nocache_headers();
}
if ( !empty( $query_vars['name'] ) ) {
$post = get_page_by_path( $query_vars['name'], OBJECT, 'post' );
if ( $post ) {
$categories = get_the_category( $post->ID );
foreach ( $categories as $category ) {
if ( $category->slug == 'uncategorized' ) {
$query_vars['p'] = $post->ID;
unset( $query_vars['name'] );
break;
}
}
}
}
return $query_vars;
}
add_filter( 'request', 'custom_request_filter' );