I need to add the author name as a subdirectory prefix for all user's posts and pages.
For example:
example/johndoe/ //The author page for John Doe
example/johndoe/category/test-post/ //Test post by user John Doe
example/johndoe/test-page/ //Test page by user John Doe
If I change the permalink structure to: /%author%/%category%/%postname%/
this works fine for displaying a user's post but not a user's page.
However I'm not sure if there is something I can do in .htaccess
or functions.php
that will allow me to get the pages
to work in the same manner.
I understand this can be accomplished with Multisite, however I'm trying to avoid using this because the client doesn't want to use it.
I need to add the author name as a subdirectory prefix for all user's posts and pages.
For example:
example/johndoe/ //The author page for John Doe
example/johndoe/category/test-post/ //Test post by user John Doe
example/johndoe/test-page/ //Test page by user John Doe
If I change the permalink structure to: /%author%/%category%/%postname%/
this works fine for displaying a user's post but not a user's page.
However I'm not sure if there is something I can do in .htaccess
or functions.php
that will allow me to get the pages
to work in the same manner.
I understand this can be accomplished with Multisite, however I'm trying to avoid using this because the client doesn't want to use it.
Share Improve this question edited May 4, 2016 at 16:07 bigmike7801 asked May 4, 2016 at 15:55 bigmike7801bigmike7801 2635 silver badges16 bronze badges 15 | Show 10 more comments2 Answers
Reset to default 1By the looks of it, there's a plugin to achieve exactly this, so save you rolling your own for it.
The plugin is: https://wordpress/plugins/permalinks-customizer/
I installed it to test that it does what you're looking for. Here's a screenshot that shows what you'd do:
Tested with Wordpress 5.0.4
The first problem to solve it's the post_name value for pages that would share the same slug (e.g. about-me).
The simpler solution I found is to add the author nicename (beware: in my solution it should not contain a hyphen!) as the first part of the slug:
about-me page post_name for john: john-about-me
about-me page post_name for mary: mary-about-me
This could be achieved using the wp_insert_post_data filter hook (see wp_insert_post() function defined in wp-includes/post.php) when creating the page:
// about-me => <author_name>-about-me
add_filter( 'wp_insert_post_data', 'custom_wp_insert_post_data', 99, 2);
function custom_wp_insert_post_data($data, $postarr)
{
if(($data["post_type"] == "page") && ($data["post_status"] != "auto-draft"))
{
$author_name = get_the_author_meta( 'user_nicename', $data["post_author"] );
// insert
if($postarr['hidden_post_status'] == "draft") {
$data["post_name"] = $author_name . "-" . $data["post_name"];
}
// update
else {
list($author, $slug) = explode("-", basename($data["post_name"]), 2 );
// wrong permalink -> prepend the author
if($author != $author_name) {
$data["post_name"] = $author_name . "-" . $data["post_name"];
}
}
}
return $data;
}
Next step it will be to change the wp rewrite rules to reflect our desires (you need also to update the settings > permalinks):
add_filter('page_rewrite_rules', 'custom_page_rewrite_rules');
function custom_page_rewrite_rules($page_rewrite)
{
// remove : john/about-me => index.php?pagename=john/about-me
unset($page_rewrite["(.?.+?)(?:/([0-9]+))?/?$"]);
// add: john/about-me => index.php?pagename=john-about-me
$page_rewrite["(.?.+?)/(.+?)/?$"] = "index.php?pagename=\$matches[1]-\$matches[2]";
return $page_rewrite;
}
add_filter('post_rewrite_rules', 'custom_post_rewrite_rules');
// posts have the /%author%/%category%/%postname% permalink structure
function custom_post_rewrite_rules($post_rewrite)
{
// remove: john/about-me => index.php?category_name=about-me&author_name=john
unset($post_rewrite["([^/]+)/(.+?)/?$"]);
return $post_rewrite;
}
Last step it will be to change the value returned when the code asks for a page permalink (e.g. in menus).
To do that we have to use the page_link filter hook (located in get_page_link() function defined in wp-includes/link-template.php)..
// http://www.example/john-about-me => http://www.example/john/about-me
add_filter('page_link', 'custom_page_link', 99, 3);
function custom_page_link( $link, $ID, $sample )
{
list($author, $slug) = explode("-", basename($link), 2 );
return ( site_url() . "/" . $author . "/" . $slug );
}
..but it won't work if you don't set to false the use_verbose_page_rules property of $wp_rewrite global instance; this will stop parse_request() to check if a "wrong" matched pagepath exixts:
add_action('init', 'disable_verbose_page_rule');
function disable_verbose_page_rule()
{
global $wp_rewrite;
$wp_rewrite->use_verbose_page_rules = false;
}
That's all.. Well, to be honest this is the main part, but it will be some other work to do, like change the rewrite rules also for all the attachment/comments/feed/embed stuff linked to a page and may be something else that I didn't have enough time to discover.
This is my first post; I hope it will help someone, like many others helped me.
utility
is for informational purposes and rarely changed, almost static data specific to the "user" or "author" in this case;archival
is the data the "user" has input over time. – Nathan Powell Commented Mar 10, 2017 at 6:38