Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Display simple public user profile for all registered users (not just authors)

In a simple WordPress plugin I have redirected commenter links to the URL /user/user_id with the following code:

define('PROFILE', '<a href="/user/%d">%s</a>');

function my_get_comment_author_link($comment_ID) {
    global $comment;
    return sprintf(PROFILE, $comment->user_id, 
                            $comment->comment_author);
}

add_action('get_comment_author_link',
           'my_get_comment_author_link');

How could I please show a simple public user profile (for all registered users and not just authors) displaying the user name at that URL?

I guess I should create a PHP script in my child 2013 theme -

<?php
/* Template Name: Public User Profile */
?>

<?php get_header(); ?>

<?php 
      $my_query = new WP_Query($args);
      // somehow get the user ID out of URL?
      // somehow get the WP_User object?
      printf('<p>Name: %s</p>', $user->display_name);
?>

<?php get_footer(); ?>

But how to make the WordPress to execute that PHP script, when the URL /user/user_id is reuqested?

Should I use the Rewrite API here and how? I have tried the following, but don't see any effect:

                    add_rewrite_rule('/user/(\d+)',
                                     'index.php?XXX=$matches[1]',
                                     'top'
                    );
                    flush_rewrite_rules();

Or am I missing something, like maybe I should add a custom post type first? (As you see - I am confused and "lost in the docs").

UPDATE:

Can I maybe override the_content hook - but how to detect that a /user/user_id page has been called?

function my_content($content)
{
    if (NOT /user/user_id CALLED)
        return $content;

    // otherwise somehow extract the user_id
    // somehow get the corresponding WP_User
    return sprintf('<p>Name: %s</p>', $user->display_name);
}

add_action('the_content', 'my_content');
like image 498
Alexander Farber Avatar asked Feb 13 '23 22:02

Alexander Farber


2 Answers

Here are some (hopefully helpful) remarks:

  • Avoid putting everything into a giant super class, keep your classes as small and focused (task oriented) as possible. Auto loading classes can also be handy.

  • Keep your add_rewrite_rule within the init hook, because you don't want to loose the rewrite when you visit the permalink settings page and re-save the permalinks:

    public static function init()
    {
        // ... your code  ...
    
        add_rewrite_rule(
            'user/([^/]*)/?',
            'index.php?wpcg_user=$matches[1]',
            'top'
        );              
    }
    

    Notice the /? part, to account for both user/123 and user/123/. The add_rewrite_rule() call will not flush the rewrite rules automatically.

  • Another way is to register an endpoint with add_rewrite_endpoint :

    public static function init()
    {
        // ... your code  ...
    
        add_rewrite_endpoint( 'user', EP_ALL );
    }
    

    where you can modify the places where it will be accessible: EP_ALL, EP_PAGES, EP_PERMALINK, ... . Notice that it will create a new rewrite rule where /user/123/ is mapped to ?user=123.

  • You can use the template_redirect action or template_include filter to modify what template you want to display.

  • You should register your custom GET variable, wpcg_user, with the query_vars filter, for example:

    public static function query_vars( $vars )
    {
        $vars[] = 'wpcg_user';
        return $vars;
    }
    

    so you can retrieve it later with get_query_var( 'wpcg_user' ).

  • When get_query_var( 'wpcg_user') is non-empty, you know that the requested url is like http://example.com/user/123/.

  • You should allow the WordPress admin to override the default plugin template, tpl-user.php, by copying it into the current theme directory. The function locate_template can help you with that:

    if ( '' != locate_template( 'tpl-user.php') ) 
    
  • Your template_redirect method, if you choose to use the corresponding hook, could then look like this:

    public static function template_redirect()
    {
        $wpcg_user = get_query_var( 'wpcg_user' );
    
        $tpl = 'tpl-user.php';  // Your custom template file.
    
        if( ! empty( $wpcg_user ) )
        {
            if ( '' == locate_template( $tpl, TRUE ) )
                include( plugin_dir_path( __FILE__ ) . $tpl );  
    
            exit();
        }
    }
    

    where you might have to adjust the path to your tpl-user.php template, for example if you keep it in a sub-directory within your wp-city-gender plugin directory. Notice that we use the second input argument of the locate_template() function, so it will load the template if it can find it.

  • Your tpl-user.php template file could look like this:

    <?php
     /* Template Name: Public User Profile */
     ?>
    
    <?php get_header(); ?>
    
    <div>
    <?php 
    // Get the user query:
    $wpcg_user = get_query_var( 'wpcg_user' );  
    
    // Get corresponding user by id:
    $user = get_user_by( 'id', absint( $wpcg_user ) );
    
    if( $user ):
        printf('<p> Name: %s </p>',   $user->display_name                      );
        printf('<p> City: %s </p>',   get_user_meta( $user->ID, 'city',   TRUE));
        printf('<p> Gender: %s </p>', get_user_meta( $user->ID, 'gender', TRUE));
    else:
        _e( 'Sorry, no user found!' );
    endif;
    ?>
    </div>
    
    <?php get_footer(); ?>
    

    where we use the get_user_by() function, to retrieve the corresponding user data.

  • We could easily have used the user slug instead of the user id, by using get_user_by( 'slug', $wpcg_user ); instead of get_user_by( 'id', absint( $wpcg_user ) );.

  • You need the following, in your current setup:

    add_action( 'template_redirect',  array( CNAME, 'template_redirect') );
    add_filter( 'query_vars',         array( CNAME, 'query_vars') );
    //add_action( 'template_include', array( CNAME, 'template_include') );
    

    activate the corresponding hook callbacks.

  • There are many tools available to help you with custom rewrites, for example the Monkeyman Rewrite Analyzer. It has not been updated in a while, but still works great.

    Here's a screenshot showing the /user/1/ inspection, with the above rewrite:

    wpcg_user inspection

    I hope this helps. Just let me know if you need help implementing this. I tested these modifications on my install and it worked there.

Update:

In response to a comment:

How to handle the case where the template is located in a sub-directory, for example /templates/profile.php?

We can use the following:

if ( '' == locate_template( 'templates/profile.php', TRUE ) )
    include( plugin_dir_path( __FILE__ ) . 'templates/profile.php' );

This means:

  • If /wp-content/themes/MYTHEME/templates/profile.php is located, then it will be automatically loaded.

  • Else: /wp-content/plugins/wp-city-gender/templates/profile.php is loaded.

where we assume that __FILE__ is in the wp-city-gender root directory.

like image 136
birgire Avatar answered May 02 '23 20:05

birgire


How about you check the page template instead of the url??

if ( is_page_template('public_profile.php') ) { // code to execute when the pages using the Template of public_profile.php file(Your Public User Profile Template file) are loaded. }

Have a look at this function is_page_template()

Or you can also get the template used by the current page to check the template. See get_page_template()

like image 21
Yamu Avatar answered May 02 '23 22:05

Yamu