The current has_capability() and load_user_capability() are very focused on the logged in user and get the caching mostly right so that stuff happens reasonably fast.
However, we need a separate set of functions to walk contexts -- functions that
- Don't call `load_user_capability()"
- Don't try and invoke the enrolment plugins!
- Can be cached across checks, but with a different caching scheme from the one for users...
There are right now 2 scenarios I can see where the current setup is doing a lot of unnecessary work, and I can't see any reasonable fix. There is a ton of work to do here so that we can say something along the lines of
// pre-walk the data we'll need
// for example, showing participants
// or forum mailouts
load_roleassignmentsforcontext($ct);
foreach (users as user) {
has_capability_by_context(x,y,z);
}
release_roleassignmentsforcontext($ct);
and
// pre-walk the data we'll need
// for example, showing the courses
// for user account
load_roleassignmentsforuser($userid);
// similar to get_my_courses() but does
// not use the infrastructure that assumes
// that the user is logged in and instead
// uses a a different cache
$courses = get_user_courses();
foreach (courses as course) {
has_capability_by_user(x,y,z);
}
release_blah($ct);
Right now we depend on has_capability() for in all and every scenario. And has_capability() has ended up doing a lot of caching and magic behind the scenes -- that benefits the single-user-logged-in-now scenario, but make things hard to deal with whenever we are working across contexts.
This affects the following scenarios:
- Login as admin, and visit a user profile with several enrolments. For every enrolment, there's check for has_capability() -- the problem is that it ends up calling
load_user_capability()
which in turn callscheck_enrolment_plugins()
. If you are using any external enrolment plugin, this is a mess. - As admin, browsing a participants list in "detailed view" mode triggers the same codepath.
And the trick in those scenarios is that we are getting a ton of data that we cannot cache efficiently.
Separating these functions from has_capability() also means that we can drop odd bits and pieces from has_capability(), and focus it on the currently-logged-in-user case.