Commit e922fe23 authored by Petr Skoda's avatar Petr Skoda
Browse files

MDL-29602 accesslib improvements

Refactoring and improvements of the accesslib.php library including prevention of access for not-logged-in users when forcelogin enabled, improved context caching, OOP refactoring of contexts, fixed context loading, deduplication of role definitions in user sessions, installation improvements, decoupling of enrolment checking from capability loading, added detection of deleted and non-existent users in has_capability(), new function accesslib test, auth and enrol upgrade notes.

More details are available in tracker subtasks.
parent 6731a04d
...@@ -65,13 +65,15 @@ if ($requestedqtype) { ...@@ -65,13 +65,15 @@ if ($requestedqtype) {
// Get the question counts, and all the context information, for each // Get the question counts, and all the context information, for each
// context. That is, rows of these results can be used as $context objects. // context. That is, rows of these results can be used as $context objects.
$ctxpreload = context_helper::get_preload_record_columns_sql('con');
$ctxgroupby = implode(',', array_keys(context_helper::get_preload_record_columns('con')));
$counts = $DB->get_records_sql(" $counts = $DB->get_records_sql("
SELECT qc.contextid, count(1) as numquestions, sum(hidden) as numhidden, con.id, con.contextlevel, con.instanceid, con.path, con.depth SELECT qc.contextid, count(1) as numquestions, sum(hidden) as numhidden, $ctxpreload
FROM {question} q FROM {question} q
JOIN {question_categories} qc ON q.category = qc.id JOIN {question_categories} qc ON q.category = qc.id
JOIN {context} con ON con.id = qc.contextid JOIN {context} con ON con.id = qc.contextid
$sqlqtypetest $sqlqtypetest
GROUP BY contextid, con.id, con.contextlevel, con.instanceid, con.path, con.depth GROUP BY qc.contextid, $ctxgroupby
ORDER BY numquestions DESC, numhidden ASC, con.contextlevel ASC, con.id ASC", $params); ORDER BY numquestions DESC, numhidden ASC, con.contextlevel ASC, con.id ASC", $params);
// Print the report heading. // Print the report heading.
...@@ -94,8 +96,10 @@ if ($requestedqtype) { ...@@ -94,8 +96,10 @@ if ($requestedqtype) {
$totalhidden = 0; $totalhidden = 0;
foreach ($counts as $count) { foreach ($counts as $count) {
// Work out a link for editing questions in this context. // Work out a link for editing questions in this context.
$contextname = print_context_name($count); context_helper::preload_from_record($count);
$url = question_edit_url($count); $context = context::instance_by_id($count->contextid);
$contextname = $context->get_context_name();
$url = question_edit_url($context);
if ($url) { if ($url) {
$contextname = '<a href="' . $url . '" title="' . $contextname = '<a href="' . $url . '" title="' .
get_string('editquestionshere', 'report_questioninstances') . get_string('editquestionshere', 'report_questioninstances') .
......
...@@ -96,7 +96,8 @@ foreach ($contexts as $conid => $con) { ...@@ -96,7 +96,8 @@ foreach ($contexts as $conid => $con) {
/// Put the contexts into a tree structure. /// Put the contexts into a tree structure.
foreach ($contexts as $conid => $con) { foreach ($contexts as $conid => $con) {
$parentcontextid = get_parent_contextid($con); $context = context::instance_by_id($conid);
$parentcontextid = get_parent_contextid($context);
if ($parentcontextid) { if ($parentcontextid) {
$contexts[$parentcontextid]->children[] = $conid; $contexts[$parentcontextid]->children[] = $conid;
} }
...@@ -156,13 +157,13 @@ function print_report_tree($contextid, $contexts, $systemcontext, $fullname) { ...@@ -156,13 +157,13 @@ function print_report_tree($contextid, $contexts, $systemcontext, $fullname) {
} }
// Pull the current context into an array for convinience. // Pull the current context into an array for convinience.
$context = $contexts[$contextid]; $context = context::instance_by_id($contextid);
// Print the context name. // Print the context name.
echo $OUTPUT->heading(print_context_name($contexts[$contextid]), 4, 'contextname'); echo $OUTPUT->heading($context->get_context_name(), 4, 'contextname');
// If there are any role assignments here, print them. // If there are any role assignments here, print them.
foreach ($context->roleassignments as $ra) { foreach ($contexts[$contextid]->roleassignments as $ra) {
$value = $ra->contextid . ',' . $ra->roleid; $value = $ra->contextid . ',' . $ra->roleid;
$inputid = 'unassign' . $value; $inputid = 'unassign' . $value;
......
...@@ -138,7 +138,8 @@ if ($capability) { ...@@ -138,7 +138,8 @@ if ($capability) {
// Put the contexts into a tree structure. // Put the contexts into a tree structure.
foreach ($contexts as $conid => $con) { foreach ($contexts as $conid => $con) {
$parentcontextid = get_parent_contextid($con); $context = context::instance_by_id($conid);
$parentcontextid = get_parent_contextid($context);
if ($parentcontextid) { if ($parentcontextid) {
$contexts[$parentcontextid]->children[] = $conid; $contexts[$parentcontextid]->children[] = $conid;
} }
...@@ -196,7 +197,8 @@ function print_report_tree($contextid, $contexts, $allroles) { ...@@ -196,7 +197,8 @@ function print_report_tree($contextid, $contexts, $allroles) {
$url = "$CFG->wwwroot/$CFG->admin/roles/override.php?contextid=$contextid"; $url = "$CFG->wwwroot/$CFG->admin/roles/override.php?contextid=$contextid";
$title = get_string('changeoverrides', 'tool_capability'); $title = get_string('changeoverrides', 'tool_capability');
} }
echo '<h3><a href="' . $url . '" title="' . $title . '">', print_context_name($contexts[$contextid]), '</a></h3>'; $context = context::instance_by_id($contextid);
echo '<h3><a href="' . $url . '" title="' . $title . '">', $context->get_context_name(), '</a></h3>';
// If there are any role overrides here, print them. // If there are any role overrides here, print them.
if (!empty($contexts[$contextid]->rolecapabilities)) { if (!empty($contexts[$contextid]->rolecapabilities)) {
......
...@@ -39,7 +39,9 @@ ...@@ -39,7 +39,9 @@
if ($shibbolethauth->user_login($frm->username, $frm->password)) { if ($shibbolethauth->user_login($frm->username, $frm->password)) {
$USER = authenticate_user_login($frm->username, $frm->password); $user = authenticate_user_login($frm->username, $frm->password);
enrol_check_plugins($user);
session_set_user($user);
$USER->loggedin = true; $USER->loggedin = true;
$USER->site = $CFG->wwwroot; // for added security, store the site in the $USER->site = $CFG->wwwroot; // for added security, store the site in the
...@@ -75,9 +77,6 @@ ...@@ -75,9 +77,6 @@
} }
} }
enrol_check_plugins($USER);
load_all_capabilities(); /// This is what lets the user do anything on the site :-)
redirect($urltogo); redirect($urltogo);
exit; exit;
......
This files describes API changes in /auth/* - plugins,
information provided here is intended especially for developers.
=== 2.2 ===
required changes in code:
* the correct sequence to set up global $USER is:
$user = get_complete_user_data('username', $username); // or $user = authenticate_user_login()
enrol_check_plugins($user);
session_set_user($user);
...@@ -143,9 +143,9 @@ if (!empty($entry->id)) { ...@@ -143,9 +143,9 @@ if (!empty($entry->id)) {
if ($CFG->useblogassociations && ($blogassociations = $DB->get_records('blog_association', array('blogid' => $entry->id)))) { if ($CFG->useblogassociations && ($blogassociations = $DB->get_records('blog_association', array('blogid' => $entry->id)))) {
foreach ($blogassociations as $assocrec) { foreach ($blogassociations as $assocrec) {
$contextrec = $DB->get_record('context', array('id' => $assocrec->contextid)); $context = get_context_instance_by_id($assocrec->contextid);
switch ($contextrec->contextlevel) { switch ($context->contextlevel) {
case CONTEXT_COURSE: case CONTEXT_COURSE:
$entry->courseassoc = $assocrec->contextid; $entry->courseassoc = $assocrec->contextid;
break; break;
......
...@@ -95,7 +95,7 @@ class blog_edit_form extends moodleform { ...@@ -95,7 +95,7 @@ class blog_edit_form extends moodleform {
$a->modname = $mod->name; $a->modname = $mod->name;
$context = get_context_instance(CONTEXT_MODULE, $modid); $context = get_context_instance(CONTEXT_MODULE, $modid);
} else { } else {
$context = $DB->get_record('context', array('id' => $entry->modassoc)); $context = get_context_instance_by_id($entry->modassoc);
$cm = $DB->get_record('course_modules', array('id' => $context->instanceid)); $cm = $DB->get_record('course_modules', array('id' => $context->instanceid));
$a = new stdClass(); $a = new stdClass();
$a->modtype = $DB->get_field('modules', 'name', array('id' => $cm->module)); $a->modtype = $DB->get_field('modules', 'name', array('id' => $cm->module));
...@@ -134,7 +134,7 @@ class blog_edit_form extends moodleform { ...@@ -134,7 +134,7 @@ class blog_edit_form extends moodleform {
// validate course association // validate course association
if (!empty($data['courseassoc']) && has_capability('moodle/blog:associatecourse', $sitecontext)) { if (!empty($data['courseassoc']) && has_capability('moodle/blog:associatecourse', $sitecontext)) {
$coursecontext = $DB->get_record('context', array('id' => $data['courseassoc'], 'contextlevel' => CONTEXT_COURSE)); $coursecontext = get_context_instance(CONTEXT_COURSE, $data['courseassoc']);
if ($coursecontext) { if ($coursecontext) {
if (!is_enrolled($coursecontext) and !is_viewing($coursecontext)) { if (!is_enrolled($coursecontext) and !is_viewing($coursecontext)) {
...@@ -149,12 +149,12 @@ class blog_edit_form extends moodleform { ...@@ -149,12 +149,12 @@ class blog_edit_form extends moodleform {
if (!empty($data['modassoc'])) { if (!empty($data['modassoc'])) {
$modcontextid = $data['modassoc']; $modcontextid = $data['modassoc'];
$modcontext = $DB->get_record('context', array('id' => $modcontextid, 'contextlevel' => CONTEXT_MODULE)); $modcontext = get_context_instance(CONTEXT_MODULE, $modcontextid);
if ($modcontext) { if ($modcontext) {
// get context of the mod's course // get context of the mod's course
$path = explode('/', $modcontext->path); $path = explode('/', $modcontext->path);
$coursecontext = $DB->get_record('context', array('id' => $path[(count($path) - 2)])); $coursecontext = get_context_instance_by_id($path[(count($path) - 2)]);
// ensure only one course is associated // ensure only one course is associated
if (!empty($data['courseassoc'])) { if (!empty($data['courseassoc'])) {
......
...@@ -247,10 +247,10 @@ class blog_entry { ...@@ -247,10 +247,10 @@ class blog_entry {
// First find and show the associated course // First find and show the associated course
foreach ($blogassociations as $assocrec) { foreach ($blogassociations as $assocrec) {
$contextrec = $DB->get_record('context', array('id' => $assocrec->contextid)); $context = get_context_instance_by_id($assocrec->contextid);
if ($contextrec->contextlevel == CONTEXT_COURSE) { if ($context->contextlevel == CONTEXT_COURSE) {
$assocurl = new moodle_url('/course/view.php', array('id' => $contextrec->instanceid)); $assocurl = new moodle_url('/course/view.php', array('id' => $context->instanceid));
$text = $DB->get_field('course', 'shortname', array('id' => $contextrec->instanceid)); //TODO: performance!!!! $text = $DB->get_field('course', 'shortname', array('id' => $context->instanceid)); //TODO: performance!!!!
$assocstr .= $OUTPUT->action_icon($assocurl, new pix_icon('i/course', $text), null, array(), true); $assocstr .= $OUTPUT->action_icon($assocurl, new pix_icon('i/course', $text), null, array(), true);
$hascourseassocs = true; $hascourseassocs = true;
$assoctype = get_string('course'); $assoctype = get_string('course');
...@@ -259,15 +259,15 @@ class blog_entry { ...@@ -259,15 +259,15 @@ class blog_entry {
// Now show mod association // Now show mod association
foreach ($blogassociations as $assocrec) { foreach ($blogassociations as $assocrec) {
$contextrec = $DB->get_record('context', array('id' => $assocrec->contextid)); $context = get_context_instance_by_id($assocrec->contextid);
if ($contextrec->contextlevel == CONTEXT_MODULE) { if ($context->contextlevel == CONTEXT_MODULE) {
if ($hascourseassocs) { if ($hascourseassocs) {
$assocstr .= ', '; $assocstr .= ', ';
$hascourseassocs = false; $hascourseassocs = false;
} }
$modinfo = $DB->get_record('course_modules', array('id' => $contextrec->instanceid)); $modinfo = $DB->get_record('course_modules', array('id' => $context->instanceid));
$modname = $DB->get_field('modules', 'name', array('id' => $modinfo->module)); $modname = $DB->get_field('modules', 'name', array('id' => $modinfo->module));
$assocurl = new moodle_url('/mod/'.$modname.'/view.php', array('id' => $modinfo->id)); $assocurl = new moodle_url('/mod/'.$modname.'/view.php', array('id' => $modinfo->id));
......
...@@ -77,7 +77,7 @@ class enrol_guest_plugin extends enrol_plugin { ...@@ -77,7 +77,7 @@ class enrol_guest_plugin extends enrol_plugin {
if (empty($instance->password)) { if (empty($instance->password)) {
// Temporarily assign them some guest role for this context // Temporarily assign them some guest role for this context
$context = get_context_instance(CONTEXT_COURSE, $instance->courseid); $context = get_context_instance(CONTEXT_COURSE, $instance->courseid);
$USER->access = load_temp_role($context, $CFG->guestroleid, $USER->access); load_temp_course_role($context, $CFG->guestroleid);
return ENROL_REQUIRE_LOGIN_CACHE_PERIOD + time(); return ENROL_REQUIRE_LOGIN_CACHE_PERIOD + time();
} }
...@@ -131,7 +131,7 @@ class enrol_guest_plugin extends enrol_plugin { ...@@ -131,7 +131,7 @@ class enrol_guest_plugin extends enrol_plugin {
// add guest role // add guest role
$context = get_context_instance(CONTEXT_COURSE, $instance->courseid); $context = get_context_instance(CONTEXT_COURSE, $instance->courseid);
$USER->access = load_temp_role($context, $CFG->guestroleid, $USER->access); load_temp_course_role($context, $CFG->guestroleid);
// go to the originally requested page // go to the originally requested page
if (!empty($SESSION->wantsurl)) { if (!empty($SESSION->wantsurl)) {
......
...@@ -38,9 +38,6 @@ $context = get_context_instance(CONTEXT_COURSE, $course->id, MUST_EXIST); ...@@ -38,9 +38,6 @@ $context = get_context_instance(CONTEXT_COURSE, $course->id, MUST_EXIST);
require_login(); require_login();
// Refreshing enrolment data in the USER session
load_all_capabilities();
if ($SESSION->wantsurl) { if ($SESSION->wantsurl) {
$destination = $SESSION->wantsurl; $destination = $SESSION->wantsurl;
unset($SESSION->wantsurl); unset($SESSION->wantsurl);
......
This files describes API changes in /enrol/* - plugins,
information provided here is intended especially for developers.
=== 2.2 ===
required changes in code:
* load_temp_role() is deprecated, use load_temp_course_role() instead, temp role not loaded
* remove_temp_role() is deprecated, use remove_temp_course_roles() instead
This diff is collapsed.
...@@ -1014,7 +1014,11 @@ function fix_course_sortorder() { ...@@ -1014,7 +1014,11 @@ function fix_course_sortorder() {
// now fix the paths and depths in context table if needed // now fix the paths and depths in context table if needed
if ($fixcontexts) { if ($fixcontexts) {
rebuild_contexts($fixcontexts); foreach ($fixcontexts as $fixcontext) {
$fixcontext->reset_paths(false);
}
context_helper::build_all_paths(false);
unset($fixcontexts);
} }
// release memory // release memory
......
...@@ -29,14 +29,17 @@ defined('MOODLE_INTERNAL') || die(); ...@@ -29,14 +29,17 @@ defined('MOODLE_INTERNAL') || die();
function xmldb_main_install() { function xmldb_main_install() {
global $CFG, $DB, $SITE; global $CFG, $DB, $SITE;
/// make sure system context exists /// Make sure system context exists
$syscontext = get_system_context(false); $syscontext = context_system::instance(0, MUST_EXIST, false);
if ($syscontext->id != 1) { if ($syscontext->id != SYSCONTEXTID) {
throw new moodle_exception('generalexceptionmessage', 'error', '', 'Unexpected new system context id!'); throw new moodle_exception('generalexceptionmessage', 'error', '', 'Unexpected new system context id!');
} }
/// create site course /// Create site course
if ($DB->record_exists('course', array())) {
throw new moodle_exception('generalexceptionmessage', 'error', '', 'Can not create frontpage course, courses already exist.');
}
$newsite = new stdClass(); $newsite = new stdClass();
$newsite->fullname = ''; $newsite->fullname = '';
$newsite->shortname = ''; $newsite->shortname = '';
...@@ -48,18 +51,38 @@ function xmldb_main_install() { ...@@ -48,18 +51,38 @@ function xmldb_main_install() {
$newsite->timecreated = time(); $newsite->timecreated = time();
$newsite->timemodified = $newsite->timecreated; $newsite->timemodified = $newsite->timecreated;
$newsite->id = $DB->insert_record('course', $newsite); if (defined('SITEID')) {
$newsite->id = SITEID;
$DB->import_record('course', $newsite);
$DB->get_manager()->reset_sequence('course');
} else {
$newsite->id = $DB->insert_record('course', $newsite);
define('SITEID', $newsite->id);
}
$SITE = get_site(); $SITE = get_site();
if ($newsite->id != 1 or $SITE->id != 1) { if ($newsite->id != $SITE->id) {
throw new moodle_exception('generalexceptionmessage', 'error', '', 'Unexpected new site course id!'); throw new moodle_exception('generalexceptionmessage', 'error', '', 'Unexpected new site course id!');
} }
// Make sure site course context exists
context_course::instance($SITE->id);
// Update the global frontpage cache
$SITE = $DB->get_record('course', array('id'=>$newsite->id), '*', MUST_EXIST);
/// make sure site course context exists /// Create default course category
get_context_instance(CONTEXT_COURSE, $SITE->id); if ($DB->record_exists('course_categories', array())) {
throw new moodle_exception('generalexceptionmessage', 'error', '', 'Can not create default course category, categories already exist.');
}
$cat = new stdClass();
$cat->name = get_string('miscellaneous');
$cat->depth = 1;
$cat->sortorder = MAX_COURSES_IN_CATEGORY;
$cat->timemodified = time();
$catid = $DB->insert_record('course_categories', $cat);
$DB->set_field('course_categories', 'path', '/'.$catid, array('id'=>$catid));
// Make sure category context exists
context_coursecat::instance($catid);
/// create default course category
$cat = get_course_category();
$defaults = array( $defaults = array(
'rolesactive' => '0', // marks fully set up system 'rolesactive' => '0', // marks fully set up system
...@@ -82,7 +105,7 @@ function xmldb_main_install() { ...@@ -82,7 +105,7 @@ function xmldb_main_install() {
} }
/// bootstrap mnet /// Bootstrap mnet
$mnethost = new stdClass(); $mnethost = new stdClass();
$mnethost->wwwroot = $CFG->wwwroot; $mnethost->wwwroot = $CFG->wwwroot;
$mnethost->name = ''; $mnethost->name = '';
...@@ -137,7 +160,10 @@ function xmldb_main_install() { ...@@ -137,7 +160,10 @@ function xmldb_main_install() {
$mnetallhosts->id = $DB->insert_record('mnet_host', $mnetallhosts, true); $mnetallhosts->id = $DB->insert_record('mnet_host', $mnetallhosts, true);
set_config('mnet_all_hosts_id', $mnetallhosts->id); set_config('mnet_all_hosts_id', $mnetallhosts->id);
/// Create guest record - do not assign any role, guest user get's the default guest role automatically on the fly /// Create guest record - do not assign any role, guest user gets the default guest role automatically on the fly
if ($DB->record_exists('user', array())) {
throw new moodle_exception('generalexceptionmessage', 'error', '', 'Can not create default users, users already exist.');
}
$guest = new stdClass(); $guest = new stdClass();
$guest->auth = 'manual'; $guest->auth = 'manual';
$guest->username = 'guest'; $guest->username = 'guest';
...@@ -156,6 +182,8 @@ function xmldb_main_install() { ...@@ -156,6 +182,8 @@ function xmldb_main_install() {
} }
// Store guest id // Store guest id
set_config('siteguest', $guest->id); set_config('siteguest', $guest->id);
// Make sure user context exists
context_user::instance($guest->id);
/// Now create admin user /// Now create admin user
...@@ -176,8 +204,10 @@ function xmldb_main_install() { ...@@ -176,8 +204,10 @@ function xmldb_main_install() {
if ($admin->id != 2) { if ($admin->id != 2) {
throw new moodle_exception('generalexceptionmessage', 'error', '', 'Unexpected new admin user id!'); throw new moodle_exception('generalexceptionmessage', 'error', '', 'Unexpected new admin user id!');
} }
/// Store list of admins // Store list of admins
set_config('siteadmins', $admin->id); set_config('siteadmins', $admin->id);
// Make sure user context exists
context_user::instance($admin->id);
/// Install the roles system. /// Install the roles system.
...@@ -264,17 +294,16 @@ function xmldb_main_install() { ...@@ -264,17 +294,16 @@ function xmldb_main_install() {
require_once($CFG->libdir . '/licenselib.php'); require_once($CFG->libdir . '/licenselib.php');
license_manager::install_licenses(); license_manager::install_licenses();
/// Add two lines of data into this new table // Init profile pages defaults
if ($DB->record_exists('my_pages', array())) {
throw new moodle_exception('generalexceptionmessage', 'error', '', 'Can not create default profile pages, records already exist.');
}
$mypage = new stdClass(); $mypage = new stdClass();
$mypage->userid = NULL; $mypage->userid = NULL;
$mypage->name = '__default'; $mypage->name = '__default';
$mypage->private = 0; $mypage->private = 0;
$mypage->sortorder = 0; $mypage->sortorder = 0;
if (!$DB->record_exists('my_pages', array('userid'=>NULL, 'private'=>0))) { $DB->insert_record('my_pages', $mypage);
$DB->insert_record('my_pages', $mypage);
}
$mypage->private = 1; $mypage->private = 1;
if (!$DB->record_exists('my_pages', array('userid'=>NULL, 'private'=>1))) { $DB->insert_record('my_pages', $mypage);
$DB->insert_record('my_pages', $mypage);
}
} }
...@@ -280,28 +280,28 @@ function isteacher() { ...@@ -280,28 +280,28 @@ function isteacher() {
* @deprecated * @deprecated
*/ */
function isteacherinanycourse() { function isteacherinanycourse() {
error('Function isteacherinanycourse() was removed, please use capabilities instead!'); throw new coding_Exception('Function isteacherinanycourse() was removed, please use capabilities instead!');
} }
/** /**
* @deprecated * @deprecated
*/ */
function get_guest() { function get_guest() {
error('Function get_guest() was removed, please use capabilities instead!'); throw new coding_Exception('Function get_guest() was removed, please use capabilities instead!');
} }
/** /**
* @deprecated * @deprecated
*/ */
function isguest() { function isguest() {
error('Function isguest() was removed, please use capabilities instead!'); throw new coding_Exception('Function isguest() was removed, please use capabilities instead!');
} }
/** /**
* @deprecated * @deprecated
*/ */
function get_teacher() { function get_teacher() {
error('Function get_teacher() was removed, please use capabilities instead!'); throw new coding_Exception('Function get_teacher() was removed, please use capabilities instead!');
} }
/** /**
...@@ -371,15 +371,7 @@ function get_recent_enrolments($courseid, $timestart) { ...@@ -371,15 +371,7 @@ function get_recent_enrolments($courseid, $timestart) {
* @return object * @return object
*/ */
function make_context_subobj($rec) { function make_context_subobj($rec) {
$ctx = new StdClass; throw new coding_Exception('make_context_subobj() was removed, use new context preloading');
$ctx->id = $rec->ctxid; unset($rec->ctxid);
$ctx->path = $rec->ctxpath; unset($rec->ctxpath);
$ctx->depth = $rec->ctxdepth; unset($rec->ctxdepth);
$ctx->contextlevel = $rec->ctxlevel; unset($rec->ctxlevel);
$ctx->instanceid = $rec->id;
$rec->context = $ctx;
return $rec;
} }
/** /**
...@@ -395,10 +387,7 @@ function make_context_subobj($rec) { ...@@ -395,10 +387,7 @@ function make_context_subobj($rec) {
* for this thing. * for this thing.
*/ */
function is_context_subobj_valid($rec, $contextlevel) { function is_context_subobj_valid($rec, $contextlevel) {
return isset($rec->context) && isset($rec->context->id) && throw new coding_Exception('is_context_subobj_valid() was removed, use new context preloading');
isset($rec->context->path) && isset($rec->context->depth) &&
isset($rec->context->contextlevel) && isset($rec->context->instanceid) &&
$rec->context->contextlevel == $contextlevel && $rec->context->instanceid == $rec->id;
} }