]> git.mjollnir.org Git - moodle.git/commitdiff
role assign: MDL-8312 Restrict which roles can be assigned at which contextlevels.
authortjhunt <tjhunt>
Thu, 6 Nov 2008 07:34:01 +0000 (07:34 +0000)
committertjhunt <tjhunt>
Thu, 6 Nov 2008 07:34:01 +0000 (07:34 +0000)
* New table role_context_levels
* Populate table with defaults on install
* Populate table on upgrade with the same defaults, plus any additional ones needed to ensure all the role assignments already in the database are allowed.
* Change get_assignable_roles to respect these settings.
* UI for these settings on the add/edit role form.
* Save these settings when a role definition is saved.
* If in a context, there are no roles you can assign, display a polite message.
* Back up these settings.
* Restore these settings. When resotring a <=1.9.x backup file, any newly imported roles are set to be assignable at all contextlevels.

Restore not tested because it is broken in HEAD.

12 files changed:
admin/roles/assign.php
admin/roles/manage.html
admin/roles/manage.php
admin/roles/override.php
admin/roles/tabs.php
backup/backuplib.php
backup/restorelib.php
lang/en_utf8/role.php
lib/accesslib.php
lib/db/install.xml
lib/db/upgrade.php
version.php

index 5b02a8f88425dd80ffbbf47dc6b3b83e6d67a6e3..33e12c63d55a84a6eb1a11479c517d34265fa4b8 100755 (executable)
@@ -60,8 +60,8 @@
 
 /// Make sure this user can assign this role
     if ($roleid && !isset($assignableroles[$roleid])) {
-        $a = stdClass;
-        $a->role = $roleid;
+        $a = new stdClass;
+        $a->roleid = $roleid;
         $a->context = $contextname;
         print_error('cannotassignrolehere', '', get_context_url($context), $a);
     }
         echo '<p><a href="' . $baseurl . '">' . get_string('backtoallroles', 'role') . '</a></p>';
         echo '</div>';
 
+    } else if (empty($assignableroles)) {
+    /// Print a message that there are no roles that can me assigned here.
+        print_heading(get_string('notabletoassignroleshere', 'role'), 'center', 3);
+
     } else {
     /// Show UI for choosing a role to assign.
 
index 4618a8275ee302e404f94ef8d7d60f8956106b74..cfec37f8471942e52e6baac5ff1b965f89877043 100755 (executable)
 <table class="roledesc" cellpadding="9" cellspacing="0">
 <?php if ($action == 'view') { ?>
     <tr valign="top">
-        <td align="right"><?php print_string('name') ?>:</td>
+        <td align="right"><?php print_string('name') ?></td>
         <td><?php p(format_string($role->name)); ?></td>
     </tr>
     <tr valign="top">
-        <td align="right"><?php print_string('shortname') ?>:</td>
+        <td align="right"><?php print_string('shortname') ?></td>
         <td><?php p($role->shortname); ?></td>
     </tr>
     <tr valign="top">
-        <td align="right"><?php print_string('description') ?>:</td>
+        <td align="right"><?php print_string('description') ?></td>
         <td><?php p(format_text($role->description, FORMAT_HTML)); $usehtmleditor = false; ?></td>
     </tr>
     <tr valign="top">
-        <td align="right"><?php print_string('legacytype', 'role') ?>:</td>
+        <td align="right"><?php print_string('legacytype', 'role') ?></td>
         <td><?php
                 $usehtmleditor = false;
                 if (empty($role->legacytype)) {
         </td>
     </tr>
 <?php } ?>
+    <tr valign="top">
+        <td align="right"><?php print_string('maybeassignedin', 'role') ?></td>
+        <td><?php
+            foreach ($allcontextlevels as $cl => $clname) {
+                $extraarguments = $disabled;
+                if (in_array($cl, $rolecontextlevels)) {
+                    $extraarguments .= 'checked="checked"';
+                }
+                echo '<input type="checkbox" id="cl' . $cl . '" name="contextlevel' . $cl .
+                        '" value="1" ' . $extraarguments . '/> ';
+                echo '<label for="cl' . $cl . '">' . $clname . "</label><br />\n";
+            }
+            ?>
+        </td>
+    </tr>
 </table>
 
 <?php
@@ -149,8 +164,6 @@ foreach ($capabilities as $capability) {
         $localoverride->permission = $role->{$capability->name};
     }
 
-    $disabled = ($action != 'edit' and $action != 'add') ? ' disabled="disabled" ' : '';
-
     $riskinfo = '<td class="risk managetrust">';
     $rowclasses = '';
     if (RISK_MANAGETRUST & (int)$capability->riskbitmask) {
index 1c823e7e519c30282e8a37f118b9456132e21a4f..b3f007e374a14ea7e8003ddeaa9c6c0d44bc68c2 100755 (executable)
     $roles = get_all_roles();
     $rolescount = count($roles);
 
+    $allcontextlevels = array(
+        CONTEXT_SYSTEM => get_string('coresystem'),
+        CONTEXT_USER => get_string('user'),
+        CONTEXT_COURSECAT => get_string('category'),
+        CONTEXT_COURSE => get_string('course'),
+        CONTEXT_MODULE => get_string('activitymodule'),
+        CONTEXT_BLOCK => get_string('block')
+    );
+
 /// fix sort order if needed
     $rolesort = array();
     $i = 0;
                     $newrole->legacytype  = $legacytype;
                 }
 
+                $newcontextlevels = array();
+                foreach (array_keys($allcontextlevels) as $cl) {
+                    if (optional_param('contextlevel' . $cl, false, PARAM_BOOL)) {
+                        $newcontextlevels[$cl] = $cl;
+                    }
+                }
+                if (empty($errors)) {
+                    set_role_contextlevels($newroleid, $newcontextlevels);
+                }
+
                 $allowed_values = array(CAP_INHERIT, CAP_ALLOW, CAP_PREVENT, CAP_PROHIBIT);
                 $capabilities = fetch_context_capabilities($sitecontext); // capabilities applicable in this context
 
                     $newrole->legacytype  = $legacytype;
                 }
 
+                $newcontextlevels = array();
+                foreach (array_keys($allcontextlevels) as $cl) {
+                    if (optional_param('contextlevel' . $cl, false, PARAM_BOOL)) {
+                        $newcontextlevels[$cl] = $cl;
+                    }
+                }
+                if (empty($errors)) {
+                    set_role_contextlevels($roleid, $newcontextlevels);
+                }
+
                 $allowed_values = array(CAP_INHERIT, CAP_ALLOW, CAP_PREVENT, CAP_PROHIBIT);
                 $capabilities = fetch_context_capabilities($sitecontext); // capabilities applicable in this context
 
                 // dupilcate all the capabilities
                 role_cap_duplicate($sourcerole, $newrole);
 
+                set_role_contextlevels($newrole, get_role_contextlevels($roleid));
+
                 // dup'ed a role sitewide...
                 mark_context_dirty($sitecontext->path);
 
             }
 
             if ($confirm and data_submitted() and confirm_sesskey()) {
+                set_role_contextlevels($roleid, get_default_contextlevels(get_legacy_type($roleid)));
+
                 reset_role_capabilities($roleid);
 
                 // reset a role sitewide...
                 $role->shortname   = '';
                 $role->description = '';
                 $role->legacytype  = '';
+                $rolecontextlevels = array();
             } else {
                 $role = $newrole;
+                $rolecontextlevels = $newcontextlevels;
             }
         } else if ($action == 'edit' and !empty($errors) and !empty($newrole)) {
-                $role = $newrole;
+            $role = $newrole;
+            $rolecontextlevels = $newcontextlevels;
+            
         } else {
             if(!$role = $DB->get_record('role', array('id'=>$roleid))) {
                 print_error('wrongroleid', 'error');
             }
             $role->legacytype = get_legacy_type($role->id);
+            $rolecontextlevels = get_role_contextlevels($roleid);
         }
 
         foreach ($roles as $rolex) {
 
         $lang = str_replace('_utf8', '', current_language());
 
+        if ($action == 'edit' || $action == 'add') {
+            $disabled = '';
+        } else {
+            $disabled = 'disabled="disabled" ';
+        }
+
         print_simple_box_start('center');
         include_once('manage.html');
         print_simple_box_end();
index 5cef6e4b4cd7c433f01b163ecc05b97c0f1fd899..e14cbe9f488afad06cec35e8eb8ac53389e323a5 100755 (executable)
         echo '<p><a href="' . $baseurl . '">' . get_string('backtoallroles', 'role') . '</a></p>';
         echo '</div>';
 
+    } else if (empty($overridableroles)) {
+    /// Print a message that there are no roles that can me assigned here.
+        print_heading(get_string('notabletooverrideroleshere', 'role'), 'center', 3);
+
     } else {
     /// Show UI for choosing a role to assign.
 
index 893763f5838c415e8db334b0a7f9271df1e56c7d..0362c576ac1ac3da6d0967b22ce5281b1e7db6e0 100755 (executable)
@@ -66,49 +66,20 @@ if ($currenttab != 'update') {
             break;
 
         case CONTEXT_MODULE:
-            // get module type?
-            if (!$cm = $DB->get_record('course_modules', array('id'=>$context->instanceid))) {
+            if (!$cm = get_coursemodule_from_id('', $context->instanceid)) {
                 print_error('invalidcoursemodule', 'error');
             }
-            if (!$module = $DB->get_record('modules', array('id'=>$cm->module))) {  //$module->name;
-                print_error('invalidmodule', 'error');
-            }
-            if (!$course = $DB->get_record('course', array('id'=>$cm->course))) {
+            if (!$course = $DB->get_record('course', array('id' => $cm->course))) {
                 print_error('invalidcourse');
             }
-            if (!$instance = $DB->get_record($module->name, array('id'=>$cm->instance))) {
-                print_error('moduledoesnotexist', 'error');
-            }
 
             require_login($course);
-
-            $fullmodulename      = get_string("modulename", $module->name);
-            $strmodulenameplural = get_string("modulenameplural", $module->name);
-
-            if ($module->name == "label") {
-                $focuscursor = "";
-            } else {
-                $focuscursor = "form.name";
-            }
-
-            $navlinks[] = array('name' => $strmodulenameplural,
-                                'link' => "$CFG->wwwroot/mod/$module->name/index.php?id=$course->id",
-                                'type' => 'misc');
-
-            $navlinks[] = array('name' => $instance->name,
-                                'link' => "$CFG->wwwroot/mod/$module->name/view.php?id=$cm->id",
-                                'type' => 'misc');
-
-            $navlinks[] = array('name' => $streditinga,
-                                'link' => "$CFG->wwwroot/course/mod.php?update=$cm->id&amp;sesskey=".sesskey(),
-                                'type' => 'misc');
-
-            $navigation = build_navigation($navlinks);
+            $navigation = build_navigation(get_string('roles'), $cm);
 
             if (empty($title)) {
                 $title = get_string("editinga", "moodle", $fullmodulename);
             }
-            print_header_simple($title, '', $navigation, $focuscursor, "", false);
+            print_header_simple($title, '', $navigation, '', '', false);
 
             break;
 
index 18cded66b69a3fb49d59006f26a153b56ed4a96d..d82e8f5e706a9f527ef23af77b7f166c642e28bb 100644 (file)
             if ($nameincourse != $role->name) {
                 fwrite ($bf,full_tag('NAMEINCOURSE', 3, false, $nameincourse));
             }
-            // find and write all default capabilities
+        /// List of context level where this role can be assigned.
+            fwrite ($bf,start_tag('CONTEXTLEVELS',3,true));
+            $contextlevels = get_role_contextlevels($role->id);
+            foreach ($contextlevels as $cl) {
+                fwrite ($bf,full_tag('CONTEXTLEVEL', 4, false, $cl));
+            }
+            fwrite ($bf,end_tag('CONTEXTLEVELS',3,true));
+        /// find and write all default capabilities
             fwrite ($bf,start_tag('CAPABILITIES',3,true));
             // pull out all default (site context) capabilities
             if ($capabilities = role_context_capabilities($role->id, $sitecontext)) {
index 030c170d93e53f49db98c786c7e799133fd0aaaf..1a422ffa4cbc3d806b4d2aa6cb5b3fb3d7aacda0 100644 (file)
@@ -5047,13 +5047,20 @@ define('RESTORE_GROUPS_GROUPINGS', 3);
                                 $this->info->roles[$this->info->tempid]->id = $this->info->tempid;
                                 break;
                             case "NAME":
-                                $this->info->roles[$this->info->tempid]->name = $this->getContents();;
+                                $this->info->roles[$this->info->tempid]->name = $this->getContents();
                                 break;
                             case "SHORTNAME":
-                                $this->info->roles[$this->info->tempid]->shortname = $this->getContents();;
+                                $this->info->roles[$this->info->tempid]->shortname = $this->getContents();
                                 break;
                             case "NAMEINCOURSE": // custom name of the role in course
-                                $this->info->roles[$this->info->tempid]->nameincourse = $this->getContents();;
+                                $this->info->roles[$this->info->tempid]->nameincourse = $this->getContents();
+                                break;
+                        }
+                    }
+                    if ($this->level == 5) {
+                        switch ($tagName) {
+                            case "CONTEXTLEVEL":
+                                $this->info->roles[$this->info->tempid]->contextlevels[] = $this->getContents();
                                 break;
                         }
                     }
@@ -8435,6 +8442,21 @@ define('RESTORE_GROUPS_GROUPINGS', 3);
                     $newroleid = create_role($roledata->name, $roledata->shortname, '');
                     $status = backup_putid($restore->backup_unique_code,"role",$oldroleid,
                                      $newroleid); // adding a new id
+
+                /// Restore the role contextlevels.
+                    if (isset($roledata->contextlevels)) {
+                        set_role_contextlevels($newroleid, $roledata->contextlevels);                        
+                    } else {
+                        // Data was not in the backup file (must be a pre-2.0 backup).
+                        // Allow this role to be assigned at all levels, which is
+                        // Which is what would have been possible where the backup
+                        // was made.
+                        set_role_contextlevels($newroleid, array(CONTEXT_SYSTEM,
+                                CONTEXT_USER, CONTEXT_COURSECAT, CONTEXT_COURSE,
+                                CONTEXT_MODULE, CONTEXT_BLOCK));
+                    }
+
+                /// Restore all the role capabiltites.
                     foreach ($roledata->capabilities as $capability) {
 
                         $roleinfo = new object();
index 97209746e2aa2473c4e47297b2b5cec87bdf8fea..6b8782b74fb6f669eca4d0d507b014e27b7ce67d 100644 (file)
@@ -110,12 +110,15 @@ $string['legacytype'] = 'Legacy role type';
 $string['listallroles'] = 'List all roles';
 $string['localroles'] = 'Locally assigned roles';
 $string['manageroles'] = 'Manage roles';
+$string['maybeassignedin'] = 'Context types where this role may be assigned';
 $string['metaassignerror'] = 'Can not assign this role to user \"$a\" because Manage metacourse capability is needed.';
 $string['metaunassignerror'] = 'Role of user \"$a\" was automatically reassigned, please unassign the role in child courses instead.';
 $string['morethan'] = 'More than $a';
 $string['multipleroles'] = 'Multiple roles';
 $string['my:manageblocks'] = 'Manage myMoodle page blocks';
 $string['nocapabilitiesincontext'] = 'No capabilities available in this context';
+$string['notabletoassignroleshere'] = 'You are not able to assign any roles here';
+$string['notabletooverrideroleshere'] = 'You are not able to override the permissions on any roles here';
 $string['notset'] = 'Not set';
 $string['overrideanotherrole'] = 'Override another role';
 $string['overridecontext'] = 'Override context';
index 42c7246da16b3e0b0435f1b952b51236c1f76924..f37ab6b4c37dbd5fd3f2e7afb116e5fc34a22f9f 100755 (executable)
@@ -1825,6 +1825,14 @@ function moodle_install_roles() {
     //allow_override($editteacherrole, $studentrole);
     //allow_override($editteacherrole, $guestrole);
 
+/// Set up the context levels where you can assign each role.
+    set_role_contextlevels($adminrole->id, get_default_contextlevels('admin'));
+    set_role_contextlevels($coursecreatorrole->id, get_default_contextlevels('coursecreator'));
+    set_role_contextlevels($editteacherrole->id, get_default_contextlevels('editingteacher'));
+    set_role_contextlevels($noneditteacherrole->id, get_default_contextlevels('teacher'));
+    set_role_contextlevels($studentrole->id, get_default_contextlevels('student'));
+    set_role_contextlevels($guestrole->id, get_default_contextlevels('guest'));
+    set_role_contextlevels($userrole->id, get_default_contextlevels('user'));
 }
 
 /**
@@ -1922,6 +1930,7 @@ function is_safe_capability($capability) {
     return (RISK_DATALOSS | RISK_MANAGETRUST | RISK_CONFIG | RISK_XSS | RISK_PERSONAL) & $capability->riskbitmask;
 }
 
+
 /**********************************
  * Context Manipulation functions *
  **********************************/
@@ -2593,6 +2602,7 @@ function delete_role($roleid) {
         $DB->delete_records('role_allow_override', array('roleid'=>$roleid));
         $DB->delete_records('role_allow_override', array('allowoverride'=>$roleid));
         $DB->delete_records('role_names',          array('roleid'=>$roleid));
+        $DB->delete_records('role_context_levels', array('roleid'=>$roleid));
     }
 
 // finally delete the role itself
@@ -3345,12 +3355,12 @@ function print_context_name($context, $withprefix = true, $short = false) {
             if ($cm = $DB->get_record_sql('SELECT cm.*, md.name AS modname FROM {course_modules} cm ' .
                     'JOIN {modules} md ON md.id = cm.module WHERE cm.id = ?', array($context->instanceid))) {
                 if ($mod = $DB->get_record($cm->modname, array('id' => $cm->instance))) {
-                    if ($withprefix){
+                        if ($withprefix){
                         $name = get_string('modulename', $cm->modname).': ';
+                        }
+                        $name .= $mod->name;
                     }
-                    $name .= $mod->name;
                 }
-            }
             break;
 
         case CONTEXT_BLOCK: // not necessarily 1 to 1 to course
@@ -4148,7 +4158,11 @@ function get_assignable_roles($context, $rolenamedisplay = ROLENAME_ALIAS, $with
     global $USER, $DB;
 
     if (!has_capability('moodle/role:assign', $context)) {
-        return array();
+        if ($withusercounts) {
+            return array(array(), array(), array());
+        } else {
+            return array();
+        }
     }
 
     $parents = get_parent_contexts($context);
@@ -4170,18 +4184,21 @@ function get_assignable_roles($context, $rolenamedisplay = ROLENAME_ALIAS, $with
     }
 
     $params['userid'] = $USER->id;
+    $params['contextlevel'] = $context->contextlevel;
     if (!$roles = $DB->get_records_sql("
-            SELECT ro.id, ro.name$extrafields
-              FROM {role} ro
+             SELECT ro.id, ro.name$extrafields
+               FROM {role} ro
               JOIN (SELECT DISTINCT r.id
-                      FROM {role} r,
-                           {role_assignments} ra,
-                           {role_allow_assign} raa
-                     WHERE ra.userid = :userid AND ra.contextid IN ($contexts)
-                       AND raa.roleid = ra.roleid AND r.id = raa.allowassign
-                   ) inline_view ON ro.id = inline_view.id
-          ORDER BY ro.sortorder ASC", $params)) {
-        return array();
+                     FROM {role} r,
+                          {role_assignments} ra,
+                          {role_allow_assign} raa
+                    WHERE ra.userid = :userid AND ra.contextid IN ($contexts)
+                      AND raa.roleid = ra.roleid AND r.id = raa.allowassign
+                    ) inline_view ON ro.id = inline_view.id
+               JOIN {role_context_levels} rcl ON ro.id = rcl.roleid
+              WHERE rcl.contextlevel = :contextlevel
+           ORDER BY ro.sortorder ASC", $params)) {
+        $roles = array();
     }
 
     $rolenames = array();
@@ -4189,7 +4206,7 @@ function get_assignable_roles($context, $rolenamedisplay = ROLENAME_ALIAS, $with
         $rolenames[$role->id] = $role->name;
         if ($rolenamedisplay == ROLENAME_ORIGINALANDSHORT) {
             $rolenames[$role->id] .= ' (' . $role->shortname . ')';
-        }
+    }
     }
     if ($rolenamedisplay != ROLENAME_ORIGINALANDSHORT) {
         $rolenames = role_fix_names($rolenames, $context, $rolenamedisplay);
@@ -4265,7 +4282,11 @@ function get_overridable_roles($context, $rolenamedisplay = ROLENAME_ALIAS, $wit
     global $USER, $DB;
 
     if (!has_any_capability(array('moodle/role:safeoverride', 'moodle/role:override'), $context)) {
-        return array();
+        if ($withcounts) {
+            return array(array(), array(), array());
+        } else {
+            return array();
+        }
     }
 
     $parents = get_parent_contexts($context);
@@ -4289,14 +4310,14 @@ function get_overridable_roles($context, $rolenamedisplay = ROLENAME_ALIAS, $wit
             SELECT ro.id, ro.name$extrafields
               FROM {role} ro
               JOIN (
-                       SELECT DISTINCT r.id
+                                                   SELECT DISTINCT r.id
                          FROM {role} r
                          JOIN {role_allow_override} rao ON r.id = rao.allowoverride
                          JOIN {role_assignments} ra ON rao.roleid = ra.roleid
-                        WHERE ra.userid = :userid AND ra.contextid IN ($contexts)
+                                                    WHERE ra.userid = :userid AND ra.contextid IN ($contexts)
                    ) inline_view ON ro.id = inline_view.id
           ORDER BY ro.sortorder ASC", $params)) {
-        return array();
+        $roles = array();
     }
 
     $rolenames = array();
@@ -4312,7 +4333,7 @@ function get_overridable_roles($context, $rolenamedisplay = ROLENAME_ALIAS, $wit
 
     if (!$withcounts) {
         return $rolenames;
-    }
+}
 
     $rolecounts = array();
     $nameswithcounts = array();
@@ -4323,6 +4344,57 @@ function get_overridable_roles($context, $rolenamedisplay = ROLENAME_ALIAS, $wit
     return array($rolenames, $rolecounts, $nameswithcounts);
 }
 
+/**
+ * @param integer $roleid the id of a role.
+ * @return array list of the context levels at which this role may be assigned.
+ */
+function get_role_contextlevels($roleid) {
+    global $DB;
+    return $DB->get_records_menu('role_context_levels', array('roleid' => $roleid),
+            'contextlevel', 'id,contextlevel');
+}
+
+/**
+ * @param string $roleid one of the legacy role types - that is, one of the keys
+ *      from the array returned by get_legacy_roles();
+ * @return array list of the context levels at which this type of role may be assigned by default.
+ */
+function get_default_contextlevels($roletype) {
+    static $defaults = array(
+        'admin' => array(CONTEXT_SYSTEM),
+        'coursecreator' => array(CONTEXT_SYSTEM, CONTEXT_COURSECAT),
+        'editingteacher' => array(CONTEXT_COURSECAT, CONTEXT_COURSE, CONTEXT_MODULE),
+        'teacher' => array(CONTEXT_COURSECAT, CONTEXT_COURSE, CONTEXT_MODULE),
+        'student' => array(CONTEXT_COURSE, CONTEXT_MODULE),
+        'guest' => array(),
+        'user' => array()
+    );
+    
+    return $defaults[$roletype];
+}
+
+/**
+ * Set the context levels at which a particular role can be assigned.
+ * Throws exceptions in case of error.
+ *
+ * @param integer $roleid the id of a role.
+ * @param array $contextlevels the context levels at which this role should be assignable.
+ */
+function set_role_contextlevels($roleid, array $contextlevels) {
+    global $DB;
+    if (!$DB->delete_records('role_context_levels', array('roleid' => $roleid))) {
+        throw new moodle_exception('couldnotdeleterolecontextlevels', '', '', $roleid);
+    }
+    $rcl = new stdClass;
+    $rcl->roleid = $roleid;
+    foreach ($contextlevels as $level) {
+        $rcl->contextlevel = $level;
+        if (!$DB->insert_record('role_context_levels', $rcl, false, true)) {
+            throw new moodle_exception('couldnotdeleterolecontextlevels', '', '', $rcl);            
+        }
+    }
+}
+
 /**
  *  Returns a role object that is the default role for new enrolments
  *  in a given course
index 6cd878eecad554f78268afc1879bd7a69b9f8b4c..ba48f95967e7db96ca81144dd20aa4db944c4a60 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8" ?>
-<XMLDB PATH="lib/db" VERSION="20081010" COMMENT="XMLDB file for core Moodle tables"
+<XMLDB PATH="lib/db" VERSION="20081022" COMMENT="XMLDB file for core Moodle tables"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:noNamespaceSchemaLocation="../../lib/xmldb/xmldb.xsd"
 >
         <INDEX NAME="roleid-contextid" UNIQUE="true" FIELDS="roleid, contextid"/>
       </INDEXES>
     </TABLE>
-    <TABLE NAME="role_sortorder" COMMENT="sort order of course managers in a course" PREVIOUS="role_names" NEXT="user_info_field">
+    <TABLE NAME="role_sortorder" COMMENT="sort order of course managers in a course" PREVIOUS="role_names" NEXT="role_context_levels">
       <FIELDS>
         <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" ENUM="false" NEXT="userid"/>
         <FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" ENUM="false" PREVIOUS="id" NEXT="roleid"/>
         <INDEX NAME="userid-roleid-contextid" UNIQUE="true" FIELDS="userid, roleid, contextid"/>
       </INDEXES>
     </TABLE>
-    <TABLE NAME="user_info_field" COMMENT="Customisable user profile fields" PREVIOUS="role_sortorder" NEXT="user_info_category">
+    <TABLE NAME="role_context_levels" COMMENT="Lists which roles can be assigned at which context levels. The assignment is allowed in the corresponding row is present in this table." PREVIOUS="role_sortorder" NEXT="user_info_field">
+      <FIELDS>
+        <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" ENUM="false" NEXT="roleid"/>
+        <FIELD NAME="roleid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" ENUM="false" PREVIOUS="id" NEXT="contextlevel"/>
+        <FIELD NAME="contextlevel" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" ENUM="false" PREVIOUS="roleid"/>
+      </FIELDS>
+      <KEYS>
+        <KEY NAME="primary" TYPE="primary" FIELDS="id" NEXT="contextlevel-roleid"/>
+        <KEY NAME="contextlevel-roleid" TYPE="unique" FIELDS="contextlevel, roleid" PREVIOUS="primary" NEXT="roleid"/>
+        <KEY NAME="roleid" TYPE="foreign" FIELDS="roleid" REFTABLE="role" REFFIELDS="id" PREVIOUS="contextlevel-roleid"/>
+      </KEYS>
+    </TABLE>
+    <TABLE NAME="user_info_field" COMMENT="Customisable user profile fields" PREVIOUS="role_context_levels" NEXT="user_info_category">
       <FIELDS>
         <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" ENUM="false" NEXT="shortname"/>
         <FIELD NAME="shortname" TYPE="char" LENGTH="255" NOTNULL="true" DEFAULT="shortname" SEQUENCE="false" ENUM="false" COMMENT="short name for each field" PREVIOUS="id" NEXT="name"/>
index fd5a0ebf3ac58644e0bbec14394b0c3d87b121c8..d529515505972b048d688932c32a4163889f012e 100644 (file)
@@ -873,6 +873,81 @@ function xmldb_main_upgrade($oldversion) {
         upgrade_main_savepoint($result, 2008101300);
     }
 
+    /// New table for storing which roles can be assigned in which contexts.
+    if ($result && $oldversion < 2008110601) {
+
+    /// Define table role_context_levels to be created
+        $table = new xmldb_table('role_context_levels');
+
+    /// Adding fields to table role_context_levels
+        $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null);
+        $table->add_field('roleid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null);
+        $table->add_field('contextlevel', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null);
+
+    /// Adding keys to table role_context_levels
+        $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
+        $table->add_key('contextlevel-roleid', XMLDB_KEY_UNIQUE, array('contextlevel', 'roleid'));
+        $table->add_key('roleid', XMLDB_KEY_FOREIGN, array('roleid'), 'role', array('id'));
+
+    /// Conditionally launch create table for role_context_levels
+        if (!$dbman->table_exists($table)) {
+            $dbman->create_table($table);
+        }
+
+    /// Main savepoint reached
+        upgrade_main_savepoint($result, 2008110601);
+    }
+
+    /// Now populate the role_context_levels table with the defaults that match
+    /// moodle_install_roles, and any other combinations that exist in this system.
+    if ($result && $oldversion < 2008110602) {
+        $roleids = $DB->get_records_menu('role', array(), '', 'shortname,id');
+
+    /// Defaults, should match moodle_install_roles.
+        $rolecontextlevels = array();
+        if (isset($roleids['admin'])) {
+            $rolecontextlevels[$roleids['admin']] = get_default_contextlevels('admin');
+        }
+        if (isset($roleids['coursecreator'])) {
+            $rolecontextlevels[$roleids['coursecreator']] = get_default_contextlevels('coursecreator');
+        }
+        if (isset($roleids['editingteacher'])) {
+            $rolecontextlevels[$roleids['editingteacher']] = get_default_contextlevels('editingteacher');
+        }
+        if (isset($roleids['teacher'])) {
+            $rolecontextlevels[$roleids['teacher']] = get_default_contextlevels('teacher');
+        }
+        if (isset($roleids['student'])) {
+            $rolecontextlevels[$roleids['student']] = get_default_contextlevels('student');
+        }
+        if (isset($roleids['guest'])) {
+            $rolecontextlevels[$roleids['guest']] = get_default_contextlevels('guest');
+        }
+        if (isset($roleids['user'])) {
+            $rolecontextlevels[$roleids['user']] = get_default_contextlevels('user');
+        }
+    
+    /// See what other role assignments are in this database, extend the allowed
+    /// lists to allow them too.
+        $existingrolecontextlevels = $DB->get_recordset_sql('SELECT DISTINCT ra.roleid, con.contextlevel FROM
+                {role_assignments} ra JOIN {context} con ON ra.contextid = con.id');
+        foreach ($existingrolecontextlevels as $rcl) {
+            if (!isset($rolecontextlevels[$rcl->roleid])) {
+                $rolecontextlevels[$rcl->roleid] = array($rcl->contextlevel);
+            } else if (!in_array($rcl->contextlevel, $rolecontextlevels[$rcl->roleid])) {
+                $rolecontextlevels[$rcl->roleid][] = $rcl->contextlevel;
+            }
+        }
+
+    /// Put the data into the database.
+        foreach ($rolecontextlevels as $roleid => $contextlevels) {
+            set_role_contextlevels($roleid, $contextlevels);
+        }
+
+    /// Main savepoint reached
+        upgrade_main_savepoint($result, 2008110602);
+    }
+
     return $result;
 }
 
index 5595602018252530489b1f0990ef3a77d5ab4e08..1610a47408329d995f185e966e800f6b2f4f3607 100644 (file)
@@ -6,7 +6,7 @@
 // This is compared against the values stored in the database to determine
 // whether upgrades should be performed (see lib/db/*.php)
 
-    $version = 2008101300;  // YYYYMMDD   = date of the last version bump
+    $version = 2008110602;  // YYYYMMDD   = date of the last version bump
                             //         XX = daily increments
 
     $release = '2.0 dev (Build: 20081106)';  // Human-friendly version name