It appear, like @milo also said, that the correct way to doing this is by using the “parse_request” action that stand before the “pre_get_posts” action (see https://codex.wordpress.org/Plugin_API/Action_Reference).
The complete solution I came with :
add_action('init', function () {
$refs_slug = getCustomRefTermsSlug(); // this will return an array of all the terms slug existing in the custom "ref" taxonomy
// @note Catch /{foo|bar|baz} and redirect to index.php?catch_me=true?ref={foo|bar|baz}
add_rewrite_rule('^(' . implode('|', $refs_slug) . ')/?', 'index.php?post_type=custom&catch_me=true&ref=$matches[1]', 'top');
});
add_action('init', function () {
add_rewrite_tag('%ref%', '([^&]+)');
add_rewrite_tag('%catch_me%', '([^&]+)');
}, 10, 0);
add_action('parse_request', function ($query) {
if (array_key_exists('catch_me', $query->query_vars) && $query->query_vars['catch_me']) {
$args = [
'post_type' => 'custom',
'posts_per_page' => 1,
'fields' => 'ids',
'tax_query' => [],
];
if (array_key_exists('ref', $query->query_vars)) {
$args['tax_query'][] = [
'taxonomy' => 'ref',
'field' => 'slug',
'terms' => $query->query_vars['ref'],
];
}
// get the right post
$tmp_query = new \WP_Query($args);
$post_id = $tmp_query->posts[0];
// tell wordpress what post to display
$query->query_vars = [
'post_type' => 'custom',
'p' => $post_id,
];
}
return $query;
});
add_filter('post_type_link', function ($url, $post) {
if (get_post_type($post) == 'custom') {
$refs_slug = getCustomRefTermsSlug($post->ID); // this will return an array of all the terms slug of the custom "ref" taxonomy assigned to the post
// @note Return "/{foo|bar|bar}" as the permalink of the post
return "https://wordpress.stackexchange.com/" . implode("https://wordpress.stackexchange.com/", $refs_slug);
}
return $url;
}, 10, 2);
Feel free to give me comments! 😉