martinlanghoff [Wed, 19 Sep 2007 07:25:10 +0000 (07:25 +0000)]
accesslib: rm get_role_context_capability() and update phpdoc
Remove unused function.
martinlanghoff [Wed, 19 Sep 2007 07:24:57 +0000 (07:24 +0000)]
accesslib: remove role_add_lastaccess_entries(),role_remove_lastaccess_entries()
Both of them are dead code in 18_STABLE and HEAD. And if
role_add_lastaccess_entries() is ever used on a large site it will
hammer the DB to bits.
Remove before anyone is foolish enough to try it.
martinlanghoff [Wed, 19 Sep 2007 07:24:43 +0000 (07:24 +0000)]
accesslib: require_capability() phpdoc notes
martinlanghoff [Wed, 19 Sep 2007 07:24:26 +0000 (07:24 +0000)]
accesslib: get_parent_cats() goes away too...
Not used anymore, and very inefficient.
If you need something like it, use course_category.path
just like we use context.path .
martinlanghoff [Wed, 19 Sep 2007 07:24:14 +0000 (07:24 +0000)]
accesslib: remove get_role_caps() merge_role_caps()
Both unused, and not part of the external API.
martinlanghoff [Wed, 19 Sep 2007 07:24:02 +0000 (07:24 +0000)]
accesslib: remove validate_context()
No longer used anywhere. Not really useful outside of accesslib, so no
point in keeping it.
martinlanghoff [Wed, 19 Sep 2007 07:23:41 +0000 (07:23 +0000)]
accesslib: get_context_instance() - ignore clearcache
"cleacache" is no longer needed, and nothing is calling it.
Still - handle it as a noop to avoid erroring out with custom/contrib
code.
martinlanghoff [Wed, 19 Sep 2007 07:23:30 +0000 (07:23 +0000)]
accesslib: get_parent_contexts() reworked to use context.path
Now that we can use $context->path trivially, and avoid touching the db
for data we already have... Just Do It!
martinlanghoff [Wed, 19 Sep 2007 07:23:15 +0000 (07:23 +0000)]
accesslib: remove insert_context_rel(), build_context_rel() and others
The context_rel table is not used anymore. Get rid of all references
to it.
TODO: Drop the orphaned table - but we'll do that on HEAD.
martinlanghoff [Wed, 19 Sep 2007 07:23:01 +0000 (07:23 +0000)]
accesslib: mark_context_dirty() - fix race condition
We had a 1s race condition where a user could get their rights loaded
at the exact time an admin is changing roles/caps and see the "old"
data. Or even see a half-updated view of the access controls.
Yuck.
So we fix the race condition backdating the dirtyness. Cheap, but
effective. And then we backdate it some more to cover for minor clock
flutter on clusters (you still need ntp however!).
martinlanghoff [Wed, 19 Sep 2007 07:22:49 +0000 (07:22 +0000)]
accesslib: mark_context_dirty() don't mark it there is no path
martinlanghoff [Wed, 19 Sep 2007 07:22:37 +0000 (07:22 +0000)]
datalib: add_to_log() fix a bug and better error handling
All the $db->Execute calls now do proper err handling, and send their
message to debugging().
martinlanghoff [Wed, 19 Sep 2007 07:22:24 +0000 (07:22 +0000)]
blocks/admin_tree: exit early for non-admins
Saves >10DBq and 18 includes at the homepage for all nonadmin users.
For non admin users, this makes the homepage _much_ more lightweight.
Before: inc 101 DBq 51 time 1.2s
After: inc 76 DBq 36 time 0.2s
So this commit shaves 1 full second for the non-logged-in homepage.
Still pretty bad on the includes, but shaved a good 25 files and 15 DBqs.
martinlanghoff [Wed, 19 Sep 2007 07:22:12 +0000 (07:22 +0000)]
accesslib: get_user_access_sitewide() fix invalid SQL for users without RAs
martinlanghoff [Wed, 19 Sep 2007 07:22:01 +0000 (07:22 +0000)]
datalib: get_admin() - cache in a static var
get_admin is called a zillion times during cron, and is a tiny
bit of data we can safely keep around... so...
(shaves 2 queries per email we send!)
martinlanghoff [Wed, 19 Sep 2007 07:21:47 +0000 (07:21 +0000)]
user/view: show user courses that are hidden, with dimmed class
If the $USER can see them, there is no reason to hide courses that
may be hidden. But show them dimmed to indicate so.
martinlanghoff [Wed, 19 Sep 2007 07:21:35 +0000 (07:21 +0000)]
datalib: get_my_courses() now returns invisible courses if visible to $USER
So admins can see the appropriate user listing in the profile page.
In fact, probably _all_ the visibility checks should be done by callers.
Hmmm...
martinlanghoff [Wed, 19 Sep 2007 07:21:23 +0000 (07:21 +0000)]
accesslib: has_capability() - fix warnings about FULLME constant
martinlanghoff [Wed, 19 Sep 2007 07:21:09 +0000 (07:21 +0000)]
mod/chat: chat_update_chat_times() smarter
If cron hasn't run for a few days, it would take
several runs for chat_update_chat_times() to get things back on track.
Now it's all fixed in one go, saving a bit of DB traffic. It all adds
up...
martinlanghoff [Wed, 19 Sep 2007 07:20:52 +0000 (07:20 +0000)]
mod/chat: reduce number of queries in cron.
Delete stale msgs in one DB query rather than in 1-per-chat-instance.
(From 600 DB queries to 1 on a site with 600 chat instances.)
Also - a walkthrough of chat_update_chat_times(), which seems buggy.
martinlanghoff [Wed, 19 Sep 2007 07:20:24 +0000 (07:20 +0000)]
accesslib: has_capability() now supports fake $USER for forum cron
has_capability() can handle the fake user that forum cron sets up
and will load the appropriate accessdata into $USER->access.
This makes forum cron work again. A test comparison between before
this patchseries yields:
With 1 forum post, sent total 24 times
- Before 11 000 DB queries (approx)
- After 506 DB queries
With 6 forum posts, sent a total of 452 times
- Before 47 876 DB queries
- After 8 256 DB queries
There is a very high variability, but we are going from 100-500
queries per sent email to 18-21 queries per sent email. The
variability probably stems from 2 of the 6 posts being in a 200-user
forum.
Still huge - by the time we are sending the email, we should know
everything we need to know about the user, the forum/thread/post and
the form. The average should be well below 1 DB query per email sent!
martinlanghoff [Wed, 19 Sep 2007 07:20:01 +0000 (07:20 +0000)]
user/index: make use of the smarter print_user_picture() -
Switch to using the smarter codepath in print_user_picture. Saves
20 DB queries in the normal page. One per user acct.
martinlanghoff [Wed, 19 Sep 2007 07:19:46 +0000 (07:19 +0000)]
course/participants: fix sort order when last access is null
martinlanghoff [Wed, 19 Sep 2007 07:19:35 +0000 (07:19 +0000)]
weblib: print_user()/print_user_picture() optimisations
print_user_picture() was forcing an unneeded dbquery
if you need an imagealt. And who doesn't need one these days.
So - teach print_user_picture() to take either $userid
_or_ $userobj as the first parameter. If that first
parameter has the fields we need, never touch the db.
In other words, only touch the DB as a last resort.
There is a bit of ugliness in testing whether we have
the fields or not, because these fields are inconsistently
with/without NOT NULL in the DB definitions. So we cannot
use isset() because it barfs on nulls. And we cannot use empty()
because it will match both on "missing key" and ''.
And while at it, silence warnings that we are missing string
for the year(s). Also fixes a missing string bug in really boring
courses that noone's visitied in many years ;-)
martinlanghoff [Wed, 19 Sep 2007 07:19:20 +0000 (07:19 +0000)]
moodlelib: require_login() - rework course/category visibility checks
Reworked the logic of the visibility checks so that we evaluate in a
chain:
- can view course (visible or user can see hidden)
- can view category (visible or user can see hidden)
Without this patch, users that could see hidden categories could not get
into courses inside of them.
While at it, fix reference to the old $USER->switchrole
martinlanghoff [Wed, 19 Sep 2007 07:19:05 +0000 (07:19 +0000)]
datalib:course_parent_visible() rework, remove category_parent_visible()
Reworked course_parent_visible() to always return in a constant
number of db queries (2 worst case) regardless of nesting depth.
The rewritten version has a small cache, but if you are going to
walk many courses, it's still 1~2 DB queries per category seen,
so the right thing to do is to check it in the caller, as seen
in get_my_courses().
martinlanghoff [Wed, 19 Sep 2007 07:18:54 +0000 (07:18 +0000)]
datalib: get_my_courses() - add course visibility checks
Reworked gmc to perform the course visibility checks. These are
very cheap if $CFG->allowvisiblecoursesinhiddencategories is true.
However, where we have to enforce category visibility, it adds a bit
of work. In simple terms, it adds a DB query to read all the categories,
and extra checks to make sure we are doing the right thing WRT
- course visibility vs the permission to see hidden courses
- category visibility vs the permission to see hidden categories
and still do it quickly.
martinlanghoff [Wed, 19 Sep 2007 07:18:37 +0000 (07:18 +0000)]
accesslib: get_user_courses_bycap() also returns categorypath
Costs next to nothing according to testing, and allows us to walk
the categories very cheaply. We'll need this in get_my_courses()...
What a cheapskates I am...
martinlanghoff [Wed, 19 Sep 2007 07:18:23 +0000 (07:18 +0000)]
accesslib: has_cap_fad() - merge switchrole with defaultuserrole
If you are a teacher in course X, you have at least
teacher-in-X + defaultloggedinuser-sitewide. So in the
course you'll have techer+defaultloggedinuser.
We try to mimic that in switchrole.
Thanks to Petr for pointing me to a similar fix in CVS.
Probably related: MDL-10945
martinlanghoff [Wed, 19 Sep 2007 07:18:10 +0000 (07:18 +0000)]
accesslib: remove unused static var
martinlanghoff [Wed, 19 Sep 2007 07:17:57 +0000 (07:17 +0000)]
accesslib: remove deprecated load_defaultuser_role()
martinlanghoff [Wed, 19 Sep 2007 07:17:45 +0000 (07:17 +0000)]
moodlelib:remove_course_contents() does not need to 'clearcache'
Now that delete_context() marks things dirty, we no longer
need to clearcache. Which is deprecated anyway.
martinlanghoff [Wed, 19 Sep 2007 07:17:34 +0000 (07:17 +0000)]
accesslib: delete_context() now appropriately marks the context dirty.
martinlanghoff [Wed, 19 Sep 2007 07:17:23 +0000 (07:17 +0000)]
Interactive enrolment/unenrolments: make sure we unset mycourses
martinlanghoff [Wed, 19 Sep 2007 07:17:08 +0000 (07:17 +0000)]
accesslib: load_all_capabilities() must clear USER->mycourses
martinlanghoff [Wed, 19 Sep 2007 07:16:56 +0000 (07:16 +0000)]
accesslib: drop rdef mangling part two
We had quite a bit of leftover rdef and ra mangling.
Be more thorough and clear it up.
While at it, make load_user_accessdata() and load_all_capabilities()
more consistent.
martinlanghoff [Wed, 19 Sep 2007 07:16:43 +0000 (07:16 +0000)]
moodlelib: require_login() - assign tempguest role using load_temp_role()
And remove the explicit handling of deprecated $USER->capabilities
martinlanghoff [Wed, 19 Sep 2007 07:16:29 +0000 (07:16 +0000)]
accesslib: intro load_temp_role() for temporary guest access
Loads a "ghost" role assignment, and all the needed rdef data
into an accessinfo array.
Also minor phpdoc update on get_role_access()
martinlanghoff [Wed, 19 Sep 2007 07:16:18 +0000 (07:16 +0000)]
accesslib: drop rdef mangling for default role - check in has_cap_fad()
There are some exceptions when checking for caps that are inherited
from the default role. Move the check into has_cap_fad() and stop
mangling the data we put in $ad[rdef].
We now also set $ad[dr] to record default roles added.
This will later allow us to share rdef across many users in $ACCESS.
Affects:
load_user_accessdata()
has_cap_fad()
While at it, document has_cap_fad() a bit.
martinlanghoff [Wed, 19 Sep 2007 07:16:04 +0000 (07:16 +0000)]
accesslib:load_all_capabilities() - fix guest user setup for multi-enrol
When setting things up for the guest user, the RA entry in accessdata
was not multi-enrol-friendly. Must have glossed it over in the
multi-enrol rework.
martinlanghoff [Wed, 19 Sep 2007 07:15:50 +0000 (07:15 +0000)]
accesslib/moodlelib: check $USER->access[rsw] for roleswitches
martinlanghoff [Wed, 19 Sep 2007 07:15:38 +0000 (07:15 +0000)]
course/unenrol: check $USER->access[rsw] for role switches
martinlanghoff [Wed, 19 Sep 2007 07:15:27 +0000 (07:15 +0000)]
accesslib: Document accessdata, public api, stale accessdata
martinlanghoff [Wed, 19 Sep 2007 07:15:12 +0000 (07:15 +0000)]
accesslib: rename "sess" and "accessinfo" to accessdata
The name for new data structure holding access control data
is "accessdata". And we have a new moniker "fad", short for
"from accessdata".
So
- has_cap_fromsess() -> has_cap_fad()
- access_inaccessdata() -> path_inaccessdata()
- aggr_roles_fromsess() -> aggr_roles_fad()
- $sess -> $ad
- $access -> $ad
Consistency, save typing, shorter codelines...
martinlanghoff [Wed, 19 Sep 2007 07:14:59 +0000 (07:14 +0000)]
accesslib:require_capability() revamp to check for USER->access
$USER->capabilities is deprecated.
martinlanghoff [Wed, 19 Sep 2007 07:14:48 +0000 (07:14 +0000)]
accesslib:context_moved() remove debugging msgs
martinlanghoff [Wed, 19 Sep 2007 07:14:34 +0000 (07:14 +0000)]
course/index: Move categories around using move_category()
Use the newfangled move_category() when moving categories
around, to ensure we Do The Right Thing in the backend,
decoupled from UI stuff.
martinlanghoff [Wed, 19 Sep 2007 07:14:23 +0000 (07:14 +0000)]
course/lib: move_courses() calls content_moved(), intro move_category()
move_courses() now calls content_moved() which will take care of any
accesslib-required changes. And introducing move_category() which
also calls content_moved() when needed.
martinlanghoff [Wed, 19 Sep 2007 07:14:11 +0000 (07:14 +0000)]
accesslib:content_moved() fix bug in depth handling
the depth was getting a bit out-of-control when moving
up the tree. Fix it...
martinlanghoff [Wed, 19 Sep 2007 07:13:57 +0000 (07:13 +0000)]
course: Changing a course cat from course/edit calls context_moved()
Changes to course cat from the main course settings form now calls
context_moved(), and accesslib data is properly maintained.
martinlanghoff [Wed, 19 Sep 2007 07:13:45 +0000 (07:13 +0000)]
accesslib: create_context() fix to also populate the depth
Set the depth field correctly.
martinlanghoff [Wed, 19 Sep 2007 07:13:33 +0000 (07:13 +0000)]
accesslib: Introducing context_moved() - call after moving courses/coursecats
With the new accesslib, moving courses and categories has a major
impact on enrolments and unenrolments.
At _least_ we need to signal accesslib that it has happened. So here
is context_moved() for exactly that.
Open to refactoring later into something along the lines of
- move_course()
- move_category()
However, at this stage the most important of those two: move_course()
does not fit very well with the code in course/edit. So keep it simple
for now.
martinlanghoff [Wed, 19 Sep 2007 07:13:20 +0000 (07:13 +0000)]
course/edit: mark the course contextpath as dirty to force a reload
Combined with the path creation in create_context() we can now create
a course, enter and edit it immediately. Amazing.
Like - 21st century technology.
martinlanghoff [Wed, 19 Sep 2007 07:13:08 +0000 (07:13 +0000)]
accesslib: create_context() now populates the path of new contexts
... and it populates the context cache too.
Unfortunately, it needs an INSERT followed by an UPDATE. Other than
a stored procedure, I don't know how to deal with this better.
(We could save the SELECT though! that's a thought...)
OTOH, we are getting so much mileage out of the path field
that it's probably a hit we have to take in the chin and move on.
martinlanghoff [Wed, 19 Sep 2007 07:12:56 +0000 (07:12 +0000)]
accesslib: simplify and speedup create_context()
Callers _must_ do their homework before calling create_context().
This allows us to save 2/3 queries per call (!!!).
As it stands, callers are all in accesslib anyway.
martinlanghoff [Wed, 19 Sep 2007 07:12:43 +0000 (07:12 +0000)]
course/unenrol codepaths mark the context dirty - bugfix
Oops. one if() branch was missing the mark_context_dirty(). Fixed.
martinlanghoff [Wed, 19 Sep 2007 07:12:33 +0000 (07:12 +0000)]
accesslib:reload_all_capabilities() - force a reload of mycourses
unset $USER->mycourses to force a reload of mycourses too.
martinlanghoff [Wed, 19 Sep 2007 07:12:22 +0000 (07:12 +0000)]
enrol/paypal: mark the contextpath as dirty on unenrolment
so the unenrolment is effective immediately.
martinlanghoff [Wed, 19 Sep 2007 07:12:10 +0000 (07:12 +0000)]
enrol/mnet: mark context as dirty after unenrol
So the unenrolment is effective immediately.
martinlanghoff [Wed, 19 Sep 2007 07:11:56 +0000 (07:11 +0000)]
deprecatedlib: Legacy interactive enrol/unenrol codepaths mark the context dirty
My heart is not so cold. These old buddies also need love and care...
martinlanghoff [Wed, 19 Sep 2007 07:11:42 +0000 (07:11 +0000)]
All interactive enrol/unenrol codepaths mark the context dirty
Manually enrolling and unenrolling self, and other users should
transparently set the context dirty. So walk all callers to
role_assign() and role_unassign() and mark the context dirty
where appropriate.
OTOH, most automated-backend enrol/unenrol mechanisms should not.
The backend lookups that happen when you login are well covered
by the login/enrolment process, and don't need to be marked dirty.
martinlanghoff [Wed, 19 Sep 2007 07:11:31 +0000 (07:11 +0000)]
cron: call cleanup_dirty_contexts()
martinlanghoff [Wed, 19 Sep 2007 07:11:18 +0000 (07:11 +0000)]
accesslib: Introduce (and use) reload_all_capabilities()
If accessinfo is stale, we need to reload it without losing
out "interesting" state -- transparently for the end user.
That means preserving active role switches, loginas (site and course
level), etc. The logic for that is encapsulated in
reload_all_capabilities().
Also affected:
- has_capability() which now calls reload_all_capabilities()
- role_switch() - minor tidyup
martinlanghoff [Wed, 19 Sep 2007 07:11:04 +0000 (07:11 +0000)]
accesslib: get_user_courses_bycap() fix bug introduced by refactor
The refactor that created make_context_subobj() triggered a bug.
Smack in the hand to the sloppy programmer using variables outside
of the context they were meant to be used in!
martinlanghoff [Wed, 19 Sep 2007 07:10:52 +0000 (07:10 +0000)]
admin/roles: context-specific role changes mark the context as dirty
And will force a reload of $USER->access for logged-in users that need
to read _this_ context. Much lower impact - still not a great idea to
edit assignments/caps on very busy courses, but impact should be low.
martinlanghoff [Wed, 19 Sep 2007 07:10:37 +0000 (07:10 +0000)]
admin/roles: sitewide role changes mark site context as dirty
And will force a reload of $USER->access for all logged-in users
on their next request.
We will have to tell admins of large sites to avoid making role changes
at busy times, as it does generate extra load.
martinlanghoff [Wed, 19 Sep 2007 07:10:24 +0000 (07:10 +0000)]
accesslib: Introduce $DIRTYCONTEXTS, $USER->access[time],is_contextpath_clean()
has_capability() now (ab)uses a new global: DIRTYCONTEXTS where we
load the contexts that have changed since since $USER->access[time]
The shallow/easy checks are done in has_capability(), deeper checks
go into the newfangled is_contextpath_clean().
The only complication now is to reload the relevant caps without losing
switches, loginas, etc...
martinlanghoff [Wed, 19 Sep 2007 07:10:09 +0000 (07:10 +0000)]
accesslib: Introduce functions to deal with dirty contexts
The accessinfo held in $USER->access can easily get out of
sync with reality if and admin has removed our access,
or expanded it after we loaded our accessinfo.
To handle this, we'll use the config_plugins table with an
'accesslib/dirtycontexts' plugin signature to store the paths of
recently changed contexts. To handle those dirrrty entries, here
we introduce
get_dirty_contexts() - for lib/setup
mark_context_dirty()
cleanup_dirty_contexts() - for cron
martinlanghoff [Wed, 19 Sep 2007 07:09:50 +0000 (07:09 +0000)]
get_role_users() callers rework to use the new $gethidden
martinlanghoff [Wed, 19 Sep 2007 07:09:36 +0000 (07:09 +0000)]
group/assign: fixed performance of assigning users to groups
- page would not display on a course with 600 users
martinlanghoff [Wed, 19 Sep 2007 07:09:24 +0000 (07:09 +0000)]
course/lib:print_course() smarter calling of get_role_users()
And saves a few dbqueries too...
martinlanghoff [Wed, 19 Sep 2007 07:09:13 +0000 (07:09 +0000)]
accesslib:get_role_users() revamp
Now get_role_users() joins with contexts and roles too, so we can
push more work into it, and simplify the callers.
One important change is that the $view flag gets reworked into
$gethidden, pushing the cap check to the caller.
This commit is followed by a cleanup of the callers...
martinlanghoff [Wed, 19 Sep 2007 07:09:01 +0000 (07:09 +0000)]
datalib: get_courses_search() remove dead code
martinlanghoff [Wed, 19 Sep 2007 07:08:50 +0000 (07:08 +0000)]
course/search.php: smarter about contexts, bugfix in pagination
Save a ton of queries about contexts, and a bugfix in how we are
calling the pagination for get_courses_search().
martinlanghoff [Wed, 19 Sep 2007 07:08:37 +0000 (07:08 +0000)]
datalib: get_courses_search() learns to be smart about contexts...
Join against contexts, save bazillion context lookups...
martinlanghoff [Wed, 19 Sep 2007 07:08:24 +0000 (07:08 +0000)]
categories: Categories page and get_courses_page() - smarter about context
This patch saves 1600 context lookups on a 1600 course category. rcache
does help a bit with small categories, but on large setups, this is
not sustainable.
And it's not needed either. We have the data right at our fingertips.
Just get it when it's cheap...
martinlanghoff [Wed, 19 Sep 2007 07:08:12 +0000 (07:08 +0000)]
accesslib: introducing make_context_subobj() - and refactor callers
We had many copies of the subcontext building bit. Time to
abstract it, and fix callers...
martinlanghoff [Wed, 19 Sep 2007 07:07:59 +0000 (07:07 +0000)]
accesslib: Fix dup enrolment entries in get_user_access_bycontext() and get_user_access_sitewide()
Avoid duplicate entries in the ra array. Now it works too!
martinlanghoff [Wed, 19 Sep 2007 07:07:45 +0000 (07:07 +0000)]
accesslib: get_context_users_bycap() draft for course participants...
Introducing get_context_users_bycap() which gets the data in
2 DB queries, takes around 10ms on my laptop, and returns
the records with a nice context property attached.
Note Note Note: right now, some user recs do not have a context
associated, so are _not_ returned. So this awaits Matt's fix
to contexts maintenance to be 100% accurate...
martinlanghoff [Wed, 19 Sep 2007 07:07:34 +0000 (07:07 +0000)]
get_my_courses() - bugfix in sitewide-login-as support.
Oops. The supportfor login-as was buggy now with sitewide
loginas. Now works in both.
martinlanghoff [Wed, 19 Sep 2007 07:07:21 +0000 (07:07 +0000)]
get_my_courses(): Support course-level login as
A walkthrough of course-login-as functionality shows that is
Just Works, except that get_my_courses() was showing all the
courses. So we fix it.
And cleanup load_all_capabilities() - things just work
transparently.
martinlanghoff [Wed, 19 Sep 2007 07:07:08 +0000 (07:07 +0000)]
accesslib: remove some functions we do not need anymore
This is *the* scary commit. No more scaffolding, no more
training wheels. Remove the legacy has_capabilty_old() and
several supporting functions.
has_capability_old()
capability_search()
is_parent_context()
roles_context_cmp()
load_user_capability()
capability_prohibits()
I've grepped far and wide. Noone else uses the supporting
functions anywhere in-the-known-universe. If I could not
find it, it does not exist.
[Thankful that cvs/git/whatever will hold on to them
if I end up having to regret this.]
martinlanghoff [Wed, 19 Sep 2007 07:06:55 +0000 (07:06 +0000)]
accesslib: Intro global $ACCESS and load_user_accessdata()
This patch introduces a new global $ACCESS that will cache
accessdata (our ra/rdef array) for users that are _not_ the
logged in user.
Most of the time it will be empty (luckily).
Each new user we have to get "in" costs us 3 or 4 cheap
dbqueries at the moment, so it is not that bad.
has_capability() now calls load_user_accessdata() if the
call is for a non-logged-user. So $ACCESS is autopopulated
transparently.
This also means that has_capability no longer calls
has_capability_old(). Yay!
With this patch, user/view.php for looking at a user in a course...
Before: 62 dbqueries, 10.3MB, 0.7s
After: 49 dbqueries, 8.5MB, 0.3s
martinlanghoff [Wed, 19 Sep 2007 07:06:44 +0000 (07:06 +0000)]
course/view: roleswitch checks moved to the course page
Implemented all the relevant checks for role_switch().
accesslib's role_switch() doesn't do any UI-related checks any more,
being a backend lib call. These belong here.
martinlanghoff [Wed, 19 Sep 2007 07:06:30 +0000 (07:06 +0000)]
accesslib: add support for multi-enrolments
I had dropped support for multi-enrolments on the same context.
Oops!
This patch reinstates it, changing the semantics of the 'ra'
array leaves from an int to an array of ints.
So no instead of
$USER->access['ra']['/1/12/543'] = 5
we have
$USER->access['ra']['/1/12/543'] = array(5)
the functions that build the array, and the array walkers have
been updated. This touches...
Writing RAs
load_all_capabilities()
get_user_access_sitewide()
get_user_access_bycontext()
Reading RAs
has_cap_fromsess()
aggr_roles_fromsess()
Thanks to Matt Clarkson for mentioning multi-enrolments!
martinlanghoff [Wed, 19 Sep 2007 07:06:17 +0000 (07:06 +0000)]
weblib: switchroles_form() user_login_string() handle the new switchroles
The switched role data bits have moved to a
different place in the session. Trivial to fix here.
martinlanghoff [Wed, 19 Sep 2007 07:06:03 +0000 (07:06 +0000)]
accesslib: role_switch() supports unswitching by passing $roleid=0
It is a good idea, silly of me to remove it...
martinlanghoff [Wed, 19 Sep 2007 07:05:48 +0000 (07:05 +0000)]
accesslib: has_cap_from_sess() now supports role switching
With this commit we now have very fast support for
roleswitching, based on $sess[rsw] entries.
And a bit of phpdoc. This is function, and the
datastructure it walks, is the heart of of it.
martinlanghoff [Wed, 19 Sep 2007 07:05:32 +0000 (07:05 +0000)]
accesslib - role_switch() revamp, introduce get_role_access_bycontext()
First stage of role_switch() rewrite - role_switch() sets up
a rsw entry in $USER->access, and makes sure we have the
appropriate role definitions in rdef.
That is where get_role_access_bycontext() comes into play -
gets all the rdef entries in one cheap sql query.
... though there may be many of them...
TODO:
- fix callers of role_switch()
- teach has_cap_fromsess() to read the rsw entries
martinlanghoff [Wed, 19 Sep 2007 07:05:21 +0000 (07:05 +0000)]
accesslib: Draft get_context_users_byrole()
Draft - use for the course participants list page
Uses 1 DB query (cheap too - 2~7ms).
TODO:
- implement additional where clauses
- sorting
- get course participants list to use it!
returns a users array, both sorted _and_ keyed
on id (as get_my_courses() does)
as a bonus, every user record comes with its own
personal context, as our callers need it straight away
{save 1 dbquery per user! yay!}
martinlanghoff [Wed, 19 Sep 2007 07:04:59 +0000 (07:04 +0000)]
get_my_courses() and get_user_courses_bycap() field handling and caching
- Field handling moves back to get_my_courses() and now we have
almost all the fields that the old get_my_courses() did
(except for summary, which is *huge*) so get_my_courses() asks
for a lot of fields, but the get_user_courses_bycap() defaults
are _much_ leaner now.
I think this makes sense ;-)
- get_my_courses() now caches the course ids for the currently logged in
user in $USER->mycourses -- as a _string_. This is magnitudes more efficient
than having it as an array.
The cache makes a difference, but it's not very visible on
normal pageloads (with my courses block, for example).
However, over 100 iterations, for a user with 50 enrolments in a site
with 6K courses, we go from 4.3s to 0.6s. And the DB queries are *cheap*.
$tt = microtime(true);
for($n=0;$n<100;$n++) {
get_my_courses($USER->id, 'sortorder ASC');
}
error_log("took " . (microtime(true) - $tt));
martinlanghoff [Wed, 19 Sep 2007 07:04:37 +0000 (07:04 +0000)]
accesslib: get_user_courses_bycap() - make $doanything work in the optimised path
OMG! Bugfix!
martinlanghoff [Wed, 19 Sep 2007 07:04:23 +0000 (07:04 +0000)]
accesslib: get_user_courses_bycap() is less of a piggy now...
get_user_courses_bycap() replaces get_courses_bycap_fromsess().
Using a combination of in-DB enrolments and in-session capability
checks, we narrow down the courses we fetch from the DB for checking.
This patch adds a small DB query, and has has a moderate impact on
the timings observable on my laptop (~300ms?), but reduces
*significantly* the bandwidth used, which in cluster environments
with frontends separate from backends has a serious impact.
martinlanghoff [Wed, 19 Sep 2007 07:04:10 +0000 (07:04 +0000)]
datalib: get_my_courses() - some fixes to the data we return
strangely, get_my_courses() is expected to return the
array keyed on id, which messes up the sorting
So let's do it ;-)
martinlanghoff [Wed, 19 Sep 2007 07:03:49 +0000 (07:03 +0000)]
accesslib: get_my_courses() rework, new get_courses_bycap_fromsess()
get_my_courses() goes from a bazillion queries (500 in some sample
cases) to 1 for the logged-in user, and 4 for a non-logged-in user.
One of those queries brings a *lot* of data across (all rows from
mdl_course) so there is room for serious optimisation.
However, this clocks at ~300 ms on my laptop, costly, but not
the end of the world. If your PHP-DB link has bandwidth probs
it might be a problem.
A few important changes to get_my_courses()
- (Compat ALERT!) the default fields are less than before --
(will be followed by patches that fix the callers!) our defaults
had grown to quite a bit because of the crazy caching scheme it had
- the $fields parameter is to name _additional_ fields you need, and
ideally wants them passed as an array. Will cope with old-style
strings too.
- the returned courses have an extra property "context" that is
a fully valid context object, so if the caller needs to perform
further accesslib checks, we save a query per course down the road
The work is done in the newfangled get_courses_bycap_fromsess()
which is brute-force but fast. I'm sure we can optimise the common
cases a lot in it if we try. It'd be worthwhile to
- reduce the rows we grab - that's really boneheaded
- if we copy and tweak the logic of has_cap_fromsess() in it
it can be made even faster
martinlanghoff [Wed, 19 Sep 2007 07:03:34 +0000 (07:03 +0000)]
accesslib: has_capability() - useful debugging bit...
martinlanghoff [Wed, 19 Sep 2007 07:03:19 +0000 (07:03 +0000)]
accesslib: get_user_access_bycontext() fetches overrides in subcontexts, intro aggr_roles_fromsess()
The main thing here is that overrides in subcontexts are
now read correctly (and still cheaply) into the access array.
Also
- introducing aggr_roles_fromsess() with gives you a list of
the relevant roles that affect the user in this context
- we clear out $USER->access on login/logout
- get_user_access_bycontext() gets a few optimisations too...
martinlanghoff [Wed, 19 Sep 2007 07:02:57 +0000 (07:02 +0000)]
accesslib: default, guest and notloggedin roles work properly now
Changes around load_user_capability() and has_capability() to make
the default role fallbacks and guest/nonloggedin roles work.
This commit also introduces the concept of having a magic
context next to the root context in $USER->access[ra], as
$USER->access[ra][/1] = 1 (admin roleid)
$USER->access[ra][/1:def] = 7 (loggedinuser roleid)
and has_cap_fromsess() now checks for that magic context
as well.
martinlanghoff [Wed, 19 Sep 2007 07:02:44 +0000 (07:02 +0000)]
accesslib: has_capability() now works for the logged in user
With this commit, the new has_capability works for the logged
in user correctly.
- load_all_capabilities() no longer calls load_user_capability()!
6K dbqueries less on login... ;-)
- When delving into a context we haven't loaded yet, we call
get_user_access_bycontext()
- Introduce: get_user_access_bycontext()
- Several fixes in get_user_access_sitewide()
(renamed from get_user_sitewide_access())
- Fixes in has_cap_fromsess()
- Introduce access_insess() to check if we have to call
get_user_access_bycontext() for the context
martinlanghoff [Wed, 19 Sep 2007 07:02:31 +0000 (07:02 +0000)]
accesslib: initial has_capability() rewrite
- has_capability() renamed has_capability_old() and we fallback
when we cannot answer the question
- has_capability() works great for the course-and-above contexts
for the logged in user - does not touch the DB
- works based on $USER->access which has a pretty compact view
of the user's access rights...
TODO:
- deal with contexts below the course - here we need to
trigger the role-assignment and role-defs load when needed
- deal with "other" contexts that hang from the system context
- deal with global roleswitch, local roleswitch