Updated: added support of params
/* maybe redirect with permalinks change */
add_action( 'template_redirect', 'maybe_redirect_404_old_permalink' );
/**
* Attempts to forward old permalinks to the new permalink structure
*
* @author Ben Lobaugh
https://ben.lobaugh.net/blog/202980/wordpress-add-category-to-permalink-and-redirect-old-permalinks
*/
function maybe_redirect_404_old_permalink() {
// Only run this function if we are on a 404
if( ! is_404() ) {
return;
}
// "trick" to get the full URL
$url = add_query_arg( '', '' );
$regex = "#\?(.*?)$#smi";
$params = "";
if(preg_match($regex, $url, $match)) {
$params = $match[1];
$url = preg_replace($regex, '', $url);
}
/*
* Pull the URL path apart to find a slug (post_name)
* The final segment should be the slug
*/
$parts = explode( '/', $url );
$parts = array_filter( $parts );
$size = count( $parts );
$maybe_slug = $parts[ $size ]; // We use size here because the filter turned 1 based
// Attempt to locate corresponding post in the database
$args = array(
'name' => $maybe_slug,
'post_type' => 'post',
'post_status' => 'publish',
'numberposts' => 1,
);
$posts = get_posts( $args );
// Identify a found post
if( $posts && ! empty( $posts[0]->ID ) ) {
$post_id = $posts[0]->ID;
$post_url = get_permalink( $post_id );
// Attempt to forward to the new post permalink
if( $post_url ) {
if(!empty($params)) {
$post_url .= "?" . $params;
}
wp_safe_redirect( $post_url, 301 ); // Permanent redirect
}
}
/*
* If we made it down here then we could not find a matching post in
* the database. No biggie, simply do nothing and display the 404 page
* as normal
*/
}