In your last code example, you’re returning a wrong type for the post_format_rewrite_base
. It should be a string, not an array. However, your idea goes in the right direction.
You have to take care about all the «routes» that are implied by the default rewrite rules, WordPress creates for post formats:
type/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$ => index.php?post_format=$matches[1]&feed=$matches[2]
type/([^/]+)/(feed|rdf|rss|rss2|atom)/?$ => index.php?post_format=$matches[1]&feed=$matches[2]
type/([^/]+)/embed/?$ => index.php?post_format=$matches[1]&embed=true
type/([^/]+)/page/?([0-9]{1,})/?$ => index.php?post_format=$matches[1]&paged=$matches[2]
type/([^/]+)/?$ => index.php?post_format=$matches[1]
How about using Cortex? It allows you to map routes directly to query parameters. Here’s an example how to use it.
<?php
use
Brain\Cortex,
Brain\Cortex\Route;
add_action( 'wp_loaded', function() {
Cortex::boot();
$post_format_slugs = get_post_format_slugs();
$post_format_slugs_pattern = implode( '|', $post_format_slugs );
add_action(
'cortex.routes',
function ( Route\RouteCollectionInterface $collection ) use ( $post_format_slugs_pattern ) {
/**
* Default route for post format slugs
*
* /(standard|aside|chat|gallery|...)
*/
$collection->addRoute(
new Route\QueryRoute(
"/{slug:{$post_format_slugs_pattern}}",
function( $matches ) {
return [
'post_format' => $matches[ 'slug' ]
];
}
)
);
/**
* Route for feed endpoints 1
*
* /(standard|aside|chat|gallery|...)/feed/(feed/rdf/rss/rss2/atom)
*/
$collection->addRoute(
new Route\QueryRoute(
"/{slug:{$post_format_slugs_pattern}}/feed/{feed:feed|rdf|rss|rss2|atom}",
function( $matches ) {
return [
'post_format' => $matches[ 'slug' ],
'feed' => $matches[ 'feed' ]
];
}
)
);
/**
* Route for feed endpoints 2
*
* /(standard|aside|chat|gallery|...)/(feed/rdf/rss/rss2/atom)
*/
$collection->addRoute(
new Route\QueryRoute(
"/{slug:{$post_format_slugs_pattern}}/{feed:feed|rdf|rss|rss2|atom}",
function( $matches ) {
return [
'post_format' => $matches[ 'slug' ],
'feed' => $matches[ 'feed' ]
];
}
)
);
/**
* Route for embed
*
* /(standard|aside|chat|gallery|...)/embed
*/
$collection->addRoute(
new Route\QueryRoute(
"/{slug:{$post_format_slugs_pattern}}/embed",
function( $matches ) {
return [
'post_format' => $matches[ 'slug' ],
'embed' => TRUE
];
}
)
);
/**
* Route for pagination
*
* ^/(standard|aside|chat|gallery|...)/page/(\d+)$
*/
$collection->addRoute(
new Route\QueryRoute(
"/{slug:{$post_format_slugs_pattern}}/page/{page:[0-9]+}",
function( $matches ) {
return [
'post_format' => $matches[ 'slug' ],
'paged' => $matches[ 'page' ]
];
}
)
);
}
);
} );
Cortex has the advantage that you don’t have to flush rewrite rules. Internally it uses FastRoute to match the patterns, so you can use any of the pattern language, FastRoute provides. Cortext does not overwrite the internal routing process of WordPress, it just acts right before and will pass the request through to WordPress if no route matches.
The example shows just the essence of how to use Cortex. Some routes could possibly combined or even removed as they are only for backward compatibility (especially the redundant feed routes).
Remember that your concept requires overlapping routes, that means you won’t be able to create pages with any of the slugs of the post format terms: standard, aside, chat, gallery, link, image, quote, status, video, audio.
You might want to implement an automated check that affects the unique post slug generation:
add_filter( 'wp_unique_post_slug_is_bad_hierarchical_slug', function( $is_bad, $slug, $post_type, $post_parent ) {
if ( 'page' !== $post_type )
return $is_bad;
return in_array( $slug, get_post_format_slugs() );
} );
Another optimization would be to only use the post format slugs, the current theme actually supports. But this will invalidate existing URLs in case the theme changes.
If you don’t want to use Cortex, the principle would be pretty much the same but you would have to manually remove the default post format rules and replace it with custom rewrite rules that follows the schema of the routes mentioned above. Remember to do this only on an activation hook and flush rewrite rules afterwards as they get cached in the database.