The solution is quite simple. And is subdivided into two separate processes - querying the posts and modifying their category terms.
Querying the posts
get_posts
is a function that returns posts. A full list of arguments can be seen in WP_Query parameters
To get all posts for a specific author, you do something like:
get_posts( 'numberposts=1&author_name=john' );
Loop over each entry like so:
foreach ( get_posts( 'author_name=john' ) as $post ) {
// set categories...
}
Setting category terms
wp_set_object_terms
is the function you'll be looking at and using.
wp_set_object_terms( $post->ID, 'John's Category', 'category', false );
Putting it together
I would probably go for something like this:
global $wpdb; // get the global db object
foreach ( (array) $wpdb->get_results("SELECT DISTINCT post_author FROM $wpdb->posts WHERE post_type = 'post' GROUP BY post_author") as $row ) {
$author = get_userdata( $row->post_author ); // get all author data
foreach ( get_posts( 'numberposts=-1&author='.$row->post_author ) as $post ) {
switch ( $author->username ) {
case 'joe':
$category = 'Joe's Entries';
...
}
// set categories
wp_set_object_terms( $post->ID, $category, 'category', false );
}
}
I'm sure there are ways in which you can further optimize this. Run this once to fix things. Then attach to save_post
with just the set category part for future.