From e1e1f498201f8852755cbbbfc5eeb7f476bca1cd Mon Sep 17 00:00:00 2001 From: martinlanghoff Date: Wed, 19 Sep 2007 06:53:09 +0000 Subject: [PATCH] pagelib: Course page - preload child contexts and smarter user_allowed_editing() With this patch we preload the child contexts for the course and hold on to them. This means that in one DB query we have all the contexts we are going to need. The checks for user_allowed_editing() move from weblib:update_icon() to user_allowed_editing(), where we cache the result, and in the process save 50% of the cap checks by testing separately blocks from modules (doh!). Still, the cap checks here are very inefficient... With the last 3 patches, a course page with default blocks and 9 modinstances goes from 157 to 86 db queries when logged in as a non-editing user (guest, student). As admin it drops from 88 to 81. Conflicts: lib/pagelib.php --- lib/pagelib.php | 46 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/lib/pagelib.php b/lib/pagelib.php index 747c2ae724..5dc5a4d544 100644 --- a/lib/pagelib.php +++ b/lib/pagelib.php @@ -344,6 +344,14 @@ class page_course extends page_base { if(empty($this->courserecord) && !defined('ADMIN_STICKYBLOCKS')) { error('Cannot fully initialize page: invalid course id '. $this->id); } + + $this->context = get_context_instance(CONTEXT_COURSE, $this->id); + + // Preload - ensures that the context cache is populated + // in one DB query... + $this->childcontexts = get_child_contexts($this->context); + + // Mark we're done $this->full_init_done = true; } @@ -352,13 +360,40 @@ class page_course extends page_base { // Can user edit the course page or "sticky page"? // This is also about editting of blocks BUT mainly activities in course page layout, see // update_course_icon() has very similar checks - it must use the same capabilities + // + // this is a _very_ expensive check - so cache it during execution + // function user_allowed_editing() { - global $USER; - if (has_capability('moodle/site:manageblocks', get_context_instance(CONTEXT_SYSTEM)) && defined('ADMIN_STICKYBLOCKS')) { + $this->init_full(); + + if (isset($this->_user_allowed_editing)) { + return $this->_user_allowed_editing; + } + + if (has_capability('moodle/site:manageblocks', get_context_instance(CONTEXT_SYSTEM)) + && defined('ADMIN_STICKYBLOCKS')) { + $this->_user_allowed_editing = true; + return true; + } + if (has_capability('moodle/course:manageactivities', $this->context)) { + $this->_user_allowed_editing = true; return true; } - return editcourseallowed($this->id); + + // Exhaustive (and expensive!) checks to see if the user + // has editing abilities to a specific module/block/group... + // This code would benefit from the ability to check specifically + // for overrides. + foreach ($this->childcontexts as $cc) { + if (($cc->contextlevel == CONTEXT_MODULE && + has_capability('moodle/course:manageactivities', $cc)) || + ($cc->contextlevel == CONTEXT_BLOCK && + has_capability('moodle/site:manageblocks', $cc))) { + $this->_user_allowed_editing = true; + return true; + } + } } // Is the user actually editing this course page or "sticky page" right now? @@ -395,7 +430,10 @@ class page_course extends page_base { // The "Editing On" button will be appearing only in the "main" course screen // (i.e., no breadcrumbs other than the default one added inside this function) - $buttons = switchroles_form($this->courserecord->id) . update_course_icon($this->courserecord->id ); + $buttons = switchroles_form($this->courserecord->id); + if ($this->user_allowed_editing()) { + $buttons .= update_course_icon($this->courserecord->id ); + } $buttons = empty($morenavlinks) ? $buttons : ' '; print_header($title, $this->courserecord->fullname, $navigation, -- 2.39.5