the problem with this question, and of a lot of questions like this, is the one pinted out by @Milo in comments: if you write a rewrite rule to handle you custom url, this goes in conflict with WordPress rules, e.g. if your urls are
htt://example.com/username/city/occupation
how WordPress can know if you are actually lookin for the page occupation
child of page city
granchild of page username
?
Answer is can’t, unless you do a query on database to see if the username
part is a real username or not.
To simplify things like that I wrote a plugin called Clever Rules and in this answer I will use a technique I used for that plugin. This technique can’t be used inside themes, but need to be used in plugins, so for this anwser I write a little plugin that uses 2 function taken from your code (just little bit optimized) and a small class that will do the magic.
How it Works
- I create a class that extends
WP
class. - Then I replace the global
$wp
variable (that normally contain an
instance ofWP
) with an instance of my class. This one contain
only a method:parse_request
that overrideWP
method, so when
WordPress callparse_request
the one my class is called instead
of the core one. - In this method I check the current url, if it seems one we want to target
I check the first part of the url and if it’s a valid username set
up the query vars otherwise let coreparse_request
run.
Code
<?php
/**
* Plugin Name: GM Custom Author Url WPSE Q#122829
* Plugin URI: http://wordpress.stackexchange.com/questions/122829/custom-wordpress-user-permalink
* Author: G.M.
* Author URI: http://wordpress.stackexchange.com/users/35541/g-m
*
*/
class GMWPE extends WP {
function parse_request( $extra_query_vars="" )
{
$home_path = trim( parse_url( home_url(), PHP_URL_PATH ), "https://wordpress.stackexchange.com/" );
$full = str_replace( $home_path, '', add_query_arg( array() ) );
$sane_array = explode( '?', $full );
$sane = trim( $sane_array[0], '/\\' );
$parts = array_filter( explode( "https://wordpress.stackexchange.com/", $sane ) );
if ( count($parts) === 3 ) {
$maybe_author = $parts[0];
$user = get_user_by('slug', $maybe_author);
if ( $user !== false ) {
remove_filter( 'template_redirect', 'redirect_canonical' );
$this->query_vars = array( 'author' => $user->ID );
return;
}
}
parent::parse_request( $extra_query_vars="" );
}
}
add_action( 'setup_theme', 'GMWPE_init', 9999 );
function GMWPE_init() {
global $wp;
if ( get_class( $wp ) === 'WP' ) $wp = new GMWPE();
}
add_filter( 'author_link', 'gmcau_author_link', 10, 3 );
function gmcau_author_link( $link, $author_id, $author_nicename )
{
$part2 = get_user_meta( $author_id, '_themex_city', true );
$part3 = get_user_meta( $author_id, '_themex_thesubject', true );
if ( $part2 && $part3 ) {
$newlink = $author_nicename . "https://wordpress.stackexchange.com/" . $part2 . "https://wordpress.stackexchange.com/" . $part3;
$link = home_url( $newlink );
}
return $link;
}
add_action( 'user_profile_update_errors', 'gmcau_set_user_nicename_to_nickname', 10, 3 );
function gmcau_set_user_nicename_to_nickname( &$errors, $update, &$user )
{
if ( ! empty( $user->nickname ) ) {
$user->user_nicename = sanitize_title( $user->nickname, $user->display_name );
}
}
This is the only thing you need (you can remove the functions you posted). Save this code in a file, put it in your plugins folder and activate it form your dashboard.
PS: if you are interested in have a look on my plugin that use this technique to give a flexible urls handling you can find it here.