The goal is to taxonomize registered user profiles using custom taxonomies, whether hierarchical or not. I couldn't find an out-of-the-box way to do it, so I'm trying to pull a custom solution myself.
First of all, I created the custom taxonomies I needed. Let's say "Gender" and "Country".
Second, I added a single custom profile user field to store all term IDs, regardless of the taxonomy they belong to (there's no duplicates between terms, so I can safely do this). Let's call this field "selected".
Third, I created a function to show the terms of a taxonomy as a set of checkboxes, checking by default the ones which IDs are stored in our custom profile user field "selected":
function term2checks($taxonomy,$userID) {
//Get the selected terms for the current user
$selected = ','.get_the_author_meta( 'selected', $userID ).',';
//Query the database to get the terms
global $wpdb;
$query = "SELECT wt.term_id, wt.name
FROM $wpdb->term_taxonomy wtt
LEFT JOIN $wpdb->terms wt ON wtt.term_id = wt.term_id
WHERE wtt.taxonomy = '".$taxonomy."'
ORDER BY wt.name";
$terms = $wpdb->get_results($query);
//Create a set of checkboxes with those terms
$checkboxes = '';
foreach($terms as $term) {
$checkboxes .= '<input type="checkbox" name="'.$taxonomy.'[]" id="'.$taxonomy.'[]" value="'.$term->term_id.'"';
//If the term is currently selected, check
if (strstr($selected,','.$term->term_id.',')) {
$checkboxes .= ' checked="checked"';
}
$checkboxes .= '/>'.$term->name.'<br />';
}
return $checkboxes;
}
Fourth, I added to the user profile admin page a set of checkboxes for each taxonomy I wanted to apply. I used Justin's functions (check the link before on custom profile fields) and modified them a bit:
add_action( 'show_user_profile', 'my_show_extra_profile_fields' );
add_action( 'edit_user_profile', 'my_show_extra_profile_fields' );
function my_show_extra_profile_fields( $user ) { ?>
<h3>Taxonomies</h3>
<table class="form-table">
<tr>
<th><label for="gender">Gender</label></th>
<td>
<?php echo term2checks('gender',$user->ID);
<span class="description">The gender of the user.</span>
</td>
</tr>
<tr>
<th><label for="country">Country</label></th>
<td>
<?php echo term2checks('country',$user->ID);
<span class="description">The country where the user comes from.</span>
</td>
</tr>
</table>
<?php }
Fifth, I collected the data from all sets of checkboxes and saved it in our custom user profile fields. Again, I modified one of Justin's functions:
add_action( 'personal_options_update', 'my_save_extra_profile_fields' );
add_action( 'edit_user_profile_update', 'my_save_extra_profile_fields' );
function my_save_extra_profile_fields( $user_id ) {
if ( !current_user_can( 'edit_user', $user_id ) )
return false;
update_usermeta( $user_id, 'selected', implode(',',$_POST['gender']).','.implode(',',$_POST['country']) );
}
And last, I used this query to get users filtered by taxonomies. In the example, I'm getting users with gender id 1 and country id 10.
SELECT user_id
FROM wp_usermeta
WHERE meta_key = 'selected'
AND FIND_IN_SET(1,meta_value)
AND FIND_IN_SET(10,meta_value)
Of course, you could join other tables in order to get display names or to order by other criteria.
What do you think of this approach? Would it work in a site with lots of traffic? Can it be improved somehow?
Feel free to say what you think, I'm here to learn :)