Merge branch 'MDL-32005-master-10' of git://git.luns.net.uk/moodle
authorAparup Banerjee <aparup@moodle.com>
Wed, 16 May 2012 02:39:48 +0000 (10:39 +0800)
committerAparup Banerjee <aparup@moodle.com>
Wed, 16 May 2012 02:39:48 +0000 (10:39 +0800)
- fixed up comments (was phpdoc blocks)

19 files changed:
backup/moodle2/backup_stepslib.php
backup/moodle2/restore_stepslib.php
group/delete.php
group/group.php
group/group_form.php
group/grouping.php
group/grouping_form.php
group/groupings.php
group/import.php
group/index.php
group/lib.php
group/module.js
lang/en/error.php
lang/en/moodle.php
lib/db/install.xml [changed mode: 0644->0755]
lib/db/upgrade.php
lib/grouplib.php
lib/tests/grouplib_test.php [new file with mode: 0644]
version.php

index fa12036..f58673c 100644 (file)
@@ -965,7 +965,7 @@ class backup_groups_structure_step extends backup_structure_step {
         $groups = new backup_nested_element('groups');
 
         $group = new backup_nested_element('group', array('id'), array(
-            'name', 'description', 'descriptionformat', 'enrolmentkey',
+            'name', 'idnumber', 'description', 'descriptionformat', 'enrolmentkey',
             'picture', 'hidepicture', 'timecreated', 'timemodified'));
 
         $members = new backup_nested_element('group_members');
@@ -976,7 +976,7 @@ class backup_groups_structure_step extends backup_structure_step {
         $groupings = new backup_nested_element('groupings');
 
         $grouping = new backup_nested_element('grouping', 'id', array(
-            'name', 'description', 'descriptionformat', 'configdata',
+            'name', 'idnumber', 'description', 'descriptionformat', 'configdata',
             'timecreated', 'timemodified'));
 
         $groupinggroups = new backup_nested_element('grouping_groups');
index 1472012..84d8e39 100644 (file)
@@ -716,6 +716,17 @@ class restore_groups_structure_step extends restore_structure_step {
         $data = (object)$data; // handy
         $data->courseid = $this->get_courseid();
 
+        // Only allow the idnumber to be set if the user has permission and the idnumber is not already in use by
+        // another a group in the same course
+        $context = context_course::instance($data->courseid);
+        if (has_capability('moodle/course:changeidnumber', $context, $this->task->get_userid())) {
+            if (groups_get_group_by_idnumber($data->courseid, $data->idnumber)) {
+                unset($data->idnumber);
+            }
+        } else {
+            unset($data->idnumber);
+        }
+
         $oldid = $data->id;    // need this saved for later
 
         $restorefiles = false; // Only if we end creating the group
@@ -765,6 +776,17 @@ class restore_groups_structure_step extends restore_structure_step {
         $data = (object)$data; // handy
         $data->courseid = $this->get_courseid();
 
+        // Only allow the idnumber to be set if the user has permission and the idnumber is not already in use by
+        // another a grouping in the same course
+        $context = context_course::instance($data->courseid);
+        if (has_capability('moodle/course:changeidnumber', $context, $this->task->get_userid())) {
+            if (groups_get_grouping_by_idnumber($data->courseid, $data->idnumber)) {
+                unset($data->idnumber);
+            }
+        } else {
+            unset($data->idnumber);
+        }
+
         $oldid = $data->id;    // need this saved for later
         $restorefiles = false; // Only if we end creating the grouping
 
index a1750df..158b8eb 100644 (file)
@@ -40,6 +40,7 @@ if (!$course = $DB->get_record('course', array('id' => $courseid))) {
 require_login($course);
 $context = get_context_instance(CONTEXT_COURSE, $course->id);
 require_capability('moodle/course:managegroups', $context);
+$changeidnumber = has_capability('moodle/course:changeidnumber', $context);
 
 // Make sure all groups are OK and belong to course
 $groupidarray = explode(',',$groupids);
@@ -48,6 +49,9 @@ foreach($groupidarray as $groupid) {
     if (!$group = $DB->get_record('groups', array('id' => $groupid))) {
         print_error('invalidgroupid');
     }
+    if (!empty($group->idnumber) && !$changeidnumber) {
+        print_error('grouphasidnumber', '', '', $group->name);
+    }
     if ($courseid != $group->courseid) {
         print_error('groupunknown', '', '', $group->courseid);
     }
index 3b23ad9..a169091 100644 (file)
@@ -92,6 +92,10 @@ if ($editform->is_cancelled()) {
     redirect($returnurl);
 
 } elseif ($data = $editform->get_data()) {
+    if (!has_capability('moodle/course:changeidnumber', $context)) {
+        // Remove the idnumber if the user doesn't have permission to modify it
+        unset($data->idnumber);
+    }
 
     if ($data->id) {
         groups_update_group($data, $editform, $editoroptions);
index 37044ef..18fe099 100644 (file)
@@ -41,14 +41,25 @@ class group_form extends moodleform {
      */
     function definition () {
         global $USER, $CFG, $COURSE;
+        $coursecontext = context_course::instance($COURSE->id);
 
         $mform =& $this->_form;
         $editoroptions = $this->_customdata['editoroptions'];
 
+        $mform->addElement('header', 'general', get_string('general', 'form'));
+
         $mform->addElement('text','name', get_string('groupname', 'group'),'maxlength="254" size="50"');
         $mform->addRule('name', get_string('required'), 'required', null, 'client');
         $mform->setType('name', PARAM_MULTILANG);
 
+        $mform->addElement('text','idnumber', get_string('idnumbergroup'), 'maxlength="100" size="10"');
+        $mform->addHelpButton('idnumber', 'idnumbergroup');
+        $mform->setType('idnumber', PARAM_RAW);
+        $mform->setAdvanced('idnumber');
+        if (!has_capability('moodle/course:changeidnumber', $coursecontext)) {
+            $mform->hardFreeze('idnumber');
+        }
+
         $mform->addElement('editor', 'description_editor', get_string('groupdescription', 'group'), null, $editoroptions);
         $mform->setType('description_editor', PARAM_RAW);
 
@@ -86,12 +97,22 @@ class group_form extends moodleform {
         $errors = parent::validation($data, $files);
 
         $name = trim($data['name']);
+        if (isset($data['idnumber'])) {
+            $idnumber = trim($data['idnumber']);
+        } else {
+            $idnumber = '';
+        }
         if ($data['id'] and $group = $DB->get_record('groups', array('id'=>$data['id']))) {
             if (textlib::strtolower($group->name) != textlib::strtolower($name)) {
                 if (groups_get_group_by_name($COURSE->id,  $name)) {
                     $errors['name'] = get_string('groupnameexists', 'group', $name);
                 }
             }
+            if (!empty($idnumber) && $group->idnumber != $idnumber) {
+                if (groups_get_group_by_idnumber($COURSE->id, $idnumber)) {
+                    $errors['idnumber']= get_string('idnumbertaken');
+                }
+            }
 
             if (!empty($CFG->groupenrolmentkeypolicy) and $data['enrolmentkey'] != '' and $group->enrolmentkey !== $data['enrolmentkey']) {
                 // enforce password policy only if changing password
@@ -103,6 +124,8 @@ class group_form extends moodleform {
 
         } else if (groups_get_group_by_name($COURSE->id, $name)) {
             $errors['name'] = get_string('groupnameexists', 'group', $name);
+        } else if (!empty($idnumber) && groups_get_group_by_idnumber($COURSE->id, $idnumber)) {
+            $errors['idnumber']= get_string('idnumbertaken');
         }
 
         return $errors;
index 8ac9eb6..b612873 100644 (file)
@@ -70,6 +70,9 @@ $returnurl = $CFG->wwwroot.'/group/groupings.php?id='.$course->id;
 
 
 if ($id and $delete) {
+    if (!empty($grouping->idnumber) && !has_capability('moodle/course:changeidnumber', $context)) {
+        print_error('groupinghasidnumber', '', '', $grouping->name);
+    }
     if (!$confirm) {
         $PAGE->set_title(get_string('deletegrouping', 'group'));
         $PAGE->set_heading($course->fullname. ': '. get_string('deletegrouping', 'group'));
@@ -108,6 +111,10 @@ if ($editform->is_cancelled()) {
 
 } elseif ($data = $editform->get_data()) {
     $success = true;
+    if (!has_capability('moodle/course:changeidnumber', $context)) {
+        // Remove the idnumber if the user doesn't have permission to modify it
+        unset($data->idnumber);
+    }
 
     if ($data->id) {
         groups_update_grouping($data, $editoroptions);
index 258234e..63248ab 100644 (file)
@@ -43,14 +43,25 @@ class grouping_form extends moodleform {
      */
     function definition () {
         global $USER, $CFG, $COURSE;
+        $coursecontext = context_course::instance($COURSE->id);
 
         $mform =& $this->_form;
         $editoroptions = $this->_customdata['editoroptions'];
 
+        $mform->addElement('header', 'general', get_string('general', 'form'));
+
         $mform->addElement('text','name', get_string('groupingname', 'group'),'maxlength="254" size="50"');
         $mform->addRule('name', get_string('required'), 'required', null, 'server');
         $mform->setType('name', PARAM_MULTILANG);
 
+        $mform->addElement('text','idnumber', get_string('idnumbergrouping'), 'maxlength="100" size="10"');
+        $mform->addHelpButton('idnumber', 'idnumbergrouping');
+        $mform->setType('idnumber', PARAM_RAW);
+        $mform->setAdvanced('idnumber');
+        if (!has_capability('moodle/course:changeidnumber', $coursecontext)) {
+            $mform->hardFreeze('idnumber');
+        }
+
         $mform->addElement('editor', 'description_editor', get_string('groupingdescription', 'group'), null, $editoroptions);
         $mform->setType('description_editor', PARAM_RAW);
 
@@ -76,15 +87,27 @@ class grouping_form extends moodleform {
         $errors = parent::validation($data, $files);
 
         $name = trim($data['name']);
+        if (isset($data['idnumber'])) {
+            $idnumber = trim($data['idnumber']);
+        } else {
+            $idnumber = '';
+        }
         if ($data['id'] and $grouping = $DB->get_record('groupings', array('id'=>$data['id']))) {
             if (textlib::strtolower($grouping->name) != textlib::strtolower($name)) {
                 if (groups_get_grouping_by_name($COURSE->id,  $name)) {
                     $errors['name'] = get_string('groupingnameexists', 'group', $name);
                 }
             }
+            if (!empty($idnumber) && $grouping->idnumber != $idnumber) {
+                if (groups_get_grouping_by_idnumber($COURSE->id, $idnumber)) {
+                    $errors['idnumber']= get_string('idnumbertaken');
+                }
+            }
 
         } else if (groups_get_grouping_by_name($COURSE->id, $name)) {
             $errors['name'] = get_string('groupingnameexists', 'group', $name);
+        } else if (!empty($idnumber) && groups_get_grouping_by_idnumber($COURSE->id, $idnumber)) {
+            $errors['idnumber']= get_string('idnumbertaken');
         }
 
         return $errors;
index b43f9b9..a137da4 100644 (file)
@@ -67,6 +67,7 @@ echo $OUTPUT->heading($strgroupings);
 
 $data = array();
 if ($groupings = $DB->get_records('groupings', array('courseid'=>$course->id), 'name')) {
+    $canchangeidnumber = has_capability('moodle/course:changeidnumber', $context);
     foreach($groupings as $grouping) {
         $line = array();
         $line[0] = format_string($grouping->name);
@@ -84,8 +85,13 @@ if ($groupings = $DB->get_records('groupings', array('courseid'=>$course->id), '
 
         $buttons  = "<a title=\"$stredit\" href=\"grouping.php?id=$grouping->id\"><img".
                     " src=\"" . $OUTPUT->pix_url('t/edit') . "\" class=\"iconsmall\" alt=\"$stredit\" /></a> ";
-        $buttons .= "<a title=\"$strdelete\" href=\"grouping.php?id=$grouping->id&amp;delete=1\"><img".
-                    " src=\"" . $OUTPUT->pix_url('t/delete') . "\" class=\"iconsmall\" alt=\"$strdelete\" /></a> ";
+        if (empty($grouping->idnumber) || $canchangeidnumber) {
+            // It's only possible to delete groups without an idnumber unless the user has the changeidnumber capability
+            $buttons .= "<a title=\"$strdelete\" href=\"grouping.php?id=$grouping->id&amp;delete=1\"><img".
+                        " src=\"" . $OUTPUT->pix_url('t/delete') . "\" class=\"iconsmall\" alt=\"$strdelete\" /></a> ";
+        } else {
+            $buttons .= $OUTPUT->spacer();
+        }
         $buttons .= "<a title=\"$strmanagegrping\" href=\"assign.php?id=$grouping->id\"><img".
                     " src=\"" . $OUTPUT->pix_url('i/group') . "\" class=\"icon\" alt=\"$strmanagegrping\" /></a> ";
 
index ae85c96..9baf372 100644 (file)
@@ -80,6 +80,7 @@ if ($mform_post->is_cancelled()) {
     $optionalDefaults = array("lang" => 1);
     $optional = array("coursename" => 1,
             "idnumber" => 1,
+            "groupidnumber" => 1,
             "description" => 1,
             "enrolmentkey" => 1);
 
@@ -166,6 +167,24 @@ if ($mform_post->is_cancelled()) {
                     echo $OUTPUT->notification(get_string('nopermissionforcreation', 'group', $groupname));
 
                 } else {
+                    if (isset($newgroup->groupidnumber)) {
+                        // The CSV field for the group idnumber is groupidnumber rather than
+                        // idnumber as that field is already in use for the course idnumber.
+                        $newgroup->groupidnumber = trim($newgroup->groupidnumber);
+                        if (has_capability('moodle/course:changeidnumber', $newgrpcoursecontext)) {
+                            $newgroup->idnumber = $newgroup->groupidnumber;
+                            if ($existing = groups_get_group_by_idnumber($newgroup->courseid, $newgroup->idnumber)) {
+                                // idnumbers must be unique to a course but we shouldn't ignore group creation for duplicates
+                                $existing->name = s($existing->name);
+                                $existing->idnumber = s($existing->idnumber);
+                                $existing->problemgroup = $groupname;
+                                echo $OUTPUT->notification(get_string('groupexistforcoursewithidnumber', 'error', $existing));
+                                unset($newgroup->idnumber);
+                            }
+                        }
+                        // Always drop the groupidnumber key. It's not a valid database field
+                        unset($newgroup->groupidnumber);
+                    }
                     if ($groupid = groups_get_group_by_name($newgroup->courseid, $groupname)) {
                         echo $OUTPUT->notification("$groupname :".get_string('groupexistforcourse', 'error', $groupname));
                     } else if (groups_create_group($newgroup)) {
index 1538f52..1f7aabd 100644 (file)
@@ -192,6 +192,7 @@ echo ' onclick="window.status=this.selectedIndex==-1 ? \'\' : this.options[this.
 
 $groups = groups_get_all_groups($courseid);
 $selectedname = '&nbsp;';
+$preventgroupremoval = array();
 
 if ($groups) {
     // Print out the HTML
@@ -206,6 +207,9 @@ if ($groups) {
                 $selectedname = $groupname;
             }
         }
+        if (!empty($group->idnumber) && !has_capability('moodle/course:changeidnumber', $context)) {
+            $preventgroupremoval[$group->id] = true;
+        }
 
         echo "<option value=\"{$group->id}\"$select title=\"$groupname\">$groupname</option>\n";
     }
@@ -276,6 +280,7 @@ echo '</form>'."\n";
 
 if (ajaxenabled()) {
     $PAGE->requires->js_init_call('M.core_group.init_index', array($CFG->wwwroot, $courseid));
+    $PAGE->requires->js_init_call('M.core_group.groupslist', array($preventgroupremoval));
 }
 
 echo $OUTPUT->footer();
index c933fbf..8addc93 100644 (file)
@@ -145,6 +145,12 @@ function groups_create_group($data, $editform = false, $editoroptions = false) {
     $data->timecreated  = time();
     $data->timemodified = $data->timecreated;
     $data->name         = trim($data->name);
+    if (isset($data->idnumber)) {
+        $data->idnumber = trim($data->idnumber);
+        if (groups_get_group_by_idnumber($course->id, $data->idnumber)) {
+            throw new moodle_exception('idnumbertaken');
+        }
+    }
 
     if ($editform and $editoroptions) {
         $data->description = $data->description_editor['text'];
@@ -188,6 +194,12 @@ function groups_create_grouping($data, $editoroptions=null) {
     $data->timecreated  = time();
     $data->timemodified = $data->timecreated;
     $data->name         = trim($data->name);
+    if (isset($data->idnumber)) {
+        $data->idnumber = trim($data->idnumber);
+        if (groups_get_grouping_by_idnumber($data->courseid, $data->idnumber)) {
+            throw new moodle_exception('idnumbertaken');
+        }
+    }
 
     if ($editoroptions !== null) {
         $data->description = $data->description_editor['text'];
@@ -256,6 +268,12 @@ function groups_update_group($data, $editform = false, $editoroptions = false) {
 
     $data->timemodified = time();
     $data->name         = trim($data->name);
+    if (isset($data->idnumber)) {
+        $data->idnumber = trim($data->idnumber);
+        if (($existing = groups_get_group_by_idnumber($data->courseid, $data->idnumber)) && $existing->id != $data->id) {
+            throw new moodle_exception('idnumbertaken');
+        }
+    }
 
     if ($editform and $editoroptions) {
         $data = file_postupdate_standard_editor($data, 'description', $editoroptions, $context, 'group', 'description', $data->id);
@@ -287,6 +305,12 @@ function groups_update_grouping($data, $editoroptions=null) {
     global $DB;
     $data->timemodified = time();
     $data->name         = trim($data->name);
+    if (isset($data->idnumber)) {
+        $data->idnumber = trim($data->idnumber);
+        if (($existing = groups_get_grouping_by_idnumber($data->courseid, $data->idnumber)) && $existing->id != $data->id) {
+            throw new moodle_exception('idnumbertaken');
+        }
+    }
     if ($editoroptions !== null) {
         $data = file_postupdate_standard_editor($data, 'description', $editoroptions, $editoroptions['context'], 'grouping', 'description', $data->id);
     }
index f5142b6..79ff974 100644 (file)
@@ -44,3 +44,33 @@ M.core_group.init_index = function(Y, wwwroot, courseid) {
     M.core_group.groupsCombo = new UpdatableGroupsCombo(wwwroot, courseid);
     M.core_group.membersCombo = new UpdatableMembersCombo(wwwroot, courseid);
 };
+
+M.core_group.groupslist = function(Y, preventgroupremoval) {
+    var actions = {
+        init : function() {
+            // We need to add check_deletable both on change for the groups, and then call it the first time the page loads
+            Y.one('#groups').on('change', this.check_deletable, this);
+            this.check_deletable();
+        },
+        check_deletable : function() {
+            // Ensure that if the 'preventremoval' attribute is set, the delete button is greyed out
+            var candelete = true;
+            var optionselected = false;
+            Y.one('#groups').get('options').each(function(option) {
+                if (option.get('selected')) {
+                    optionselected = true;
+                    if (option.getAttribute('value') in preventgroupremoval) {
+                        candelete = false;
+                    }
+                }
+            }, this);
+            var deletebutton = Y.one('#deletegroup');
+            if (candelete && optionselected) {
+                deletebutton.removeAttribute('disabled');
+            } else {
+                deletebutton.setAttribute('disabled', 'disabled');
+            }
+        }
+    }
+    actions.init();
+};
index ee6eb50..96ed4ef 100644 (file)
@@ -238,6 +238,9 @@ $string['generalexceptionmessage'] = 'Exception - {$a}';
 $string['gradepubdisable'] = 'Grade publishing disabled';
 $string['groupalready'] = 'User already belongs to group {$a}';
 $string['groupexistforcourse'] = 'Group "{$a}" already exists for this course';
+$string['groupexistforcoursewithidnumber'] = '{$a->problemgroup}: Group "{$a->name}" with an idnumber of "{$a->idnumber}" already exists for this course';
+$string['grouphasidnumber'] = 'Group "{$a}" has an idnumber and may have been automatically created by an external system. You do not have permission to remove this group.';
+$string['groupinghasidnumber'] = 'Grouping "{$a}" has an idnumber and may have been automatically created by an external system. You do not have permission to remove this grouping.';
 $string['groupnotaddederror'] = 'Group "{$a}" not added';
 $string['groupunknown'] = 'Group {$a} not associated to specified course';
 $string['groupusernotmember'] = 'User is not member of this group.';
index d5ee920..0109f55 100644 (file)
@@ -855,6 +855,10 @@ $string['icon'] = 'Icon';
 $string['idnumber'] = 'ID number';
 $string['idnumbercourse'] = 'Course ID number';
 $string['idnumbercourse_help'] = 'The ID number of a course is only used when matching the course against external systems and is not displayed anywhere on the site. If the course has an official code name it may be entered, otherwise the field can be left blank.';
+$string['idnumbergroup'] = 'Group ID number';
+$string['idnumbergroup_help'] = 'The ID number of a group is only used when matching the group against external systems and is not displayed anywhere on the site. If the group has an official code name it may be entered, otherwise the field can be left blank.';
+$string['idnumbergrouping'] = 'Grouping ID number';
+$string['idnumbergrouping_help'] = 'The ID number of a grouping is only used when matching the grouping against external systems and is not displayed anywhere on the site. If the grouping has an official code name it may be entered, otherwise the field can be left blank.';
 $string['idnumbermod'] = 'ID number';
 $string['idnumbermod_help'] = 'Setting an ID number provides a way of identifying the activity for grade calculation purposes. If the activity is not included in any grade calculation then the ID number field may be left blank.
 
old mode 100644 (file)
new mode 100755 (executable)
index 69e608b..b4cf2d2
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8" ?>
-<XMLDB PATH="lib/db" VERSION="20120505" COMMENT="XMLDB file for core Moodle tables"
+<XMLDB PATH="lib/db" VERSION="20120515" COMMENT="XMLDB file for core Moodle tables"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:noNamespaceSchemaLocation="../../lib/xmldb/xmldb.xsd"
 >
     <TABLE NAME="groups" COMMENT="Each record represents a group." PREVIOUS="tag_instance" NEXT="groupings">
       <FIELDS>
         <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" NEXT="courseid"/>
-        <FIELD NAME="courseid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" PREVIOUS="id" NEXT="name"/>
-        <FIELD NAME="name" TYPE="char" LENGTH="254" NOTNULL="true" SEQUENCE="false" COMMENT="Short human readable unique name for the group." PREVIOUS="courseid" NEXT="description"/>
+        <FIELD NAME="courseid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" PREVIOUS="id" NEXT="idnumber"/>
+        <FIELD NAME="idnumber" TYPE="char" LENGTH="100" NOTNULL="true" SEQUENCE="false" PREVIOUS="courseid" NEXT="name"/>
+        <FIELD NAME="name" TYPE="char" LENGTH="254" NOTNULL="true" SEQUENCE="false" COMMENT="Short human readable unique name for the group." PREVIOUS="idnumber" NEXT="description"/>
         <FIELD NAME="description" TYPE="text" NOTNULL="false" SEQUENCE="false" PREVIOUS="name" NEXT="descriptionformat"/>
         <FIELD NAME="descriptionformat" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="description" NEXT="enrolmentkey"/>
         <FIELD NAME="enrolmentkey" TYPE="char" LENGTH="50" NOTNULL="false" SEQUENCE="false" PREVIOUS="descriptionformat" NEXT="picture"/>
         <KEY NAME="primary" TYPE="primary" FIELDS="id" NEXT="courseid"/>
         <KEY NAME="courseid" TYPE="foreign" FIELDS="courseid" REFTABLE="course" REFFIELDS="id" PREVIOUS="primary"/>
       </KEYS>
+      <INDEXES>
+        <INDEX NAME="idnumber" UNIQUE="false" FIELDS="idnumber"/>
+      </INDEXES>
     </TABLE>
     <TABLE NAME="groupings" COMMENT="A grouping is a collection of groups. WAS: groups_groupings" PREVIOUS="groups" NEXT="groups_members">
       <FIELDS>
         <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" NEXT="courseid"/>
         <FIELD NAME="courseid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="id" NEXT="name"/>
-        <FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="Short human readable unique name for group." PREVIOUS="courseid" NEXT="description"/>
-        <FIELD NAME="description" TYPE="text" NOTNULL="false" SEQUENCE="false" PREVIOUS="name" NEXT="descriptionformat"/>
+        <FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="Short human readable unique name for group." PREVIOUS="courseid" NEXT="idnumber"/>
+        <FIELD NAME="idnumber" TYPE="char" LENGTH="100" NOTNULL="true" SEQUENCE="false" PREVIOUS="name" NEXT="description"/>
+        <FIELD NAME="description" TYPE="text" NOTNULL="false" SEQUENCE="false" PREVIOUS="idnumber" NEXT="descriptionformat"/>
         <FIELD NAME="descriptionformat" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="description" NEXT="configdata"/>
         <FIELD NAME="configdata" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="extra configuration data - may be used by group IU tools" PREVIOUS="descriptionformat" NEXT="timecreated"/>
         <FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="configdata" NEXT="timemodified"/>
         <KEY NAME="primary" TYPE="primary" FIELDS="id" NEXT="courseid"/>
         <KEY NAME="courseid" TYPE="foreign" FIELDS="courseid" REFTABLE="course" REFFIELDS="id" PREVIOUS="primary"/>
       </KEYS>
+      <INDEXES>
+        <INDEX NAME="idnumber" UNIQUE="false" FIELDS="idnumber"/>
+      </INDEXES>
     </TABLE>
     <TABLE NAME="groups_members" COMMENT="Link a user to a group." PREVIOUS="groupings" NEXT="groupings_groups">
       <FIELDS>
index bc48dde..17441dc 100644 (file)
@@ -448,6 +448,7 @@ function xmldb_main_upgrade($oldversion) {
         $field = new xmldb_field('coursedisplay', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0', 'completionnotify');
 
         // Conditionally launch add field coursedisplay
+        //
         if (!$dbman->field_exists($table, $field)) {
             $dbman->add_field($table, $field);
         }
@@ -501,5 +502,41 @@ function xmldb_main_upgrade($oldversion) {
         upgrade_main_savepoint(true, 2012050400.02);
     }
 
+    if ($oldversion < 2012051100.01) {
+
+        // Define field idnumber to be added to groups
+        $table = new xmldb_table('groups');
+        $field = new xmldb_field('idnumber', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null, 'courseid');
+        $index = new xmldb_index('idnumber', XMLDB_INDEX_NOTUNIQUE, array('idnumber'));
+
+        // Conditionally launch add field idnumber
+        if (!$dbman->field_exists($table, $field)) {
+            $dbman->add_field($table, $field);
+        }
+
+        // Conditionally launch add index idnumber
+        if (!$dbman->index_exists($table, $index)) {
+            $dbman->add_index($table, $index);
+        }
+
+        // Define field idnumber to be added to groupings
+        $table = new xmldb_table('groupings');
+        $field = new xmldb_field('idnumber', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null, 'name');
+        $index = new xmldb_index('idnumber', XMLDB_INDEX_NOTUNIQUE, array('idnumber'));
+
+        // Conditionally launch add field idnumber
+        if (!$dbman->field_exists($table, $field)) {
+            $dbman->add_field($table, $field);
+        }
+
+        // Conditionally launch add index idnumber
+        if (!$dbman->index_exists($table, $index)) {
+            $dbman->add_index($table, $index);
+        }
+
+        // Main savepoint reached
+        upgrade_main_savepoint(true, 2012051100.01);
+    }
+
     return true;
 }
index 82fa4d3..f758cca 100644 (file)
@@ -93,6 +93,25 @@ function groups_get_group_by_name($courseid, $name) {
     return false;
 }
 
+/**
+ * Returns the groupid of a group with the idnumber specified for the course.
+ * Group idnumbers should be unique within course
+ *
+ * @category group
+ * @param int $courseid The id of the course
+ * @param string $idnumber idnumber of group
+ * @return group object
+ */
+function groups_get_group_by_idnumber($courseid, $idnumber) {
+    global $DB;
+    if (empty($idnumber)) {
+        return false;
+    } else if ($group = $DB->get_record('groups', array('courseid' => $courseid, 'idnumber' => $idnumber))) {
+        return $group;
+    }
+    return false;
+}
+
 /**
  * Returns the groupingid of a grouping with the name specified for the course.
  * Grouping names should be unique in course
@@ -110,6 +129,25 @@ function groups_get_grouping_by_name($courseid, $name) {
     return false;
 }
 
+/**
+ * Returns the groupingid of a grouping with the idnumber specified for the course.
+ * Grouping names should be unique within course
+ *
+ * @category group
+ * @param int $courseid The id of the course
+ * @param string $idnumber idnumber of the group
+ * @return grouping object
+ */
+function groups_get_grouping_by_idnumber($courseid, $idnumber) {
+    global $DB;
+    if (empty($idnumber)) {
+        return false;
+    } else if ($grouping = $DB->get_record('groupings', array('courseid' => $courseid, 'idnumber' => $idnumber))) {
+        return $grouping;
+    }
+    return false;
+}
+
 /**
  * Get the group object
  *
@@ -762,4 +800,4 @@ function _group_verify_activegroup($courseid, $groupmode, $groupingid, array $al
             $SESSION->activegroup[$courseid][$groupmode][$groupingid] = 0;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/lib/tests/grouplib_test.php b/lib/tests/grouplib_test.php
new file mode 100644 (file)
index 0000000..3f256b2
--- /dev/null
@@ -0,0 +1,174 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Tests events subsystems
+ *
+ * @package    core
+ * @subpackage group
+ * @copyright  2007 onwards Martin Dougiamas (http://dougiamas.com)
+ * @author     Andrew Nicols
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+class grouplib_testcase extends advanced_testcase {
+
+    public function test_groups_get_group_by_idnumber() {
+        $this->resetAfterTest(true);
+
+        $generator = $this->getDataGenerator();
+
+        // Create a course category and course
+        $cat = $generator->create_category(array('parent' => 0));
+        $course = $generator->create_course(array('category' => $cat->id));
+
+        $idnumber1 = 'idnumber1';
+        $idnumber2 = 'idnumber2';
+
+        /**
+         * Test with an empty and a null idnumber
+         */
+        // An empty idnumber should always return a false value
+        $this->assertFalse(groups_get_group_by_idnumber($course->id, ''));
+        $this->assertFalse(groups_get_group_by_idnumber($course->id, null));
+
+        // Even when a group exists which also has an empty idnumber
+        $generator->create_group(array('courseid' => $course->id));
+        $this->assertFalse(groups_get_group_by_idnumber($course->id, ''));
+        $this->assertFalse(groups_get_group_by_idnumber($course->id, null));
+
+        /**
+         * Test with a valid idnumber
+         */
+        // There is no matching idnumber at present
+        $this->assertFalse(groups_get_group_by_idnumber($course->id, $idnumber1));
+
+        // We should now have a valid group returned by the idnumber search
+        $group = $generator->create_group(array('courseid' => $course->id, 'idnumber' => $idnumber1));
+        $this->assertEquals(groups_get_group_by_idnumber($course->id, $idnumber1), $group);
+
+        // An empty idnumber should still return false
+        $this->assertFalse(groups_get_group_by_idnumber($course->id, ''));
+        $this->assertFalse(groups_get_group_by_idnumber($course->id, null));
+
+        /**
+         * Test with another idnumber
+         */
+        // There is no matching idnumber at present
+        $this->assertFalse(groups_get_group_by_idnumber($course->id, $idnumber2));
+
+        // We should now have a valid group returned by the idnumber search
+        $group = $generator->create_group(array('courseid' => $course->id, 'idnumber' => $idnumber2));
+        $this->assertEquals(groups_get_group_by_idnumber($course->id, $idnumber2), $group);
+
+        /**
+         * Group idnumbers are unique within a course so test that we don't
+         * retrieve groups for the first course
+         */
+
+        // Create a second course
+        $course = $generator->create_course(array('category' => $cat->id));
+
+        // An empty idnumber should always return a false value
+        $this->assertFalse(groups_get_group_by_idnumber($course->id, ''));
+        $this->assertFalse(groups_get_group_by_idnumber($course->id, null));
+
+        // Our existing idnumbers shouldn't be returned here as we're in a different course
+        $this->assertFalse(groups_get_group_by_idnumber($course->id, $idnumber1));
+        $this->assertFalse(groups_get_group_by_idnumber($course->id, $idnumber2));
+
+        // We should be able to reuse the idnumbers again since this is a different course
+        $group = $generator->create_group(array('courseid' => $course->id, 'idnumber' => $idnumber1));
+        $this->assertEquals(groups_get_group_by_idnumber($course->id, $idnumber1), $group);
+
+        $group = $generator->create_group(array('courseid' => $course->id, 'idnumber' => $idnumber2));
+        $this->assertEquals(groups_get_group_by_idnumber($course->id, $idnumber2), $group);
+    }
+
+    public function test_groups_get_grouping_by_idnumber() {
+        $this->resetAfterTest(true);
+
+        $generator = $this->getDataGenerator();
+
+        // Create a course category and course
+        $cat = $generator->create_category(array('parent' => 0));
+        $course = $generator->create_course(array('category' => $cat->id));
+
+        $idnumber1 = 'idnumber1';
+        $idnumber2 = 'idnumber2';
+
+        /**
+         * Test with an empty and a null idnumber
+         */
+        // An empty idnumber should always return a false value
+        $this->assertFalse(groups_get_grouping_by_idnumber($course->id, ''));
+        $this->assertFalse(groups_get_grouping_by_idnumber($course->id, null));
+
+        // Even when a grouping exists which also has an empty idnumber
+        $generator->create_grouping(array('courseid' => $course->id));
+        $this->assertFalse(groups_get_grouping_by_idnumber($course->id, ''));
+        $this->assertFalse(groups_get_grouping_by_idnumber($course->id, null));
+
+        /**
+         * Test with a valid idnumber
+         */
+        // There is no matching idnumber at present
+        $this->assertFalse(groups_get_grouping_by_idnumber($course->id, $idnumber1));
+
+        // We should now have a valid group returned by the idnumber search
+        $grouping = $generator->create_grouping(array('courseid' => $course->id, 'idnumber' => $idnumber1));
+        $this->assertEquals(groups_get_grouping_by_idnumber($course->id, $idnumber1), $grouping);
+
+        // An empty idnumber should still return false
+        $this->assertFalse(groups_get_grouping_by_idnumber($course->id, ''));
+        $this->assertFalse(groups_get_grouping_by_idnumber($course->id, null));
+
+        /**
+         * Test with another idnumber
+         */
+        // There is no matching idnumber at present
+        $this->assertFalse(groups_get_grouping_by_idnumber($course->id, $idnumber2));
+
+        // We should now have a valid grouping returned by the idnumber search
+        $grouping = $generator->create_grouping(array('courseid' => $course->id, 'idnumber' => $idnumber2));
+        $this->assertEquals(groups_get_grouping_by_idnumber($course->id, $idnumber2), $grouping);
+
+        /**
+         * Grouping idnumbers are unique within a course so test that we don't
+         * retrieve groupings for the first course
+         */
+
+        // Create a second course
+        $course = $generator->create_course(array('category' => $cat->id));
+
+        // An empty idnumber should always return a false value
+        $this->assertFalse(groups_get_grouping_by_idnumber($course->id, ''));
+        $this->assertFalse(groups_get_grouping_by_idnumber($course->id, null));
+
+        // Our existing idnumbers shouldn't be returned here as we're in a different course
+        $this->assertFalse(groups_get_grouping_by_idnumber($course->id, $idnumber1));
+        $this->assertFalse(groups_get_grouping_by_idnumber($course->id, $idnumber2));
+
+        // We should be able to reuse the idnumbers again since this is a different course
+        $grouping = $generator->create_grouping(array('courseid' => $course->id, 'idnumber' => $idnumber1));
+        $this->assertEquals(groups_get_grouping_by_idnumber($course->id, $idnumber1), $grouping);
+
+        $grouping = $generator->create_grouping(array('courseid' => $course->id, 'idnumber' => $idnumber2));
+        $this->assertEquals(groups_get_grouping_by_idnumber($course->id, $idnumber2), $grouping);
+    }
+}
index 4168b33..1389596 100644 (file)
@@ -30,7 +30,7 @@
 defined('MOODLE_INTERNAL') || die();
 
 
-$version  = 2012051100.00;              // YYYYMMDD      = weekly release date of this DEV branch
+$version  = 2012051100.01;              // YYYYMMDD      = weekly release date of this DEV branch
                                         //         RR    = release increments - 00 in DEV branches
                                         //           .XX = incremental changes