Custom WordPress user permalink

I have a little problem with my wordpress site. I need to change the user permalinks. The permalinks should contain data from wp_usermeta table.
I’ve made some functions and the links are changed, but when i access them it says: Page not found.
I’ll buy you a beer if you can tell me what is wrong in my code.
Here is the code:

add_filter( 'request', 'wpse5742_request' );
function wpse5742_request( $query_vars )
{
    if ( array_key_exists( 'author_name', $query_vars ) ) {
        global $wpdb;
        $author_id = $wpdb->get_var( $wpdb->prepare( "SELECT user_id FROM {$wpdb->usermeta} WHERE meta_key='nickname' AND meta_value = %s", $query_vars['author_name'] ) );
        $query_vars['author'] = $author_id;
        unset( $query_vars['author_name'] );    
    }
    return $query_vars;
}

add_filter( 'author_link', 'wpse5742_author_link', 10, 3 );
function wpse5742_author_link( $link, $author_id, $author_nicename )
{
    $part1 = get_user_meta( $author_id, 'nickname', true );
    $part2 = get_user_meta( $author_id, '_themex_city', true );
    $part3 = get_user_meta( $author_id, '_themex_thesubject', true );
    $newlink  = $part1.'/'.$part2.'/'.$part3;

    if ( $newlink ) {
        $link = str_replace( $author_nicename, $newlink, $link );
    }
    return $link; 
}

add_action( 'user_profile_update_errors', 'wpse5742_set_user_nicename_to_nickname', 10, 3 );
function wpse5742_set_user_nicename_to_nickname( &$errors, $update, &$user )
{
    if ( ! empty( $user->nickname ) ) {
        $user->user_nicename = sanitize_title( $user->nickname, $user->display_name );
    } }

The permalink I want to create is: example.com/username/city/occupation

Related posts

1 comment

  1. 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

    1. I create a class that extends WP class.
    2. Then I replace the global $wp variable (that normally contain an
      instance of WP) with an instance of my class. This one contain
      only a method: parse_request that override WP method, so when
      WordPress call parse_request the one my class is called instead
      of the core one.
    3. 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 core parse_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 ), '/' );
        $full = str_replace( $home_path, '', add_query_arg( array() ) );
        $sane_array = explode( '?', $full );
        $sane = trim( $sane_array[0], '/\' );
        $parts = array_filter( explode( '/', $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 . '/' . $part2 . '/' . $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.

Comments are closed.