I’m about to release a plugin to do just that (and some other things). You’ll have to modify your rewrite rules. This code works for category posts. Perhaps, if you work on it a little bit it will get you the same behavior for post types and taxonomies.
First, generate the rules you need:
function get_category_rules() {
$rules = array();
/*
* Will generate patterns for:
* (category)/
* category/(subcategory)
* category/subcategory/(post)
* feed/(category)
* feed/category/(subcategory)
*/
$feed_sufix = '/feed/?(rss|rss2|atom)?/?$';
$page_sufix = '/page/?([0-9]{1,})?/?$';
/* Walk within the categories by level */
$categories = get_categories(array(
'orderby' => 'slug',
'hide_empty' => false,
'exclude' => implode(',', $excludes)
));
foreach($categories as $category) {
$level = 0;
$path="(" . $category->slug . ')';
while (($category = get_category($category->parent)) && isset($category->term_id)) {
$level++;
$path = $category->slug . "https://wordpress.stackexchange.com/" . $path;
}
// Feeds
$rules[$level][$path . $feed_sufix] = 'index.php?category_name=$matches[1]&feed=atom';
// Category archives
$rules[$level][$path . '/?$'] = 'index.php?category_name=$matches[1]';
// Category archive pages
$rules[$level][$path . $page_sufix] = 'index.php?category_name=$matches[1]&paged=$matches[2]';
// Posts
$rules[$level][$path . '/([^/]+)/?$'] = 'index.php?name=$matches[2]';
}
$retval = array();
for ($i = count($rules) - 1; $i >= 0; $i--) {
$retval = array_merge($retval, $rules[$i]);
}
return $retval;
}
Then, merge these rules with the existing ones:
add_action('rewrite_rules_array', 'rewrite_rules');
function rewrite_rules($rules) {
$category_rules = get_category_rules();
$rules = array_merge($category_rules, $rules);
return $rules;
}
And make *_permalink
functions work with it.
add_filter('post_link', 'custom_post_permalink');
function custom_post_permalink ($post_link) {
global $post;
$cats = array_reverse(get_the_category($post->ID));
if (!isset($cats[0]))
return $post_link;
$category = $cats[0];
$path = $category->slug;
while (($category = get_category($category->parent)) && isset($category->term_id)) {
$path = $category->slug . "https://wordpress.stackexchange.com/" . $path;
}
return str_replace(home_url(), home_url() . "https://wordpress.stackexchange.com/" . $path, $post_link);
}