I found a solution, and while I’m not convinced it’s the simplest or most performant solution, it does the job. If someone some day takes interest in this and has a cleaner method, I’d love to revisit it. For now, here’s what worked:
In my register_taxonomy
function, set the rewrites as such:
'rewrite' => array(
'slug' => 'media-type',
'hierarchical' => true,
),
Then, set rewrite rules for posts:
add_action( 'init', 'xx_media_type_rewrite_tag', 10, 0 );
function xx_media_type_rewrite_tag() {
add_rewrite_tag( '%media_type%', '([^&]+)', 'media-type=" );
add_rewrite_rule( "^insights/([^/]*)/([^/]*)/([^/]*)/?','index.php?media_type=$matches[1]&media_type=$matches[2]&name=$matches[3]','top' );
add_rewrite_rule( '^insights/([^/]*)/([^/]*)/?','index.php?media_type=$matches[1]&name=$matches[2]','top' );
}
Then, filter the post link (this the part I’d imagine could look a lot cleaner if I knew what I was doing):
add_filter( 'post_link', 'xx_filter_post_type_link', 10, 2 );
function xx_filter_post_type_link( $link, $post ) {
if ( false === strpos( $link, '%media_type%') )
return $link;
$terms = wp_get_post_terms( $post->ID, 'media-type');
// set media type; if none is found, provide a default value.
if ( 0 < count($terms) ) {
// Get first term in array
$first_term = $terms[0]->term_id;
// Create a string to represent hierarchy of terms
// get_taxonomy_parents() is a custom function that returns a string formatted as `$tax_parent . $separator . $tax_child . $separator` etc.
$media_type = get_taxonomy_parents( $first_term, 'media-type', false, "https://wordpress.stackexchange.com/", true );
// Remove everything after second `/` character (we only want to go two levels deep into the tax hierarchy)
if ( 2 < substr_count( $media_type, "https://wordpress.stackexchange.com/" ) ) {
$media_type = substr( $media_type, 0, strpos( $media_type, "https://wordpress.stackexchange.com/", strpos( $media_type, "https://wordpress.stackexchange.com/") + 1 ) );
}
// Remove trailing slash
$media_type = trim( $media_type, "https://wordpress.stackexchange.com/" );
} else {
// Set default
$media_type="articles";
}
// Encode for URL usage, but preserve slashes
$media_type = str_replace( '%2F', "https://wordpress.stackexchange.com/" , urlencode($media_type) );
$link = str_replace( '%media_type%', $media_type , $link );
return $link;
}