I appreciate the discussion and critique of my original solution. I usually work exclusively with the USA alphabet, so I don't think about encoding in other languages. Besides that (as Hubert points out), it was wrong anyway. I should have known better than to do that.
I don't think that the changed sort argument in get_users_by_capability() is the complete solution, though.
The foreach() loop iterates over $rawresponses, which has elements in an order other than by name. Because the elements of $rawresponses are not sorted, when elements of $allresponses[0] are moved to the other elements of $allresponses (by calls to clone() and unset()), the other elements of $alresponses are ordered by whatever order $rawresponses was in - not the sorted order of $allresponses[0].
By itself, modifying the SQL sort string sorts the users with no response, but does not sort the users who did respond.
I've looked at several discussions on various forums about sorting utf8 strings in PHP. The conclusion appears to be that it won't work reliably - especially on Windows servers (like mine). It looks like we do have to rely on the SQL sort string to get the order right.
The next problem is that $rawresponses uses a key that is not the userid (which is the key in $allresponses[0]). My new approach is: make a clone of $rawresponses with the userid as the key. Then run the foreach loop over $allresponses[0] (which is sorted the way we want it). For each user in $allresponses, if the user has a response in $rawresponses then move it to the correct part of $allresponses and remove it from $allresponses[0] as before.
It's not as pretty as I would like, but it works in more cases than my first - naive - try.
if ($rawresponses) {
$rawResponsesByUid = array();
foreach ($rawresponses as $resp) {
$rawResponsesByUid[$resp->userid] = clone($resp);
}
foreach ($allresponses[0] as $user) {
if (isset($rawResponsesByUid[$user->id])) { // This person has responded
$response = $rawResponsesByUid[$user->id];
$allresponses[0][$response->userid]->timemodified = $response->timemodified;
$allresponses[$response->optionid][$response->userid] = clone($allresponses[0][$response->userid]);
unset($allresponses[0][$response->userid]); // Remove from unanswered column
}
}
}
Is there a more direct way? What about doing a JOIN between table 'choice_answers' and table 'user' (joined on user id's), so that we can then sort on the user names? That seems better to me, but I don't know enough about the Moodle database calls to know how to do it. Are there any performance issues with JOIN on a large user list?
bkg
modified original post to use the correct sort method. Should be uasort() to maintain the keys.