Пример #1
0
/**
 * Fixes course category and course sortorder, also verifies category and course parents and paths.
 * (circular references are not fixed)
 *
 * @global object
 * @global object
 * @uses MAX_COURSES_IN_CATEGORY
 * @uses MAX_COURSE_CATEGORIES
 * @uses SITEID
 * @uses CONTEXT_COURSE
 * @return void
 */
function fix_course_sortorder()
{
    global $DB, $SITE;
    //WARNING: this is PHP5 only code!
    if ($unsorted = $DB->get_records('course_categories', array('sortorder' => 0))) {
        //move all categories that are not sorted yet to the end
        $DB->set_field('course_categories', 'sortorder', MAX_COURSES_IN_CATEGORY * MAX_COURSE_CATEGORIES, array('sortorder' => 0));
    }
    $allcats = $DB->get_records('course_categories', null, 'sortorder, id', 'id, sortorder, parent, depth, path');
    $topcats = array();
    $brokencats = array();
    foreach ($allcats as $cat) {
        $sortorder = (int) $cat->sortorder;
        if (!$cat->parent) {
            while (isset($topcats[$sortorder])) {
                $sortorder++;
            }
            $topcats[$sortorder] = $cat;
            continue;
        }
        if (!isset($allcats[$cat->parent])) {
            $brokencats[] = $cat;
            continue;
        }
        if (!isset($allcats[$cat->parent]->children)) {
            $allcats[$cat->parent]->children = array();
        }
        while (isset($allcats[$cat->parent]->children[$sortorder])) {
            $sortorder++;
        }
        $allcats[$cat->parent]->children[$sortorder] = $cat;
    }
    unset($allcats);
    // add broken cats to category tree
    if ($brokencats) {
        $defaultcat = reset($topcats);
        foreach ($brokencats as $cat) {
            $topcats[] = $cat;
        }
    }
    // now walk recursively the tree and fix any problems found
    $sortorder = 0;
    $fixcontexts = array();
    _fix_course_cats($topcats, $sortorder, 0, 0, '', $fixcontexts);
    // detect if there are "multiple" frontpage courses and fix them if needed
    $frontcourses = $DB->get_records('course', array('category' => 0), 'id');
    if (count($frontcourses) > 1) {
        if (isset($frontcourses[SITEID])) {
            $frontcourse = $frontcourses[SITEID];
            unset($frontcourses[SITEID]);
        } else {
            $frontcourse = array_shift($frontcourses);
        }
        $defaultcat = reset($topcats);
        foreach ($frontcourses as $course) {
            $DB->set_field('course', 'category', $defaultcat->id, array('id' => $course->id));
            $context = get_context_instance(CONTEXT_COURSE, $course->id);
            $fixcontexts[$context->id] = $context;
        }
        unset($frontcourses);
    } else {
        $frontcourse = reset($frontcourses);
    }
    // now fix the paths and depths in context table if needed
    if ($fixcontexts) {
        rebuild_contexts($fixcontexts);
    }
    // release memory
    unset($topcats);
    unset($brokencats);
    unset($fixcontexts);
    // fix frontpage course sortorder
    if ($frontcourse->sortorder != 1) {
        $DB->set_field('course', 'sortorder', 1, array('id' => $frontcourse->id));
    }
    // now fix the course counts in category records if needed
    $sql = "SELECT cc.id, cc.coursecount, COUNT(c.id) AS newcount\n              FROM {course_categories} cc\n              LEFT JOIN {course} c ON c.category = cc.id\n          GROUP BY cc.id, cc.coursecount\n            HAVING cc.coursecount <> COUNT(c.id)";
    if ($updatecounts = $DB->get_records_sql($sql)) {
        foreach ($updatecounts as $cat) {
            $cat->coursecount = $cat->newcount;
            unset($cat->newcount);
            $DB->update_record_raw('course_categories', $cat, true);
        }
    }
    // now make sure that sortorders in course table are withing the category sortorder ranges
    $sql = "SELECT DISTINCT cc.id, cc.sortorder\n              FROM {course_categories} cc\n              JOIN {course} c ON c.category = cc.id\n             WHERE c.sortorder < cc.sortorder OR c.sortorder > cc.sortorder + " . MAX_COURSES_IN_CATEGORY;
    if ($fixcategories = $DB->get_records_sql($sql)) {
        //fix the course sortorder ranges
        foreach ($fixcategories as $cat) {
            $sql = "UPDATE {course}\n                       SET sortorder = " . $DB->sql_modulo('sortorder', MAX_COURSES_IN_CATEGORY) . " + ?\n                     WHERE category = ?";
            $DB->execute($sql, array($cat->sortorder, $cat->id));
        }
    }
    unset($fixcategories);
    // categories having courses with sortorder duplicates or having gaps in sortorder
    $sql = "SELECT DISTINCT c1.category AS id , cc.sortorder\n              FROM {course} c1\n              JOIN {course} c2 ON c1.sortorder = c2.sortorder\n              JOIN {course_categories} cc ON (c1.category = cc.id)\n             WHERE c1.id <> c2.id";
    $fixcategories = $DB->get_records_sql($sql);
    $sql = "SELECT cc.id, cc.sortorder, cc.coursecount, MAX(c.sortorder) AS maxsort, MIN(c.sortorder) AS minsort\n              FROM {course_categories} cc\n              JOIN {course} c ON c.category = cc.id\n          GROUP BY cc.id, cc.sortorder, cc.coursecount\n            HAVING (MAX(c.sortorder) <>  cc.sortorder + cc.coursecount) OR (MIN(c.sortorder) <>  cc.sortorder + 1)";
    $gapcategories = $DB->get_records_sql($sql);
    foreach ($gapcategories as $cat) {
        if (isset($fixcategories[$cat->id])) {
            // duplicates detected already
        } else {
            if ($cat->minsort == $cat->sortorder and $cat->maxsort == $cat->sortorder + $cat->coursecount - 1) {
                // easy - new course inserted with sortorder 0, the rest is ok
                $sql = "UPDATE {course}\n                       SET sortorder = sortorder + 1\n                     WHERE category = ?";
                $DB->execute($sql, array($cat->id));
            } else {
                // it needs full resorting
                $fixcategories[$cat->id] = $cat;
            }
        }
    }
    unset($gapcategories);
    // fix course sortorders in problematic categories only
    foreach ($fixcategories as $cat) {
        $i = 1;
        $courses = $DB->get_records('course', array('category' => $cat->id), 'sortorder ASC, id DESC', 'id, sortorder');
        foreach ($courses as $course) {
            if ($course->sortorder != $cat->sortorder + $i) {
                $course->sortorder = $cat->sortorder + $i;
                $DB->update_record_raw('course', $course, true);
            }
            $i++;
        }
    }
}
 /**
  * A small functional test of permission evaluations.
  */
 public function test_permission_evaluation()
 {
     global $USER, $SITE, $CFG, $DB, $ACCESSLIB_PRIVATE;
     $this->resetAfterTest();
     $generator = $this->getDataGenerator();
     // Fill the site with some real data.
     $testcategories = array();
     $testcourses = array();
     $testpages = array();
     $testblocks = array();
     $allroles = $DB->get_records_menu('role', array(), 'id', 'archetype, id');
     $systemcontext = context_system::instance();
     $frontpagecontext = context_course::instance(SITEID);
     // Add block to system context.
     $bi = $generator->create_block('online_users');
     context_block::instance($bi->id);
     $testblocks[] = $bi->id;
     // Some users.
     $testusers = array();
     for ($i = 0; $i < 20; $i++) {
         $user = $generator->create_user();
         $testusers[$i] = $user->id;
         $usercontext = context_user::instance($user->id);
         // Add block to user profile.
         $bi = $generator->create_block('online_users', array('parentcontextid' => $usercontext->id));
         $testblocks[] = $bi->id;
     }
     // Deleted user - should be ignored everywhere, can not have context.
     $generator->create_user(array('deleted' => 1));
     // Add block to frontpage.
     $bi = $generator->create_block('online_users', array('parentcontextid' => $frontpagecontext->id));
     $frontpageblockcontext = context_block::instance($bi->id);
     $testblocks[] = $bi->id;
     // Add a resource to frontpage.
     $page = $generator->create_module('page', array('course' => $SITE->id));
     $testpages[] = $page->id;
     $frontpagepagecontext = context_module::instance($page->cmid);
     // Add block to frontpage resource.
     $bi = $generator->create_block('online_users', array('parentcontextid' => $frontpagepagecontext->id));
     $frontpagepageblockcontext = context_block::instance($bi->id);
     $testblocks[] = $bi->id;
     // Some nested course categories with courses.
     $manualenrol = enrol_get_plugin('manual');
     $parentcat = 0;
     for ($i = 0; $i < 5; $i++) {
         $cat = $generator->create_category(array('parent' => $parentcat));
         $testcategories[] = $cat->id;
         $catcontext = context_coursecat::instance($cat->id);
         $parentcat = $cat->id;
         if ($i >= 4) {
             continue;
         }
         // Add resource to each category.
         $bi = $generator->create_block('online_users', array('parentcontextid' => $catcontext->id));
         context_block::instance($bi->id);
         // Add a few courses to each category.
         for ($j = 0; $j < 6; $j++) {
             $course = $generator->create_course(array('category' => $cat->id));
             $testcourses[] = $course->id;
             $coursecontext = context_course::instance($course->id);
             if ($j >= 5) {
                 continue;
             }
             // Add manual enrol instance.
             $manualenrol->add_default_instance($DB->get_record('course', array('id' => $course->id)));
             // Add block to each course.
             $bi = $generator->create_block('online_users', array('parentcontextid' => $coursecontext->id));
             $testblocks[] = $bi->id;
             // Add a resource to each course.
             $page = $generator->create_module('page', array('course' => $course->id));
             $testpages[] = $page->id;
             $modcontext = context_module::instance($page->cmid);
             // Add block to each module.
             $bi = $generator->create_block('online_users', array('parentcontextid' => $modcontext->id));
             $testblocks[] = $bi->id;
         }
     }
     // Make sure all contexts were created properly.
     $count = 1;
     // System.
     $count += $DB->count_records('user', array('deleted' => 0));
     $count += $DB->count_records('course_categories');
     $count += $DB->count_records('course');
     $count += $DB->count_records('course_modules');
     $count += $DB->count_records('block_instances');
     $this->assertEquals($count, $DB->count_records('context'));
     $this->assertEquals(0, $DB->count_records('context', array('depth' => 0)));
     $this->assertEquals(0, $DB->count_records('context', array('path' => null)));
     // Test context_helper::get_level_name() method.
     $levels = context_helper::get_all_levels();
     foreach ($levels as $level => $classname) {
         $name = context_helper::get_level_name($level);
         $this->assertNotEmpty($name);
     }
     // Test context::instance_by_id(), context_xxx::instance() methods.
     $context = context::instance_by_id($frontpagecontext->id);
     $this->assertSame(CONTEXT_COURSE, $context->contextlevel);
     $this->assertFalse(context::instance_by_id(-1, IGNORE_MISSING));
     try {
         context::instance_by_id(-1);
         $this->fail('exception expected');
     } catch (moodle_exception $e) {
         $this->assertTrue(true);
     }
     $this->assertInstanceOf('context_system', context_system::instance());
     $this->assertInstanceOf('context_coursecat', context_coursecat::instance($testcategories[0]));
     $this->assertInstanceOf('context_course', context_course::instance($testcourses[0]));
     $this->assertInstanceOf('context_module', context_module::instance($testpages[0]));
     $this->assertInstanceOf('context_block', context_block::instance($testblocks[0]));
     $this->assertFalse(context_coursecat::instance(-1, IGNORE_MISSING));
     $this->assertFalse(context_course::instance(-1, IGNORE_MISSING));
     $this->assertFalse(context_module::instance(-1, IGNORE_MISSING));
     $this->assertFalse(context_block::instance(-1, IGNORE_MISSING));
     try {
         context_coursecat::instance(-1);
         $this->fail('exception expected');
     } catch (moodle_exception $e) {
         $this->assertTrue(true);
     }
     try {
         context_course::instance(-1);
         $this->fail('exception expected');
     } catch (moodle_exception $e) {
         $this->assertTrue(true);
     }
     try {
         context_module::instance(-1);
         $this->fail('exception expected');
     } catch (moodle_exception $e) {
         $this->assertTrue(true);
     }
     try {
         context_block::instance(-1);
         $this->fail('exception expected');
     } catch (moodle_exception $e) {
         $this->assertTrue(true);
     }
     // Test $context->get_url(), $context->get_context_name(), $context->get_capabilities() methods.
     $testcontexts = array();
     $testcontexts[CONTEXT_SYSTEM] = context_system::instance();
     $testcontexts[CONTEXT_COURSECAT] = context_coursecat::instance($testcategories[0]);
     $testcontexts[CONTEXT_COURSE] = context_course::instance($testcourses[0]);
     $testcontexts[CONTEXT_MODULE] = context_module::instance($testpages[0]);
     $testcontexts[CONTEXT_BLOCK] = context_block::instance($testblocks[0]);
     foreach ($testcontexts as $context) {
         $name = $context->get_context_name(true, true);
         $this->assertNotEmpty($name);
         $this->assertInstanceOf('moodle_url', $context->get_url());
         $caps = $context->get_capabilities();
         $this->assertTrue(is_array($caps));
         foreach ($caps as $cap) {
             $cap = (array) $cap;
             $this->assertSame(array_keys($cap), array('id', 'name', 'captype', 'contextlevel', 'component', 'riskbitmask'));
         }
     }
     unset($testcontexts);
     // Test $context->get_course_context() method.
     $this->assertFalse($systemcontext->get_course_context(false));
     try {
         $systemcontext->get_course_context();
         $this->fail('exception expected');
     } catch (moodle_exception $e) {
         $this->assertInstanceOf('coding_exception', $e);
     }
     $context = context_coursecat::instance($testcategories[0]);
     $this->assertFalse($context->get_course_context(false));
     try {
         $context->get_course_context();
         $this->fail('exception expected');
     } catch (moodle_exception $e) {
         $this->assertInstanceOf('coding_exception', $e);
     }
     $this->assertEquals($frontpagecontext, $frontpagecontext->get_course_context(true));
     $this->assertEquals($frontpagecontext, $frontpagepagecontext->get_course_context(true));
     $this->assertEquals($frontpagecontext, $frontpagepageblockcontext->get_course_context(true));
     // Test $context->get_parent_context(), $context->get_parent_contexts(), $context->get_parent_context_ids() methods.
     $userid = reset($testusers);
     $usercontext = context_user::instance($userid);
     $this->assertEquals($systemcontext, $usercontext->get_parent_context());
     $this->assertEquals(array($systemcontext->id => $systemcontext), $usercontext->get_parent_contexts());
     $this->assertEquals(array($usercontext->id => $usercontext, $systemcontext->id => $systemcontext), $usercontext->get_parent_contexts(true));
     $this->assertEquals(array(), $systemcontext->get_parent_contexts());
     $this->assertEquals(array($systemcontext->id => $systemcontext), $systemcontext->get_parent_contexts(true));
     $this->assertEquals(array(), $systemcontext->get_parent_context_ids());
     $this->assertEquals(array($systemcontext->id), $systemcontext->get_parent_context_ids(true));
     $this->assertEquals($systemcontext, $frontpagecontext->get_parent_context());
     $this->assertEquals(array($systemcontext->id => $systemcontext), $frontpagecontext->get_parent_contexts());
     $this->assertEquals(array($frontpagecontext->id => $frontpagecontext, $systemcontext->id => $systemcontext), $frontpagecontext->get_parent_contexts(true));
     $this->assertEquals(array($systemcontext->id), $frontpagecontext->get_parent_context_ids());
     $this->assertEquals(array($frontpagecontext->id, $systemcontext->id), $frontpagecontext->get_parent_context_ids(true));
     $this->assertFalse($systemcontext->get_parent_context());
     $frontpagecontext = context_course::instance($SITE->id);
     $parent = $systemcontext;
     foreach ($testcategories as $catid) {
         $catcontext = context_coursecat::instance($catid);
         $this->assertEquals($parent, $catcontext->get_parent_context());
         $parent = $catcontext;
     }
     $this->assertEquals($frontpagecontext, $frontpagepagecontext->get_parent_context());
     $this->assertEquals($frontpagecontext, $frontpageblockcontext->get_parent_context());
     $this->assertEquals($frontpagepagecontext, $frontpagepageblockcontext->get_parent_context());
     // Test $context->get_child_contexts() method.
     $children = $systemcontext->get_child_contexts();
     $this->resetDebugging();
     $this->assertEquals(count($children) + 1, $DB->count_records('context'));
     $context = context_coursecat::instance($testcategories[3]);
     $children = $context->get_child_contexts();
     $countcats = 0;
     $countcourses = 0;
     $countblocks = 0;
     foreach ($children as $child) {
         if ($child->contextlevel == CONTEXT_COURSECAT) {
             $countcats++;
         }
         if ($child->contextlevel == CONTEXT_COURSE) {
             $countcourses++;
         }
         if ($child->contextlevel == CONTEXT_BLOCK) {
             $countblocks++;
         }
     }
     $this->assertCount(8, $children);
     $this->assertEquals(1, $countcats);
     $this->assertEquals(6, $countcourses);
     $this->assertEquals(1, $countblocks);
     $context = context_course::instance($testcourses[2]);
     $children = $context->get_child_contexts();
     $this->assertCount(7, $children);
     // Depends on number of default blocks.
     $context = context_module::instance($testpages[3]);
     $children = $context->get_child_contexts();
     $this->assertCount(1, $children);
     $context = context_block::instance($testblocks[1]);
     $children = $context->get_child_contexts();
     $this->assertCount(0, $children);
     unset($children);
     unset($countcats);
     unset($countcourses);
     unset($countblocks);
     // Test context_helper::reset_caches() method.
     context_helper::reset_caches();
     $this->assertEquals(0, context_inspection::test_context_cache_size());
     context_course::instance($SITE->id);
     $this->assertEquals(1, context_inspection::test_context_cache_size());
     // Test context preloading.
     context_helper::reset_caches();
     $sql = "SELECT " . context_helper::get_preload_record_columns_sql('c') . "\n                  FROM {context} c\n                 WHERE c.contextlevel <> " . CONTEXT_SYSTEM;
     $records = $DB->get_records_sql($sql);
     $firstrecord = reset($records);
     $columns = context_helper::get_preload_record_columns('c');
     $firstrecord = (array) $firstrecord;
     $this->assertSame(array_keys($firstrecord), array_values($columns));
     context_helper::reset_caches();
     foreach ($records as $record) {
         context_helper::preload_from_record($record);
         $this->assertEquals(new stdClass(), $record);
     }
     $this->assertEquals(count($records), context_inspection::test_context_cache_size());
     unset($records);
     unset($columns);
     context_helper::reset_caches();
     context_helper::preload_course($SITE->id);
     $numfrontpagemodules = $DB->count_records('course_modules', array('course' => $SITE->id));
     $this->assertEquals(6 + $numfrontpagemodules, context_inspection::test_context_cache_size());
     // Depends on number of default blocks.
     // Test assign_capability(), unassign_capability() functions.
     $rc = $DB->get_record('role_capabilities', array('contextid' => $frontpagecontext->id, 'roleid' => $allroles['teacher'], 'capability' => 'moodle/site:accessallgroups'));
     $this->assertFalse($rc);
     assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $allroles['teacher'], $frontpagecontext->id);
     $rc = $DB->get_record('role_capabilities', array('contextid' => $frontpagecontext->id, 'roleid' => $allroles['teacher'], 'capability' => 'moodle/site:accessallgroups'));
     $this->assertEquals(CAP_ALLOW, $rc->permission);
     assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $allroles['teacher'], $frontpagecontext->id);
     $rc = $DB->get_record('role_capabilities', array('contextid' => $frontpagecontext->id, 'roleid' => $allroles['teacher'], 'capability' => 'moodle/site:accessallgroups'));
     $this->assertEquals(CAP_ALLOW, $rc->permission);
     assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $allroles['teacher'], $frontpagecontext, true);
     $rc = $DB->get_record('role_capabilities', array('contextid' => $frontpagecontext->id, 'roleid' => $allroles['teacher'], 'capability' => 'moodle/site:accessallgroups'));
     $this->assertEquals(CAP_PREVENT, $rc->permission);
     assign_capability('moodle/site:accessallgroups', CAP_INHERIT, $allroles['teacher'], $frontpagecontext);
     $rc = $DB->get_record('role_capabilities', array('contextid' => $frontpagecontext->id, 'roleid' => $allroles['teacher'], 'capability' => 'moodle/site:accessallgroups'));
     $this->assertFalse($rc);
     assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $allroles['teacher'], $frontpagecontext);
     unassign_capability('moodle/site:accessallgroups', $allroles['teacher'], $frontpagecontext, true);
     $rc = $DB->get_record('role_capabilities', array('contextid' => $frontpagecontext->id, 'roleid' => $allroles['teacher'], 'capability' => 'moodle/site:accessallgroups'));
     $this->assertFalse($rc);
     unassign_capability('moodle/site:accessallgroups', $allroles['teacher'], $frontpagecontext->id, true);
     unset($rc);
     accesslib_clear_all_caches_for_unit_testing();
     // Must be done after assign_capability().
     // Test role_assign(), role_unassign(), role_unassign_all() functions.
     $context = context_course::instance($testcourses[1]);
     $this->assertEquals(0, $DB->count_records('role_assignments', array('contextid' => $context->id)));
     role_assign($allroles['teacher'], $testusers[1], $context->id);
     role_assign($allroles['teacher'], $testusers[2], $context->id);
     role_assign($allroles['manager'], $testusers[1], $context->id);
     $this->assertEquals(3, $DB->count_records('role_assignments', array('contextid' => $context->id)));
     role_unassign($allroles['teacher'], $testusers[1], $context->id);
     $this->assertEquals(2, $DB->count_records('role_assignments', array('contextid' => $context->id)));
     role_unassign_all(array('contextid' => $context->id));
     $this->assertEquals(0, $DB->count_records('role_assignments', array('contextid' => $context->id)));
     unset($context);
     accesslib_clear_all_caches_for_unit_testing();
     // Just in case.
     // Test has_capability(), get_users_by_capability(), role_switch(), reload_all_capabilities() and friends functions.
     $adminid = get_admin()->id;
     $guestid = $CFG->siteguest;
     // Enrol some users into some courses.
     $course1 = $DB->get_record('course', array('id' => $testcourses[22]), '*', MUST_EXIST);
     $course2 = $DB->get_record('course', array('id' => $testcourses[7]), '*', MUST_EXIST);
     $cms = $DB->get_records('course_modules', array('course' => $course1->id), 'id');
     $cm1 = reset($cms);
     $blocks = $DB->get_records('block_instances', array('parentcontextid' => context_module::instance($cm1->id)->id), 'id');
     $block1 = reset($blocks);
     $instance1 = $DB->get_record('enrol', array('enrol' => 'manual', 'courseid' => $course1->id));
     $instance2 = $DB->get_record('enrol', array('enrol' => 'manual', 'courseid' => $course2->id));
     for ($i = 0; $i < 9; $i++) {
         $manualenrol->enrol_user($instance1, $testusers[$i], $allroles['student']);
     }
     $manualenrol->enrol_user($instance1, $testusers[8], $allroles['teacher']);
     $manualenrol->enrol_user($instance1, $testusers[9], $allroles['editingteacher']);
     for ($i = 10; $i < 15; $i++) {
         $manualenrol->enrol_user($instance2, $testusers[$i], $allroles['student']);
     }
     $manualenrol->enrol_user($instance2, $testusers[15], $allroles['editingteacher']);
     // Add tons of role assignments - the more the better.
     role_assign($allroles['coursecreator'], $testusers[11], context_coursecat::instance($testcategories[2]));
     role_assign($allroles['manager'], $testusers[12], context_coursecat::instance($testcategories[1]));
     role_assign($allroles['student'], $testusers[9], context_module::instance($cm1->id));
     role_assign($allroles['teacher'], $testusers[8], context_module::instance($cm1->id));
     role_assign($allroles['guest'], $testusers[13], context_course::instance($course1->id));
     role_assign($allroles['teacher'], $testusers[7], context_block::instance($block1->id));
     role_assign($allroles['manager'], $testusers[9], context_block::instance($block1->id));
     role_assign($allroles['editingteacher'], $testusers[9], context_course::instance($course1->id));
     role_assign($allroles['teacher'], $adminid, context_course::instance($course1->id));
     role_assign($allroles['editingteacher'], $adminid, context_block::instance($block1->id));
     // Add tons of overrides - the more the better.
     assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultuserroleid, $frontpageblockcontext, true);
     assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpageblockcontext, true);
     assign_capability('moodle/block:view', CAP_PROHIBIT, $allroles['guest'], $frontpageblockcontext, true);
     assign_capability('block/online_users:viewlist', CAP_PREVENT, $allroles['user'], $frontpageblockcontext, true);
     assign_capability('block/online_users:viewlist', CAP_PREVENT, $allroles['student'], $frontpageblockcontext, true);
     assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $CFG->defaultuserroleid, $frontpagepagecontext, true);
     assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpagepagecontext, true);
     assign_capability('mod/page:view', CAP_PREVENT, $allroles['guest'], $frontpagepagecontext, true);
     assign_capability('mod/page:view', CAP_ALLOW, $allroles['user'], $frontpagepagecontext, true);
     assign_capability('moodle/page:view', CAP_ALLOW, $allroles['student'], $frontpagepagecontext, true);
     assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultuserroleid, $frontpagecontext, true);
     assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpagecontext, true);
     assign_capability('mod/page:view', CAP_ALLOW, $allroles['guest'], $frontpagecontext, true);
     assign_capability('mod/page:view', CAP_PROHIBIT, $allroles['user'], $frontpagecontext, true);
     assign_capability('mod/page:view', CAP_PREVENT, $allroles['guest'], $systemcontext, true);
     accesslib_clear_all_caches_for_unit_testing();
     /// Must be done after assign_capability().
     // Extra tests for guests and not-logged-in users because they can not be verified by cross checking
     // with get_users_by_capability() where they are ignored.
     $this->assertFalse(has_capability('moodle/block:view', $frontpageblockcontext, $guestid));
     $this->assertFalse(has_capability('mod/page:view', $frontpagepagecontext, $guestid));
     $this->assertTrue(has_capability('mod/page:view', $frontpagecontext, $guestid));
     $this->assertFalse(has_capability('mod/page:view', $systemcontext, $guestid));
     $this->assertFalse(has_capability('moodle/block:view', $frontpageblockcontext, 0));
     $this->assertFalse(has_capability('mod/page:view', $frontpagepagecontext, 0));
     $this->assertTrue(has_capability('mod/page:view', $frontpagecontext, 0));
     $this->assertFalse(has_capability('mod/page:view', $systemcontext, 0));
     $this->assertFalse(has_capability('moodle/course:create', $systemcontext, $testusers[11]));
     $this->assertTrue(has_capability('moodle/course:create', context_coursecat::instance($testcategories[2]), $testusers[11]));
     $this->assertFalse(has_capability('moodle/course:create', context_course::instance($testcourses[1]), $testusers[11]));
     $this->assertTrue(has_capability('moodle/course:create', context_course::instance($testcourses[19]), $testusers[11]));
     $this->assertFalse(has_capability('moodle/course:update', context_course::instance($testcourses[1]), $testusers[9]));
     $this->assertFalse(has_capability('moodle/course:update', context_course::instance($testcourses[19]), $testusers[9]));
     $this->assertFalse(has_capability('moodle/course:update', $systemcontext, $testusers[9]));
     // Test the list of enrolled users.
     $coursecontext = context_course::instance($course1->id);
     $enrolled = get_enrolled_users($coursecontext);
     $this->assertCount(10, $enrolled);
     for ($i = 0; $i < 10; $i++) {
         $this->assertTrue(isset($enrolled[$testusers[$i]]));
     }
     $enrolled = get_enrolled_users($coursecontext, 'moodle/course:update');
     $this->assertCount(1, $enrolled);
     $this->assertTrue(isset($enrolled[$testusers[9]]));
     unset($enrolled);
     // Role switching.
     $userid = $testusers[9];
     $USER = $DB->get_record('user', array('id' => $userid));
     load_all_capabilities();
     $coursecontext = context_course::instance($course1->id);
     $this->assertTrue(has_capability('moodle/course:update', $coursecontext));
     $this->assertFalse(is_role_switched($course1->id));
     role_switch($allroles['student'], $coursecontext);
     $this->assertTrue(is_role_switched($course1->id));
     $this->assertEquals($allroles['student'], $USER->access['rsw'][$coursecontext->path]);
     $this->assertFalse(has_capability('moodle/course:update', $coursecontext));
     reload_all_capabilities();
     $this->assertFalse(has_capability('moodle/course:update', $coursecontext));
     role_switch(0, $coursecontext);
     $this->assertTrue(has_capability('moodle/course:update', $coursecontext));
     $userid = $adminid;
     $USER = $DB->get_record('user', array('id' => $userid));
     load_all_capabilities();
     $coursecontext = context_course::instance($course1->id);
     $blockcontext = context_block::instance($block1->id);
     $this->assertTrue(has_capability('moodle/course:update', $blockcontext));
     role_switch($allroles['student'], $coursecontext);
     $this->assertEquals($allroles['student'], $USER->access['rsw'][$coursecontext->path]);
     $this->assertFalse(has_capability('moodle/course:update', $blockcontext));
     reload_all_capabilities();
     $this->assertFalse(has_capability('moodle/course:update', $blockcontext));
     load_all_capabilities();
     $this->assertTrue(has_capability('moodle/course:update', $blockcontext));
     // Temp course role for enrol.
     $DB->delete_records('cache_flags', array());
     // This prevents problem with dirty contexts immediately resetting the temp role - this is a known problem...
     $userid = $testusers[5];
     $roleid = $allroles['editingteacher'];
     $USER = $DB->get_record('user', array('id' => $userid));
     load_all_capabilities();
     $coursecontext = context_course::instance($course1->id);
     $this->assertFalse(has_capability('moodle/course:update', $coursecontext));
     $this->assertFalse(isset($USER->access['ra'][$coursecontext->path][$roleid]));
     load_temp_course_role($coursecontext, $roleid);
     $this->assertEquals($USER->access['ra'][$coursecontext->path][$roleid], $roleid);
     $this->assertTrue(has_capability('moodle/course:update', $coursecontext));
     remove_temp_course_roles($coursecontext);
     $this->assertFalse(has_capability('moodle/course:update', $coursecontext, $userid));
     load_temp_course_role($coursecontext, $roleid);
     reload_all_capabilities();
     $this->assertFalse(has_capability('moodle/course:update', $coursecontext, $userid));
     $USER = new stdClass();
     $USER->id = 0;
     // Now cross check has_capability() with get_users_by_capability(), each using different code paths,
     // they have to be kept in sync, usually only one of them breaks, so we know when something is wrong,
     // at the same time validate extra restrictions (guest read only no risks, admin exception, non existent and deleted users).
     $contexts = $DB->get_records('context', array(), 'id');
     $contexts = array_values($contexts);
     $capabilities = $DB->get_records('capabilities', array(), 'id');
     $capabilities = array_values($capabilities);
     $roles = array($allroles['guest'], $allroles['user'], $allroles['teacher'], $allroles['editingteacher'], $allroles['coursecreator'], $allroles['manager']);
     $userids = array_values($testusers);
     $userids[] = get_admin()->id;
     if (!PHPUNIT_LONGTEST) {
         $contexts = array_slice($contexts, 0, 10);
         $capabilities = array_slice($capabilities, 0, 5);
         $userids = array_slice($userids, 0, 5);
     }
     foreach ($userids as $userid) {
         // No guest or deleted.
         // Each user gets 0-10 random roles.
         $rcount = rand(0, 10);
         for ($j = 0; $j < $rcount; $j++) {
             $roleid = $roles[rand(0, count($roles) - 1)];
             $contextid = $contexts[rand(0, count($contexts) - 1)]->id;
             role_assign($roleid, $userid, $contextid);
         }
     }
     $permissions = array(CAP_ALLOW, CAP_PREVENT, CAP_INHERIT, CAP_PREVENT);
     $maxoverrides = count($contexts) * 10;
     for ($j = 0; $j < $maxoverrides; $j++) {
         $roleid = $roles[rand(0, count($roles) - 1)];
         $contextid = $contexts[rand(0, count($contexts) - 1)]->id;
         $permission = $permissions[rand(0, count($permissions) - 1)];
         $capname = $capabilities[rand(0, count($capabilities) - 1)]->name;
         assign_capability($capname, $permission, $roleid, $contextid, true);
     }
     unset($permissions);
     unset($roles);
     accesslib_clear_all_caches_for_unit_testing();
     // must be done after assign_capability().
     // Test time - let's set up some real user, just in case the logic for USER affects the others...
     $USER = $DB->get_record('user', array('id' => $testusers[3]));
     load_all_capabilities();
     $userids[] = $CFG->siteguest;
     $userids[] = 0;
     // Not-logged-in user.
     $userids[] = -1;
     // Non-existent user.
     foreach ($contexts as $crecord) {
         $context = context::instance_by_id($crecord->id);
         if ($coursecontext = $context->get_course_context(false)) {
             $enrolled = get_enrolled_users($context);
         } else {
             $enrolled = array();
         }
         foreach ($capabilities as $cap) {
             $allowed = get_users_by_capability($context, $cap->name, 'u.id, u.username');
             if ($enrolled) {
                 $enrolledwithcap = get_enrolled_users($context, $cap->name);
             } else {
                 $enrolledwithcap = array();
             }
             foreach ($userids as $userid) {
                 if ($userid == 0 or isguestuser($userid)) {
                     if ($userid == 0) {
                         $CFG->forcelogin = true;
                         $this->assertFalse(has_capability($cap->name, $context, $userid));
                         unset($CFG->forcelogin);
                     }
                     if ($cap->captype === 'write' or $cap->riskbitmask & (RISK_XSS | RISK_CONFIG | RISK_DATALOSS)) {
                         $this->assertFalse(has_capability($cap->name, $context, $userid));
                     }
                     $this->assertFalse(isset($allowed[$userid]));
                 } else {
                     if (is_siteadmin($userid)) {
                         $this->assertTrue(has_capability($cap->name, $context, $userid, true));
                     }
                     $hascap = has_capability($cap->name, $context, $userid, false);
                     $this->assertSame($hascap, isset($allowed[$userid]), "Capability result mismatch user:{$userid}, context:{$context->id}, {$cap->name}, hascap: " . (int) $hascap . " ");
                     if (isset($enrolled[$userid])) {
                         $this->assertSame(isset($allowed[$userid]), isset($enrolledwithcap[$userid]), "Enrolment with capability result mismatch user:{$userid}, context:{$context->id}, {$cap->name}, hascap: " . (int) $hascap . " ");
                     }
                 }
             }
         }
     }
     // Back to nobody.
     $USER = new stdClass();
     $USER->id = 0;
     unset($contexts);
     unset($userids);
     unset($capabilities);
     // Now let's do all the remaining tests that break our carefully prepared fake site.
     // Test $context->mark_dirty() method.
     $DB->delete_records('cache_flags', array());
     accesslib_clear_all_caches(false);
     $systemcontext->mark_dirty();
     $dirty = get_cache_flags('accesslib/dirtycontexts', time() - 2);
     $this->assertTrue(isset($dirty[$systemcontext->path]));
     $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$systemcontext->path]));
     // Test $context->reload_if_dirty() method.
     $DB->delete_records('cache_flags', array());
     accesslib_clear_all_caches(false);
     load_all_capabilities();
     $context = context_course::instance($testcourses[2]);
     $page = $DB->get_record('page', array('course' => $testcourses[2]));
     $pagecm = get_coursemodule_from_instance('page', $page->id);
     $pagecontext = context_module::instance($pagecm->id);
     $context->mark_dirty();
     $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$context->path]));
     $USER->access['test'] = true;
     $context->reload_if_dirty();
     $this->assertFalse(isset($USER->access['test']));
     $context->mark_dirty();
     $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$context->path]));
     $USER->access['test'] = true;
     $pagecontext->reload_if_dirty();
     $this->assertFalse(isset($USER->access['test']));
     // Test context_helper::build_all_paths() method.
     $oldcontexts = $DB->get_records('context', array(), 'id');
     $DB->set_field_select('context', 'path', null, "contextlevel <> " . CONTEXT_SYSTEM);
     $DB->set_field_select('context', 'depth', 0, "contextlevel <> " . CONTEXT_SYSTEM);
     context_helper::build_all_paths();
     $newcontexts = $DB->get_records('context', array(), 'id');
     $this->assertEquals($oldcontexts, $newcontexts);
     unset($oldcontexts);
     unset($newcontexts);
     // Test $context->reset_paths() method.
     $context = context_course::instance($testcourses[2]);
     $children = $context->get_child_contexts();
     $context->reset_paths(false);
     $this->assertNull($DB->get_field('context', 'path', array('id' => $context->id)));
     $this->assertEquals(0, $DB->get_field('context', 'depth', array('id' => $context->id)));
     foreach ($children as $child) {
         $this->assertNull($DB->get_field('context', 'path', array('id' => $child->id)));
         $this->assertEquals(0, $DB->get_field('context', 'depth', array('id' => $child->id)));
     }
     $this->assertEquals(count($children) + 1, $DB->count_records('context', array('depth' => 0)));
     $this->assertEquals(count($children) + 1, $DB->count_records('context', array('path' => null)));
     $context = context_course::instance($testcourses[2]);
     $context->reset_paths(true);
     $context = context_course::instance($testcourses[2]);
     $this->assertSame($context->path, $DB->get_field('context', 'path', array('id' => $context->id)));
     $this->assertSame($context->depth, $DB->get_field('context', 'depth', array('id' => $context->id)));
     $this->assertEquals(0, $DB->count_records('context', array('depth' => 0)));
     $this->assertEquals(0, $DB->count_records('context', array('path' => null)));
     // Test $context->update_moved() method.
     accesslib_clear_all_caches(false);
     $DB->delete_records('cache_flags', array());
     $course = $DB->get_record('course', array('id' => $testcourses[0]));
     $context = context_course::instance($course->id);
     $oldpath = $context->path;
     $miscid = $DB->get_field_sql("SELECT MIN(id) FROM {course_categories}");
     $categorycontext = context_coursecat::instance($miscid);
     $course->category = $miscid;
     $DB->update_record('course', $course);
     $context->update_moved($categorycontext);
     $context = context_course::instance($course->id);
     $this->assertEquals($categorycontext, $context->get_parent_context());
     $dirty = get_cache_flags('accesslib/dirtycontexts', time() - 2);
     $this->assertTrue(isset($dirty[$oldpath]));
     $this->assertTrue(isset($dirty[$context->path]));
     // Test $context->delete_content() method.
     context_helper::reset_caches();
     $context = context_module::instance($testpages[3]);
     $this->assertTrue($DB->record_exists('context', array('id' => $context->id)));
     $this->assertEquals(1, $DB->count_records('block_instances', array('parentcontextid' => $context->id)));
     $context->delete_content();
     $this->assertTrue($DB->record_exists('context', array('id' => $context->id)));
     $this->assertEquals(0, $DB->count_records('block_instances', array('parentcontextid' => $context->id)));
     // Test $context->delete() method.
     context_helper::reset_caches();
     $context = context_module::instance($testpages[4]);
     $this->assertTrue($DB->record_exists('context', array('id' => $context->id)));
     $this->assertEquals(1, $DB->count_records('block_instances', array('parentcontextid' => $context->id)));
     $bi = $DB->get_record('block_instances', array('parentcontextid' => $context->id));
     $bicontext = context_block::instance($bi->id);
     $DB->delete_records('cache_flags', array());
     $context->delete();
     // Should delete also linked blocks.
     $dirty = get_cache_flags('accesslib/dirtycontexts', time() - 2);
     $this->assertTrue(isset($dirty[$context->path]));
     $this->assertFalse($DB->record_exists('context', array('id' => $context->id)));
     $this->assertFalse($DB->record_exists('context', array('id' => $bicontext->id)));
     $this->assertFalse($DB->record_exists('context', array('contextlevel' => CONTEXT_MODULE, 'instanceid' => $testpages[4])));
     $this->assertFalse($DB->record_exists('context', array('contextlevel' => CONTEXT_BLOCK, 'instanceid' => $bi->id)));
     $this->assertEquals(0, $DB->count_records('block_instances', array('parentcontextid' => $context->id)));
     context_module::instance($testpages[4]);
     // Test context_helper::delete_instance() method.
     context_helper::reset_caches();
     $lastcourse = array_pop($testcourses);
     $this->assertTrue($DB->record_exists('context', array('contextlevel' => CONTEXT_COURSE, 'instanceid' => $lastcourse)));
     $coursecontext = context_course::instance($lastcourse);
     $this->assertEquals(1, context_inspection::test_context_cache_size());
     $this->assertNotEquals(CONTEXT_COURSE, $coursecontext->instanceid);
     $DB->delete_records('cache_flags', array());
     context_helper::delete_instance(CONTEXT_COURSE, $lastcourse);
     $dirty = get_cache_flags('accesslib/dirtycontexts', time() - 2);
     $this->assertTrue(isset($dirty[$coursecontext->path]));
     $this->assertEquals(0, context_inspection::test_context_cache_size());
     $this->assertFalse($DB->record_exists('context', array('contextlevel' => CONTEXT_COURSE, 'instanceid' => $lastcourse)));
     context_course::instance($lastcourse);
     // Test context_helper::create_instances() method.
     $prevcount = $DB->count_records('context');
     $DB->delete_records('context', array('contextlevel' => CONTEXT_BLOCK));
     context_helper::create_instances(null, true);
     $this->assertSame($DB->count_records('context'), $prevcount);
     $this->assertEquals(0, $DB->count_records('context', array('depth' => 0)));
     $this->assertEquals(0, $DB->count_records('context', array('path' => null)));
     $DB->delete_records('context', array('contextlevel' => CONTEXT_BLOCK));
     $DB->delete_records('block_instances', array());
     $prevcount = $DB->count_records('context');
     $DB->delete_records_select('context', 'contextlevel <> ' . CONTEXT_SYSTEM);
     context_helper::create_instances(null, true);
     $this->assertSame($prevcount, $DB->count_records('context'));
     $this->assertEquals(0, $DB->count_records('context', array('depth' => 0)));
     $this->assertEquals(0, $DB->count_records('context', array('path' => null)));
     // Test context_helper::cleanup_instances() method.
     $lastcourse = $DB->get_field_sql("SELECT MAX(id) FROM {course}");
     $DB->delete_records('course', array('id' => $lastcourse));
     $lastcategory = $DB->get_field_sql("SELECT MAX(id) FROM {course_categories}");
     $DB->delete_records('course_categories', array('id' => $lastcategory));
     $lastuser = $DB->get_field_sql("SELECT MAX(id) FROM {user} WHERE deleted=0");
     $DB->delete_records('user', array('id' => $lastuser));
     $DB->delete_records('block_instances', array('parentcontextid' => $frontpagepagecontext->id));
     $DB->delete_records('course_modules', array('id' => $frontpagepagecontext->instanceid));
     context_helper::cleanup_instances();
     $count = 1;
     // System.
     $count += $DB->count_records('user', array('deleted' => 0));
     $count += $DB->count_records('course_categories');
     $count += $DB->count_records('course');
     $count += $DB->count_records('course_modules');
     $count += $DB->count_records('block_instances');
     $this->assertEquals($count, $DB->count_records('context'));
     // Test context cache size restrictions.
     $testusers = array();
     for ($i = 0; $i < CONTEXT_CACHE_MAX_SIZE + 100; $i++) {
         $user = $generator->create_user();
         $testusers[$i] = $user->id;
     }
     context_helper::create_instances(null, true);
     context_helper::reset_caches();
     for ($i = 0; $i < CONTEXT_CACHE_MAX_SIZE + 100; $i++) {
         context_user::instance($testusers[$i]);
         if ($i == CONTEXT_CACHE_MAX_SIZE - 1) {
             $this->assertEquals(CONTEXT_CACHE_MAX_SIZE, context_inspection::test_context_cache_size());
         } else {
             if ($i == CONTEXT_CACHE_MAX_SIZE) {
                 // Once the limit is reached roughly 1/3 of records should be removed from cache.
                 $this->assertEquals((int) ceil(CONTEXT_CACHE_MAX_SIZE * (2 / 3) + 101), context_inspection::test_context_cache_size());
             }
         }
     }
     // We keep the first 100 cached.
     $prevsize = context_inspection::test_context_cache_size();
     for ($i = 0; $i < 100; $i++) {
         context_user::instance($testusers[$i]);
         $this->assertEquals($prevsize, context_inspection::test_context_cache_size());
     }
     context_user::instance($testusers[102]);
     $this->assertEquals($prevsize + 1, context_inspection::test_context_cache_size());
     unset($testusers);
     // Test basic test of legacy functions.
     // Note: watch out, the fake site might be pretty borked already.
     $this->assertEquals(get_system_context(), context_system::instance());
     foreach ($DB->get_records('context') as $contextid => $record) {
         $context = context::instance_by_id($contextid);
         $this->assertEquals($context, get_context_instance_by_id($contextid, IGNORE_MISSING));
         $this->assertEquals($context, get_context_instance($record->contextlevel, $record->instanceid));
         $this->assertEquals($context->get_parent_context_ids(), get_parent_contexts($context));
         if ($context->id == SYSCONTEXTID) {
             $this->assertFalse(get_parent_contextid($context));
         } else {
             $this->assertSame($context->get_parent_context()->id, get_parent_contextid($context));
         }
     }
     $children = get_child_contexts($systemcontext);
     // Using assertEquals here as assertSame fails for some reason...
     $this->assertEquals($children, $systemcontext->get_child_contexts());
     $this->assertEquals(count($children), $DB->count_records('context') - 1);
     $this->resetDebugging();
     unset($children);
     // Make sure a debugging is thrown.
     get_context_instance($record->contextlevel, $record->instanceid);
     $this->assertDebuggingCalled('get_context_instance() is deprecated, please use context_xxxx::instance() instead.', DEBUG_DEVELOPER);
     get_context_instance_by_id($record->id);
     $this->assertDebuggingCalled('get_context_instance_by_id() is deprecated, please use context::instance_by_id($id) instead.', DEBUG_DEVELOPER);
     get_system_context();
     $this->assertDebuggingCalled('get_system_context() is deprecated, please use context_system::instance() instead.', DEBUG_DEVELOPER);
     get_parent_contexts($context);
     $this->assertDebuggingCalled('get_parent_contexts() is deprecated, please use $context->get_parent_context_ids() instead.', DEBUG_DEVELOPER);
     get_parent_contextid($context);
     $this->assertDebuggingCalled('get_parent_contextid() is deprecated, please use $context->get_parent_context() instead.', DEBUG_DEVELOPER);
     get_child_contexts($frontpagecontext);
     $this->assertDebuggingCalled('get_child_contexts() is deprecated, please use $context->get_child_contexts() instead.', DEBUG_DEVELOPER);
     $DB->delete_records('context', array('contextlevel' => CONTEXT_BLOCK));
     create_contexts();
     $this->assertDebuggingCalled('create_contexts() is deprecated, please use context_helper::create_instances() instead.', DEBUG_DEVELOPER);
     $this->assertFalse($DB->record_exists('context', array('contextlevel' => CONTEXT_BLOCK)));
     $DB->set_field('context', 'depth', 0, array('contextlevel' => CONTEXT_BLOCK));
     build_context_path();
     $this->assertDebuggingCalled('build_context_path() is deprecated, please use context_helper::build_all_paths() instead.', DEBUG_DEVELOPER);
     $this->assertFalse($DB->record_exists('context', array('depth' => 0)));
     $lastcourse = $DB->get_field_sql("SELECT MAX(id) FROM {course}");
     $DB->delete_records('course', array('id' => $lastcourse));
     $lastcategory = $DB->get_field_sql("SELECT MAX(id) FROM {course_categories}");
     $DB->delete_records('course_categories', array('id' => $lastcategory));
     $lastuser = $DB->get_field_sql("SELECT MAX(id) FROM {user} WHERE deleted=0");
     $DB->delete_records('user', array('id' => $lastuser));
     $DB->delete_records('block_instances', array('parentcontextid' => $frontpagepagecontext->id));
     $DB->delete_records('course_modules', array('id' => $frontpagepagecontext->instanceid));
     cleanup_contexts();
     $this->assertDebuggingCalled('cleanup_contexts() is deprecated, please use context_helper::cleanup_instances() instead.', DEBUG_DEVELOPER);
     $count = 1;
     // System.
     $count += $DB->count_records('user', array('deleted' => 0));
     $count += $DB->count_records('course_categories');
     $count += $DB->count_records('course');
     $count += $DB->count_records('course_modules');
     $count += $DB->count_records('block_instances');
     $this->assertEquals($count, $DB->count_records('context'));
     // Test legacy rebuild_contexts().
     $context = context_course::instance($testcourses[2]);
     rebuild_contexts(array($context));
     $this->assertDebuggingCalled('rebuild_contexts() is deprecated, please use $context->reset_paths(true) instead.', DEBUG_DEVELOPER);
     $context = context_course::instance($testcourses[2]);
     $this->assertSame($context->path, $DB->get_field('context', 'path', array('id' => $context->id)));
     $this->assertSame($context->depth, $DB->get_field('context', 'depth', array('id' => $context->id)));
     $this->assertEquals(0, $DB->count_records('context', array('depth' => 0)));
     $this->assertEquals(0, $DB->count_records('context', array('path' => null)));
     context_helper::reset_caches();
     preload_course_contexts($SITE->id);
     $this->assertDebuggingCalled('preload_course_contexts() is deprecated, please use context_helper::preload_course() instead.', DEBUG_DEVELOPER);
     $this->assertEquals(1 + $DB->count_records('course_modules', array('course' => $SITE->id)), context_inspection::test_context_cache_size());
     context_helper::reset_caches();
     list($select, $join) = context_instance_preload_sql('c.id', CONTEXT_COURSECAT, 'ctx');
     $this->assertDebuggingCalled('context_instance_preload_sql() is deprecated, please use context_helper::get_preload_record_columns_sql() instead.', DEBUG_DEVELOPER);
     $this->assertEquals(', ' . context_helper::get_preload_record_columns_sql('ctx'), $select);
     $this->assertEquals('LEFT JOIN {context} ctx ON (ctx.instanceid = c.id AND ctx.contextlevel = ' . CONTEXT_COURSECAT . ')', $join);
     $sql = "SELECT c.id {$select} FROM {course_categories} c {$join}";
     $records = $DB->get_records_sql($sql);
     foreach ($records as $record) {
         context_instance_preload($record);
         $this->assertDebuggingCalled('context_instance_preload() is deprecated, please use context_helper::preload_from_record() instead.', DEBUG_DEVELOPER);
         $record = (array) $record;
         $this->assertEquals(1, count($record));
         // Only id left.
     }
     $this->assertEquals(count($records), context_inspection::test_context_cache_size());
     accesslib_clear_all_caches(true);
     $DB->delete_records('cache_flags', array());
     mark_context_dirty($systemcontext->path);
     $this->assertDebuggingCalled('mark_context_dirty() is deprecated, please use $context->mark_dirty() instead.', DEBUG_DEVELOPER);
     $dirty = get_cache_flags('accesslib/dirtycontexts', time() - 2);
     $this->assertTrue(isset($dirty[$systemcontext->path]));
     accesslib_clear_all_caches(false);
     $DB->delete_records('cache_flags', array());
     $course = $DB->get_record('course', array('id' => $testcourses[2]));
     $context = context_course::instance($course->id);
     $oldpath = $context->path;
     $miscid = $DB->get_field_sql("SELECT MIN(id) FROM {course_categories}");
     $categorycontext = context_coursecat::instance($miscid);
     $course->category = $miscid;
     $DB->update_record('course', $course);
     context_moved($context, $categorycontext);
     $this->assertDebuggingCalled('context_moved() is deprecated, please use context::update_moved() instead.', DEBUG_DEVELOPER);
     $context = context_course::instance($course->id);
     $this->assertEquals($categorycontext, $context->get_parent_context());
     $this->assertTrue($DB->record_exists('context', array('contextlevel' => CONTEXT_COURSE, 'instanceid' => $testcourses[2])));
     delete_context(CONTEXT_COURSE, $testcourses[2]);
     $this->assertDebuggingCalled('delete_context() is deprecated, please use context_helper::delete_instance() instead.', DEBUG_DEVELOPER);
     $this->assertFalse($DB->record_exists('context', array('contextlevel' => CONTEXT_COURSE, 'instanceid' => $testcourses[2])));
     delete_context(CONTEXT_COURSE, $testcourses[2], false);
     $this->assertDebuggingCalled('delete_context() is deprecated, please use $context->delete_content() instead.', DEBUG_DEVELOPER);
     $name = get_contextlevel_name(CONTEXT_COURSE);
     $this->assertDebuggingCalled('get_contextlevel_name() is deprecated, please use context_helper::get_level_name() instead.', DEBUG_DEVELOPER);
     $this->assertFalse(empty($name));
     $context = context_course::instance($testcourses[2]);
     $name = print_context_name($context);
     $this->assertDebuggingCalled('print_context_name() is deprecated, please use $context->get_context_name() instead.', DEBUG_DEVELOPER);
     $this->assertFalse(empty($name));
     $url1 = get_context_url($coursecontext);
     $this->assertDebuggingCalled('get_context_url() is deprecated, please use $context->get_url() instead.', DEBUG_DEVELOPER);
     $url2 = $coursecontext->get_url();
     $this->assertEquals($url1, $url2);
     $this->assertInstanceOf('moodle_url', $url2);
     $pagecm = get_coursemodule_from_instance('page', $testpages[7]);
     $context = context_module::instance($pagecm->id);
     $coursecontext1 = get_course_context($context);
     $this->assertDebuggingCalled('get_course_context() is deprecated, please use $context->get_course_context(true) instead.', DEBUG_DEVELOPER);
     $coursecontext2 = $context->get_course_context(true);
     $this->assertEquals($coursecontext1, $coursecontext2);
     $this->assertEquals(CONTEXT_COURSE, $coursecontext2->contextlevel);
     $this->assertEquals($pagecm->course, get_courseid_from_context($context));
     $this->assertDebuggingCalled('get_courseid_from_context() is deprecated, please use $context->get_course_context(false) instead.', DEBUG_DEVELOPER);
     $caps = fetch_context_capabilities($systemcontext);
     $this->assertDebuggingCalled('fetch_context_capabilities() is deprecated, please use $context->get_capabilities() instead.', DEBUG_DEVELOPER);
     $this->assertEquals($caps, $systemcontext->get_capabilities());
     unset($caps);
 }