How to create virtual pages with information from user meta profile fields?

Dave Jesch on his site presents a way to create virtual pages in WordPress. Dave created a class “to do all the heavy lifting“, as he says. I think, for my purposes this class not require changes, so I do not put it here. Also, Dave created a function (see bellow) that calls the above mentioned class to create a virtual page when is needed. I tested this method and it just works.

What I want, is to use the Dave’s class and function to put on my site a list of department members with links to their virtual pages with some content from their profiles. Pages must be virtual, so I do not have to create for each new member a real page, it must be created automatically (virtually) from his profile.

Read More

This is how I create and save some extra user profile fields:

/* Add Extra Fields to the User Profile */
add_action( 'show_user_profile', 'extra_user_profile_fields' );
add_action( 'edit_user_profile', 'extra_user_profile_fields' );

function extra_user_profile_fields( $user ) { ?>
   <h3><?php _e("Academic", "blank"); ?></h3>
   <table class="form-table">
      <!-- Teaching position -->
      <tr>
      <th><label for="teaching_position"><?php _e("Teaching position"); ?></label></th>
      <td>
      <input type="text" name="teaching_position" id="teaching_position" value="<?php echo esc_attr( get_the_author_meta( 'teaching_position', $user->ID ) ); ?>" class="regular-text" /><br />
      <span class="description"><?php _e("Put here your teaching position"); ?></span>
      </td>
      </tr>
   </table>
}

/* Save Extra User Profile Fields */
add_action( 'personal_options_update', 'save_extra_user_profile_fields' );
add_action( 'edit_user_profile_update', 'save_extra_user_profile_fields' );

function save_extra_user_profile_fields( $user_id ) {
   if ( !current_user_can( 'edit_user', $user_id ) ) { return false; }
   update_user_meta( $user_id, 'teaching_position', $_POST['teaching_position'] );
}

This is the Daves’s function that calls his class to create virtual pages:

function dj_create_virtual()
{
    $url = trim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), '/');
    if ($url == 'dave-virtual-page') {
       $args = array('slug' => 'dave-virtual-page',
          'title' => 'Dave's Virtual Page',
          'content' => "This can be generated content, or static content<br />
          Whatever you put here will appear on your virtual page.");
       $pg = new DJVirtualPage($args);
    }
}
add_action('init', 'dj_create_virtual');

And this is how I display currently the members list of specific department on my site (with a shortcode):

add_shortcode( 'list_of_members', 'members_listing' );
/* usage: [list_of_members department = 'psychology'] */

function members_listing( $department ) {

   $members = get_users( array( 'meta_key' => 'department', 'meta_value' => $department ) ); 

   usort($members, create_function('$a, $b', 'return strnatcasecmp($a->last_name, $b->last_name);'));

   echo '<div id="memberlist"><ul>';
   foreach ( $members as $member ) {
      echo '<li>';
      echo get_avatar($member->ID);
      /* Bellow I want to put their names in a link to their virtual pages with some information from their profiles */
      echo '<div class="authname">' . $member->first_name . ' ' . $member->last_name;
      echo '</div></li>';
   }
   echo '</ul></div>';
}

Now I want, with the Dave’s class and function, to put in my (last) members_listing function the members names in links to their virtual pages with some information from their profiles. How to do this?

EDIT

Here are the functions in question as I have used them finally (many thanks to @g-m!):

function dj_create_virtual() {
   $url = trim( parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH ), '/');
   if ( strpos( $url, 'users/' ) === 0 ) {
      $user_nicename = str_replace('users/', '', $url );
      $user = get_user_by( 'slug', $user_nicename );
      $user_info = array_map( function( $a ){ return $a[0]; }, get_user_meta( $user->ID ) );
      $args = array(
         'slug' => 'users/' . $user_nicename,
         'title' => $user_info['first_name'] . ' ' . $user_info['last_name'],
         'content' => get_avatar( $user->ID ));
      if( !empty( $user_info['teaching_position'] ) ) $args['content'] = $args['content'] . '<h5>Teaching position</h5>' . $user_info['teaching_position'];
      /* heare are some more user meta profile fields */
      $pg = new DJVirtualPage($args);
   }
}
add_action('init', 'dj_create_virtual');

and the members_listing function:

add_shortcode( 'list_of_members', 'members_listing' );
/* usage: [list_of_members department = 'psychology'] */

function members_listing( $department ) {
   $members = get_users( array( 'meta_key' => 'department', 'meta_value' => $department ) ); 
   usort( $members, create_function( '$a, $b', 'return strnatcasecmp($a->last_name, $b->last_name);' ) );
   echo '<div id="memberlist"><ul>';
   foreach ( $members as $member ) {
      echo '<li>';
      printf( '<div class="authname"><a href="%s">%s</a>', home_url( '/users/' . $member->user_nicename ), get_avatar( $member->ID ) );
      printf( '<div class="authname"><a href="%s">%s</a>', home_url( '/users/' . $member->user_nicename ), $member->display_name );
      if( !empty( $member->teaching_position ) ) { echo '<br />' . mb_convert_case( $member->teaching_position, MB_CASE_LOWER, 'UTF-8' ); };
      echo '</div></li>';
   }
   echo '</ul></div>';
}

Related posts

1 comment

  1. Before answer, a side note: what you want can be done a in a lot simpler and more performant way just creating a real post type: register a cpt, maybe not public (so no ui is showed on dashboard), and on user profile saving/updating just create/update a cpt entry.

    Doing so you do not need any external class and you can just use the core wp functions, to show all member pages, show single member page, link them and any other things you need.

    As bonus you can also make use of the template hierarchy and have a lot more flexibility.

    One my personal rule of thumb is: “never write code for custom features when core can do same thing”. In your case core features don’t do the same, do it better and simpler.

    However, this is a Q&A site, you asked a question and this is the answer:

    the dj_create_virtual function must be changed in something like this:

    function dj_create_virtual() {
      $url = trim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), '/');
      if ( strpos($url, 'member-') === 0 ) {
        $user_nicename = str_replace('member-', '', $url);
        $user = get_user_by( 'slug', $user_nicename );
        $user_info = array_map( function( $a ){ return $a[0]; }, get_user_meta( $user->ID ) );
        $args = array(
          'slug' => 'member-' . $user_nicename,
          'title' => $user_info['first_name'] . ' ' . $user_info['last_name'],
          // following is just an example
          'content' => 'This is the page for:' . $user_info['first_name'] . ' ' . $user_info['last_name']
        );
        $pg = new DJVirtualPage($args);
      }
    }
    add_action('init', 'dj_create_virtual');
    

    and your members_listing function need just a little edit:

    function members_listing( $department ) {
       $members = get_users( array( 'meta_key' => 'department', 'meta_value' => $department ) ); 
       usort($members, create_function('$a, $b', 'return strnatcasecmp($a->last_name, $b->last_name);'));
       echo '<div id="memberlist"><ul>';
       foreach ( $members as $member ) {
          echo '<li>';
          echo get_avatar($member->ID);
          $user_info = array_map( function( $a ){ return $a[0]; }, get_user_meta( $member->ID ) );
          $fullname = $user_info['first_name'] && $user_info['first_name'] ? $user_info['first_name'] . ' ' . $user_info['last_name'] : $member->display_name;
          printf( '<div class="authname"><a href="%s">%s</a></div></li>', home_url('/member-' . $member->user_nicename), $fullname);
       }
       echo '</ul></div>';
    }
    

Comments are closed.