/** * Add to the access ctrl array the data needed by a user for a given course. * * This function injects all course related access info into the accessdata array. * * @private * @param int $userid the id of the user * @param context_course $coursecontext course context * @param array $accessdata accessdata array (modified) * @return void modifies $accessdata parameter */ function load_course_context($userid, context_course $coursecontext, &$accessdata) { global $DB, $CFG, $ACCESSLIB_PRIVATE; if (empty($coursecontext->path)) { // weird, this should not happen return; } if (isset($accessdata['loaded'][$coursecontext->instanceid])) { // already loaded, great! return; } $roles = array(); if (empty($userid)) { if (!empty($CFG->notloggedinroleid)) { $roles[$CFG->notloggedinroleid] = $CFG->notloggedinroleid; } } else { if (isguestuser($userid)) { if ($guestrole = get_guest_role()) { $roles[$guestrole->id] = $guestrole->id; } } else { // Interesting role assignments at, above and below the course context list($parentsaself, $params) = $DB->get_in_or_equal($coursecontext->get_parent_context_ids(true), SQL_PARAMS_NAMED, 'pc_'); $params['userid'] = $userid; $params['children'] = $coursecontext->path . "/%"; $sql = "SELECT ra.*, ctx.path\n FROM {role_assignments} ra\n JOIN {context} ctx ON ra.contextid = ctx.id\n WHERE ra.userid = :userid AND (ctx.id {$parentsaself} OR ctx.path LIKE :children)"; $rs = $DB->get_recordset_sql($sql, $params); // add missing role definitions foreach ($rs as $ra) { $accessdata['ra'][$ra->path][(int) $ra->roleid] = (int) $ra->roleid; $roles[$ra->roleid] = $ra->roleid; } $rs->close(); // add the "default frontpage role" when on the frontpage if (!empty($CFG->defaultfrontpageroleid)) { $frontpagecontext = context_course::instance(get_site()->id); if ($frontpagecontext->id == $coursecontext->id) { $roles[$CFG->defaultfrontpageroleid] = $CFG->defaultfrontpageroleid; } } // do not forget the default role if (!empty($CFG->defaultuserroleid)) { $roles[$CFG->defaultuserroleid] = $CFG->defaultuserroleid; } } } if (!$roles) { // weird, default roles must be missing... $accessdata['loaded'][$coursecontext->instanceid] = 1; return; } // now get overrides of interesting roles in all interesting contexts (this course + children + parents) $params = array('c' => $coursecontext->id); list($parentsaself, $rparams) = $DB->get_in_or_equal($coursecontext->get_parent_context_ids(true), SQL_PARAMS_NAMED, 'pc_'); $params = array_merge($params, $rparams); list($roleids, $rparams) = $DB->get_in_or_equal($roles, SQL_PARAMS_NAMED, 'r_'); $params = array_merge($params, $rparams); $sql = "SELECT ctx.path, rc.roleid, rc.capability, rc.permission\n FROM {role_capabilities} rc\n JOIN {context} ctx\n ON (ctx.id = rc.contextid)\n JOIN {context} cctx\n ON (cctx.id = :c\n AND (ctx.id {$parentsaself} OR ctx.path LIKE " . $DB->sql_concat('cctx.path', "'/%'") . "))\n WHERE rc.roleid {$roleids}\n ORDER BY rc.capability"; // fixed capability order is necessary for rdef dedupe $rs = $DB->get_recordset_sql($sql, $params); $newrdefs = array(); foreach ($rs as $rd) { $k = $rd->path . ':' . $rd->roleid; if (isset($accessdata['rdef'][$k])) { continue; } $newrdefs[$k][$rd->capability] = (int) $rd->permission; } $rs->close(); // share new role definitions foreach ($newrdefs as $k => $unused) { if (!isset($ACCESSLIB_PRIVATE->rolepermissions[$k])) { $ACCESSLIB_PRIVATE->rolepermissions[$k] = $newrdefs[$k]; } $accessdata['rdef_count']++; $accessdata['rdef'][$k] =& $ACCESSLIB_PRIVATE->rolepermissions[$k]; } $accessdata['loaded'][$coursecontext->instanceid] = 1; // we want to deduplicate the USER->access from time to time, this looks like a good place, // because we have to do it before the end of session dedupe_user_access(); }