/**
 * @package block
 * @subpackage demostudent
 * @author Dominik Royko royko@ualberta.ca
 */
function xmldb_block_demostudent_install()
{
    global $DB;
    $result = true;
    $systemcontext = context_system::instance();
    // Create DemoStudent role.
    $contextlevels = array(CONTEXT_COURSE, CONTEXT_MODULE);
    if (!($demostudentrole = $DB->get_record('role', array('shortname' => 'demostudent')))) {
        if ($roleid = create_role(get_string('roledemostudentname', 'block_demostudent'), 'demostudent', get_string('roledemostudentdescription', 'block_demostudent'), 'student')) {
            $newrole = new stdClass();
            $newrole->id = $roleid;
            // Set the capabilities to the archetype (student).
            // Caution: new capabilities un/set here can get clobbered by 'clonepermissionsfrom',
            // defined in access.php.
            reset_role_capabilities($roleid);
            // DemoStudent needs to see the DemoStudent block.
            $result = $result && assign_capability('block/demostudent:seedemostudentblock', CAP_ALLOW, $newrole->id, $systemcontext->id);
            // DemoStudent should be able to see hidden courses to facilitate testing.
            $result = $result && assign_capability('moodle/course:viewhiddencourses', CAP_ALLOW, $newrole->id, $systemcontext->id);
            // DemoStudent should NOT be able to add more demostudents!
            $result = $result && unassign_capability('block/demostudent:addinstance', $newrole->id);
            $systemcontext->mark_dirty();
            set_role_contextlevels($newrole->id, $contextlevels);
        } else {
            $result = false;
        }
    }
    return $result;
}
/**
 * Called from cron and update_instance. Not called from add_instance as the contexts are not set up yet.
 */
function qcreate_student_q_access_sync($qcreate, $cmcontext = null, $course = null, $forcesync = false)
{
    //check if a check is needed
    $timenow = time();
    $activityopen = ($qcreate->timeopen == 0 || $qcreate->timeopen < $timenow) && ($qcreate->timeclose == 0 || $qcreate->timeclose > $timenow);
    $activitywasopen = ($qcreate->timeopen == 0 || $qcreate->timeopen < $qcreate->timesync) && ($qcreate->timeclose == 0 || $qcreate->timeclose > $qcreate->timesync);
    $needsync = empty($qcreate->timesync) || $activitywasopen != $activityopen;
    if ($forcesync || $needsync) {
        if ($cmcontext == null) {
            $cm = get_coursemodule_from_instance('qcreate', $qcreate->id);
            $cmcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
        }
        if ($course == null) {
            $course = get_record('course', 'id', $qcreate->course);
        }
        $studentrole = get_default_course_role($course);
        if ($activityopen) {
            $capabilitiestoassign = array(0 => array('moodle/question:add' => 1, 'moodle/question:usemine' => -1, 'moodle/question:viewmine' => -1, 'moodle/question:editmine' => -1), 1 => array('moodle/question:add' => 1, 'moodle/question:usemine' => 1, 'moodle/question:viewmine' => -1, 'moodle/question:editmine' => -1), 2 => array('moodle/question:add' => 1, 'moodle/question:usemine' => 1, 'moodle/question:viewmine' => 1, 'moodle/question:editmine' => -1), 3 => array('moodle/question:add' => 1, 'moodle/question:usemine' => 1, 'moodle/question:viewmine' => 1, 'moodle/question:editmine' => 1));
            foreach ($capabilitiestoassign[$qcreate->studentqaccess] as $capability => $permission) {
                assign_capability($capability, $permission, $studentrole->id, $cmcontext->id, true);
            }
        } else {
            $capabilitiestounassign = array('moodle/question:add', 'moodle/question:usemine', 'moodle/question:viewmine', 'moodle/question:editmine');
            foreach ($capabilitiestounassign as $capability) {
                unassign_capability($capability, $studentrole->id, $cmcontext->id);
            }
        }
        set_field('qcreate', 'timesync', $timenow, 'id', $qcreate->id);
    }
}
Exemple #3
0
    /**
     * Unassign a capability to $USER
     *
     * @param string $capability capability name
     * @param int $contextid
     * @param int $roleid
     */
    public static function unassignUserCapability($capability, $contextid, $roleid) {
        global $USER;

        unassign_capability($capability, $roleid, $contextid);

        accesslib_clear_all_caches_for_unit_testing();
    }
Exemple #4
0
 /**
  * Unassign a capability to $USER.
  *
  * @param string $capability capability name.
  * @param int $contextid set the context id if you used assignUserCapability.
  * @param int $roleid set the role id if you used assignUserCapability.
  * @param int $courseid set the course id if you used getDataGenerator->enrol_users.
  * @param string $enrol set the enrol plugin name if you used getDataGenerator->enrol_users with a different plugin than 'manual'.
  */
 public static function unassignUserCapability($capability, $contextid = null, $roleid = null, $courseid = null, $enrol = 'manual')
 {
     global $DB;
     if (!empty($courseid)) {
         // Retrieve the role id.
         $instances = $DB->get_records('enrol', array('courseid' => $courseid, 'enrol' => $enrol));
         if (count($instances) != 1) {
             throw new coding_exception('No found enrol instance for courseid: ' . $courseid . ' and enrol: ' . $enrol);
         }
         $instance = reset($instances);
         if (is_null($roleid) and $instance->roleid) {
             $roleid = $instance->roleid;
         }
     } else {
         if (empty($contextid) or empty($roleid)) {
             throw new coding_exception('unassignUserCapaibility requires contextid/roleid or courseid');
         }
     }
     unassign_capability($capability, $roleid, $contextid);
     accesslib_clear_all_caches_for_unit_testing();
 }
Exemple #5
0
 public function setUp()
 {
     global $DB;
     $this->resetAfterTest();
     $this->course = self::getDataGenerator()->create_course();
     $this->student1 = $this->getDataGenerator()->create_user();
     $this->student2 = $this->getDataGenerator()->create_user();
     $this->teacher1 = $this->getDataGenerator()->create_user();
     $this->teacher2 = $this->getDataGenerator()->create_user();
     $this->teacher3 = $this->getDataGenerator()->create_user();
     $this->studentrole = $DB->get_record('role', array('shortname' => 'student'));
     $this->teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
     unassign_capability('moodle/site:accessallgroups', $this->teacherrole->id);
     $this->getDataGenerator()->enrol_user($this->student1->id, $this->course->id, $this->studentrole->id);
     $this->getDataGenerator()->enrol_user($this->student2->id, $this->course->id, $this->studentrole->id);
     $this->getDataGenerator()->enrol_user($this->teacher1->id, $this->course->id, $this->teacherrole->id);
     $this->getDataGenerator()->enrol_user($this->teacher2->id, $this->course->id, $this->teacherrole->id);
     $this->getDataGenerator()->enrol_user($this->teacher3->id, $this->course->id, $this->teacherrole->id);
     // Create the forum.
     $record = new stdClass();
     $record->introformat = FORMAT_HTML;
     $record->course = $this->course->id;
     // Set Aggregate type = Average of ratings.
     $record->assessed = RATING_AGGREGATE_AVERAGE;
     $record->scale = 100;
     $this->forum = self::getDataGenerator()->create_module('forum', $record);
     $this->contextid = context_module::instance($this->forum->cmid)->id;
     // Add discussion to the forums.
     $record = new stdClass();
     $record->course = $this->course->id;
     $record->userid = $this->student1->id;
     $record->forum = $this->forum->id;
     $this->discussion = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
     // Retrieve the first post.
     $this->post = $DB->get_record('forum_posts', array('discussion' => $this->discussion->id));
 }
Exemple #6
0
         }
         if (empty($errors)) {
             // update normal role settings
             $role->id = $roleid;
             $role->name = $name;
             $role->shortname = $shortname;
             $role->description = $description;
             if (!update_record('role', $role)) {
                 error('Could not update role!');
             }
             // set proper legacy type
             foreach ($legacyroles as $ltype => $lcap) {
                 if ($ltype == $legacytype) {
                     assign_capability($lcap, CAP_ALLOW, $roleid, $sitecontext->id);
                 } else {
                     unassign_capability($lcap, $roleid);
                 }
             }
             // edited a role sitewide...
             mark_context_dirty($sitecontext->path);
             add_to_log(SITEID, 'role', 'edit', 'admin/roles/manage.php?action=edit&roleid=' . $role->id, $role->name, '', $USER->id);
             redirect('manage.php');
         }
         // edited a role sitewide - with errors, but still...
         mark_context_dirty($sitecontext->path);
     }
     break;
 case 'delete':
     if (in_array($roleid, $defaultroles)) {
         error('This role is used as one of the default system roles, it can not be deleted');
     }
/**
 * Called from the settings form. Assigns or unassigns capabilities from Group Manager role.
 * Assumes that this role exists, and that capabilities have numeric values 1 and 2 from form.
 *
 * @param $settingname
 * @return unknown_type
 */
function fn_sg_set_user_capability($settingname)
{
    global $CFG;
    $context = get_system_context();
    $role = get_record('role', 'shortname', FNGRPMANROLESNAME);
    if ($settingname == 's__block_fn_site_groups_users') {
        $capsset = explode(',', $CFG->block_fn_site_groups_users);
        if (in_array(1, $capsset)) {
            assign_capability('block/fn_site_groups:assignowngroupusers', CAP_ALLOW, $role->id, $context->id);
        } else {
            unassign_capability('block/fn_site_groups:assignowngroupusers', $role->id, $context->id);
        }
        if (in_array(2, $capsset)) {
            assign_capability('block/fn_site_groups:assignallusers', CAP_ALLOW, $role->id, $context->id);
        } else {
            unassign_capability('block/fn_site_groups:assignallusers', $role->id, $context->id);
        }
    } else {
        if ($settingname == 's__block_fn_site_groups_creategroups') {
            if (!empty($CFG->block_fn_site_groups_creategroups)) {
                assign_capability('block/fn_site_groups:createnewgroups', CAP_ALLOW, $role->id, $context->id);
            } else {
                unassign_capability('block/fn_site_groups:createnewgroups', $role->id, $context->id);
            }
        }
    }
    return true;
}
function xmldb_oublog_upgrade($oldversion = 0)
{
    global $CFG, $THEME, $db;
    $result = true;
    if ($result && $oldversion < 2008022600) {
        /// Define field views to be added to oublog_instances
        $table = new XMLDBTable('oublog_instances');
        $field = new XMLDBField('views');
        $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'accesstoken');
        /// Launch add field views
        $result = $result && add_field($table, $field);
        $table = new XMLDBTable('oublog');
        $field = new XMLDBField('views');
        $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'global');
        /// Launch add field views
        $result = $result && add_field($table, $field);
    }
    if ($result && $oldversion < 2008022700) {
        /// Define field oublogid to be added to oublog_links
        $table = new XMLDBTable('oublog_links');
        $field = new XMLDBField('oublogid');
        $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null, 'id');
        /// Launch add field oublogid
        $result = $result && add_field($table, $field);
        /// Define key oublog_links_oublog_fk (foreign) to be added to oublog_links
        $table = new XMLDBTable('oublog_links');
        $key = new XMLDBKey('oublog_links_oublog_fk');
        $key->setAttributes(XMLDB_KEY_FOREIGN, array('oublogid'), 'oublog', array('id'));
        /// Launch add key oublog_links_oublog_fk
        $result = $result && add_key($table, $key);
        /// Changing nullability of field oubloginstancesid on table oublog_links to null
        $table = new XMLDBTable('oublog_links');
        $field = new XMLDBField('oubloginstancesid');
        $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, null, null, 'oublogid');
        /// Launch change of nullability for field oubloginstancesid
        $result = $result && change_field_notnull($table, $field);
    }
    if ($result && $oldversion < 2008022701) {
        /// Define field sortorder to be added to oublog_links
        $table = new XMLDBTable('oublog_links');
        $field = new XMLDBField('sortorder');
        $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null, 'url');
        /// Launch add field sortorder
        $result = $result && add_field($table, $field);
    }
    if ($result && $oldversion < 2008030704) {
        /// Add search data
        require_once dirname(__FILE__) . '/../locallib.php';
        require_once dirname(__FILE__) . '/../lib.php';
        if (oublog_search_installed()) {
            global $db;
            $olddebug = $db->debug;
            $db->debug = false;
            print '<ul>';
            oublog_ousearch_update_all(true);
            print '</ul>';
            $db->debug = $olddebug;
        }
    }
    if ($result && $oldversion < 2008030707) {
        /// Define field lasteditedby to be added to oublog_posts
        $table = new XMLDBTable('oublog_posts');
        $field = new XMLDBField('lasteditedby');
        $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, null, null, 'visibility');
        /// Launch add field lasteditedby
        $result = $result && add_field($table, $field);
        /// Transfer edit data to lasteditedby
        $result = $result && execute_sql("\r\nUPDATE {$CFG->prefix}oublog_posts SET lasteditedby=(\r\n    SELECT userid FROM {$CFG->prefix}oublog_edits WHERE {$CFG->prefix}oublog_posts.id=postid ORDER BY id DESC LIMIT 1 \r\n) WHERE editsummary IS NOT NULL\r\n        ");
        /// Define field editsummary to be dropped from oublog_posts
        $table = new XMLDBTable('oublog_posts');
        $field = new XMLDBField('editsummary');
        /// Launch drop field editsummary
        $result = $result && drop_field($table, $field);
    }
    if ($result && $oldversion < 2008073000) {
        /// Define field completionposts to be added to oublog
        $table = new XMLDBTable('oublog');
        $field = new XMLDBField('completionposts');
        $field->setAttributes(XMLDB_TYPE_INTEGER, '9', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'views');
        /// Launch add field completionposts
        $result = $result && add_field($table, $field);
        /// Define field completioncomments to be added to oublog
        $field = new XMLDBField('completioncomments');
        $field->setAttributes(XMLDB_TYPE_INTEGER, '9', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'completionposts');
        /// Launch add field completioncomments
        $result = $result && add_field($table, $field);
    }
    if ($result && $oldversion < 2008121100) {
        // remove oublog:view from legacy:user roles
        $roles = get_roles_with_capability('moodle/legacy:user', CAP_ALLOW);
        foreach ($roles as $role) {
            $result = $result && unassign_capability('mod/oublog:view', $role->id);
        }
    }
    if ($result && $oldversion < 2009012600) {
        // Remove oublog:post and oublog:comment from legacy:user roles (if present)
        $roles = get_roles_with_capability('moodle/legacy:user', CAP_ALLOW);
        // Also from default user role if not already included
        if (!array_key_exists($CFG->defaultuserroleid, $roles)) {
            $roles[] = get_record('role', 'id', $CFG->defaultuserroleid);
        }
        print '<p><strong>Warning</strong>: The OU blog system capabilities 
            have changed (again) in order to fix bugs and clarify access control.
            The system will automatically remove the capabilities 
            <tt>mod/oublog:view</tt>, <tt>mod/oublog:post</tt>, and
            <tt>mod/oublog:comment</tt> from the following role(s):</p><ul>';
        foreach ($roles as $role) {
            print '<li>' . htmlspecialchars($role->name) . '</li>';
            $result = $result && unassign_capability('mod/oublog:view', $role->id);
            $result = $result && unassign_capability('mod/oublog:post', $role->id);
            $result = $result && unassign_capability('mod/oublog:comment', $role->id);
        }
        print '</ul><p>On a default Moodle installation this is the correct 
            behaviour. Personal blog access is now controlled via the 
            <tt>mod/oublog:viewpersonal</tt> and 
            <tt>mod/oublog:contributepersonal</tt>
            capabilities. These capabilities have been added to the 
            authenticated user role and any equivalent roles.</p>
            <p>If in doubt, please examine your role configuration with regard
            to these <tt>mod/oublog</tt> capabilities.</p>';
    }
    if ($result && $oldversion < 2010031200) {
        /// Define field completionposts to be added to oublog
        $table = new XMLDBTable('oublog');
        $field = new XMLDBField('individual');
        $field->setAttributes(XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'completioncomments');
        /// Launch add field completioncomments
        $result = $result && add_field($table, $field);
    }
    if ($result && $oldversion < 2010062400) {
        /// Define table oublog_comments_moderated to be created
        $table = new XMLDBTable('oublog_comments_moderated');
        /// Adding fields to table oublog_comments_moderated
        $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null);
        $table->addFieldInfo('postid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null);
        $table->addFieldInfo('title', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, null, null);
        $table->addFieldInfo('message', XMLDB_TYPE_TEXT, 'medium', null, XMLDB_NOTNULL, null, null, null, null);
        $table->addFieldInfo('timeposted', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null);
        $table->addFieldInfo('authorname', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, null, null);
        $table->addFieldInfo('ipaddress', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, null, null);
        $table->addFieldInfo('approval', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0');
        $table->addFieldInfo('timeset', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, null, null);
        $table->addFieldInfo('secretkey', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, null, null);
        /// Adding keys to table oublog_comments_moderated
        $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id'));
        $table->addKeyInfo('postid', XMLDB_KEY_FOREIGN, array('postid'), 'oublog_posts', array('id'));
        /// Adding indexes to table oublog_comments_moderated
        $table->addIndexInfo('ipaddress', XMLDB_INDEX_NOTUNIQUE, array('ipaddress'));
        /// Launch create table for oublog_comments_moderated
        $result = $result && create_table($table);
        /// Changing nullability of field userid on table oublog_comments to null
        $table = new XMLDBTable('oublog_comments');
        $field = new XMLDBField('userid');
        $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, null, null, 'postid');
        /// Launch change of nullability for field userid
        $result = $result && change_field_notnull($table, $field);
        /// Define field authorname to be added to oublog_comments
        $field = new XMLDBField('authorname');
        $field->setAttributes(XMLDB_TYPE_CHAR, '255', null, null, null, null, null, null, 'timedeleted');
        /// Launch add field authorname
        $result = $result && add_field($table, $field);
        /// Define field authorip to be added to oublog_comments
        $field = new XMLDBField('authorip');
        $field->setAttributes(XMLDB_TYPE_CHAR, '255', null, null, null, null, null, null, 'authorname');
        /// Launch add field authorip
        $result = $result && add_field($table, $field);
        /// Define field timeapproved to be added to oublog_comments
        $field = new XMLDBField('timeapproved');
        $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, null, null, 'authorip');
        /// Launch add field timeapproved
        $result = $result && add_field($table, $field);
    }
    if ($result && $oldversion < 2010062500) {
        // Change the 'allow comments' value to 2 on global blog, if it is
        // currently set to 1
        $result = $result && set_field('oublog', 'allowcomments', 2, 'global', 1, 'allowcomments', 1);
    }
    if ($result && $oldversion < 2010063000) {
        /// Define index ipaddress (not unique) to be dropped form oublog_comments_moderated
        $table = new XMLDBTable('oublog_comments_moderated');
        $index = new XMLDBIndex('ipaddress');
        $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('ipaddress'));
        /// Launch drop index authorip
        $result = $result && drop_index($table, $index);
        /// Rename field ipaddress on table oublog_comments_moderated to authorip
        $field = new XMLDBField('ipaddress');
        $field->setAttributes(XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, null, null, 'authorname');
        /// Launch rename field ipaddress
        $result = $result && rename_field($table, $field, 'authorip');
        /// Define index authorip (not unique) to be added to oublog_comments_moderated
        $table = new XMLDBTable('oublog_comments_moderated');
        $index = new XMLDBIndex('authorip');
        $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('authorip'));
        /// Launch add index authorip
        $result = $result && add_index($table, $index);
    }
    if ($result && $oldversion < 2010070101) {
        // Make cron start working - in some servers I found there was
        // 9999999999 in the lastcron field which caused it never to run; not
        // very helpful
        $result = $result && set_field('modules', 'lastcron', 1, 'name', 'oublog');
    }
    return $result;
}
Exemple #9
0
    /**
     * A small functional test of accesslib functions and classes.
     * @return void
     */
    public function test_everything_in_accesslib() {
        global $USER, $SITE, $CFG, $DB, $ACCESSLIB_PRIVATE;

        $this->resetAfterTest(true);

        $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($DB->count_records('context'), $count);
        $this->assertEquals($DB->count_records('context', array('depth'=>0)), 0);
        $this->assertEquals($DB->count_records('context', array('path'=>NULL)), 0);


        // ====== context_helper::get_level_name() ================================

        $levels = context_helper::get_all_levels();
        foreach ($levels as $level=>$classname) {
            $name = context_helper::get_level_name($level);
            $this->assertFalse(empty($name));
        }


        // ======= context::instance_by_id(), context_xxx::instance();

        $context = context::instance_by_id($frontpagecontext->id);
        $this->assertSame($context->contextlevel, CONTEXT_COURSE);
        $this->assertFalse(context::instance_by_id(-1, IGNORE_MISSING));
        try {
            context::instance_by_id(-1);
            $this->fail('exception expected');
        } catch (Exception $e) {
            $this->assertTrue(true);
        }
        $this->assertTrue(context_system::instance() instanceof context_system);
        $this->assertTrue(context_coursecat::instance($testcategories[0]) instanceof context_coursecat);
        $this->assertTrue(context_course::instance($testcourses[0]) instanceof context_course);
        $this->assertTrue(context_module::instance($testpages[0]) instanceof context_module);
        $this->assertTrue(context_block::instance($testblocks[0]) instanceof context_block);

        $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 (Exception $e) {
            $this->assertTrue(true);
        }
        try {
            context_course::instance(-1);
            $this->fail('exception expected');
        } catch (Exception $e) {
            $this->assertTrue(true);
        }
        try {
            context_module::instance(-1);
            $this->fail('exception expected');
        } catch (Exception $e) {
            $this->assertTrue(true);
        }
        try {
            context_block::instance(-1);
            $this->fail('exception expected');
        } catch (Exception $e) {
            $this->assertTrue(true);
        }


        // ======= $context->get_url(), $context->get_context_name(), $context->get_capabilities() =========

        $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->assertFalse(empty($name));

            $this->assertTrue($context->get_url() instanceof moodle_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);

        // ===== $context->get_course_context() =========================================

        $this->assertFalse($systemcontext->get_course_context(false));
        try {
            $systemcontext->get_course_context();
            $this->fail('exception expected');
        } catch (Exception $e) {
            $this->assertTrue(true);
        }
        $context = context_coursecat::instance($testcategories[0]);
        $this->assertFalse($context->get_course_context(false));
        try {
            $context->get_course_context();
            $this->fail('exception expected');
        } catch (Exception $e) {
            $this->assertTrue(true);
        }
        $this->assertSame($frontpagecontext->get_course_context(true), $frontpagecontext);
        $this->assertSame($frontpagepagecontext->get_course_context(true), $frontpagecontext);
        $this->assertSame($frontpagepageblockcontext->get_course_context(true), $frontpagecontext);


        // ======= $context->get_parent_context(), $context->get_parent_contexts(), $context->get_parent_context_ids() =======

        $userid = reset($testusers);
        $usercontext = context_user::instance($userid);
        $this->assertSame($usercontext->get_parent_context(), $systemcontext);
        $this->assertSame($usercontext->get_parent_contexts(), array($systemcontext->id=>$systemcontext));
        $this->assertSame($usercontext->get_parent_contexts(true), array($usercontext->id=>$usercontext, $systemcontext->id=>$systemcontext));

        $this->assertSame($systemcontext->get_parent_contexts(), array());
        $this->assertSame($systemcontext->get_parent_contexts(true), array($systemcontext->id=>$systemcontext));
        $this->assertSame($systemcontext->get_parent_context_ids(), array());
        $this->assertSame($systemcontext->get_parent_context_ids(true), array($systemcontext->id));

        $this->assertSame($frontpagecontext->get_parent_context(), $systemcontext);
        $this->assertSame($frontpagecontext->get_parent_contexts(), array($systemcontext->id=>$systemcontext));
        $this->assertSame($frontpagecontext->get_parent_contexts(true), array($frontpagecontext->id=>$frontpagecontext, $systemcontext->id=>$systemcontext));
        $this->assertSame($frontpagecontext->get_parent_context_ids(), array($systemcontext->id));
        $this->assertEquals($frontpagecontext->get_parent_context_ids(true), array($frontpagecontext->id, $systemcontext->id));

        $this->assertSame($systemcontext->get_parent_context(), false);
        $frontpagecontext = context_course::instance($SITE->id);
        $parent = $systemcontext;
        foreach ($testcategories as $catid) {
            $catcontext = context_coursecat::instance($catid);
            $this->assertSame($catcontext->get_parent_context(), $parent);
            $parent = $catcontext;
        }
        $this->assertSame($frontpagepagecontext->get_parent_context(), $frontpagecontext);
        $this->assertSame($frontpageblockcontext->get_parent_context(), $frontpagecontext);
        $this->assertSame($frontpagepageblockcontext->get_parent_context(), $frontpagepagecontext);


        // ====== $context->get_child_contexts() ================================

        $CFG->debug = 0;
        $children = $systemcontext->get_child_contexts();
        $CFG->debug = DEBUG_DEVELOPER;
        $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->assertEquals(count($children), 8);
        $this->assertEquals($countcats, 1);
        $this->assertEquals($countcourses, 6);
        $this->assertEquals($countblocks, 1);

        $context = context_course::instance($testcourses[2]);
        $children = $context->get_child_contexts();
        $this->assertEquals(count($children), 7); // depends on number of default blocks

        $context = context_module::instance($testpages[3]);
        $children = $context->get_child_contexts();
        $this->assertEquals(count($children), 1);

        $context = context_block::instance($testblocks[1]);
        $children = $context->get_child_contexts();
        $this->assertEquals(count($children), 0);

        unset($children);
        unset($countcats);
        unset($countcourses);
        unset($countblocks);


        // ======= context_helper::reset_caches() ============================

        context_helper::reset_caches();
        $this->assertEquals(context_inspection::test_context_cache_size(), 0);
        context_course::instance($SITE->id);
        $this->assertEquals(context_inspection::test_context_cache_size(), 1);


        // ======= context preloading ========================================

        context_helper::reset_caches();
        $sql = "SELECT ".context_helper::get_preload_record_columns_sql('c')."
                  FROM {context} c
                 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($record, new stdClass());
        }
        $this->assertEquals(context_inspection::test_context_cache_size(), count($records));
        unset($records);
        unset($columns);

        context_helper::reset_caches();
        context_helper::preload_course($SITE->id);
        $this->assertEquals(7, context_inspection::test_context_cache_size()); // depends on number of default blocks

        // ====== assign_capability(), unassign_capability() ====================

        $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($rc->permission, CAP_ALLOW);
        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($rc->permission, CAP_ALLOW);
        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($rc->permission, CAP_PREVENT);

        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(false); // must be done after assign_capability()


        // ======= role_assign(), role_unassign(), role_unassign_all() ==============

        $context = context_course::instance($testcourses[1]);
        $this->assertEquals($DB->count_records('role_assignments', array('contextid'=>$context->id)), 0);
        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($DB->count_records('role_assignments', array('contextid'=>$context->id)), 3);
        role_unassign($allroles['teacher'], $testusers[1], $context->id);
        $this->assertEquals($DB->count_records('role_assignments', array('contextid'=>$context->id)), 2);
        role_unassign_all(array('contextid'=>$context->id));
        $this->assertEquals($DB->count_records('role_assignments', array('contextid'=>$context->id)), 0);
        unset($context);

        accesslib_clear_all_caches(false); // just in case


        // ====== has_capability(), get_users_by_capability(), role_switch(), reload_all_capabilities() and friends ========================

        $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(false); // 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->assertEquals(count($enrolled), 10);
        for($i=0; $i<10; $i++) {
            $this->assertTrue(isset($enrolled[$testusers[$i]]));
        }
        $enrolled = get_enrolled_users($coursecontext, 'moodle/course:update');
        $this->assertEquals(count($enrolled), 1);
        $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($USER->access['rsw'][$coursecontext->path],  $allroles['student']);
        $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($USER->access['rsw'][$coursecontext->path],  $allroles['student']);
        $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);
        }

        // Random time!
        //srand(666);
        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(false); // 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



        // ======= $context->mark_dirty() =======================================

        $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]));


        // ======= $context->reload_if_dirty(); =================================

        $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]));
        $pagecontext = context_module::instance($page->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']));


        // ======= context_helper::build_all_paths() ============================

        $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);


        // ======= $context->reset_paths() ======================================

        $context = context_course::instance($testcourses[2]);
        $children = $context->get_child_contexts();
        $context->reset_paths(false);
        $this->assertSame($DB->get_field('context', 'path', array('id'=>$context->id)), NULL);
        $this->assertEquals($DB->get_field('context', 'depth', array('id'=>$context->id)), 0);
        foreach ($children as $child) {
            $this->assertSame($DB->get_field('context', 'path', array('id'=>$child->id)), NULL);
            $this->assertEquals($DB->get_field('context', 'depth', array('id'=>$child->id)), 0);
        }
        $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->assertEquals($DB->get_field('context', 'path', array('id'=>$context->id)), $context->path);
        $this->assertEquals($DB->get_field('context', 'depth', array('id'=>$context->id)), $context->depth);
        $this->assertEquals(0, $DB->count_records('context', array('depth'=>0)));
        $this->assertEquals(0, $DB->count_records('context', array('path'=>NULL)));


        // ====== $context->update_moved(); ======================================

        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($context->get_parent_context(), $categorycontext);
        $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
        $this->assertTrue(isset($dirty[$oldpath]));
        $this->assertTrue(isset($dirty[$context->path]));


        // ====== $context->delete_content() =====================================

        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)));


        // ====== $context->delete() =============================

        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]);


        // ====== context_helper::delete_instance() =============================

        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(context_inspection::test_context_cache_size(), 1);
        $this->assertFalse($coursecontext->instanceid == CONTEXT_COURSE);
        $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(context_inspection::test_context_cache_size(), 0);
        $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$lastcourse)));
        context_course::instance($lastcourse);


        // ======= context_helper::create_instances() ==========================

        $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($DB->count_records('context', array('depth'=>0)), 0);
        $this->assertEquals($DB->count_records('context', array('path'=>NULL)), 0);

        $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($DB->count_records('context'), $prevcount);
        $this->assertEquals($DB->count_records('context', array('depth'=>0)), 0);
        $this->assertEquals($DB->count_records('context', array('path'=>NULL)), 0);


        // ======= context_helper::cleanup_instances() ==========================

        $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($DB->count_records('context'), $count);


        // ======= 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_inspection::test_context_cache_size(), CONTEXT_CACHE_MAX_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(context_inspection::test_context_cache_size(), (int)(CONTEXT_CACHE_MAX_SIZE * (2/3) +102));
            }
        }
        // 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(context_inspection::test_context_cache_size(), $prevsize);
        }
        context_user::instance($testusers[102]);
        $this->assertEquals(context_inspection::test_context_cache_size(), $prevsize+1);
        unset($testusers);



        // =================================================================
        // ======= basic test of legacy functions ==========================
        // =================================================================
        // note: watch out, the fake site might be pretty borked already

        $this->assertSame(get_system_context(), context_system::instance());

        foreach ($DB->get_records('context') as $contextid=>$record) {
            $context = context::instance_by_id($contextid);
            $this->assertSame(get_context_instance_by_id($contextid), $context);
            $this->assertSame(get_context_instance($record->contextlevel, $record->instanceid), $context);
            $this->assertSame(get_parent_contexts($context), $context->get_parent_context_ids());
            if ($context->id == SYSCONTEXTID) {
                $this->assertSame(get_parent_contextid($context), false);
            } else {
                $this->assertSame(get_parent_contextid($context), $context->get_parent_context()->id);
            }
        }

        $CFG->debug = 0;
        $children = get_child_contexts($systemcontext);
        $CFG->debug = DEBUG_DEVELOPER;
        $this->assertEquals(count($children), $DB->count_records('context')-1);
        unset($children);

        $DB->delete_records('context', array('contextlevel'=>CONTEXT_BLOCK));
        create_contexts();
        $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_BLOCK)));

        $DB->set_field('context', 'depth', 0, array('contextlevel'=>CONTEXT_BLOCK));
        build_context_path();
        $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();
        $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($DB->count_records('context'), $count);

        context_helper::reset_caches();
        preload_course_contexts($SITE->id);
        $this->assertEquals(context_inspection::test_context_cache_size(), 1);

        context_helper::reset_caches();
        list($select, $join) = context_instance_preload_sql('c.id', CONTEXT_COURSECAT, 'ctx');
        $sql = "SELECT c.id $select FROM {course_categories} c $join";
        $records = $DB->get_records_sql($sql);
        foreach ($records as $record) {
            context_instance_preload($record);
            $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);
        $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 = get_context_instance(CONTEXT_COURSE, $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);
        $context = get_context_instance(CONTEXT_COURSE, $course->id);
        $this->assertEquals($context->get_parent_context(), $categorycontext);

        $this->assertTrue($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$testcourses[2])));
        delete_context(CONTEXT_COURSE, $testcourses[2]);
        $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$testcourses[2])));

        $name = get_contextlevel_name(CONTEXT_COURSE);
        $this->assertFalse(empty($name));

        $context = get_context_instance(CONTEXT_COURSE, $testcourses[2]);
        $name = print_context_name($context);
        $this->assertFalse(empty($name));

        $url = get_context_url($coursecontext);
        $this->assertFalse($url instanceof modole_url);

        $page = $DB->get_record('page', array('id'=>$testpages[7]));
        $context = get_context_instance(CONTEXT_MODULE, $page->id);
        $coursecontext = get_course_context($context);
        $this->assertEquals($coursecontext->contextlevel, CONTEXT_COURSE);
        $this->assertEquals(get_courseid_from_context($context), $page->course);

        $caps = fetch_context_capabilities($systemcontext);
        $this->assertTrue(is_array($caps));
        unset($caps);
    }
/**
 * Deletes cached capabilities that are no longer needed by the component.
 * Also unassigns these capabilities from any roles that have them.
 * @param $component - examples: 'moodle', 'mod/forum', 'block/quiz_results'
 * @param $newcapdef - array of the new capability definitions that will be
 *                     compared with the cached capabilities
 * @return int - number of deprecated capabilities that have been removed
 */
function capabilities_cleanup($component, $newcapdef = NULL)
{
    global $DB;
    $removedcount = 0;
    if ($cachedcaps = get_cached_capabilities($component)) {
        foreach ($cachedcaps as $cachedcap) {
            if (empty($newcapdef) || array_key_exists($cachedcap->name, $newcapdef) === false) {
                // Remove from capabilities cache.
                if (!$DB->delete_records('capabilities', array('name' => $cachedcap->name))) {
                    print_error('cannotdeletecap', '', '', $cachedcap->name);
                } else {
                    $removedcount++;
                }
                // Delete from roles.
                if ($roles = get_roles_with_capability($cachedcap->name)) {
                    foreach ($roles as $role) {
                        if (!unassign_capability($cachedcap->name, $role->id)) {
                            print_error('cannotunassigncap', 'error', '', (object) array('cap' => $cachedcap->name, 'role' => $role->name));
                        }
                    }
                }
            }
            // End if.
        }
    }
    return $removedcount;
}
Exemple #11
0
 /**
  * Test workshop::check_group_membership() functionality.
  */
 public function test_check_group_membership()
 {
     global $DB, $CFG;
     $this->resetAfterTest();
     $courseid = $this->course->id;
     $generator = $this->getDataGenerator();
     // Make test groups.
     $group1 = $generator->create_group(array('courseid' => $courseid));
     $group2 = $generator->create_group(array('courseid' => $courseid));
     $group3 = $generator->create_group(array('courseid' => $courseid));
     // Revoke the accessallgroups from non-editing teachers (tutors).
     $roleids = $DB->get_records_menu('role', null, '', 'shortname, id');
     unassign_capability('moodle/site:accessallgroups', $roleids['teacher']);
     // Create test use accounts.
     $teacher1 = $generator->create_user();
     $tutor1 = $generator->create_user();
     $tutor2 = $generator->create_user();
     $student1 = $generator->create_user();
     $student2 = $generator->create_user();
     $student3 = $generator->create_user();
     // Enrol the teacher (has the access all groups permission).
     $generator->enrol_user($teacher1->id, $courseid, $roleids['editingteacher']);
     // Enrol tutors (can not access all groups).
     $generator->enrol_user($tutor1->id, $courseid, $roleids['teacher']);
     $generator->enrol_user($tutor2->id, $courseid, $roleids['teacher']);
     // Enrol students.
     $generator->enrol_user($student1->id, $courseid, $roleids['student']);
     $generator->enrol_user($student2->id, $courseid, $roleids['student']);
     $generator->enrol_user($student3->id, $courseid, $roleids['student']);
     // Add users in groups.
     groups_add_member($group1, $tutor1);
     groups_add_member($group2, $tutor2);
     groups_add_member($group1, $student1);
     groups_add_member($group2, $student2);
     groups_add_member($group3, $student3);
     // Workshop with no groups.
     $workshopitem1 = $this->getDataGenerator()->create_module('workshop', ['course' => $courseid, 'groupmode' => NOGROUPS]);
     $cm = get_coursemodule_from_instance('workshop', $workshopitem1->id, $courseid, false, MUST_EXIST);
     $workshop1 = new testable_workshop($workshopitem1, $cm, $this->course);
     $this->setUser($teacher1);
     $this->assertTrue($workshop1->check_group_membership($student1->id));
     $this->assertTrue($workshop1->check_group_membership($student2->id));
     $this->assertTrue($workshop1->check_group_membership($student3->id));
     $this->setUser($tutor1);
     $this->assertTrue($workshop1->check_group_membership($student1->id));
     $this->assertTrue($workshop1->check_group_membership($student2->id));
     $this->assertTrue($workshop1->check_group_membership($student3->id));
     // Workshop in visible groups mode.
     $workshopitem2 = $this->getDataGenerator()->create_module('workshop', ['course' => $courseid, 'groupmode' => VISIBLEGROUPS]);
     $cm = get_coursemodule_from_instance('workshop', $workshopitem2->id, $courseid, false, MUST_EXIST);
     $workshop2 = new testable_workshop($workshopitem2, $cm, $this->course);
     $this->setUser($teacher1);
     $this->assertTrue($workshop2->check_group_membership($student1->id));
     $this->assertTrue($workshop2->check_group_membership($student2->id));
     $this->assertTrue($workshop2->check_group_membership($student3->id));
     $this->setUser($tutor1);
     $this->assertTrue($workshop2->check_group_membership($student1->id));
     $this->assertTrue($workshop2->check_group_membership($student2->id));
     $this->assertTrue($workshop2->check_group_membership($student3->id));
     // Workshop in separate groups mode.
     $workshopitem3 = $this->getDataGenerator()->create_module('workshop', ['course' => $courseid, 'groupmode' => SEPARATEGROUPS]);
     $cm = get_coursemodule_from_instance('workshop', $workshopitem3->id, $courseid, false, MUST_EXIST);
     $workshop3 = new testable_workshop($workshopitem3, $cm, $this->course);
     $this->setUser($teacher1);
     $this->assertTrue($workshop3->check_group_membership($student1->id));
     $this->assertTrue($workshop3->check_group_membership($student2->id));
     $this->assertTrue($workshop3->check_group_membership($student3->id));
     $this->setUser($tutor1);
     $this->assertTrue($workshop3->check_group_membership($student1->id));
     $this->assertFalse($workshop3->check_group_membership($student2->id));
     $this->assertFalse($workshop3->check_group_membership($student3->id));
     $this->setUser($tutor2);
     $this->assertFalse($workshop3->check_group_membership($student1->id));
     $this->assertTrue($workshop3->check_group_membership($student2->id));
     $this->assertFalse($workshop3->check_group_membership($student3->id));
 }
 public function test_remove_competency_from_template()
 {
     $syscontext = context_system::instance();
     $this->setUser($this->creator);
     $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
     // Create a template.
     $template = $this->create_template(1, true);
     // Create a competency.
     $framework = $lpg->create_framework();
     $competency = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
     // Add the competency.
     external::add_competency_to_template($template->id, $competency->get_id());
     // Check that it was added.
     $this->assertEquals(1, external::count_competencies_in_template($template->id));
     // Check that we can remove the competency.
     external::remove_competency_from_template($template->id, $competency->get_id());
     // Check that it was removed.
     $this->assertEquals(0, external::count_competencies_in_template($template->id));
     // Unassign capability.
     unassign_capability('moodle/competency:templatemanage', $this->creatorrole, $syscontext->id);
     accesslib_clear_all_caches_for_unit_testing();
     // Check we can not remove the competency now.
     try {
         external::add_competency_to_template($template->id, $competency->get_id());
         $this->fail('Exception expected due to not permissions to manage template competencies');
     } catch (moodle_exception $e) {
         $this->assertEquals('nopermissions', $e->errorcode);
     }
 }
Exemple #13
0
 /**
  * Setup function- we will create a course and add an assign instance to it.
  */
 protected function setUp()
 {
     global $DB;
     $this->resetAfterTest(true);
     // Create some users.
     $creator = $this->getDataGenerator()->create_user();
     $user = $this->getDataGenerator()->create_user();
     $catuser = $this->getDataGenerator()->create_user();
     $catcreator = $this->getDataGenerator()->create_user();
     $category = $this->getDataGenerator()->create_category();
     $othercategory = $this->getDataGenerator()->create_category();
     $syscontext = context_system::instance();
     $catcontext = context_coursecat::instance($category->id);
     // Fetching default authenticated user role.
     $userroles = get_archetype_roles('user');
     $this->assertCount(1, $userroles);
     $authrole = array_pop($userroles);
     // Reset all default authenticated users permissions.
     unassign_capability('moodle/competency:competencygrade', $authrole->id);
     unassign_capability('moodle/competency:competencymanage', $authrole->id);
     unassign_capability('moodle/competency:competencyview', $authrole->id);
     unassign_capability('moodle/competency:planmanage', $authrole->id);
     unassign_capability('moodle/competency:planmanagedraft', $authrole->id);
     unassign_capability('moodle/competency:planmanageown', $authrole->id);
     unassign_capability('moodle/competency:planview', $authrole->id);
     unassign_capability('moodle/competency:planviewdraft', $authrole->id);
     unassign_capability('moodle/competency:planviewown', $authrole->id);
     unassign_capability('moodle/competency:planviewowndraft', $authrole->id);
     unassign_capability('moodle/competency:templatemanage', $authrole->id);
     unassign_capability('moodle/competency:templateview', $authrole->id);
     unassign_capability('moodle/cohort:manage', $authrole->id);
     unassign_capability('moodle/competency:coursecompetencyconfigure', $authrole->id);
     // Creating specific roles.
     $this->creatorrole = create_role('Creator role', 'lpcreatorrole', 'learning plan creator role description');
     $this->userrole = create_role('User role', 'lpuserrole', 'learning plan user role description');
     assign_capability('moodle/competency:competencymanage', CAP_ALLOW, $this->creatorrole, $syscontext->id);
     assign_capability('moodle/competency:competencycompetencyconfigure', CAP_ALLOW, $this->creatorrole, $syscontext->id);
     assign_capability('moodle/competency:planmanage', CAP_ALLOW, $this->creatorrole, $syscontext->id);
     assign_capability('moodle/competency:planmanagedraft', CAP_ALLOW, $this->creatorrole, $syscontext->id);
     assign_capability('moodle/competency:planmanageown', CAP_ALLOW, $this->creatorrole, $syscontext->id);
     assign_capability('moodle/competency:planview', CAP_ALLOW, $this->creatorrole, $syscontext->id);
     assign_capability('moodle/competency:planviewdraft', CAP_ALLOW, $this->creatorrole, $syscontext->id);
     assign_capability('moodle/competency:templatemanage', CAP_ALLOW, $this->creatorrole, $syscontext->id);
     assign_capability('moodle/competency:competencygrade', CAP_ALLOW, $this->creatorrole, $syscontext->id);
     assign_capability('moodle/cohort:manage', CAP_ALLOW, $this->creatorrole, $syscontext->id);
     assign_capability('moodle/competency:competencyview', CAP_ALLOW, $this->userrole, $syscontext->id);
     assign_capability('moodle/competency:templateview', CAP_ALLOW, $this->userrole, $syscontext->id);
     assign_capability('moodle/competency:planviewown', CAP_ALLOW, $this->userrole, $syscontext->id);
     assign_capability('moodle/competency:planviewowndraft', CAP_ALLOW, $this->userrole, $syscontext->id);
     role_assign($this->creatorrole, $creator->id, $syscontext->id);
     role_assign($this->creatorrole, $catcreator->id, $catcontext->id);
     role_assign($this->userrole, $user->id, $syscontext->id);
     role_assign($this->userrole, $catuser->id, $catcontext->id);
     $this->creator = $creator;
     $this->catcreator = $catcreator;
     $this->user = $user;
     $this->catuser = $catuser;
     $this->category = $category;
     $this->othercategory = $othercategory;
     accesslib_clear_all_caches_for_unit_testing();
 }
Exemple #14
0
 /**
  * Test get_item_ratings
  */
 public function test_get_item_ratings()
 {
     global $DB, $USER;
     $this->resetAfterTest(true);
     $course = self::getDataGenerator()->create_course();
     $student = $this->getDataGenerator()->create_user();
     $teacher1 = $this->getDataGenerator()->create_user();
     $teacher2 = $this->getDataGenerator()->create_user();
     $teacher3 = $this->getDataGenerator()->create_user();
     $studentrole = $DB->get_record('role', array('shortname' => 'student'));
     $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
     unassign_capability('moodle/site:accessallgroups', $teacherrole->id);
     $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id);
     $this->getDataGenerator()->enrol_user($teacher1->id, $course->id, $teacherrole->id);
     $this->getDataGenerator()->enrol_user($teacher2->id, $course->id, $teacherrole->id);
     $this->getDataGenerator()->enrol_user($teacher3->id, $course->id, $teacherrole->id);
     // Create the forum.
     $record = new stdClass();
     $record->introformat = FORMAT_HTML;
     $record->course = $course->id;
     // Set Aggregate type = Average of ratings.
     $record->assessed = RATING_AGGREGATE_AVERAGE;
     $forum = self::getDataGenerator()->create_module('forum', $record);
     $contextid = context_module::instance($forum->cmid)->id;
     // Add discussion to the forums.
     $record = new stdClass();
     $record->course = $course->id;
     $record->userid = $student->id;
     $record->forum = $forum->id;
     $discussion = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
     // Retrieve the first post.
     $post = $DB->get_record('forum_posts', array('discussion' => $discussion->id));
     // Rete the discussion as teacher1.
     $rating1 = new stdClass();
     $rating1->contextid = $contextid;
     $rating1->component = 'mod_forum';
     $rating1->ratingarea = 'post';
     $rating1->itemid = $post->id;
     $rating1->rating = 90;
     $rating1->scaleid = 100;
     $rating1->userid = $teacher1->id;
     $rating1->timecreated = time();
     $rating1->timemodified = time();
     $rating1->id = $DB->insert_record('rating', $rating1);
     // Rete the discussion as teacher2.
     $rating2 = new stdClass();
     $rating2->contextid = $contextid;
     $rating2->component = 'mod_forum';
     $rating2->ratingarea = 'post';
     $rating2->itemid = $post->id;
     $rating2->rating = 95;
     $rating2->scaleid = 100;
     $rating2->userid = $teacher2->id;
     $rating2->timecreated = time() + 1;
     $rating2->timemodified = time() + 1;
     $rating2->id = $DB->insert_record('rating', $rating2);
     // Delete teacher2, we must still receive the ratings.
     delete_user($teacher2);
     // Teachers can see all the ratings.
     $this->setUser($teacher1);
     $ratings = core_rating_external::get_item_ratings('module', $forum->cmid, 'mod_forum', 'post', $post->id, 100, '');
     // We need to execute the return values cleaning process to simulate the web service server.
     $ratings = external_api::clean_returnvalue(core_rating_external::get_item_ratings_returns(), $ratings);
     $this->assertCount(2, $ratings['ratings']);
     $indexedratings = array();
     foreach ($ratings['ratings'] as $rating) {
         $indexedratings[$rating['id']] = $rating;
     }
     $this->assertEquals($rating1->rating . ' / ' . $rating1->scaleid, $indexedratings[$rating1->id]['rating']);
     $this->assertEquals($rating2->rating . ' / ' . $rating2->scaleid, $indexedratings[$rating2->id]['rating']);
     $this->assertEquals($rating1->userid, $indexedratings[$rating1->id]['userid']);
     $this->assertEquals($rating2->userid, $indexedratings[$rating2->id]['userid']);
     // Student can see ratings.
     $this->setUser($student);
     $ratings = core_rating_external::get_item_ratings('module', $forum->cmid, 'mod_forum', 'post', $post->id, 100, '');
     // We need to execute the return values cleaning process to simulate the web service server.
     $ratings = external_api::clean_returnvalue(core_rating_external::get_item_ratings_returns(), $ratings);
     $this->assertCount(2, $ratings['ratings']);
     // Invalid item.
     try {
         $ratings = core_rating_external::get_item_ratings('module', $forum->cmid, 'mod_forum', 'post', 0, 100, '');
         $this->fail('Exception expected due invalid itemid.');
     } catch (moodle_exception $e) {
         $this->assertEquals('invalidrecord', $e->errorcode);
     }
     // Invalid area.
     try {
         $ratings = core_rating_external::get_item_ratings('module', $forum->cmid, 'mod_forum', 'xyz', $post->id, 100, '');
         $this->fail('Exception expected due invalid rating area.');
     } catch (moodle_exception $e) {
         $this->assertEquals('invalidratingarea', $e->errorcode);
     }
     // Invalid context. invalid_parameter_exception.
     try {
         $ratings = core_rating_external::get_item_ratings('module', 0, 'mod_forum', 'post', $post->id, 100, '');
         $this->fail('Exception expected due invalid context.');
     } catch (invalid_parameter_exception $e) {
         $this->assertEquals('invalidparameter', $e->errorcode);
     }
     // Test for groupmode.
     set_coursemodule_groupmode($forum->cmid, SEPARATEGROUPS);
     $group = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
     groups_add_member($group, $teacher1);
     $discussion->groupid = $group->id;
     $DB->update_record('forum_discussions', $discussion);
     // Error for teacher3 and 2 ratings for teacher1 should be returned.
     $this->setUser($teacher1);
     $ratings = core_rating_external::get_item_ratings('module', $forum->cmid, 'mod_forum', 'post', $post->id, 100, '');
     // We need to execute the return values cleaning process to simulate the web service server.
     $ratings = external_api::clean_returnvalue(core_rating_external::get_item_ratings_returns(), $ratings);
     $this->assertCount(2, $ratings['ratings']);
     $this->setUser($teacher3);
     try {
         $ratings = core_rating_external::get_item_ratings('module', $forum->cmid, 'mod_forum', 'post', $post->id, 100, '');
         $this->fail('Exception expected due invalid group permissions.');
     } catch (moodle_exception $e) {
         $this->assertEquals('noviewrate', $e->errorcode);
     }
 }
 /**
  * Revokes the capability assignment.
  */
 public function revoke()
 {
     foreach ($this->capability as $capability) {
         unassign_capability($capability, $this->roleid, $this->contextid);
     }
     accesslib_clear_all_caches_for_unit_testing();
 }
/**
 * Deletes cached capabilities that are no longer needed by the component.
 * Also unassigns these capabilities from any roles that have them.
 * @param $component - examples: 'moodle', 'mod/forum', 'block/quiz_results'
 * @param $newcapdef - array of the new capability definitions that will be
 *                     compared with the cached capabilities
 * @return int - number of deprecated capabilities that have been removed
 */
function capabilities_cleanup($component, $newcapdef = NULL)
{
    $removedcount = 0;
    if ($cachedcaps = get_cached_capabilities($component)) {
        foreach ($cachedcaps as $cachedcap) {
            if (empty($newcapdef) || array_key_exists($cachedcap->name, $newcapdef) === false) {
                // Remove from capabilities cache.
                if (!delete_records('capabilities', 'name', $cachedcap->name)) {
                    error('Could not delete deprecated capability ' . $cachedcap->name);
                } else {
                    $removedcount++;
                }
                // Delete from roles.
                if ($roles = get_roles_with_capability($cachedcap->name)) {
                    foreach ($roles as $role) {
                        if (!unassign_capability($cachedcap->name, $role->id)) {
                            error('Could not unassign deprecated capability ' . $cachedcap->name . ' from role ' . $role->name);
                        }
                    }
                }
            }
            // End if.
        }
    }
    return $removedcount;
}
Exemple #17
0
 public function test_reorder_template_competencies_permissions()
 {
     $this->resetAfterTest(true);
     $dg = $this->getDataGenerator();
     $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
     $cat = $dg->create_category();
     $catcontext = context_coursecat::instance($cat->id);
     $syscontext = context_system::instance();
     $user = $dg->create_user();
     $role = $dg->create_role();
     assign_capability('moodle/competency:templatemanage', CAP_ALLOW, $role, $syscontext->id, true);
     $dg->role_assign($role, $user->id, $syscontext->id);
     // Create a template.
     $template = $lpg->create_template(array('contextid' => $catcontext->id));
     // Create a competency framework.
     $framework = $lpg->create_framework(array('contextid' => $catcontext->id));
     // Create competencies.
     $competency1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
     $competency2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
     // Add the competencies.
     $lpg->create_template_competency(array('templateid' => $template->get_id(), 'competencyid' => $competency1->get_id()));
     $lpg->create_template_competency(array('templateid' => $template->get_id(), 'competencyid' => $competency2->get_id()));
     $this->setUser($user);
     // Can reorder competencies with system context permissions in category context.
     $result = api::reorder_template_competency($template->get_id(), $competency2->get_id(), $competency1->get_id());
     $this->assertTrue($result);
     unassign_capability('moodle/competency:templatemanage', $role, $syscontext->id);
     accesslib_clear_all_caches_for_unit_testing();
     try {
         api::reorder_template_competency($template->get_id(), $competency2->get_id(), $competency1->get_id());
         $this->fail('Exception expected due to not permissions to manage template competencies');
     } catch (required_capability_exception $e) {
         $this->assertEquals('nopermissions', $e->errorcode);
     }
     // Giving permissions in category context.
     assign_capability('moodle/competency:templatemanage', CAP_ALLOW, $role, $catcontext->id, true);
     $dg->role_assign($role, $user->id, $catcontext->id);
     // User with templatemanage capability in category context can reorder competencies in temple.
     $result = api::reorder_template_competency($template->get_id(), $competency1->get_id(), $competency2->get_id());
     $this->assertTrue($result);
     // Removing templatemanage capability in category context.
     unassign_capability('moodle/competency:templatemanage', $role, $catcontext->id);
     accesslib_clear_all_caches_for_unit_testing();
     try {
         api::reorder_template_competency($template->get_id(), $competency2->get_id(), $competency1->get_id());
         $this->fail('Exception expected due to not permissions to manage template competencies');
     } catch (required_capability_exception $e) {
         $this->assertEquals('nopermissions', $e->errorcode);
     }
 }
Exemple #18
0
/**
* When called resets all custom roles as per definition set down in /local/roles.php
*
* Note that this uses the non-core role.custom field to isolate roles to remove.
*
* Utilise the $path parameter to allow for localisation (i.e. different roles defintion than core).
*
* Sort order is reset based on the order listed in the defintion.
*
* WARNING: as long as you retain the same shortname existing user role assigments will
*             be retained.  if you change the shortname they will be lost.
*
* KNOWN ISSUE: we rely on shortname being unique, but this is not enforced by the db.
*                       this is more a problem with moodle.
*
* @param text $path
*
*/
function tao_reset_custom_roles($path = 'local')
{
    global $CFG;
    if (!get_site()) {
        // not finished installing, skip
        return true;
    }
    // get latest role definition from roles file
    $rolespath = $CFG->dirroot . '/' . $path . '/roles.php';
    if (!file_exists($rolespath)) {
        debugging("Local caps reassignment called with invalid path {$path}");
        return false;
    }
    require_once $rolespath;
    if (!isset($customroles)) {
        return true;
        // nothing to do.
    }
    $undeletableroles = array();
    $undeletableroles[$CFG->notloggedinroleid] = 1;
    $undeletableroles[$CFG->guestroleid] = 1;
    $undeletableroles[$CFG->defaultuserroleid] = 1;
    $undeletableroles[$CFG->defaultcourseroleid] = 1;
    // If there is only one admin role, add that to $undeletableroles too.
    $adminroles = get_admin_roles();
    if (count($adminroles) == 1) {
        $undeletableroles[reset($adminroles)->id] = 1;
    }
    // get recordset of existing custom roles
    $sql = "SELECT id, name, shortname, description, sortorder, custom\n              FROM {$CFG->prefix}role\n              WHERE custom IS NOT NULL";
    $roles = get_records_sql($sql);
    // remove custom roles that are not in the latest definition
    foreach ($roles as $role) {
        // check whether this role is in the latest definition
        if (array_key_exists($role->shortname, $customroles)) {
            continue;
        }
        // extra safety: check undeletable roles
        if (isset($undeletableroles[$role->id])) {
            continue;
        }
        delete_role($role->id);
    }
    // hack to avoid sortorder unique constraint
    execute_sql("UPDATE {$CFG->prefix}role SET sortorder = (sortorder+1000) WHERE custom IS NOT NULL");
    // set sortorder to current highest value
    $sortorder = get_field_sql("SELECT " . sql_max('sortorder') . " FROM {$CFG->prefix}role WHERE custom IS NULL");
    // now loop through the new settings
    foreach ($customroles as $shortname => $role) {
        $sortorder++;
        // get the roleid
        $roleid = get_field('role', 'id', 'shortname', $shortname);
        // if exists then make updates
        if (!empty($roleid)) {
            // only update fields that have been set
            if (isset($role['name'])) {
                set_field('role', 'name', $role['name'], 'shortname', $shortname);
            }
            if (isset($role['description'])) {
                set_field('role', 'description', $role['description'], 'shortname', $shortname);
            }
            // reset sortorder
            set_field('role', 'sortorder', $sortorder, 'shortname', $shortname);
            // else create record
        } else {
            $newrole = new stdclass();
            $newrole->name = $role['name'];
            $newrole->shortname = $shortname;
            $newrole->description = $role['description'];
            $newrole->sortorder = $sortorder;
            $newrole->custom = 1;
            $roleid = insert_record('role', $newrole);
        }
        // remove any previously set legacy roles
        $legacyroles = get_legacy_roles();
        foreach ($legacyroles as $ltype => $lcap) {
            unassign_capability($lcap, $roleid);
        }
        // reset legacy role
        if (isset($role['legacy'])) {
            $legacycap = $legacyroles[$role['legacy']];
            $context = get_context_instance(CONTEXT_SYSTEM);
            assign_capability($legacycap, CAP_ALLOW, $roleid, $context->id);
        }
        // update the context settings
        set_role_contextlevels($roleid, $role['context']);
        //  e.g. array(CONTEXT_SYSTEM, CONTEXT_COURSECAT)
        // set allow assigns
        if (is_array($role['canassign'])) {
            // delete existing
            delete_records('role_allow_assign', 'allowassign', $roleid);
            foreach ($role['canassign'] as $canassign) {
                $canassignid = get_field('role', 'id', 'shortname', $canassign);
                allow_assign($canassignid, $roleid);
            }
        }
    }
    // reset custom capabilities to keep up with changes
    return tao_reset_capabilities();
}
 public function test_get_notified_users()
 {
     global $CFG, $DB;
     $capability = 'mod/assign:receivegradernotifications';
     $coursecontext = context_course::instance($this->course->id);
     $role = $DB->get_record('role', array('shortname' => 'teacher'));
     $this->create_extra_users();
     $this->setUser($this->editingteachers[0]);
     // Create an assignment with no groups.
     $assign = $this->create_instance();
     $this->assertCount(self::DEFAULT_TEACHER_COUNT + self::DEFAULT_EDITING_TEACHER_COUNT + self::EXTRA_TEACHER_COUNT + self::EXTRA_EDITING_TEACHER_COUNT, $assign->testable_get_notifiable_users($this->students[0]->id));
     // Change nonediting teachers role to not receive grader notifications.
     assign_capability($capability, CAP_PROHIBIT, $role->id, $coursecontext);
     $this->assertCount(self::DEFAULT_EDITING_TEACHER_COUNT + self::EXTRA_EDITING_TEACHER_COUNT, $assign->testable_get_notifiable_users($this->students[0]->id));
     // Reset nonediting teachers role to default.
     unassign_capability($capability, $role->id, $coursecontext);
     // Force create an assignment with SEPARATEGROUPS.
     $data = new stdClass();
     $data->courseid = $this->course->id;
     $data->name = 'Grouping';
     $groupingid = groups_create_grouping($data);
     groups_assign_grouping($groupingid, $this->groups[0]->id);
     $assign = $this->create_instance(array('groupingid' => $groupingid, 'groupmode' => SEPARATEGROUPS));
     $this->setUser($this->students[1]);
     $this->assertCount(4, $assign->testable_get_notifiable_users($this->students[0]->id));
     // Note the second student is in a group that is not in the grouping.
     // This means that we get all graders that are not in a group in the grouping.
     $this->assertCount(10, $assign->testable_get_notifiable_users($this->students[1]->id));
     // Change nonediting teachers role to not receive grader notifications.
     assign_capability($capability, CAP_PROHIBIT, $role->id, $coursecontext);
     $this->assertCount(2, $assign->testable_get_notifiable_users($this->students[0]->id));
     // Note the second student is in a group that is not in the grouping.
     // This means that we get all graders that are not in a group in the grouping.
     $this->assertCount(5, $assign->testable_get_notifiable_users($this->students[1]->id));
 }
Exemple #20
0
 /**
  * Tests the user can't post a message without proper capability.
  */
 public function test_can_post_message_without_cap()
 {
     global $DB;
     // Create some users.
     $user1 = self::getDataGenerator()->create_user();
     $user2 = self::getDataGenerator()->create_user();
     // Set as the user 1.
     $this->setUser($user1);
     // Remove the capability to send a message.
     $roleids = $DB->get_records_menu('role', null, '', 'shortname, id');
     unassign_capability('moodle/site:sendmessage', $roleids['user'], context_system::instance());
     // Check that we can not post a message without the capability.
     $this->assertFalse(\core_message\api::can_post_message($user2));
 }
Exemple #21
0
 /**
  * Tests for mod_forum_rating_can_see_item_ratings().
  *
  * @throws coding_exception
  * @throws rating_exception
  */
 public function test_mod_forum_rating_can_see_item_ratings()
 {
     global $DB;
     $this->resetAfterTest();
     // Setup test data.
     $course = new stdClass();
     $course->groupmode = SEPARATEGROUPS;
     $course->groupmodeforce = true;
     $course = $this->getDataGenerator()->create_course($course);
     $forum = $this->getDataGenerator()->create_module('forum', array('course' => $course->id));
     $generator = self::getDataGenerator()->get_plugin_generator('mod_forum');
     $cm = get_coursemodule_from_instance('forum', $forum->id);
     $context = context_module::instance($cm->id);
     // Create users.
     $user1 = $this->getDataGenerator()->create_user();
     $user2 = $this->getDataGenerator()->create_user();
     $user3 = $this->getDataGenerator()->create_user();
     $user4 = $this->getDataGenerator()->create_user();
     // Groups and stuff.
     $role = $DB->get_record('role', array('shortname' => 'teacher'), '*', MUST_EXIST);
     $this->getDataGenerator()->enrol_user($user1->id, $course->id, $role->id);
     $this->getDataGenerator()->enrol_user($user2->id, $course->id, $role->id);
     $this->getDataGenerator()->enrol_user($user3->id, $course->id, $role->id);
     $this->getDataGenerator()->enrol_user($user4->id, $course->id, $role->id);
     $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
     $group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
     groups_add_member($group1, $user1);
     groups_add_member($group1, $user2);
     groups_add_member($group2, $user3);
     groups_add_member($group2, $user4);
     $record = new stdClass();
     $record->course = $forum->course;
     $record->forum = $forum->id;
     $record->userid = $user1->id;
     $record->groupid = $group1->id;
     $discussion = $generator->create_discussion($record);
     // Retrieve the first post.
     $post = $DB->get_record('forum_posts', array('discussion' => $discussion->id));
     $ratingoptions = new stdClass();
     $ratingoptions->context = $context;
     $ratingoptions->ratingarea = 'post';
     $ratingoptions->component = 'mod_forum';
     $ratingoptions->itemid = $post->id;
     $ratingoptions->scaleid = 2;
     $ratingoptions->userid = $user2->id;
     $rating = new rating($ratingoptions);
     $rating->update_rating(2);
     // Now try to access it as various users.
     unassign_capability('moodle/site:accessallgroups', $role->id);
     $params = array('contextid' => 2, 'component' => 'mod_forum', 'ratingarea' => 'post', 'itemid' => $post->id, 'scaleid' => 2);
     $this->setUser($user1);
     $this->assertTrue(mod_forum_rating_can_see_item_ratings($params));
     $this->setUser($user2);
     $this->assertTrue(mod_forum_rating_can_see_item_ratings($params));
     $this->setUser($user3);
     $this->assertFalse(mod_forum_rating_can_see_item_ratings($params));
     $this->setUser($user4);
     $this->assertFalse(mod_forum_rating_can_see_item_ratings($params));
     // Now try with accessallgroups cap and make sure everything is visible.
     assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $role->id, $context->id);
     $this->setUser($user1);
     $this->assertTrue(mod_forum_rating_can_see_item_ratings($params));
     $this->setUser($user2);
     $this->assertTrue(mod_forum_rating_can_see_item_ratings($params));
     $this->setUser($user3);
     $this->assertTrue(mod_forum_rating_can_see_item_ratings($params));
     $this->setUser($user4);
     $this->assertTrue(mod_forum_rating_can_see_item_ratings($params));
     // Change group mode and verify visibility.
     $course->groupmode = VISIBLEGROUPS;
     $DB->update_record('course', $course);
     unassign_capability('moodle/site:accessallgroups', $role->id);
     $this->setUser($user1);
     $this->assertTrue(mod_forum_rating_can_see_item_ratings($params));
     $this->setUser($user2);
     $this->assertTrue(mod_forum_rating_can_see_item_ratings($params));
     $this->setUser($user3);
     $this->assertTrue(mod_forum_rating_can_see_item_ratings($params));
     $this->setUser($user4);
     $this->assertTrue(mod_forum_rating_can_see_item_ratings($params));
 }
 /**
  * A small functional test of accesslib functions and classes.
  */
 public function test_everything_in_accesslib()
 {
     global $USER, $SITE, $CFG, $DB, $ACCESSLIB_PRIVATE;
     // First of all finalize the session, we must not carry over any of this mess to the next page via SESSION!!!
     session_get_instance()->write_close();
     // hack - this is going to take very long time
     set_time_limit(3600);
     // Get rid of current user that would not work anyway,
     // do NOT even think about using $this->switch_global_user_id()!
     if (!isset($this->accesslibprevuser)) {
         $this->accesslibprevuser = clone $USER;
         $USER = new stdClass();
         $USER->id = 0;
     }
     // Backup $SITE global
     if (!isset($this->accesslibprevsite)) {
         $this->accesslibprevsite = $SITE;
     }
     // Switch DB, if it somehow fails or you specified wrong unittest prefix it will nuke real data, you have been warned!
     $this->switch_to_test_db();
     // Let's switch the CFG
     $prevcfg = clone $CFG;
     $this->switch_to_test_cfg();
     $CFG->config_php_settings = $prevcfg->config_php_settings;
     $CFG->noemailever = true;
     $CFG->admin = $prevcfg->admin;
     $CFG->lang = 'en';
     $CFG->tempdir = $prevcfg->tempdir;
     $CFG->cachedir = $prevcfg->cachedir;
     $CFG->directorypermissions = $prevcfg->directorypermissions;
     $CFG->filepermissions = $prevcfg->filepermissions;
     // Reset all caches
     accesslib_clear_all_caches_for_unit_testing();
     // Add some core tables - this is known to break constantly because we keep adding dependencies...
     $tablenames = array('config', 'config_plugins', 'modules', 'course', 'course_modules', 'course_sections', 'course_categories', 'mnet_host', 'mnet_application', 'capabilities', 'context', 'context_temp', 'role', 'role_capabilities', 'role_allow_switch', 'license', 'my_pages', 'block', 'block_instances', 'block_positions', 'role_allow_assign', 'role_allow_override', 'role_assignments', 'role_context_levels', 'enrol', 'user_enrolments', 'filter_active', 'filter_config', 'comments', 'user', 'groups_members', 'cache_flags', 'events_handlers', 'user_lastaccess', 'rating', 'files', 'role_names', 'user_preferences');
     $this->create_test_tables($tablenames, 'lib');
     // Create all core default records and default settings
     require_once "{$CFG->libdir}/db/install.php";
     xmldb_main_install();
     // installs the capabilities too
     // Fake mod_page install
     $tablenames = array('page');
     $this->create_test_tables($tablenames, 'mod/page');
     $module = new stdClass();
     require $CFG->dirroot . '/mod/page/version.php';
     $module->name = 'page';
     $pagemoduleid = $DB->insert_record('modules', $module);
     update_capabilities('mod_page');
     // Fake block_online_users install
     $plugin = new stdClass();
     $plugin->version = NULL;
     $plugin->cron = 0;
     include $CFG->dirroot . '/blocks/online_users/version.php';
     $plugin->name = 'online_users';
     $onlineusersblockid = $DB->insert_record('block', $plugin);
     update_capabilities('block_online_users');
     // Finish roles setup
     set_config('defaultfrontpageroleid', $DB->get_field('role', 'id', array('archetype' => 'frontpage')));
     set_config('defaultuserroleid', $DB->get_field('role', 'id', array('archetype' => 'user')));
     set_config('notloggedinroleid', $DB->get_field('role', 'id', array('archetype' => 'guest')));
     set_config('rolesactive', 1);
     // Init manual enrol
     set_config('status', ENROL_INSTANCE_ENABLED, 'enrol_manual');
     set_config('defaultperiod', 0, 'enrol_manual');
     $manualenrol = enrol_get_plugin('manual');
     // 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 = new stdClass();
     $bi->blockname = 'online_users';
     $bi->parentcontextid = $systemcontext->id;
     $bi->showinsubcontexts = 1;
     $bi->pagetypepattern = '';
     $bi->subpagepattern = '';
     $bi->defaultregion = '';
     $bi->defaultweight = 0;
     $bi->configdata = '';
     $biid = $DB->insert_record('block_instances', $bi);
     context_block::instance($biid);
     $testblocks[] = $biid;
     // Some users
     $testusers = array();
     for ($i = 0; $i < 20; $i++) {
         $user = new stdClass();
         $user->auth = 'manual';
         $user->firstname = 'user' . $i;
         $user->lastname = 'user' . $i;
         $user->username = '******' . $i;
         $user->password = '******';
         $user->email = "user{$i}@example.com";
         $user->confirmed = 1;
         $user->mnethostid = $CFG->mnet_localhost_id;
         $user->lang = $CFG->lang;
         $user->maildisplay = 1;
         $user->timemodified = time();
         $user->deleted = 0;
         $user->lastip = '0.0.0.0';
         $userid = $DB->insert_record('user', $user);
         $testusers[$i] = $userid;
         $usercontext = context_user::instance($userid);
         // Add block to user profile
         $bi->parentcontextid = $usercontext->id;
         $biid = $DB->insert_record('block_instances', $bi);
         context_block::instance($biid);
         $testblocks[] = $biid;
     }
     // Deleted user - should be ignored everywhere, can not have context
     $user = new stdClass();
     $user->auth = 'manual';
     $user->firstname = '';
     $user->lastname = '';
     $user->username = '******';
     $user->password = '';
     $user->email = '';
     $user->confirmed = 1;
     $user->mnethostid = $CFG->mnet_localhost_id;
     $user->lang = $CFG->lang;
     $user->maildisplay = 1;
     $user->timemodified = time();
     $user->deleted = 1;
     $user->lastip = '0.0.0.0';
     $DB->insert_record('user', $user);
     unset($user);
     // Add block to frontpage
     $bi->parentcontextid = $frontpagecontext->id;
     $biid = $DB->insert_record('block_instances', $bi);
     $frontpageblockcontext = context_block::instance($biid);
     $testblocks[] = $biid;
     // Add a resource to frontpage
     $page = new stdClass();
     $page->course = $SITE->id;
     $page->intro = '...';
     $page->introformat = FORMAT_HTML;
     $page->content = '...';
     $page->contentformat = FORMAT_HTML;
     $pageid = $DB->insert_record('page', $page);
     $testpages[] = $pageid;
     $cm = new stdClass();
     $cm->course = $SITE->id;
     $cm->module = $pagemoduleid;
     $cm->section = 1;
     $cm->instance = $pageid;
     $cmid = $DB->insert_record('course_modules', $cm);
     $frontpagepagecontext = context_module::instance($cmid);
     // Add block to frontpage resource
     $bi->parentcontextid = $frontpagepagecontext->id;
     $biid = $DB->insert_record('block_instances', $bi);
     $frontpagepageblockcontext = context_block::instance($biid);
     $testblocks[] = $biid;
     // Some nested course categories with courses
     require_once "{$CFG->dirroot}/course/lib.php";
     $path = '';
     $parentcat = 0;
     for ($i = 0; $i < 5; $i++) {
         $cat = new stdClass();
         $cat->name = 'category' . $i;
         $cat->parent = $parentcat;
         $cat->depth = $i + 1;
         $cat->sortorder = MAX_COURSES_IN_CATEGORY * ($i + 2);
         $cat->timemodified = time();
         $catid = $DB->insert_record('course_categories', $cat);
         $path = $path . '/' . $catid;
         $DB->set_field('course_categories', 'path', $path, array('id' => $catid));
         $parentcat = $catid;
         $testcategories[] = $catid;
         $catcontext = context_coursecat::instance($catid);
         if ($i >= 4) {
             continue;
         }
         // Add resource to each category
         $bi->parentcontextid = $catcontext->id;
         $biid = $DB->insert_record('block_instances', $bi);
         context_block::instance($biid);
         // Add a few courses to each category
         for ($j = 0; $j < 6; $j++) {
             $course = new stdClass();
             $course->fullname = 'course' . $j;
             $course->shortname = 'c' . $j;
             $course->summary = 'bah bah bah';
             $course->newsitems = 0;
             $course->numsections = 1;
             $course->category = $catid;
             $course->format = 'topics';
             $course->timecreated = time();
             $course->visible = 1;
             $course->timemodified = $course->timecreated;
             $courseid = $DB->insert_record('course', $course);
             $section = new stdClass();
             $section->course = $courseid;
             $section->section = 0;
             $section->summaryformat = FORMAT_HTML;
             $DB->insert_record('course_sections', $section);
             $section->section = 1;
             $DB->insert_record('course_sections', $section);
             $testcourses[] = $courseid;
             $coursecontext = context_course::instance($courseid);
             if ($j >= 5) {
                 continue;
             }
             // Add manual enrol instance
             $manualenrol->add_default_instance($DB->get_record('course', array('id' => $courseid)));
             // Add block to each course
             $bi->parentcontextid = $coursecontext->id;
             $biid = $DB->insert_record('block_instances', $bi);
             context_block::instance($biid);
             $testblocks[] = $biid;
             // Add a resource to each course
             $page->course = $courseid;
             $pageid = $DB->insert_record('page', $page);
             $testpages[] = $pageid;
             $cm->course = $courseid;
             $cm->instance = $pageid;
             $cm->id = $DB->insert_record('course_modules', $cm);
             $modcontext = context_module::instance($cm->id);
             // Add block to each module
             $bi->parentcontextid = $modcontext->id;
             $biid = $DB->insert_record('block_instances', $bi);
             context_block::instance($biid);
             $testblocks[] = $biid;
         }
     }
     // 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->assertEqual($DB->count_records('context'), $count);
     $this->assertEqual($DB->count_records('context', array('depth' => 0)), 0);
     $this->assertEqual($DB->count_records('context', array('path' => NULL)), 0);
     // ====== context_helper::get_level_name() ================================
     $levels = context_helper::get_all_levels();
     foreach ($levels as $level => $classname) {
         $name = context_helper::get_level_name($level);
         $this->assertFalse(empty($name));
     }
     // ======= context::instance_by_id(), context_xxx::instance();
     $context = context::instance_by_id($frontpagecontext->id);
     $this->assertidentical($context->contextlevel, CONTEXT_COURSE);
     $this->assertFalse(context::instance_by_id(-1, IGNORE_MISSING));
     try {
         context::instance_by_id(-1);
         $this->fail('exception expected');
     } catch (Exception $e) {
         $this->assertTrue(true);
     }
     $this->assertTrue(context_system::instance() instanceof context_system);
     $this->assertTrue(context_coursecat::instance($testcategories[0]) instanceof context_coursecat);
     $this->assertTrue(context_course::instance($testcourses[0]) instanceof context_course);
     $this->assertTrue(context_module::instance($testpages[0]) instanceof context_module);
     $this->assertTrue(context_block::instance($testblocks[0]) instanceof context_block);
     $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 (Exception $e) {
         $this->assertTrue(true);
     }
     try {
         context_course::instance(-1);
         $this->fail('exception expected');
     } catch (Exception $e) {
         $this->assertTrue(true);
     }
     try {
         context_module::instance(-1);
         $this->fail('exception expected');
     } catch (Exception $e) {
         $this->assertTrue(true);
     }
     try {
         context_block::instance(-1);
         $this->fail('exception expected');
     } catch (Exception $e) {
         $this->assertTrue(true);
     }
     // ======= $context->get_url(), $context->get_context_name(), $context->get_capabilities() =========
     $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->assertFalse(empty($name));
         $this->assertTrue($context->get_url() instanceof moodle_url);
         $caps = $context->get_capabilities();
         $this->assertTrue(is_array($caps));
         foreach ($caps as $cap) {
             $cap = (array) $cap;
             $this->assertIdentical(array_keys($cap), array('id', 'name', 'captype', 'contextlevel', 'component', 'riskbitmask'));
         }
     }
     unset($testcontexts);
     // ===== $context->get_course_context() =========================================
     $this->assertFalse($systemcontext->get_course_context(false));
     try {
         $systemcontext->get_course_context();
         $this->fail('exception expected');
     } catch (Exception $e) {
         $this->assertTrue(true);
     }
     $context = context_coursecat::instance($testcategories[0]);
     $this->assertFalse($context->get_course_context(false));
     try {
         $context->get_course_context();
         $this->fail('exception expected');
     } catch (Exception $e) {
         $this->assertTrue(true);
     }
     $this->assertIdentical($frontpagecontext->get_course_context(true), $frontpagecontext);
     $this->assertIdentical($frontpagepagecontext->get_course_context(true), $frontpagecontext);
     $this->assertIdentical($frontpagepageblockcontext->get_course_context(true), $frontpagecontext);
     // ======= $context->get_parent_context(), $context->get_parent_contexts(), $context->get_parent_context_ids() =======
     $userid = reset($testusers);
     $usercontext = context_user::instance($userid);
     $this->assertIdentical($usercontext->get_parent_context(), $systemcontext);
     $this->assertIdentical($usercontext->get_parent_contexts(), array($systemcontext->id => $systemcontext));
     $this->assertIdentical($usercontext->get_parent_contexts(true), array($usercontext->id => $usercontext, $systemcontext->id => $systemcontext));
     $this->assertIdentical($systemcontext->get_parent_contexts(), array());
     $this->assertIdentical($systemcontext->get_parent_contexts(true), array($systemcontext->id => $systemcontext));
     $this->assertIdentical($systemcontext->get_parent_context_ids(), array());
     $this->assertIdentical($systemcontext->get_parent_context_ids(true), array($systemcontext->id));
     $this->assertIdentical($frontpagecontext->get_parent_context(), $systemcontext);
     $this->assertIdentical($frontpagecontext->get_parent_contexts(), array($systemcontext->id => $systemcontext));
     $this->assertIdentical($frontpagecontext->get_parent_contexts(true), array($frontpagecontext->id => $frontpagecontext, $systemcontext->id => $systemcontext));
     $this->assertIdentical($frontpagecontext->get_parent_context_ids(), array($systemcontext->id));
     $this->assertEqual($frontpagecontext->get_parent_context_ids(true), array($frontpagecontext->id, $systemcontext->id));
     $this->assertIdentical($systemcontext->get_parent_context(), false);
     $frontpagecontext = context_course::instance($SITE->id);
     $parent = $systemcontext;
     foreach ($testcategories as $catid) {
         $catcontext = context_coursecat::instance($catid);
         $this->assertIdentical($catcontext->get_parent_context(), $parent);
         $parent = $catcontext;
     }
     $this->assertIdentical($frontpagepagecontext->get_parent_context(), $frontpagecontext);
     $this->assertIdentical($frontpageblockcontext->get_parent_context(), $frontpagecontext);
     $this->assertIdentical($frontpagepageblockcontext->get_parent_context(), $frontpagepagecontext);
     // ====== $context->get_child_contexts() ================================
     $children = $systemcontext->get_child_contexts();
     $this->assertEqual(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->assertEqual(count($children), 8);
     $this->assertEqual($countcats, 1);
     $this->assertEqual($countcourses, 6);
     $this->assertEqual($countblocks, 1);
     $context = context_course::instance($testcourses[2]);
     $children = $context->get_child_contexts();
     $this->assertEqual(count($children), 3);
     $context = context_module::instance($testpages[3]);
     $children = $context->get_child_contexts();
     $this->assertEqual(count($children), 1);
     $context = context_block::instance($testblocks[1]);
     $children = $context->get_child_contexts();
     $this->assertEqual(count($children), 0);
     unset($children);
     unset($countcats);
     unset($countcourses);
     unset($countblocks);
     // ======= context_helper::reset_caches() ============================
     context_helper::reset_caches();
     $this->assertEqual(context_inspection::test_context_cache_size(), 0);
     context_course::instance($SITE->id);
     $this->assertEqual(context_inspection::test_context_cache_size(), 1);
     // ======= 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->assertIdentical(array_keys($firstrecord), array_values($columns));
     context_helper::reset_caches();
     foreach ($records as $record) {
         context_helper::preload_from_record($record);
         $this->assertIdentical($record, new stdClass());
     }
     $this->assertEqual(context_inspection::test_context_cache_size(), count($records));
     unset($records);
     unset($columns);
     context_helper::reset_caches();
     context_helper::preload_course($SITE->id);
     $this->assertEqual(context_inspection::test_context_cache_size(), 4);
     // ====== assign_capability(), unassign_capability() ====================
     $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->assertEqual($rc->permission, CAP_ALLOW);
     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->assertEqual($rc->permission, CAP_ALLOW);
     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->assertEqual($rc->permission, CAP_PREVENT);
     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(false);
     // must be done after assign_capability()
     // ======= role_assign(), role_unassign(), role_unassign_all() ==============
     $context = context_course::instance($testcourses[1]);
     $this->assertEqual($DB->count_records('role_assignments', array('contextid' => $context->id)), 0);
     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->assertEqual($DB->count_records('role_assignments', array('contextid' => $context->id)), 3);
     role_unassign($allroles['teacher'], $testusers[1], $context->id);
     $this->assertEqual($DB->count_records('role_assignments', array('contextid' => $context->id)), 2);
     role_unassign_all(array('contextid' => $context->id));
     $this->assertEqual($DB->count_records('role_assignments', array('contextid' => $context->id)), 0);
     unset($context);
     accesslib_clear_all_caches(false);
     // just in case
     // ====== has_capability(), get_users_by_capability(), role_switch(), reload_all_capabilities() and friends ========================
     $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(false);
     // 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->assertEqual(count($enrolled), 10);
     for ($i = 0; $i < 10; $i++) {
         $this->assertTrue(isset($enrolled[$testusers[$i]]));
     }
     $enrolled = get_enrolled_users($coursecontext, 'moodle/course:update');
     $this->assertEqual(count($enrolled), 1);
     $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->assertEqual($USER->access['rsw'][$coursecontext->path], $allroles['student']);
     $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->assertEqual($USER->access['rsw'][$coursecontext->path], $allroles['student']);
     $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->assertEqual($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']);
     // Random time!
     srand(666);
     foreach ($testusers as $userid) {
         // no guest or deleted
         // each user gets 0-20 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);
     for ($j = 0; $j < 10000; $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);
     unset($contexts);
     unset($users);
     unset($capabilities);
     accesslib_clear_all_caches(false);
     // 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();
     $contexts = $DB->get_records('context', array(), 'id');
     $users = $DB->get_records('user', array(), 'id', 'id');
     $capabilities = $DB->get_records('capabilities', array(), 'id');
     $users[0] = null;
     // not-logged-in user
     $users[-1] = null;
     // 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 ($users as $userid => $unused) {
                 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->assertIdentical($hascap, isset($allowed[$userid]), "Capability result mismatch user:{$userid}, context:{$context->id}, {$cap->name}, hascap: " . (int) $hascap . " ");
                     if (isset($enrolled[$userid])) {
                         $this->assertIdentical(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($users);
     unset($capabilities);
     // Now let's do all the remaining tests that break our carefully prepared fake site
     // ======= $context->mark_dirty() =======================================
     $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]));
     // ======= $context->reload_if_dirty(); =================================
     $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]));
     $pagecontext = context_module::instance($page->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']));
     // ======= context_helper::build_all_paths() ============================
     $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->assertIdentical($oldcontexts, $newcontexts);
     unset($oldcontexts);
     unset($newcontexts);
     // ======= $context->reset_paths() ======================================
     $context = context_course::instance($testcourses[2]);
     $children = $context->get_child_contexts();
     $context->reset_paths(false);
     $this->assertIdentical($DB->get_field('context', 'path', array('id' => $context->id)), NULL);
     $this->assertEqual($DB->get_field('context', 'depth', array('id' => $context->id)), 0);
     foreach ($children as $child) {
         $this->assertIdentical($DB->get_field('context', 'path', array('id' => $child->id)), NULL);
         $this->assertEqual($DB->get_field('context', 'depth', array('id' => $child->id)), 0);
     }
     $this->assertEqual(count($children) + 1, $DB->count_records('context', array('depth' => 0)));
     $this->assertEqual(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->assertEqual($DB->get_field('context', 'path', array('id' => $context->id)), $context->path);
     $this->assertEqual($DB->get_field('context', 'depth', array('id' => $context->id)), $context->depth);
     $this->assertEqual(0, $DB->count_records('context', array('depth' => 0)));
     $this->assertEqual(0, $DB->count_records('context', array('path' => NULL)));
     // ====== $context->update_moved(); ======================================
     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->assertIdentical($context->get_parent_context(), $categorycontext);
     $dirty = get_cache_flags('accesslib/dirtycontexts', time() - 2);
     $this->assertTrue(isset($dirty[$oldpath]));
     $this->assertTrue(isset($dirty[$context->path]));
     // ====== $context->delete_content() =====================================
     context_helper::reset_caches();
     $context = context_module::instance($testpages[3]);
     $this->assertTrue($DB->record_exists('context', array('id' => $context->id)));
     $this->assertEqual(1, $DB->count_records('block_instances', array('parentcontextid' => $context->id)));
     $context->delete_content();
     $this->assertTrue($DB->record_exists('context', array('id' => $context->id)));
     $this->assertEqual(0, $DB->count_records('block_instances', array('parentcontextid' => $context->id)));
     // ====== $context->delete() =============================
     context_helper::reset_caches();
     $context = context_module::instance($testpages[4]);
     $this->assertTrue($DB->record_exists('context', array('id' => $context->id)));
     $this->assertEqual(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->assertEqual(0, $DB->count_records('block_instances', array('parentcontextid' => $context->id)));
     context_module::instance($testpages[4]);
     // ====== context_helper::delete_instance() =============================
     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->assertEqual(context_inspection::test_context_cache_size(), 1);
     $this->assertFalse($coursecontext->instanceid == CONTEXT_COURSE);
     $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->assertEqual(context_inspection::test_context_cache_size(), 0);
     $this->assertFalse($DB->record_exists('context', array('contextlevel' => CONTEXT_COURSE, 'instanceid' => $lastcourse)));
     context_course::instance($lastcourse);
     // ======= context_helper::create_instances() ==========================
     $prevcount = $DB->count_records('context');
     $DB->delete_records('context', array('contextlevel' => CONTEXT_BLOCK));
     context_helper::create_instances(null, true);
     $this->assertIdentical($DB->count_records('context'), $prevcount);
     $this->assertEqual($DB->count_records('context', array('depth' => 0)), 0);
     $this->assertEqual($DB->count_records('context', array('path' => NULL)), 0);
     $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->assertIdentical($DB->count_records('context'), $prevcount);
     $this->assertEqual($DB->count_records('context', array('depth' => 0)), 0);
     $this->assertEqual($DB->count_records('context', array('path' => NULL)), 0);
     // ======= context_helper::cleanup_instances() ==========================
     $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->assertEqual($DB->count_records('context'), $count);
     // ======= context cache size restrictions ==============================
     $testusers = array();
     for ($i = 0; $i < CONTEXT_CACHE_MAX_SIZE + 100; $i++) {
         $user = new stdClass();
         $user->auth = 'manual';
         $user->firstname = 'xuser' . $i;
         $user->lastname = 'xuser' . $i;
         $user->username = '******' . $i;
         $user->password = '******';
         $user->email = "xuser{$i}@example.com";
         $user->confirmed = 1;
         $user->mnethostid = $CFG->mnet_localhost_id;
         $user->lang = $CFG->lang;
         $user->maildisplay = 1;
         $user->timemodified = time();
         $user->lastip = '0.0.0.0';
         $userid = $DB->insert_record('user', $user);
         $testusers[$i] = $userid;
     }
     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->assertEqual(context_inspection::test_context_cache_size(), CONTEXT_CACHE_MAX_SIZE);
         } else {
             if ($i == CONTEXT_CACHE_MAX_SIZE) {
                 // once the limit is reached roughly 1/3 of records should be removed from cache
                 $this->assertEqual(context_inspection::test_context_cache_size(), (int) (CONTEXT_CACHE_MAX_SIZE * (2 / 3) + 102));
             }
         }
     }
     // 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->assertEqual(context_inspection::test_context_cache_size(), $prevsize);
     }
     context_user::instance($testusers[102]);
     $this->assertEqual(context_inspection::test_context_cache_size(), $prevsize + 1);
     unset($testusers);
     // =================================================================
     // ======= basic test of legacy functions ==========================
     // =================================================================
     // note: watch out, the fake site might be pretty borked already
     $this->assertIdentical(get_system_context(), context_system::instance());
     foreach ($DB->get_records('context') as $contextid => $record) {
         $context = context::instance_by_id($contextid);
         $this->assertIdentical(get_context_instance_by_id($contextid), $context);
         $this->assertIdentical(get_context_instance($record->contextlevel, $record->instanceid), $context);
         $this->assertIdentical(get_parent_contexts($context), $context->get_parent_context_ids());
         if ($context->id == SYSCONTEXTID) {
             $this->assertIdentical(get_parent_contextid($context), false);
         } else {
             $this->assertIdentical(get_parent_contextid($context), $context->get_parent_context()->id);
         }
     }
     $children = get_child_contexts($systemcontext);
     $this->assertEqual(count($children), $DB->count_records('context') - 1);
     unset($children);
     $DB->delete_records('context', array('contextlevel' => CONTEXT_BLOCK));
     create_contexts();
     $this->assertFalse($DB->record_exists('context', array('contextlevel' => CONTEXT_BLOCK)));
     $DB->set_field('context', 'depth', 0, array('contextlevel' => CONTEXT_BLOCK));
     build_context_path();
     $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();
     $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->assertEqual($DB->count_records('context'), $count);
     context_helper::reset_caches();
     preload_course_contexts($SITE->id);
     $this->assertEqual(context_inspection::test_context_cache_size(), 1);
     context_helper::reset_caches();
     list($select, $join) = context_instance_preload_sql('c.id', CONTEXT_COURSECAT, 'ctx');
     $sql = "SELECT c.id {$select} FROM {course_categories} c {$join}";
     $records = $DB->get_records_sql($sql);
     foreach ($records as $record) {
         context_instance_preload($record);
         $record = (array) $record;
         $this->assertEqual(1, count($record));
         // only id left
     }
     $this->assertEqual(count($records), context_inspection::test_context_cache_size());
     accesslib_clear_all_caches(true);
     $DB->delete_records('cache_flags', array());
     mark_context_dirty($systemcontext->path);
     $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 = get_context_instance(CONTEXT_COURSE, $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);
     $context = get_context_instance(CONTEXT_COURSE, $course->id);
     $this->assertIdentical($context->get_parent_context(), $categorycontext);
     $this->assertTrue($DB->record_exists('context', array('contextlevel' => CONTEXT_COURSE, 'instanceid' => $testcourses[2])));
     delete_context(CONTEXT_COURSE, $testcourses[2]);
     $this->assertFalse($DB->record_exists('context', array('contextlevel' => CONTEXT_COURSE, 'instanceid' => $testcourses[2])));
     $name = get_contextlevel_name(CONTEXT_COURSE);
     $this->assertFalse(empty($name));
     $context = get_context_instance(CONTEXT_COURSE, $testcourses[2]);
     $name = print_context_name($context);
     $this->assertFalse(empty($name));
     $url = get_context_url($coursecontext);
     $this->assertFalse($url instanceof modole_url);
     $page = $DB->get_record('page', array('id' => $testpages[7]));
     $context = get_context_instance(CONTEXT_MODULE, $page->id);
     $coursecontext = get_course_context($context);
     $this->assertEqual($coursecontext->contextlevel, CONTEXT_COURSE);
     $this->assertEqual(get_courseid_from_context($context), $page->course);
     $caps = fetch_context_capabilities($systemcontext);
     $this->assertTrue(is_array($caps));
     unset($caps);
 }
 /**
  * Tests for mod_data_rating_can_see_item_ratings().
  *
  * @throws coding_exception
  * @throws rating_exception
  */
 public function test_mod_data_rating_can_see_item_ratings()
 {
     global $DB;
     $this->resetAfterTest();
     // Setup test data.
     $course = new stdClass();
     $course->groupmode = SEPARATEGROUPS;
     $course->groupmodeforce = true;
     $course = $this->getDataGenerator()->create_course($course);
     $data = $this->getDataGenerator()->create_module('data', array('course' => $course->id));
     $cm = get_coursemodule_from_instance('data', $data->id);
     $context = context_module::instance($cm->id);
     // Create users.
     $user1 = $this->getDataGenerator()->create_user();
     $user2 = $this->getDataGenerator()->create_user();
     $user3 = $this->getDataGenerator()->create_user();
     $user4 = $this->getDataGenerator()->create_user();
     // Groups and stuff.
     $role = $DB->get_record('role', array('shortname' => 'teacher'), '*', MUST_EXIST);
     $this->getDataGenerator()->enrol_user($user1->id, $course->id, $role->id);
     $this->getDataGenerator()->enrol_user($user2->id, $course->id, $role->id);
     $this->getDataGenerator()->enrol_user($user3->id, $course->id, $role->id);
     $this->getDataGenerator()->enrol_user($user4->id, $course->id, $role->id);
     $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
     $group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
     groups_add_member($group1, $user1);
     groups_add_member($group1, $user2);
     groups_add_member($group2, $user3);
     groups_add_member($group2, $user4);
     // Add data.
     $field = data_get_field_new('text', $data);
     $fielddetail = new stdClass();
     $fielddetail->name = 'Name';
     $fielddetail->description = 'Some name';
     $field->define_field($fielddetail);
     $field->insert_field();
     // Add a record with a group id of zero (all participants).
     $recordid1 = data_add_record($data, 0);
     $datacontent = array();
     $datacontent['fieldid'] = $field->field->id;
     $datacontent['recordid'] = $recordid1;
     $datacontent['content'] = 'Obelix';
     $DB->insert_record('data_content', $datacontent);
     $recordid = data_add_record($data, $group1->id);
     $datacontent = array();
     $datacontent['fieldid'] = $field->field->id;
     $datacontent['recordid'] = $recordid;
     $datacontent['content'] = 'Asterix';
     $DB->insert_record('data_content', $datacontent);
     // Now try to access it as various users.
     unassign_capability('moodle/site:accessallgroups', $role->id);
     // Eveyone should have access to the record with the group id of zero.
     $params1 = array('contextid' => 2, 'component' => 'mod_data', 'ratingarea' => 'entry', 'itemid' => $recordid1, 'scaleid' => 2);
     $params = array('contextid' => 2, 'component' => 'mod_data', 'ratingarea' => 'entry', 'itemid' => $recordid, 'scaleid' => 2);
     $this->setUser($user1);
     $this->assertTrue(mod_data_rating_can_see_item_ratings($params));
     $this->assertTrue(mod_data_rating_can_see_item_ratings($params1));
     $this->setUser($user2);
     $this->assertTrue(mod_data_rating_can_see_item_ratings($params));
     $this->assertTrue(mod_data_rating_can_see_item_ratings($params1));
     $this->setUser($user3);
     $this->assertFalse(mod_data_rating_can_see_item_ratings($params));
     $this->assertTrue(mod_data_rating_can_see_item_ratings($params1));
     $this->setUser($user4);
     $this->assertFalse(mod_data_rating_can_see_item_ratings($params));
     $this->assertTrue(mod_data_rating_can_see_item_ratings($params1));
     // Now try with accessallgroups cap and make sure everything is visible.
     assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $role->id, $context->id);
     $this->setUser($user1);
     $this->assertTrue(mod_data_rating_can_see_item_ratings($params));
     $this->assertTrue(mod_data_rating_can_see_item_ratings($params1));
     $this->setUser($user2);
     $this->assertTrue(mod_data_rating_can_see_item_ratings($params));
     $this->assertTrue(mod_data_rating_can_see_item_ratings($params1));
     $this->setUser($user3);
     $this->assertTrue(mod_data_rating_can_see_item_ratings($params));
     $this->assertTrue(mod_data_rating_can_see_item_ratings($params1));
     $this->setUser($user4);
     $this->assertTrue(mod_data_rating_can_see_item_ratings($params));
     $this->assertTrue(mod_data_rating_can_see_item_ratings($params1));
     // Change group mode and verify visibility.
     $course->groupmode = VISIBLEGROUPS;
     $DB->update_record('course', $course);
     unassign_capability('moodle/site:accessallgroups', $role->id);
     $this->setUser($user1);
     $this->assertTrue(mod_data_rating_can_see_item_ratings($params));
     $this->assertTrue(mod_data_rating_can_see_item_ratings($params1));
     $this->setUser($user2);
     $this->assertTrue(mod_data_rating_can_see_item_ratings($params));
     $this->assertTrue(mod_data_rating_can_see_item_ratings($params1));
     $this->setUser($user3);
     $this->assertTrue(mod_data_rating_can_see_item_ratings($params));
     $this->assertTrue(mod_data_rating_can_see_item_ratings($params1));
     $this->setUser($user4);
     $this->assertTrue(mod_data_rating_can_see_item_ratings($params));
     $this->assertTrue(mod_data_rating_can_see_item_ratings($params1));
 }
Exemple #24
0
 public function save_changes()
 {
     global $DB;
     if (!$this->roleid) {
         // Creating role
         if (isset($this->legacyroles[$this->role->legacytype])) {
             $legacycap = $this->legacyroles[$this->role->legacytype];
         } else {
             $legacycap = '';
         }
         $this->role->id = create_role($this->role->name, $this->role->shortname, $this->role->description, $legacycap);
         $this->roleid = $this->role->id;
         // Needed to make the parent::save_changes(); call work.
     } else {
         // Updating role
         $DB->update_record('role', $this->role);
         // Legacy type
         foreach ($this->legacyroles as $type => $cap) {
             if ($type == $this->role->legacytype) {
                 assign_capability($cap, CAP_ALLOW, $this->role->id, $this->context->id);
             } else {
                 unassign_capability($cap, $this->role->id);
             }
         }
     }
     // Assignable contexts.
     set_role_contextlevels($this->role->id, $this->contextlevels);
     // Permissions.
     parent::save_changes();
 }
Exemple #25
0
/**
 * More user friendly role permission changing,
 * it should produce as few overrides as possible.
 * @param int $roleid
 * @param object $context
 * @param string $capname capability name
 * @param int $permission
 * @return void
 */
function role_change_permission($roleid, $context, $capname, $permission)
{
    global $DB;
    if ($permission == CAP_INHERIT) {
        unassign_capability($capname, $roleid, $context->id);
        $context->mark_dirty();
        return;
    }
    $ctxids = trim($context->path, '/');
    // kill leading slash
    $ctxids = str_replace('/', ',', $ctxids);
    $params = array('roleid' => $roleid, 'cap' => $capname);
    $sql = "SELECT ctx.id, rc.permission, ctx.depth\n              FROM {role_capabilities} rc\n              JOIN {context} ctx ON ctx.id = rc.contextid\n             WHERE rc.roleid = :roleid AND rc.capability = :cap AND ctx.id IN ({$ctxids})\n          ORDER BY ctx.depth DESC";
    if ($existing = $DB->get_records_sql($sql, $params)) {
        foreach ($existing as $e) {
            if ($e->permission == CAP_PROHIBIT) {
                // prohibit can not be overridden, no point in changing anything
                return;
            }
        }
        $lowest = array_shift($existing);
        if ($lowest->permission == $permission) {
            // permission already set in this context or parent - nothing to do
            return;
        }
        if ($existing) {
            $parent = array_shift($existing);
            if ($parent->permission == $permission) {
                // permission already set in parent context or parent - just unset in this context
                // we do this because we want as few overrides as possible for performance reasons
                unassign_capability($capname, $roleid, $context->id);
                $context->mark_dirty();
                return;
            }
        }
    } else {
        if ($permission == CAP_PREVENT) {
            // nothing means role does not have permission
            return;
        }
    }
    // assign the needed capability
    assign_capability($capname, $permission, $roleid, $context->id, true);
    // force cap reloading
    $context->mark_dirty();
}
 /**
  * Clears capabilities from all roles so that they may be reassigned as specified.
  */
 public static function clear_capabilities_for_course($courseid)
 {
     $coursecontext = context_course::instance($courseid);
     // Get all roles for current course.
     $currentcourseroles = get_all_roles($coursecontext);
     // Remove publisher and creator capabilities from all roles.
     foreach ($currentcourseroles as $role) {
         unassign_capability('block/panopto:provision_aspublisher', $role->id, $coursecontext);
         unassign_capability('block/panopto:provision_asteacher', $role->id, $coursecontext);
         // Mark dirty (moodle standard for capability changes at context level).
         $coursecontext->mark_dirty();
     }
 }