It’s a bit unwieldy to just grab all posts by an author and filter through them to only return a category list. If you wish to use the default widgets in the sidebar and have them filtered by the author only on the author template then I’d suggest using the following approach.
First, filter the tag and category widget queries for categories and tags.
add_filter( 'widget_tag_cloud_args', 'filter_categories_by_author' );
add_filter( 'widget_categories_dropdown_args', 'filter_categories_by_author' );
add_filter( 'widget_categories_args', 'filter_categories_by_author' );
function filter_categories_by_author( $args ){
// only process if on the author template
if( is_author() ){
$author_id = get_the_author_meta( 'ID' );
$taxonomy = !empty( $args['taxonomy'] ) ? $args['taxonomy'] : 'category';
// filter by including only IDs associated to the author
$args['include'] = get_taxonomy_ids_by_author( $author_id, $taxonomy );
}
return $args;
}
Then using the dependent method to retrieve taxonomy ids filtered by the user ID.
function get_taxonomy_ids_by_author( $user_id, $taxonomy = 'category' ){
global $wpdb;
return $wpdb->get_col( $wpdb->prepare( "
SELECT DISTINCT(terms.term_id) as ID
FROM $wpdb->posts as posts
LEFT JOIN $wpdb->term_relationships as relationships ON posts.ID = relationships.object_ID
LEFT JOIN $wpdb->term_taxonomy as tax ON relationships.term_taxonomy_id = tax.term_taxonomy_id
LEFT JOIN $wpdb->terms as terms ON tax.term_id = terms.term_id
WHERE 1=1 AND (
posts.post_status="publish" AND
posts.post_author = %d AND
tax.taxonomy = '%s' )
ORDER BY terms.name ASC
", $user_id, $taxonomy ) );
}