Aha, I see the change to central/reused user_get_user_details() like a nice thing... but...
1 - why fake $course @ get_users_by_id() ? It should be course-independent user information IMO, so surely should accept empty $course.
2 - same for $usercontext @ get_users_by_id(). It is ALWAYS the $user context, isn't it? Why do we need to pass the same info twice?
3 - why "innocent" information like the theme or the timezone is dependent of $hasuserupdatecap ?
4 - get_course_participants_by_id() sets the context to course context when calling user_get_user_details(), isn't that, again repeating information? IMO the $course optional param commented in 1) should be enough to calculate context.
5 - also note I'm not 100% sure that all the checks performed within the user_get_user_details() can be done both when the function is called with a $course (course context) or without it (user context). IMO they are not interchangeable at all. Some only have sense at one context and not at the other at all.
6 - get_users_by_courseid() is subject to exactly the same problem that the ones commented @ 4) and 5) above.
7 - So, based in all the above IMO user_get_user_details():
7a) should accept mandatory $user and optional $course.
7b) based on the params in 7a and 7b, it should calculate the proper user and course contexts and then, use them as necessary for each capability check. But for sure a lot of them are not interchangeable at all
8) Integrating this means that the 3 services involved (get_users_by_id, get_course_participants_by_id, get_users_by_courseid) and the new central function itself (user_get_user_details) must be:
8b) fully covered by unit tests
I'm sorry but I'm not 100% confident all this stuff is ready for integration in current form. After all, those services are about disclosing personal info and must be triple checked / ensured to be doing everything in a correct way. An right now they seem to need some more love.