From: nfreear Date: Tue, 7 Nov 2006 11:42:49 +0000 (+0000) Subject: Initial commit for Bug MDL-7380 "groups" - Juliette White's code. NOTE, for the momen... X-Git-Url: http://git.mjollnir.org/gw?a=commitdiff_plain;h=897e026f44a209529ebea2f6974b670322998c2f;p=moodle.git Initial commit for Bug MDL-7380 "groups" - Juliette White's code. NOTE, for the moment the existing code/tables will be used by default. --- diff --git a/group/db/dbbasicgrouplib.php b/group/db/dbbasicgrouplib.php new file mode 100644 index 0000000000..5cf61172b9 --- /dev/null +++ b/group/db/dbbasicgrouplib.php @@ -0,0 +1,402 @@ +dirroot.'/lib/datalib.php'); +include_once($CFG->dirroot.'/course/groups/lib/lib.php'); + + +/******************************************************************************* + * Utility functions + ******************************************************************************/ + +/** + * Returns the user record for a given userid - I can't seem to find a function + * anywhere else to do this + * (and we need it to use the fullname() function). + * @param int $userid The id of the user to get the record for + * @return object The user record + */ +function groups_db_get_user($userid) { + $query = get_record('user', 'id', $userid); + return $query; + +} + + +/******************************************************************************* + List functions + ******************************************************************************/ + + +/** + * Returns all the ids of all the groups for the specified course. + * @uses $CFG + * @param int $courseid The courseid to get the groups for. + * @return array|false Returns an array of the group ids or false if no groups + * or an error returned + */ + function groups_db_get_groups($courseid) { + if (!$courseid) { + $groupid = false; + } else { + $groups = get_records('groups_courses_groups', 'courseid', $courseid, + '', $fields='id, groupid'); + // Put the results into an array + $groupids = array(); + if (!$groups) { + $groupids = false; + } else { + foreach ($groups as $group) { + array_push($groupids, $group->groupid); + } + } + } + + return $groupids; +} + + +/** + * Returns the ids of the users in the specified group. + * @param int $groupid The groupid to get the users for + * @return array| false Returns an array of the user ids for the specified + * group or false if no users or an error returned. + */ +function groups_db_get_members($groupid) { + if (!$groupid) { + $userids = false; + } else { + $users = get_records('groups_groups_users', 'groupid ', $groupid, '', + $fields='id, userid'); + if (!$users) { + $userids = false; + } else { + $userids = array(); + foreach ($users as $user) { + array_push($userids, $user->userid); + } + } + } + return $userids; +} + + +/** + * Gets the groups to which a user belongs for a specified course. + * @uses $CFG + * @param int $userid The id of the specified user + * @param int $courseid The id of the course. + * @return array | false An array of the group ids of the groups to which the + * user belongs or false if there are no groups or an error occurred. + */ +function groups_db_get_groups_for_user($userid, $courseid) { + if (!$userid or !$courseid) { + $groupid = false; + } else { + global $CFG; + $table_prefix = $CFG->prefix; + $sql = "SELECT g.id, userid + FROM {$table_prefix}groups_groups_users AS gm + INNER JOIN {$table_prefix}groups_groups AS g + ON gm.groupid = g.id + INNER JOIN {$table_prefix}groups_courses_groups AS cg + ON g.id = cg.groupid + WHERE cg.courseid = $courseid AND gm.userid=$userid"; + + $groups = get_records_sql($sql); + + if (!$groups) { + $groupids = false; + } else { + // Put the results into an array + $groupids = array(); + foreach ($groups as $group) { + array_push($groupids, $group->id); + } + } + } + + return $groupids; +} + + +/** + * Get the group settings object for a group - this contains the following + * properties: + * name, description, lang, theme, picture, hidepicture + * @param int $groupid The id of the gruop + * @return object The group settings object + */ +function groups_db_get_group_settings($groupid) { + if (!$groupid) { + $groupsettings = false; + } else { + global $CFG; + $tableprefix = $CFG->prefix; + $sql = "SELECT id, name, description, lang, theme, picture, hidepicture + FROM {$tableprefix}groups_groups + WHERE id = $groupid"; + $groupsettings = get_record_sql($sql); + } + + return $groupsettings; + +} + +/** + * Given two users, determines if there exists a group to which they both belong + * @param int $userid1 The id of the first user + * @param int $userid2 The id of the second user + * @return boolean True if the users are in a common group, false otherwise or + * if an error occurred. + */ +function groups_db_users_in_common_group($userid1, $userid2) { + $havecommongroup = false; + $sql = "SELECT gm1.groupid, 1 FROM {$tableprefix}groups_members AS gm1 " . + "INNER JOIN {$tableprefix}groups_members AS gm2 " . + "ON gm1.groupid =gm2.groupid" . + "WHERE gm1.userid = $userid1 AND gm2.userid = $userid2"; + $commonggroups = get_record_sql($sql); + if ($commongroups) { + $havecommongroup = true; + } + + return $havecommongroup; +} + + + +/******************************************************************************* + Membership functions + ******************************************************************************/ + + +/** + * Determines if a group with a given groupid exists. + * @param int $groupid The groupid to check for + * @return boolean True if the group exists, false otherwise or if an error + * occurred. + */ +function groups_db_group_exists($groupid) { + if (!$groupid) { + $exists = false; + } else { + $exists = record_exists($table = 'groups_groups', 'id', $groupid); + } + + return $exists; +} + + +/** + * Determines if a specified user is a member of a specified group + * @param int $groupid The group about which the request has been made + * @param int $userid The user about which the request has been made + * @return boolean True if the user is a member of the group, false otherwise + */ +function groups_db_is_member($groupid, $userid) { + if (!$groupid or !$userid) { + $ismember = false; + } else { + $ismember = record_exists($table = 'groups_groups_users', 'groupid', + $groupid, 'userid', $userid); + } + + return $ismember; +} + + +/** + * Determines if a specified group is a group for a specified course + * @param int $groupid The group about which the request has been made + * @param int $courseid The course for which the request has been made + * @return boolean True if the group belongs to the course, false otherwise + */ +function groups_db_group_belongs_to_course($groupid, $courseid) { + if (!$groupid or !$courseid) { + $ismember = false; + } else { + $ismember = record_exists($table = 'groups_courses_groups', + 'groupid', $groupid, + 'courseid', $courseid); + } + + return $ismember; +} + + +/******************************************************************************* + Creation functions + ******************************************************************************/ + + +/** + * Creates a group for a specified course + * @param int $courseid The course to create the group for + * @return int The id of the group created or false if the create failed. + */ +function groups_db_create_group($courseid, $groupsettings = false) { + // Check we have a valid course id + if (!$courseid) { + $groupid = false; + } else { + $groupsettings = groups_set_default_group_settings($groupsettings); + + $record = $groupsettings; + $record->timecreated = time(); + $record->timemodified = time(); + print_r($record); + $groupid = insert_record('groups_groups', $record); + + + if ($groupid != false) { + $record2->courseid = $courseid; + $record2->groupid = $groupid; + $record2->timeadded = time(); + $groupadded = insert_record('groups_courses_groups', $record2); + if (!$groupadded) { + $groupid = false; + } + } + } + return $groupid; +} + + +/** + * Adds a specified user to a group + * @param int $groupid The group id + * @param int $userid The user id + * @return boolean True if user added successfully, false otherwise. + */ +function groups_db_add_member($userid, $groupid) { + // Check that the user and group are valid + if (!$userid or !$groupid or !groups_db_group_exists($groupid)) { + $useradded = false; + // If the user is already a member of the group, just return success + } elseif (groups_is_member($groupid, $userid)) { + $useradded = true; + } else { + // Add the user to the group + $record->groupid = $groupid; + $record->userid = $userid; + $record->timeadded = time(); + $useradded = insert_record($table = 'groups_groups_users', $record); + } + + return $useradded; +} + + +/** + * Sets the information about a group + * @param object $groupsettings An object containing some or all of the + * following properties: + * name, description, lang, theme, picture, hidepicture + * @return boolean True if info was added successfully, false otherwise. + */ +function groups_db_set_group_settings($groupid, $groupsettings) { + $success = true; + if (!$groupid or !$groupsettings or !groups_db_group_exists($groupid)) { + $success = false; + } else { + $record = $groupsettings; + $record->id = $groupid; + $record->timemodified = time(); + $result = update_record('groups_groups', $record); + if (!$result) { + $success = false; + } + } + + return $success; + +} + +/******************************************************************************* + Deletion functions + ******************************************************************************/ + + +/** + * Deletes the specified user from the specified group + * @param int $userid The user to delete + * @param int $groupid The group to delete the user from + * @return boolean True if deletion was successful, false otherwise + */ +function groups_db_remove_member($userid, $groupid) { + if (!$userid or !$groupid) { + $success = false; + } else { + $results = delete_records('groups_groups_users', + 'groupid', $groupid, 'userid', $userid); + // delete_records returns an array of the results from the sql call, + // not a boolean, so we have to set our return variable + if ($results == false) { + $success = false; + } else { + $success = true; + } + } + + return $success; +} + + +/** + * Deletes a specified group + * @param int $groupid The group to delete + * @return boolean True if deletion was successful, false otherwise + */ +function groups_db_delete_group($groupid) { + if (!$groupid) { + $success = false; + } else { + $success = true; + // Get a list of the users for the group and delete them all from the + // group + + $userids = groups_db_get_members($groupid); + if ($userids != false) { + foreach($userids as $userid) { + $userdeleted = groups_db_remove_member($userid, $groupid); + if (!$userdeleted) { + $success = false; + } + } + } + + // Remove any groupings that the group belongs to + $groupingids = groups_get_groupings_for_group($groupid); + if ($groupingids != false) { + foreach($groupingids as $groupingid) { + $groupremoved = groups_remove_group_from_grouping($groupid, + $groupingid); + if(!$groupremoved) { + $success = false; + } + } + } + + $results = delete_records('groups_courses_groups', 'groupid', $groupid); + if ($results == false) { + $success = false; + } + + // Delete the group itself + $results = delete_records($table = 'groups_groups', $field1 = 'id', + $value1 = $groupid); + // delete_records returns an array of the results from the sql call, + // not a boolean, so we have to set our return variable + if ($results == false) { + $success = false; + } + } + + return $success; +} +?> diff --git a/group/db/dbcleanup.php b/group/db/dbcleanup.php new file mode 100644 index 0000000000..35c61b5e82 --- /dev/null +++ b/group/db/dbcleanup.php @@ -0,0 +1,59 @@ + diff --git a/group/db/dbcourselib.php b/group/db/dbcourselib.php new file mode 100644 index 0000000000..f87d8edb78 --- /dev/null +++ b/group/db/dbcourselib.php @@ -0,0 +1,10 @@ + diff --git a/group/db/dbgroupinglib.php b/group/db/dbgroupinglib.php new file mode 100644 index 0000000000..90e241f62c --- /dev/null +++ b/group/db/dbgroupinglib.php @@ -0,0 +1,425 @@ +dirroot.'/lib/datalib.php'); + +/******************************************************************************* + Access/List functions + ******************************************************************************/ + +/** + * Gets a list of the groupings for a specified course + * @param int $courseid The id of the course + * @return array | false An array of the ids of the groupings, or false if there + * are none or there was an error. + */ +function groups_db_get_groupings($courseid) { + if (!$courseid) { + $groupingid = false; + } else { + $groupings = get_records('groups_courses_groupings', 'courseid ', + $courseid, '', $fields='id, groupingid'); + if (!$groupings) { + $groupingsids = false; + } else { + // Put the results into an array + $groupingids = array(); + foreach ($groupings as $grouping) { + array_push($groupingids, $grouping->groupingid); + } + } + } + + return $groupingids; +} + + +/** + * Gets a list of the groups in a specified grouping + * @param int $groupingid The id of the grouping + * @return array | false. An array of the ids of the groups, or false if there + * are none or an error occurred. + */ +function groups_db_get_groups_in_grouping($groupingid) { + if (!$groupingid) { + $groupid = false; + } else { + + $groups = get_records('groups_groupings_groups', 'groupingid ', + $groupingid, '', $fields='id, groupid'); + if (!$groups) { + $groupids = false; + } else { + // Put the results into an array + $groupids = array(); + foreach ($groups as $group) { + array_push($groupids, $group->groupid); + } + } + } + + return $groupids; +} + + +/* + * Gets the groupings that a group belongs to + * @param int $groupid The id of the group + * @return array An array of the ids of the groupings that the group belongs to, + * or false if there are none or if an error occurred. + */ +function groups_db_get_groupings_for_group($groupid) { + if (!$groupid) { + $groupingids = false; + } else { + $groupings = get_records('groups_groupings_groups', 'groupid ', + $groupid, '', $fields='id, groupingid'); + if (!$groupings) { + $groupingids = false; + } else { + // Put the results into an array + $groupingids = array(); + foreach ($groupings as $grouping) { + array_push($groupingids, $grouping->groupingid); + } + } + } + + return $groupingids; +} + + +/** + * Gets the information about a specified grouping + * @param int $groupingid + * @return object The grouping settings object - properties are name and + * description. + */ +function groups_db_get_grouping_settings($groupingid) { + if (!$groupingid) { + $groupingsettings = false; + } else { + global $CFG; + $tableprefix = $CFG->prefix; + $sql = "SELECT * + FROM {$tableprefix}groups_groupings + WHERE id = $groupingid"; + $groupingsettings = get_record_sql($sql); + } + + return $groupingsettings; +} + +/** + * Gets the grouping to use for a particular instance of a module in a course + * @param int $coursemoduleid The id of the instance of the module in the course + * @return int The id of the grouping or false if there is no such id recorded + * or if an error occurred. + */ +function groups_db_get_grouping_for_coursemodule($coursemoduleid) { + if (!$coursemoduleid) { + $groupingid = false; + } else { + $record = get_record('course_modules', 'id', $coursemoduleid, 'id, ' . + 'groupingid'); + if (!$record) { + $groupingid = false; + } else { + $groupingid = $record->groupingid; + } + } + + return $groupingid; +} + + +/******************************************************************************* + Membership functions + ******************************************************************************/ + + + /** + * Determines if a grouping with a specified id exists + * @param int $groupingid The grouping id. + * @return True if the grouping exists, false otherwise or if an error occurred. + */ +function groups_db_grouping_exists($groupingid) { + if (!$groupingid) { + $exists = false; + } else { + $exists = record_exists('groups_groupings', 'id', + $groupingid); + } + + return $exists; +} + + + /** + * Determines if a group belongs to any grouping for the course that it belongs + * to + * @param int $groupid The id of the group + * @return boolean. True if the group belongs to a grouping, false otherwise or + * if an error has occurred. + */ + function groups_db_belongs_to_any_grouping($groupid) { + if (!$groupid) { + $isingrouping = false; + } else { + $isingrouping = record_exists('groups_groupings_groups', 'groupid', + $groupid); + } + + return $isingrouping; + } + + + /** + * Determines if a group belongs to a specified grouping + * @param int $groupid The id of the group + * @param int $groupingid The id of the grouping + * @return boolean. True if the group belongs to a grouping, false otherwise or + * if an error has occurred. + */ + function groups_db_belongs_to_grouping($groupid, $groupingid) { + if (!$groupid or !$groupingid) { + $isingrouping = false; + } else { + $isingrouping = record_exists('groups_groupings_groups', 'groupid', + $groupid, 'groupingid', $groupingid); + } + + return $isingrouping; + } + + + /** + * Detemines if a specified user belongs to any group of a specified grouping. + * @param int $userid The id of the user + * @param int $groupingid The id of the grouping + * @return boolean True if the user belongs to some group in the grouping, + * false otherwise or if an error occurred. + */ + function groups_db_is_member_of_some_group_in_grouping($userid, $groupingid) { + if (!$userid or !$groupingid) { + $belongstogroup = false; + } else { + global $CFG; + $tableprefix = $CFG->prefix; + $sql = "SELECT gm.id + FROM {$tableprefix}groups_groupings_groups AS gg + INNER JOIN {$tableprefix}groups_groups_users AS gm + ON gg.groupid = gm.groupid + WHERE gm.userid = $userid AND gg.groupingid = $groupingid"; + $belongstogroup = record_exists_sql($sql); + } + return $belongstogroup; + } + + + /** + * Determines if a grouping belongs to a specified course + * @param int $groupingid The id of the grouping + * @param int $courseid The id of the course + * @return boolean True if the grouping belongs to the course, false otherwise, + * or if an error occurred. + */ + function groups_db_grouping_belongs_to_course($groupingid, $courseid) { + if (!$groupingid or !$courseid) { + $belongstocourse = false; + } else { + $belongstocourse = record_exists('groups_courses_groupings', + 'groupingid', $groupingid, 'courseid', + $courseid); + } + + return $belongstocourse; + } + + + + +/******************************************************************************* + Creation/Update functions + ******************************************************************************/ + + +/** + * Marks a set of groups as a grouping. + * + * @param array $groupidarray An array of the ids of the groups to marks as a + * grouping. + * @param int $courseid The id of the course for which the groups should form + * a grouping + * @return int | false The id of the grouping, or false if an error occurred. + * Also returns false if any of the groups specified do not belong to the + * course. + */ +function groups_db_create_grouping($courseid, $groupingsettings = false) { + if (!$courseid or !groups_get_course_info($courseid)) { + $groupingid = false; + } else { + // Replace any empty groupsettings + $groupingsettings = groups_set_default_grouping_settings($groupingsettings); + $record = $groupingsettings; + $record->timecreated = time(); + + $groupingid = insert_record('groups_groupings', $record); + if ($groupingid != false) { + $record2->courseid = $courseid; + $record2->groupingid = $groupingid; + $record2->timeadded = time(); + $id= insert_record('groups_courses_groupings', $record2); + if (!$id) { + $groupingid = false; + } + } + } + + return $groupingid; +} + + +/** + * Adds a specified group to a specified grouping. + * @param int $groupid The id of the group + * @param int $groupingid The id of the grouping + * @return boolean True if the group was added successfully, false otherwise + */ +function groups_db_add_group_to_grouping($groupid, $groupingid) { + if (!$groupid or !$groupingid or !groups_db_group_exists($groupid) + or !groups_db_grouping_exists($groupingid)) { + $success = false; + } else { + $success = true; + $record->groupingid = $groupingid; + $record->groupid = $groupid; + $record->timeadded = time(); + $results = insert_record('groups_groupings_groups', $record); + if (!$results) { + $success = false; + } + } + + return $groupingid; +} + + +/** + * Set information about a grouping + * @param int $groupingid The grouping to update the info for. + * @param object $groupingsettings + */ +function groups_db_set_grouping_settings($groupingid, $groupingsettings) { + $success = true; + if (!$groupingid or !$groupingsettings + or !groups_db_grouping_exists($groupingid)) { + $success = false; + } else { + // Replace any empty group settings. + $record = $groupingsettings; + $record->id = $groupingid; + $record->timemodified = time(); + $result = update_record('groups_groupings', $record); + if (!$result) { + $success = false; + } + } + + return $success; +} + + +/** + * Sets a grouping to use for a particular instance of a module in a course + * @param int $groupingid The id of the grouping + * @param int $coursemoduleid The id of the instance of the module in the course + * @return boolean True if the operation was successful, false otherwise + */ +function groups_db_set_grouping_for_coursemodule($groupingid, $coursemoduleid) { + $success = true; + if (!$groupingid or !$coursemoduleid) { + $success = false; + } else { + $record->id = $coursemoduleid; + $record->groupingid = $groupingid; + $result = update_record('course_modules', $record); + if (!$result) { + $success = false; + } + } + return $success; +} + + +/******************************************************************************* + Deletion functions + ******************************************************************************/ + + +/** + * Removes a specified group from a specified grouping. Note that this does + * not delete the group. + * @param int $groupid The id of the group. + * @param int $groupingid The id of the grouping + * @return boolean True if the deletion was successful, false otherwise. + */ +function groups_db_remove_group_from_grouping($groupid, $groupingid) { + $success = true; + if (!$groupingid or !$groupid) { + $success = false; + } else { + $results = delete_records('groups_groupings_groups', 'groupid', + $groupid, 'groupingid', $groupingid); + // delete_records returns an array of the results from the sql call, + // not a boolean, so we have to set our return variable + if ($results == false) { + $success = false; + } + } + + return $success; +} + + +/** + * Removes a grouping from a course - note that this function removes but does + * not delete any of the groups in the grouping. + * @param int $groupingid The id of the grouping + * @return boolean True if the deletion was successful, false otherwise. + */ +function groups_db_delete_grouping($groupingid) { + $success = true; + if (!$groupingid) { + $success = false; + } else { + + $results = delete_records('groups_courses_groupings', 'groupingid', + $groupingid); + if ($results == false) { + $success = false; + } + + $results = delete_records('groups_groupings_groups', 'groupingid', + $groupingid); + if ($results == false) { + $success = false; + } + + $results = delete_records('groups_groupings', 'id', $groupingid); + if ($results == false) { + $success = false; + } + } + + return $success; + +} + +?> + diff --git a/group/db/dbmodulelib.php b/group/db/dbmodulelib.php new file mode 100644 index 0000000000..5ad604f87d --- /dev/null +++ b/group/db/dbmodulelib.php @@ -0,0 +1,46 @@ + \ No newline at end of file diff --git a/group/db/dbsetup.php b/group/db/dbsetup.php new file mode 100644 index 0000000000..7e6b5006f8 --- /dev/null +++ b/group/db/dbsetup.php @@ -0,0 +1,177 @@ +dirroot.'/lib/datalib.php'); + + +// @@@ TO DO Needs lots of sorting out so proper install/upgrade and also +// so used new db stuff. In practice we probably don't actually want to rename +// the tables (the group_member table in particular as this is basically +// unchanged)that already exist on the whole if we can help it so this and the +// the other dblib files should really be sorted out to do this. + +// Database changes +// New tables - the SQL for creating the tables is below (though should be +// foreign keys!) - however it might be more sensible to modify the existing +// tables instead as much as we can so that we don't need to copy data over and +// that any existing code that does assume the existence of those tables +// might still work. +// Another caveat - the code below doesn't contain the new fields in the +// groupings table - viewowngroup, viewallgroupsmemebers, viewallgroupsactivities, +// teachersgroupmark, teachersgroupview, teachersoverride, teacherdeletetable. +// Other changes: +// * course currently contains groupmode and groupmodeforce - we need to change +// this to groupingid which is either null or a forced groupingid - need to +// copy over existing data sensibly. +// * course_modules needs groupingid (think it previously had groupmode) + + +// Change database tables - course table need to remove two fields add groupingid field +// Move everything over +// Course module instance need to add groupingid field +// Module table - add group support field. +// Add deletable by teacher field. + + +/** + * Creates the database tables required + */ +function groups_create_database_tables() { + global $CFG; + $table_prefix = $CFG->prefix; + + $createcoursegrouptablesql = "CREATE TABLE IF NOT EXISTS `{$table_prefix}groups_courses_groups` + (`id` int(10) unsigned NOT NULL auto_increment, + `courseid` int(10) unsigned NOT NULL default '0', + `groupid` int(11) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `id` (`id`), KEY `courseid` (`courseid`))"; + + $creategroupstablesql = "CREATE TABLE IF NOT EXISTS `{$table_prefix}groups_groups` ( + `id` int(10) unsigned NOT NULL auto_increment, + `name` varchar(254) collate latin1_general_ci NOT NULL default '', + `description` text collate latin1_general_ci NOT NULL, + `enrolmentkey` varchar(50) collate latin1_general_ci NOT NULL default '', + `lang` varchar(10) collate latin1_general_ci NOT NULL default 'en', + `theme` varchar(50) collate latin1_general_ci NOT NULL default '', + `picture` int(10) unsigned NOT NULL default '0', + `hidepicture` int(2) unsigned NOT NULL default '0', + `timecreated` int(10) unsigned NOT NULL default '0', + `timemodified` int(10) unsigned NOT NULL default '0', + PRIMARY KEY (`id`), UNIQUE KEY `id` (`id`))"; + + + $creategroupsuserstablesql = "CREATE TABLE IF NOT EXISTS `{$table_prefix}groups_groups_users` ( + `id` int(10) unsigned NOT NULL auto_increment, + `groupid` int(10) unsigned NOT NULL default '0', + `userid` int(10) unsigned NOT NULL default '0', + `timeadded` int(10) unsigned NOT NULL default '0', + PRIMARY KEY (`id`), UNIQUE KEY `id` (`id`), + KEY `groupid` (`groupid`), KEY `userid` (`userid`)) "; + + $createcoursesgroupingtablesql = "CREATE TABLE IF NOT EXISTS `{$table_prefix}groups_courses_groupings` ( + `id` int(10) unsigned NOT NULL auto_increment, + `courseid` int(10) unsigned NOT NULL default '0', + `groupingid` mediumint(9) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `id` (`id`), + KEY `courseid` (`courseid`) + )"; + + $creategroupingstablesql = "CREATE TABLE `{$table_prefix}groups_groupings` ( + `id` int(10) unsigned NOT NULL auto_increment, + `name` varchar(254) collate latin1_general_ci NOT NULL default '', + `description` text collate latin1_general_ci NOT NULL, + `timecreated` int(10) unsigned NOT NULL default '0', + PRIMARY KEY (`id`), + UNIQUE KEY `id` (`id`) + ) "; + + $creategroupingsgroupstablesql = "CREATE TABLE IF NOT EXISTS `{$table_prefix}groups_groupings_groups` ( + `id` int(10) unsigned NOT NULL auto_increment, + `groupingid` int(10) unsigned default '0', + `groupid` int(10) NOT NULL, + `timecreated` int(10) unsigned NOT NULL default '0', `viewowngroup` binary(1) NOT NULL, + `viewallgroupsmembers` binary(1) NOT NULL, + `viewallgroupsactivities` binary(1) NOT NULL, + `teachersgroupmark` binary(1) NOT NULL, + `teachersgroupview` binary(1) NOT NULL, + `teachersoverride` binary(1) NOT NULL, . + PRIMARY KEY (`id`), + UNIQUE KEY `id` (`id`), + KEY `courseid` (`groupingid`) + ) "; + + modify_database('',$createcoursegrouptablesql ); + modify_database('',$creategroupstablesql ); + modify_database('',$creategroupsuserstablesql); + modify_database('',$createcoursesgroupingtablesql); + modify_database('',$creategroupingstablesql); + modify_database('',$creategroupingsgroupstablesql ); + +} + + +/** + * Copies any old style moodle group to a new style moodle group - we'll need this for any upgrade code + * @param int $groupid The 'old moodle groups' id of the group to copy + * @param int $courseid The course id + * @param boolean True if the operation was successful, false otherwise. + */ +function groups_db_copy_moodle_group_to_imsgroup($groupid, $courseid) { + + $success = true; + + $groupsettings = get_record('groups', 'id ', $groupid, ''); + + // Only copy the group if the group exists. + if ($groupsettings != false) { + $record->name = $groupsettings->name; + $record->description = $groupsettings->description; + $record->password = $groupsettings->password; + $record->lang = $groupsettings->lang; + $record->theme = $groupsettings->theme; + $record->picture = $groupsettings->picture; + $record->hidepicture = $groupsettings->hidepicture; + $record->timecreated = $groupsettings->timecreated; + $record->timemodified = $groupsettings->timemodified; + $newgroupid = insert_record('groups_groups', $record); + if (!$newgroupid) { + $success = false; + } + + $courserecord->courseid = $groupsettings->courseid; + $courserecord->groupid = $newgroupid; + + $added = insert_record('groups_courses_groups', $courserecord); + + if (!$added) { + $success = false; + } + + // Copy over the group members + $groupmembers = get_records('groups_users', 'groupid', $groupid); + if ($groupmembers != false) { + foreach($groupmembers as $member) { + $record->groupid = $newgroupid; + $record->userid = $member->userid; + $useradded = insert_record('groups_groups_users', $record); + if (!$useradded) { + $success = false; + } + } + } + + } + + if (!$success) { + notify('Copy operations from Moodle groups to IMS Groups failed'); + } + + return $success; +} + +?> \ No newline at end of file diff --git a/group/db/vssver.scc b/group/db/vssver.scc new file mode 100644 index 0000000000..24b8503868 Binary files /dev/null and b/group/db/vssver.scc differ diff --git a/group/groupui/addgroupstogrouping-form.html b/group/groupui/addgroupstogrouping-form.html new file mode 100644 index 0000000000..c199ad6f26 --- /dev/null +++ b/group/groupui/addgroupstogrouping-form.html @@ -0,0 +1,9 @@ + diff --git a/group/groupui/addgroupstogrouping-form.js b/group/groupui/addgroupstogrouping-form.js new file mode 100644 index 0000000000..c9bf9696fb --- /dev/null +++ b/group/groupui/addgroupstogrouping-form.js @@ -0,0 +1,73 @@ + + +function onAddGroupsToGrouping() { + hideAllForms(); + showElement("groupeditform"); + addGroupsToGrouping(); + setText('selectedgroupingforaddinggroups', ""); + return false; +} + + +/* + * Adds the selected groups to the selected groupings + */ +function addGroupsToGrouping() { + //alert("Called addGroupsToGrouping"); + selectedgroups = getMultipleSelect("groupsnotingrouping"); + if (selectedgroups != '') { + var url = "addgroupstogrouping-xml.php"; + var requeststring = "groupingid="+selectedgroupingid + +"&groups="+selectedgroups; + sendPostRequest(request, url, requeststring, addGroupsToGroupingResponse); + } +} + + +/** + * The callback for the response to the request sent in addGroupsToGrouping() + */ +function addGroupsToGroupingResponse() { + if (checkAjaxResponse(request)) { + //alert("addGroupsToGrouping called"); + //alert(request.responseText); + // Need XML sent back with groupingid + // Really want to set this to be the grouping before + error = getFromXML(request.responseXML, 'error'); + if (error != null) { + alert(error); + } + updateGroupings(); + hideElement("addgroupstogroupingform"); + } +} + + +/** + * Updates the groups not in the selected grouping for the form for adding groups to a grouping + */ +function updateGroupsNotInGrouping() { + //alert("updateNonMembers called"); + var url="getgroupsnotingrouping-xml.php"; + var requeststring = "groupingid="+selectedgroupingid; + sendPostRequest(request, url, requeststring, updateGroupsNotInGroupingResponse); +} + + +/** + * The callback for the response to the request sent in updateGroupsNotInGrouping() + */ +function updateGroupsNotInGroupingResponse() { + if (checkAjaxResponse(request)) { + //alert("updateGroupsNotInGroupingResponse"); + var xmlDoc = request.responseXML; + //alert(request.responseText); + error = getFromXML(request.responseXML, 'error'); + if (error != null) { + alert(error); + } + addOptionsFromXML("groupsnotingrouping", xmlDoc); + } +} + + diff --git a/group/groupui/addgroupstogrouping-xml.php b/group/groupui/addgroupstogrouping-xml.php new file mode 100644 index 0000000000..82f98e3852 --- /dev/null +++ b/group/groupui/addgroupstogrouping-xml.php @@ -0,0 +1,33 @@ +"; +echo ''; + +include_once('../../../config.php'); +include('../lib/lib.php'); + +$groupingid = required_param('groupingid', PARAM_INT); +$groups = required_param('groups'); +$courseid = required_param('courseid', PARAM_INT); + +require_login($courseid); + +if (confirm_sesskey() and isteacheredit($courseid)) { + $groupids = explode(',', $groups); + + if ($groupids != false) { + foreach($groupids as $groupid) { + $groupadded = groups_add_group_to_grouping($groupid, $groupingid); + if (!$groupadded) { + echo 'Failed to add group $groupid to grouping'; + } + } + } +} + +echo ''; +?> diff --git a/group/groupui/addmembers-form.html b/group/groupui/addmembers-form.html new file mode 100644 index 0000000000..cfa98abbba --- /dev/null +++ b/group/groupui/addmembers-form.html @@ -0,0 +1,9 @@ + diff --git a/group/groupui/addmembers-form.js b/group/groupui/addmembers-form.js new file mode 100644 index 0000000000..fc3019d9c7 --- /dev/null +++ b/group/groupui/addmembers-form.js @@ -0,0 +1,81 @@ + + +function onAddMembers() { + hideAllForms(); + showElement("groupeditform"); + addMembers(); + return false; +} + +function onShowAll() { + updateNonMembers(); + return false; +} + + + +/* + * Adds the selected users to the selected group + */ +function addMembers() { + //alert("Called addMembers"); + users = getMultipleSelect("nonmembers"); + if (users != '') { + var url = "addmembers-xml.php"; + var requeststring = "groupid="+selectedgroupid+"&users="+users; + sendPostRequest(request, url, requeststring, addMembersResponse); + } +} + +/** + * The callback for the response to the request sent in addMembers() + */ +function addMembersResponse() { + if (checkAjaxResponse(request)) { + //alert("addMembersResponse called"); + //alert(request.responseText); + // Need XML sent back with groupingid + // Really want to set this to be the grouping before + error = getFromXML(request.responseXML, 'error'); + if (error != null) { + alert(error); + } + updateSelectedGrouping(); + hideElement("addmembersform"); + } +} + + +/** + * Updates the list of non members of a group in the form for adding members to a group + */ +function updateNonMembers() { + //alert("updateNonMembers called"); + var url="getnonmembers-xml.php"; + // showall indicates if we should show users already in groups in the grouping + // we have to turn it into a variable that we can put in a post + var showall = getCheckBoxValue('showall');; + var requeststring = "groupid="+selectedgroupid + +"&groupingid="+selectedgroupingid + +"&showall="+showall; + + sendPostRequest(request, url, requeststring, updateNonMembersResponse); +} + +/** + * The callback for the response to the request sent in updateNonMembers() + */ +function updateNonMembersResponse() { + if (checkAjaxResponse(request)) { + //alert("updateNonMembersResponse"); + var xmlDoc = request.responseXML; + // alert(request.responseText); + error = getFromXML(request.responseXML, 'error'); + if (error != null) { + alert(error); + } + addOptionsFromXML("nonmembers", xmlDoc); + } +} + + diff --git a/group/groupui/addmembers-xml.php b/group/groupui/addmembers-xml.php new file mode 100644 index 0000000000..834ca29aef --- /dev/null +++ b/group/groupui/addmembers-xml.php @@ -0,0 +1,33 @@ +"; +echo ''; + +include_once('../../../config.php'); +include('../lib/lib.php'); + +$groupid = required_param('groupid', PARAM_INT); +$users = required_param('users'); +$courseid = required_param('courseid', PARAM_INT); + +require_login($courseid); + +if (confirm_sesskey() and isteacheredit($courseid)) { + $userids = explode(',', $users); + + if ($userids != false) { + foreach($userids as $userid) { + $useradded = groups_add_member($userid, $groupid); + if (!$useradded) { + echo 'Failed to add user $userid to group'; + } + } + } +} + +echo ''; +?> \ No newline at end of file diff --git a/group/groupui/ajax.js b/group/groupui/ajax.js new file mode 100644 index 0000000000..ff7e9042fb --- /dev/null +++ b/group/groupui/ajax.js @@ -0,0 +1,77 @@ +/*********************************************************************************************************** + * Contains functions for creating and sending Ajax requests. + * This code needs to be a bit more careful about creating separate requests for different events - if + * somebody presses a button several times in quick succession (such as the delete grouping button) then + * we get an error. + * There also seems to a problem with IE - need to check this out + ***********************************************************************************************************/ + + + + +/* + * Creates an XMLHttpRequest object + * @return The XMLHttpRequest object created. + */ +function createRequest() { + var newrequest = null; + try { + newrequest = new XMLHttpRequest(); + } catch (trymicrosoft) { + // Deal with Microsoft browsers + try { + newrequest = new ActiveXObject("Msxml2.XMLHTTP"); + } catch (othermicrosoft) { + try { + newrequest = new ActiveXObject("Microsoft.XMLHTTP"); + } catch (failed) { + newrequest = null; + } + } + } + + if (newrequest == null) { + alert("Error creating request object!"); + } else { + return newrequest; + } +} + +/* + * Sends an Ajax post request + * @param request - The XMLHttpRequest object + * @param url - The URL to send the request to + * @param requeststring - The string containing the variables to send in the post request - the format + * is basically the same as a GET string + * @callbackfunction - The function to call when the response to the request is received +*/ +function sendPostRequest(postrequest, url, requeststring, callbackfunction) { + // Add on the date and time to get round caching problem + url = url + "?dummy=" + new Date().getTime(); + // Add the course id and sesskey so we can check these on the server + requeststring = 'courseid='+courseid+'&'+'sesskey='+sesskey+'&'+requeststring; + postrequest.abort(); + postrequest.open('post', url, true); + postrequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); + postrequest.onreadystatechange = callbackfunction; + postrequest.send(requeststring); +} + +function checkAjaxResponse(request) { + process = false; + + if (request.readyState == 4 && request.status == 200) { + process = true; + } + if (request.readyState == 4 && request.status != 200) { + alert('An error has occurred - the page returned a '+ request.status + ' error'); + } + return process; +} + +var responseFailure = function(o){ + alert("Failure callback"); +} diff --git a/group/groupui/connection.js b/group/groupui/connection.js new file mode 100644 index 0000000000..670a10600d --- /dev/null +++ b/group/groupui/connection.js @@ -0,0 +1,775 @@ +/* +Copyright (c) 2006, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.net/yui/license.txt +version: 0.11.0 +*/ + +/** + * The Connection Manager provides a simplified interface to the XMLHttpRequest + * object. It handles cross-browser instantiantion of XMLHttpRequest, negotiates the + * interactive states and server response, returning the results to a pre-defined + * callback you create. + * @ class + */ +YAHOO.util.Connect = +{ +/** + * Array of MSFT ActiveX ids for XMLHttpRequest. + * @private + * @type array + */ + _msxml_progid:[ + 'MSXML2.XMLHTTP.3.0', + 'MSXML2.XMLHTTP', + 'Microsoft.XMLHTTP' + ], + + /** + * Object literal of HTTP header(s) + * @private + * @type object + */ + _http_header:{}, + + /** + * Determines if HTTP headers are set. + * @private + * @type boolean + */ + _has_http_headers:false, + + /** + * Determines if a default header of + * Content-Type of 'application/x-www-form-urlencoded' + * will be added to any client HTTP headers sent for POST + * transactions. + * @private + * @type boolean + */ + _default_post_header:true, + + /** + * Property modified by setForm() to determine if the data + * should be submitted as an HTML form. + * @private + * @type boolean + */ + _isFormSubmit:false, + + /** + * Property modified by setForm() to determine if a file(s) + * upload is expected. + * @private + * @type boolean + */ + _isFileUpload:false, + + /** + * Property modified by setForm() to set a reference to the HTML + * form node if the desired action is file upload. + * @private + * @type object + */ + _formNode:null, + + /** + * Property modified by setForm() to set the HTML form data + * for each transaction. + * @private + * @type string + */ + _sFormData:null, + + /** + * Collection of polling references to the polling mechanism in handleReadyState. + * @private + * @type string + */ + _poll:[], + + /** + * Queue of timeout values for each transaction callback with a defined timeout value. + * @private + * @type string + */ + _timeOut:[], + + /** + * The polling frequency, in milliseconds, for HandleReadyState. + * when attempting to determine a transaction's XHR readyState. + * The default is 50 milliseconds. + * @private + * @type int + */ + _polling_interval:50, + + /** + * A transaction counter that increments the transaction id for each transaction. + * @private + * @type int + */ + _transaction_id:0, + + /** + * Member to add an ActiveX id to the existing xml_progid array. + * In the event(unlikely) a new ActiveX id is introduced, it can be added + * without internal code modifications. + * @public + * @param string id The ActiveX id to be added to initialize the XHR object. + * @return void + */ + setProgId:function(id) + { + this._msxml_progid.unshift(id); + }, + + /** + * Member to enable or disable the default POST header. + * @public + * @param boolean b Set and use default header - true or false . + * @return void + */ + setDefaultPostHeader:function(b) + { + this._default_post_header = b; + }, + + /** + * Member to modify the default polling interval. + * @public + * @param {int} i The polling interval in milliseconds. + * @return void + */ + setPollingInterval:function(i) + { + if(typeof i == 'number' && isFinite(i)){ + this._polling_interval = i; + } + }, + + /** + * Instantiates a XMLHttpRequest object and returns an object with two properties: + * the XMLHttpRequest instance and the transaction id. + * @private + * @param {int} transactionId Property containing the transaction id for this transaction. + * @return connection object + */ + createXhrObject:function(transactionId) + { + var obj,http; + try + { + // Instantiates XMLHttpRequest in non-IE browsers and assigns to http. + http = new XMLHttpRequest(); + // Object literal with http and tId properties + obj = { conn:http, tId:transactionId }; + } + catch(e) + { + for(var i=0; i= 200 && httpStatus < 300){ + responseObject = this.createResponseObject(o, callback.argument); + if(callback.success){ + if(!callback.scope){ + callback.success(responseObject); + } + else{ + // If a scope property is defined, the callback will be fired from + // the context of the object. + callback.success.apply(callback.scope, [responseObject]); + } + } + } + else{ + switch(httpStatus){ + // The following case labels are wininet.dll error codes that may be encountered. + // Server timeout + case 12002: + // 12029 to 12031 correspond to dropped connections. + case 12029: + case 12030: + case 12031: + // Connection closed by server. + case 12152: + // See above comments for variable status. + case 13030: + responseObject = this.createExceptionObject(o.tId, callback.argument, isAbort); + if(callback.failure){ + if(!callback.scope){ + callback.failure(responseObject); + } + else{ + callback.failure.apply(callback.scope, [responseObject]); + } + } + break; + default: + responseObject = this.createResponseObject(o, callback.argument); + if(callback.failure){ + if(!callback.scope){ + callback.failure(responseObject); + } + else{ + callback.failure.apply(callback.scope, [responseObject]); + } + } + } + } + + this.releaseObject(o); + }, + + /** + * This method evaluates the server response, creates and returns the results via + * its properties. Success and failure cases will differ in the response + * object's property values. + * @private + * @param {object} o The connection object + * @param {} callbackArg User-defined argument or arguments to be passed to the callback + * @return object + */ + createResponseObject:function(o, callbackArg) + { + var obj = {}; + var headerObj = {}; + + try + { + var headerStr = o.conn.getAllResponseHeaders(); + var header = headerStr.split('\n'); + for(var i=0; i < header.length; i++){ + var delimitPos = header[i].indexOf(':'); + if(delimitPos != -1){ + headerObj[header[i].substring(0,delimitPos)] = header[i].substring(delimitPos+1); + } + } + } + catch(e){} + + obj.tId = o.tId; + obj.status = o.conn.status; + obj.statusText = o.conn.statusText; + obj.getResponseHeader = headerObj; + obj.getAllResponseHeaders = headerStr; + obj.responseText = o.conn.responseText; + obj.responseXML = o.conn.responseXML; + + if(typeof callbackArg !== undefined){ + obj.argument = callbackArg; + } + + return obj; + }, + + /** + * If a transaction cannot be completed due to dropped or closed connections, + * there may be not be enough information to build a full response object. + * The failure callback will be fired and this specific condition can be identified + * by a status property value of 0. + * + * If an abort was successful, the status property will report a value of -1. + * + * @private + * @param {int} tId Transaction Id + * @param callbackArg The user-defined arguments + * @param isAbort Determines if the exception is an abort. + * @return object + */ + createExceptionObject:function(tId, callbackArg, isAbort) + { + var COMM_CODE = 0; + var COMM_ERROR = 'communication failure'; + var ABORT_CODE = -1; + var ABORT_ERROR = 'transaction aborted'; + + var obj = {}; + + obj.tId = tId; + if(isAbort){ + obj.status = ABORT_CODE; + obj.statusText = ABORT_ERROR; + } + else{ + obj.status = COMM_CODE; + obj.statusText = COMM_ERROR; + } + + if(callbackArg){ + obj.argument = callbackArg; + } + + return obj; + }, + + /** + * Public method that stores the custom HTTP headers for each transaction. + * @public + * @param {string} label The HTTP header label + * @param {string} value The HTTP header value + * @return void + */ + initHeader:function(label,value) + { + if(this._http_header[label] === undefined){ + this._http_header[label] = value; + } + else{ + this._http_header[label] = value + "," + this._http_header[label]; + } + + this._has_http_headers = true; + }, + + /** + * Accessor that sets the HTTP headers for each transaction. + * @private + * @param {object} o The connection object for the transaction. + * @return void + */ + setHeader:function(o) + { + for(var prop in this._http_header){ + if(this._http_header.propertyIsEnumerable){ + o.conn.setRequestHeader(prop, this._http_header[prop]); + } + } + delete this._http_header; + + this._http_header = {}; + this._has_http_headers = false; + }, + + /** + * This method assembles the form label and value pairs and + * constructs an encoded string. + * asyncRequest() will automatically initialize the + * transaction with a HTTP header Content-Type of + * application/x-www-form-urlencoded. + * @public + * @param {string || object} form id or name attribute, or form object. + * @param {string} optional boolean to indicate SSL environment. + * @param {string} optional qualified path of iframe resource for SSL in IE. + * @return void + */ + setForm:function(formId, isUpload, secureUri) + { + this._sFormData = ''; + if(typeof formId == 'string'){ + // Determine if the argument is a form id or a form name. + // Note form name usage is deprecated by supported + // here for legacy reasons. + var oForm = (document.getElementById(formId) || document.forms[formId]); + } + else if(typeof formId == 'object'){ + var oForm = formId; + } + else{ + return; + } + + // If the isUpload argument is true, setForm will call createFrame to initialize + // an iframe as the form target. + // + // The argument secureURI is also required by IE in SSL environments + // where the secureURI string is a fully qualified HTTP path, used to set the source + // of the iframe, to a stub resource in the same domain. + if(isUpload){ + (typeof secureUri == 'string')?this.createFrame(secureUri):this.createFrame(); + this._isFormSubmit = true; + this._isFileUpload = true; + this._formNode = oForm; + + return; + } + + var oElement, oName, oValue, oDisabled; + var hasSubmit = false; + + // Iterate over the form elements collection to construct the + // label-value pairs. + for (var i=0; i'); + if(secureUri){ + // IE will throw a security exception in an SSL environment if the + // iframe source isn't set to a valid resource. + io.src = secureUri; + } + } + else{ + var io = document.createElement('IFRAME'); + io.id = 'ioFrame'; + io.name = 'ioFrame'; + } + + io.style.position = 'absolute'; + io.style.top = '-1000px'; + io.style.left = '-1000px'; + + document.body.appendChild(io); + }, + + /** + * Uploads HTML form, including files/attachments, targeting the + * iframe created in createFrame. + * + * @private + * @param {int} id The transaction id. + * @param {object} callback - User-defined callback object. + * @param {string} uri Fully qualified path of resource. + * @return void + */ + uploadFile:function(id, callback, uri){ + // Initialize the HTML form properties in case they are + // not defined in the HTML form. + this._formNode.action = uri; + this._formNode.enctype = 'multipart/form-data'; + this._formNode.method = 'POST'; + this._formNode.target = 'ioFrame'; + this._formNode.submit(); + + // Reset form status properties. + this._formNode = null; + this._isFileUpload = false; + this._isFormSubmit = false; + + // Create the upload callback handler that fires when the iframe + // receives the load event. Subsequently, the event handler is detached + // and the iframe removed from the document. + + var uploadCallback = function() + { + var oResponse = + { + tId: id, + responseText: document.getElementById("ioFrame").contentWindow.document.body.innerHTML, + argument: callback.argument + } + + if(callback.upload && !callback.scope){ + callback.upload(oResponse); + } + else{ + callback.upload.apply(callback.scope, [oResponse]); + } + + YAHOO.util.Event.removeListener("ioFrame", "load", uploadCallback); + window.ioFrame.location.replace('#'); + setTimeout("document.body.removeChild(document.getElementById('ioFrame'))",100); + }; + + // Bind the onload handler to the iframe to detect the file upload response. + YAHOO.util.Event.addListener("ioFrame", "load", uploadCallback); + }, + + /** + * Public method to terminate a transaction, if it has not reached readyState 4. + * @public + * @param {object} o The connection object returned by asyncRequest. + * @param {object} callback User-defined callback object. + * @param {string} isTimeout boolean to indicate if abort was a timeout. + * @return void + */ + abort:function(o, callback, isTimeout) + { + if(this.isCallInProgress(o)){ + window.clearInterval(this._poll[o.tId]); + this._poll.splice(o.tId); + if(isTimeout){ + this._timeOut.splice(o.tId); + } + o.conn.abort(); + this.handleTransactionResponse(o, callback, true); + + return true; + } + else{ + return false; + } + }, + + /** + * Public method to check if the transaction is still being processed. + * @public + * @param {object} o The connection object returned by asyncRequest + * @return boolean + */ + isCallInProgress:function(o) + { + // if the XHR object assigned to the transaction has not been dereferenced, + // then check its readyState status. Otherwise, return false. + if(o.conn){ + return o.conn.readyState != 4 && o.conn.readyState != 0; + } + else{ + //The XHR object has been destroyed. + return false; + } + }, + + /** + * Dereference the XHR instance and the connection object after the transaction is completed. + * @private + * @param {object} o The connection object + * @return void + */ + releaseObject:function(o) + { + //dereference the XHR instance. + o.conn = null; + //dereference the connection object. + o = null; + } +}; diff --git a/group/groupui/createautomaticgrouping-form.html b/group/groupui/createautomaticgrouping-form.html new file mode 100644 index 0000000000..001bb5d4e3 --- /dev/null +++ b/group/groupui/createautomaticgrouping-form.html @@ -0,0 +1,54 @@ +
+

+
+ + + + + + +
+

+

+

+

+

+

+

+

+
+

+ + + + + + + + + +
+ +
  +

+

+
+ + + + + + + + + + +
  +

+
+ +

  +

+
+
+
diff --git a/group/groupui/createautomaticgrouping-form.js b/group/groupui/createautomaticgrouping-form.js new file mode 100644 index 0000000000..4f779206d2 --- /dev/null +++ b/group/groupui/createautomaticgrouping-form.js @@ -0,0 +1,81 @@ +function onCreateAutomaticGrouping() { + valid = validateAutomaticGroupingForm(); + if (valid) { + hideAllForms(); + showElement("groupeditform"); + createAutomaticGrouping(); + } + + return false; +} + + +/** + * Adds an automatically generated grouping with the details as specified in the form + */ +function createAutomaticGrouping() { + //alert("Called createAutomaticGrouping"); + var url = "createautomaticgrouping-xml.php"; + var requeststring = "noofstudents="+getTextInputValue('noofstudents') + +"&noofgroups="+getTextInputValue('noofgroups') + +"&distribevenly="+getCheckBoxValue('distribevenly') + +"&alphabetical="+getCheckBoxValue('alphabetical') + +"&generationtype="+getRadioValue(document.automaticgroupingform.generationtype) + +"&name="+getTextInputValue('automaticgroupingname') + +"&description="+getTextInputValue('edit-automaticgroupingdescription') + +"&prefix="+getTextInputValue('groupprefix') + +"&defaultgroupdescription="+getTextInputValue('edit-defaultgroupdescription'); + + // alert(requeststring); + sendPostRequest(request, url, requeststring, createAutomaticGroupingResponse); + } + + + + /** + * The callback for the response to the request sent in createAutomaticGrouping() + * It sets the new grouping to be selected in the form. + */ + function createAutomaticGroupingResponse() { + if (checkAjaxResponse(request)) { + //alert("createAutomaticGroupingResponse"); + //alert(request.responseText); + error = getFromXML(request.responseXML, 'error'); + if (error != null) { + alert(error); + } + selectedgroupingid = getFromXML(request.responseXML, 'groupingid'); + selectedgroupid = null; + updateGroupings(); + hideElement("createautomaticgroupingform"); + } +} + +function validateAutomaticGroupingForm() { + valid = true; + generationtype = getRadioValue(document.automaticgroupingform.generationtype); + noofstudents = getTextInputValue('noofstudents'); + noofgroups = getTextInputValue('noofgroups'); + groupingname = getTextInputValue('automaticgroupingname'); + + if (generationtype == 'nostudents') { + if (!isPositiveInt(noofstudents)) { + alert('The number of students is not valid.'); + valid = false; + } + } else { + if (!isPositiveInt(noofgroups)) { + alert('The number of groups is not valid.'); + valid = false; + } + } + + if (groupingname == '') { + alert('You must enter a name for the new grouping'); + valid = false; + } + + return valid; +} + + diff --git a/group/groupui/createautomaticgrouping-xml.php b/group/groupui/createautomaticgrouping-xml.php new file mode 100644 index 0000000000..775c6c2438 --- /dev/null +++ b/group/groupui/createautomaticgrouping-xml.php @@ -0,0 +1,46 @@ +"; +echo ''; + + +include_once("../../../config.php"); +include("../lib/lib.php"); + +require_login($courseid); + +groups_seed_random_number_generator(); + +$courseid = required_param('courseid', PARAM_INT); + +$noofstudents = required_param('noofstudents', PARAM_INT); +$noofgroups = required_param('noofgroups', PARAM_INT); +$distribevenly = required_param('distribevenly'); +$alphabetical = required_param('alphabetical'); +$generationtype = required_param('generationtype'); + +$groupingsettings->name =required_param('name'); +$groupingsettings->description = required_param('description'); +$groupingsettings->prefix = required_param('prefix'); +$groupingsettings->defaultgroupdescription = required_param('defaultgroupdescription'); + +if (confirm_sesskey() and isteacheredit($courseid)) { + if ($generationtype == 'nogroups') { + $noofstudents = false; + } + + $groupingid = groups_create_automatic_grouping($courseid, $noofstudents, $noofgroups, + $distribevenly, $groupingsettings, false, $alphabetical); + if (!$groupingid) { + echo 'Failed to create grouping'; + } else { + echo ''.$groupingid.''; + } +} + +echo ''; +?> \ No newline at end of file diff --git a/group/groupui/creategroup-form.html b/group/groupui/creategroup-form.html new file mode 100644 index 0000000000..a76f18584d --- /dev/null +++ b/group/groupui/creategroup-form.html @@ -0,0 +1,30 @@ + diff --git a/group/groupui/creategroup-form.js b/group/groupui/creategroup-form.js new file mode 100644 index 0000000000..76d0af8f21 --- /dev/null +++ b/group/groupui/creategroup-form.js @@ -0,0 +1,61 @@ + +function onCreateGroup() { + valid = validateCreateGroupForm(); + + if (valid) { + hideAllForms(); + showElement("groupeditform"); + createGroup(); + replaceText('selectedgroupingforcreatinggroup', ""); + } + + return false; +} + +/* + * Adds a group with the name specified in the form to the selected grouping. + */ +function createGroup() { + //alert("Called createGroup"); + var url = "creategroup-xml.php"; + var requeststring = "groupname="+getTextInputValue('newgroupname') + +"&groupingid="+selectedgroupingid + +"&description="+getTextInputValue('edit-newgroupdescription') + +"&enrolmentkey="+getTextInputValue('newgroupenrolmentkey'); + // The picture fields aren't displayed if the right library isn't present + if (document.getElementById('menunewgrouphidepicture')) { + requeststring = requeststring+"&hidepicture="+getTextInputValue('menunewgrouphidepicture'); + } + sendPostRequest(request, url, requeststring, createGroupResponse); +} + +/** + * The callback for the response to the request sent in createGroup() + * The function sets the new group as selected in the form. + */ +function createGroupResponse() { + if (checkAjaxResponse(request)) { + //alert("createGroupResponse called"); + //alert(request.responseText); + error = getFromXML(request.responseXML, 'error'); + if (error != null) { + alert(error); + } + selectedgroupid = getFromXML(request.responseXML, 'groupid'); + updateGroupings(); + hideElement("creategroupform"); + } +} + + +function validateCreateGroupForm() { + valid = true; + groupname = getTextInputValue('newgroupname'); + + if (groupname == '') { + alert('You must enter a name for the new group'); + valid = false; + } + return valid; +} + diff --git a/group/groupui/creategroup-xml.php b/group/groupui/creategroup-xml.php new file mode 100644 index 0000000000..5336b628e6 --- /dev/null +++ b/group/groupui/creategroup-xml.php @@ -0,0 +1,53 @@ +"; +echo ''; + +include_once('../../../config.php'); +include('../lib/lib.php'); +$groupingid = required_param('groupingid', PARAM_INT); + +$groupsettings->name = required_param('groupname'); +$courseid = required_param('courseid', PARAM_INT); +$groupsettings->description = required_param('description'); +$groupsettings->enrolmentkey = required_param('enrolmentkey', PARAM_ALPHANUM); +$groupsettings->hidepicture = optional_param('hidepicture'); + +require_login($courseid); + +if (confirm_sesskey() and isteacheredit($courseid)) { + $groupid = groups_create_group($courseid, $groupsettings); + + if (!$groupid) { + echo 'Failed to create group'; + } else { + $groupadded = groups_add_group_to_grouping($groupid, $groupingid); + + if (!$groupadded) { + echo 'Failed to add group to grouping'; + } else { + // Upload a picture file if there was one - note that we don't remove any previous icons + require_once($CFG->dirroot.'/lib/uploadlib.php'); + $um = new upload_manager('newgroupicon', false, false, null, false, 0, true, true); + if ($um->preprocess_files()) { + require_once("$CFG->libdir/gdlib.php"); + if (save_profile_image($groupid, $um, 'groups')) { + $groupsettings->picture = 1; + $infoset = groups_set_group_settings($groupid, $groupsettings); + if (!$infoset) { + echo 'Failed to save the fact that the group image was uploaded'; + } + } + } + + echo ''.$groupid.''; + } + } +} + +echo ''; +?> diff --git a/group/groupui/creategrouping-form.html b/group/groupui/creategrouping-form.html new file mode 100644 index 0000000000..5c8b4c47bb --- /dev/null +++ b/group/groupui/creategrouping-form.html @@ -0,0 +1,11 @@ + diff --git a/group/groupui/creategrouping-form.js b/group/groupui/creategrouping-form.js new file mode 100644 index 0000000000..8263f45cec --- /dev/null +++ b/group/groupui/creategrouping-form.js @@ -0,0 +1,56 @@ + + +function onCreateGrouping() { + valid = validateCreateGroupingForm(); + if (valid) { + hideAllForms(); + showElement("groupeditform"); + createGrouping(); + } + + return false; +} + +/** + * Creates a new grouping for the course. + */ +function createGrouping() { + // alert("Called createGrouping"); + var url = "creategrouping-xml.php"; + var requeststring = "groupingname="+getTextInputValue('newgroupingname') + +"&description="+getTextInputValue('edit-newgroupingdescription'); + sendPostRequest(request, url, requeststring, createGroupingResponse); + } + + /** + * The callback for the response to the request sent in createGrouping() + * It sets the new grouping as selected in the form. + */ + function createGroupingResponse() { + if (checkAjaxResponse(request)) { + // alert("createGroupingResponse"); + // alert(request.responseText); + error = getFromXML(request.responseXML, 'error'); + if (error != null) { + alert(error); + } + selectedgroupingid = getFromXML(request.responseXML, 'groupingid'); + selectedgroupid = null; + updateGroupings(); + hideElement("creategroupingform"); + } +} + +function validateCreateGroupingForm() { + valid = true; + groupingname = getTextInputValue('newgroupingname'); + + if (groupingname == '') { + alert('You must enter a name for the new grouping'); + valid = false; + } + return valid; +} + + + diff --git a/group/groupui/creategrouping-xml.php b/group/groupui/creategrouping-xml.php new file mode 100644 index 0000000000..bac4b49fa4 --- /dev/null +++ b/group/groupui/creategrouping-xml.php @@ -0,0 +1,31 @@ +"; +echo ''; + +include_once('../../../config.php'); +include('../lib/lib.php'); + +$courseid= required_param('courseid', PARAM_INT); + +$groupingsettings->name =required_param('groupingname'); +$groupingsettings->description = required_param('description'); + +require_login($courseid); + +if (confirm_sesskey() and isteacheredit($courseid)) { + $groupingid = groups_create_grouping($courseid, $groupingsettings); + + if (!$groupingid) { + echo 'Failed to create grouping'; + } else { + echo ''.$groupingid.''; + } +} + +echo ''; +?> \ No newline at end of file diff --git a/group/groupui/deletegroup-xml.php b/group/groupui/deletegroup-xml.php new file mode 100644 index 0000000000..6ff439f01a --- /dev/null +++ b/group/groupui/deletegroup-xml.php @@ -0,0 +1,26 @@ +"; +echo ''; + +include_once('../../../config.php'); +include("../lib/lib.php"); + +$groupid = required_param('groupid', PARAM_INT); +$courseid = required_param('courseid', PARAM_INT); + +require_login($courseid); + +if (confirm_sesskey() and isteacheredit($courseid)) { + $groupremoved = groups_delete_group($groupid); + + if ($groupremoved == false) { + echo "Could not delete group $groupid"; + } +} + +echo ''; +?> diff --git a/group/groupui/deletegroup.js b/group/groupui/deletegroup.js new file mode 100644 index 0000000000..888e21fe99 --- /dev/null +++ b/group/groupui/deletegroup.js @@ -0,0 +1,35 @@ +function onDeleteGroup() { + hideAllForms() + showElement("groupeditform"); + deleteGroup(); + return false; +} + + +/** + * Deletes the selected group + */ +function deleteGroup() { + //alert("Called deleteGroup"); + var url = "deletegroup-xml.php"; + var requeststring = "groupid="+selectedgroupid; + sendPostRequest(request, url, requeststring, deleteGroupResponse); +} + +/** + * The callback for the response to the request sent in updateSelectedGrouping() + */ +function deleteGroupResponse() { + if (checkAjaxResponse(request)) { + //alert("deleteGroupResponse called"); + // alert(request.responseText); + error = getFromXML(request.responseXML, 'error'); + if (error != null) { + alert(error); + } + // Need XML sent back with groupingid + // Really want to set this to be the grouping before + selectedgroupid = null; + updateGroupings(); + } +} diff --git a/group/groupui/deletegrouping-xml.php b/group/groupui/deletegrouping-xml.php new file mode 100644 index 0000000000..863a3161a0 --- /dev/null +++ b/group/groupui/deletegrouping-xml.php @@ -0,0 +1,26 @@ +"; +echo ''; + +include_once("../../../config.php"); +include("../lib/lib.php"); + +$groupingid = required_param('groupingid', PARAM_INT); +$courseid = required_param('courseid', PARAM_INT); + +require_login($courseid); + +if (confirm_sesskey() and isteacheredit($courseid)) { + $groupingremoved = groups_delete_grouping($groupingid); + if (!$groupingremoved) { + echo 'Failed to delete grouping'; + } +} + +echo ''; +?> diff --git a/group/groupui/deletegrouping.js b/group/groupui/deletegrouping.js new file mode 100644 index 0000000000..23952fdb66 --- /dev/null +++ b/group/groupui/deletegrouping.js @@ -0,0 +1,37 @@ + +function onDeleteGrouping() { + hideAllForms() + showElement("groupeditform"); + deleteGrouping(); + return false; +} + + +/* + * Deletes the selected grouping + */ +function deleteGrouping() { + //alert("Called deleteGrouping"); + var url = "deletegrouping-xml.php"; + var requeststring = "groupingid="+selectedgroupingid; + confirm('Are you sure you want to delete this grouping and the groups that it contains?'); + sendPostRequest(request, url, requeststring, deleteGroupingResponse); + } + + /** + * The callback for the response to the request sent in deleteGrouping() + */ + function deleteGroupingResponse() { + if (checkAjaxResponse(request)) { + //alert("deleteGroupingResponse called"); + //alert(request.responseText); + error = getFromXML(request.responseXML, 'error'); + if (error != null) { + alert(error); + } + selectedgroupingid = null; + selectedgroupid = null; + updateGroupings(); + } +} + diff --git a/group/groupui/editgroupingpermissions-form.html b/group/groupui/editgroupingpermissions-form.html new file mode 100644 index 0000000000..e7764230f2 --- /dev/null +++ b/group/groupui/editgroupingpermissions-form.html @@ -0,0 +1,13 @@ + diff --git a/group/groupui/editgroupingpermissions-form.js b/group/groupui/editgroupingpermissions-form.js new file mode 100644 index 0000000000..e33ab93d20 --- /dev/null +++ b/group/groupui/editgroupingpermissions-form.js @@ -0,0 +1,66 @@ + +function onEditGroupingPermissionsSave() { + hideAllForms(); + showElement("groupeditform"); + editGroupingPermissions() ; + return false; +} + + +/** + * Creates a new grouping for the course. + */ +function editGroupingPermissions() { + var url = "editgroupingpermissions-xml.php"; + var requeststring = "groupingid=" + selectedgroupingid + +"&viewowngroup=" + getCheckBoxValue('edit-viewowngroup') + +"&viewallgroupsmembers=" + getCheckBoxValue('edit-viewallgroupsmembers') + +"&viewallgroupsactivities=" + getCheckBoxValue('edit-viewallgroupsactivities') + +"&teachersgroupmark=" + getCheckBoxValue('edit-teachersgroupmark') + +"&teachersgroupview=" + getCheckBoxValue('edit-teachersgroupview') + +"&teachersoverride=" + getCheckBoxValue('edit-teachersoverride'); + sendPostRequest(request, url, requeststring, editGroupingPermissionsResponse); + } + + /** + * The callback for the response to the request sent in editgroupingpermissions() + * It sets the new grouping as selected in the form. + */ + function editGroupingPermissionsResponse() { + if (checkAjaxResponse(request)) { + //alert("editGroupingPermissionsResponse called"); + //alert(request.responseText); + error = getFromXML(request.responseXML, 'error'); + if (error != null) { + alert(error); + } + updateGroupings(); + hideElement("editgroupingpermissionsform"); + } +} + +function getGroupingPermissions() { + //alert("Called getgroupingpermissions"); + var url = "getgroupingpermissions-xml.php"; + var requeststring = "groupingid="+selectedgroupingid; + sendPostRequest(request, url, requeststring, getGroupingPermissionsResponse); +} + +function getGroupingPermissionsResponse() { + if (checkAjaxResponse(request)) { + //alert("getgroupingpermissionsResponse"); + //alert(request.responseText); + error = getFromXML(request.responseXML, 'error'); + if (error != null) { + alert(error); + } + xml = request.responseXML; + replaceText('editperm-groupingname', getFromXML(xml, 'name')); + setCheckBoxValue('edit-viewowngroup', boolStringToBool(getFromXML(xml, 'viewowngroup'))); + setCheckBoxValue('edit-viewallgroupsmembers', boolStringToBool(getFromXML(xml, 'viewallgroupsmembers'))); + setCheckBoxValue('edit-viewallgroupsactivities', boolStringToBool(getFromXML(xml, 'viewallgroupsactivities'))); + setCheckBoxValue('edit-teachersgroupmark', boolStringToBool(getFromXML(xml, 'teachersgroupmark'))); + setCheckBoxValue('edit-teachersgroupview', boolStringToBool(getFromXML(xml, 'teachersgroupview'))); + setCheckBoxValue('edit-teachersoverride', boolStringToBool(getFromXML(xml, 'teachersoverride'))); + } +} diff --git a/group/groupui/editgroupingpermissions-xml.php b/group/groupui/editgroupingpermissions-xml.php new file mode 100644 index 0000000000..2531ed0259 --- /dev/null +++ b/group/groupui/editgroupingpermissions-xml.php @@ -0,0 +1,29 @@ +"; +echo ''; + +include_once('../../../config.php'); +include('../lib/lib.php'); +$groupingid = required_param('groupingid'); +$courseid = required_param('courseid', PARAM_INT); + +$groupingsettings->viewowngroup = required_param('viewowngroup'); +$groupingsettings->viewallgroupsmembers = required_param('viewallgroupsmembers'); +$groupingsettings->viewallgroupsactivities = required_param('viewallgroupsactivities'); +$groupingsettings->teachersgroupmark = required_param('teachersgroupmark'); +$groupingsettings->teachersgroupview = required_param('teachersgroupview'); +$groupingsettings->teachersoverride = required_param('teachersoverride'); + +require_login($courseid); + +if (confirm_sesskey() and isteacheredit($courseid)) { + $groupingid = groups_set_grouping_settings($groupingid, $groupingsettings); +} + +echo ''; +?> \ No newline at end of file diff --git a/group/groupui/editgroupingsettings-form.html b/group/groupui/editgroupingsettings-form.html new file mode 100644 index 0000000000..b4b16df04c --- /dev/null +++ b/group/groupui/editgroupingsettings-form.html @@ -0,0 +1,11 @@ + diff --git a/group/groupui/editgroupingsettings-form.js b/group/groupui/editgroupingsettings-form.js new file mode 100644 index 0000000000..ca7ca0a90c --- /dev/null +++ b/group/groupui/editgroupingsettings-form.js @@ -0,0 +1,75 @@ + +function onEditGroupingSettingsSave() { + valid = validateEditGroupingSettingsForm(); + if (valid) { + hideAllForms(); + showElement("groupeditform"); + editGroupingSettings() ; + return false; + } +} + + +/** + * Creates a new grouping for the course. + */ +function editGroupingSettings() { + var url = "editgroupingsettings-xml.php"; + var requeststring = "groupingid="+selectedgroupingid + +"&groupingname="+getTextInputValue('edit-groupingname') + +"&description="+getTextInputValue('edit-edit-groupingdescription'); + sendPostRequest(request, url, requeststring, editGroupingSettingsResponse); + } + + /** + * The callback for the response to the request sent in editgroupingsettings() + * It sets the new grouping as selected in the form. + */ + function editGroupingSettingsResponse() { + if (checkAjaxResponse(request)) { + //alert("editGroupingSettingsResponse called"); + //alert(request.responseText); + error = getFromXML(request.responseXML, 'error'); + if (error != null) { + alert(error); + } + updateGroupings(); + hideElement("editgroupingsettingsform"); + } +} + +function getGroupingSettings() { + //alert("Called getgroupingsettings"); + var url = "getgroupingsettings-xml.php"; + var requeststring = "groupingid="+selectedgroupingid; + sendPostRequest(request, url, requeststring, getGroupingSettingsResponse); +} + +function getGroupingSettingsResponse() { + if (checkAjaxResponse(request)) { + //alert("getgroupingsettingsResponse"); + //alert(request.responseText); + error = getFromXML(request.responseXML, 'error'); + if (error != null) { + alert(error); + } + xml = request.responseXML; + setTextInputValue('edit-groupingname', getFromXML(xml, 'name')); + setTextInputValue('edit-edit-groupingdescription', getFromXML(xml, 'description')); + } +} + + +function validateEditGroupingSettingsForm() { + valid = true; + groupingname = getTextInputValue('edit-groupingname'); + + if (groupingname == '') { + alert('You must enter a name for the new grouping'); + valid = false; + } + return valid; +} + + + diff --git a/group/groupui/editgroupingsettings-xml.php b/group/groupui/editgroupingsettings-xml.php new file mode 100644 index 0000000000..0ffc0d2580 --- /dev/null +++ b/group/groupui/editgroupingsettings-xml.php @@ -0,0 +1,25 @@ +"; +echo ''; + +include_once('../../../config.php'); +include('../lib/lib.php'); +$groupingid = required_param('groupingid'); +$courseid = required_param('courseid', PARAM_INT); + +$groupingsettings->name =required_param('groupingname'); +$groupingsettings->description = required_param('description'); + +require_login($courseid); + +if (confirm_sesskey() and isteacheredit($courseid)) { + $groupingid = groups_set_grouping_settings($groupingid, $groupingsettings); +} + +echo ''; +?> \ No newline at end of file diff --git a/group/groupui/editgroupsettings-form.html b/group/groupui/editgroupsettings-form.html new file mode 100644 index 0000000000..35bbdae7b1 --- /dev/null +++ b/group/groupui/editgroupsettings-form.html @@ -0,0 +1,22 @@ + diff --git a/group/groupui/editgroupsettings-form.js b/group/groupui/editgroupsettings-form.js new file mode 100644 index 0000000000..7bd9e22725 --- /dev/null +++ b/group/groupui/editgroupsettings-form.js @@ -0,0 +1,79 @@ + +function onEditGroupSettingsSave() { + valid = validateEditgroupsettingsForm(); + if (valid) { + editgroupsettings() ; + hideAllForms(); + showElement("groupeditform"); + } + return false; +} + +/** + * Creates a new group for the course. + */ +function editGroupSettings() { + // alert("Called editgroupsettings"); + var url = "editgroupsettings-xml.php"; + var requeststring = "groupid="+selectedgroupid + +"&groupname="+getTextInputValue('groupname') + +"&description="+getTextInputValue('edit-groupdescription') + +"&enrolmentkey="+getTextInputValue('enrolmentkey') + +"&hidepicture="+hidepicture; + // The picture fields aren't displayed if the right library isn't present + if (document.getElementById('menuhidepicture')) { + requeststring = requeststring+"&hidepicture="+getTextInputValue('menuhidepicture'); + } + sendPostRequest(request, url, requeststring, editGroupSettingsResponse); + } + + /** + * The callback for the response to the request sent in editgroupsettings(() + */ + function editGroupSettingsResponse() { + if (checkAjaxResponse(request)) { + // alert("editgroupsettingsResponse"); + // alert(request.responseText); + error = getFromXML(request.responseXML, 'error'); + if (error != null) { + alert(error); + } + updateSelectedGrouping(); + hideElement("editgroupsettingsform"); + } +} + +function getGroupSettings() { + // alert("Called getgroupsettings"); + groupid = getSelectedGroup(); + var url = "getgroupsettings-xml.php"; + var requeststring = "groupid="+groupid; + sendPostRequest(request, url, requeststring, getGroupSettingsResponse); +} + +function getGroupSettingsResponse() { + if (checkAjaxResponse(request)) { + // alert("getgroupsettingsResponse"); + // alert(request.responseText); + error = getFromXML(request.responseXML, 'error'); + if (error != null) { + alert(error); + } + xml = request.responseXML; + setTextInputValue('groupname', getFromXML(xml, 'name')); + setTextInputValue('edit-groupdescription', getFromXML(xml, 'description')); + setTextInputValue('enrolmentkey', getFromXML(xml, 'enrolmentkey')); + } +} + +function validateEditgroupsettingsForm() { + valid = true; + groupname = getTextInputValue('groupname'); + + if (groupname == '') { + alert('You must enter a name for the new group'); + valid = false; + } + return valid; +} + diff --git a/group/groupui/editgroupsettings-xml.php b/group/groupui/editgroupsettings-xml.php new file mode 100644 index 0000000000..f9baae05b9 --- /dev/null +++ b/group/groupui/editgroupsettings-xml.php @@ -0,0 +1,48 @@ +"; +echo ''; + +include_once('../../../config.php'); +include('../lib/lib.php'); +$groupid = required_param('groupid'); +$groupname = required_param('groupname'); +$description = required_param('description'); +$enrolmentkey = required_param('enrolmentkey'); +$hidepicture = required_param('hidepicture'); +$courseid = required_param('courseid', PARAM_INT); + +require_login($courseid); + +if (confirm_sesskey() and isteacheredit($courseid)) { + $groupsettings->name = $groupname; + $groupsettings->description = $description; + $groupsettings->enrolmentkey = $enrolmentkey; + $groupsettings->hidepicture = $hidepicture; + + // Upload the group icon if there is one - note that we don't remove any previous icons + require_once($CFG->dirroot.'/lib/uploadlib.php'); + $um = new upload_manager('groupicon', false, false, null, false, 0, true, true); + if ($um->preprocess_files()) { + require_once("$CFG->libdir/gdlib.php"); + if (save_profile_image($groupid, $um, 'groups')) { + $groupsettings->picture = 1; + } else { + echo 'Failed to save group image'; + } + } else { + $groupsettings->picture = 0; + } + + $infoset = groups_set_group_settings($groupid, $groupsettings); + if (!$infoset) { + echo "Failed to set new group settings"; + } +} + +echo ''; +?> \ No newline at end of file diff --git a/group/groupui/form.css b/group/groupui/form.css new file mode 100644 index 0000000000..e8e92f01e6 --- /dev/null +++ b/group/groupui/form.css @@ -0,0 +1,52 @@ +.popup +{ + position:absolute; + left:300px; + top:80px; + width:550px; + border-style:solid; + border-color: grey; + border-width: 1px; + background-color: white; + padding:10px; + z-index:1; + visibility: hidden; +} + +.popupwide +{ + position:absolute; + left:200px; + top:80px; + width:900px; + border-style:solid; + border-color: grey; + border-width: 1px; + background-color: white; + padding:10px; + z-index:1; + visibility: hidden; +} + +.select +{ + overflow: visible; + clip: auto; + width:200px; +} + +.groupmanagementtable +{ + padding: 10px; + margin-left: auto; + margin-right: auto; + text-align: center; +} + +.groupmanagementtableheader +{ + width: 300px; +} + + + diff --git a/group/groupui/form.html b/group/groupui/form.html new file mode 100644 index 0000000000..e193f668a5 --- /dev/null +++ b/group/groupui/form.html @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/group/groupui/getgroupingpermissions-xml.php b/group/groupui/getgroupingpermissions-xml.php new file mode 100644 index 0000000000..eecd903104 --- /dev/null +++ b/group/groupui/getgroupingpermissions-xml.php @@ -0,0 +1,64 @@ +"; +echo ''; + +include_once("../../../config.php"); +include("../lib/lib.php"); + + + +$courseid = required_param('courseid', PARAM_INT); +$groupingid = required_param('groupingid', PARAM_INT); + +require_login($courseid); + +if (confirm_sesskey() and isteacheredit($courseid)) { + $groupingsettings = groups_get_grouping_settings($groupingid); + echo ''.$groupingsettings->name.''; + + if ($groupingsettings->viewowngroup) { + echo 'true'; + } else { + echo 'false'; + } + + if ($groupingsettings->viewallgroupsmembers) { + echo 'true'; + } else { + echo 'false'; + } + + if ($groupingsettings->viewallgroupsactivities) { + echo 'true'; + } else { + echo 'false'; + } + + if ($groupingsettings->teachersgroupmark) { + echo 'true'; + } else { + echo 'false'; + } + + if ($groupingsettings->teachersgroupview) { + echo 'true'; + } else { + echo 'false'; + } + + if ($groupingsettings->teachersoverride) { + echo 'true'; + } else { + echo 'false'; + } + +} + +echo ''; +?> \ No newline at end of file diff --git a/group/groupui/getgroupings-xml.php b/group/groupui/getgroupings-xml.php new file mode 100644 index 0000000000..13ab9174c1 --- /dev/null +++ b/group/groupui/getgroupings-xml.php @@ -0,0 +1,41 @@ +"; +echo ''; + +include_once("../../../config.php"); +include("../lib/lib.php"); + +$courseid = required_param('courseid', PARAM_INT); + +require_login($courseid); + +if (confirm_sesskey() and isteacheredit($courseid)) { + $groupingids = groups_get_groupings($courseid); + if ($groupingids != false) { + // Put the groupings into a hash and sort them + foreach($groupingids as $groupingid) { + $listgroupings[$groupingid] = groups_get_grouping_displayname($groupingid); + } + natcasesort($listgroupings); + + // Print out the XML + echo ''; + } +} + +echo ''; +?> + + + diff --git a/group/groupui/getgroupingsettings-xml.php b/group/groupui/getgroupingsettings-xml.php new file mode 100644 index 0000000000..5c4d51f774 --- /dev/null +++ b/group/groupui/getgroupingsettings-xml.php @@ -0,0 +1,29 @@ +"; +echo ''; + +include_once("../../../config.php"); +include("../lib/lib.php"); + + + +$courseid = required_param('courseid', PARAM_INT); +$groupingid = required_param('groupingid', PARAM_INT); + +require_login($courseid); + +if (confirm_sesskey() and isteacheredit($courseid)) { + $groupingsettings = groups_get_grouping_settings($groupingid); + echo ''.$groupingsettings->name.''; + echo ''.$groupingsettings->description.''; + +} + +echo ''; +?> \ No newline at end of file diff --git a/group/groupui/getgroupsettings-xml.php b/group/groupui/getgroupsettings-xml.php new file mode 100644 index 0000000000..1a4f3ba99f --- /dev/null +++ b/group/groupui/getgroupsettings-xml.php @@ -0,0 +1,37 @@ +"; +echo ''; + +include_once("../../../config.php"); +include("../lib/lib.php"); + + + +$courseid = required_param('courseid', PARAM_INT); +$groupid = required_param('groupid', PARAM_INT); +require_login($courseid); + +if (confirm_sesskey() and isteacheredit($courseid)) { + + $groupsettings = groups_get_group_settings($groupid); + if (!$groupsettings) { + echo 'Failed to get group details'; + } else { + echo ''.$groupsettings->name.''; + echo ''.$groupsettings->description.''; + echo ''.$groupsettings->enrolmentkey.''; + echo ''.$groupsettings->hidepicture.''; + echo ''.$groupsettings->picture.''; + echo ''.$groupinkfo->lang.''; + echo ''.$groupsettings->theme.''; + } +} + +echo ''; +?> \ No newline at end of file diff --git a/group/groupui/getgroupsingrouping-xml.php b/group/groupui/getgroupsingrouping-xml.php new file mode 100644 index 0000000000..c7d210ca43 --- /dev/null +++ b/group/groupui/getgroupsingrouping-xml.php @@ -0,0 +1,39 @@ +"; +echo ''; + +include_once("../../../config.php"); +include_once("../lib/lib.php"); + +$groupingid = required_param('groupingid', PARAM_INT); +$courseid = required_param('courseid', PARAM_INT); + +require_login($courseid); + +if (confirm_sesskey() and isteacheredit($courseid)) { + $groupids = groups_get_groups_in_grouping($groupingid); + + if ($groupids != false) { + // Put the groupings into a hash and sort them + foreach($groupids as $groupid) { + $listgroups[$groupid] = groups_get_group_displayname($groupid); + } + + natcasesort($listgroups); + + // Print out the XML + echo ""; + } +} + +echo ''; +?> diff --git a/group/groupui/getgroupsnotingrouping-xml.php b/group/groupui/getgroupsnotingrouping-xml.php new file mode 100644 index 0000000000..9adcb00b54 --- /dev/null +++ b/group/groupui/getgroupsnotingrouping-xml.php @@ -0,0 +1,39 @@ +"; +echo ''; + +include_once("../lib/lib.php"); +include_once("../../../config.php"); + +$groupingid = required_param('groupingid'); +$courseid = required_param('courseid'); + +require_login($courseid); + +if (confirm_sesskey() and isteacheredit($courseid)) { + $groupids = groups_get_groups_not_in_grouping($groupingid, $courseid); + if ($groupids != false) { + // Put the groupings into a hash and sort them + foreach($groupids as $groupid) { + $listgroups[$groupid] = groups_get_group_displayname($groupid); + } + + natcasesort($listgroups); + + // Print out the XML + echo ""; + } +} + +echo ''; +?> diff --git a/group/groupui/getmembers-xml.php b/group/groupui/getmembers-xml.php new file mode 100644 index 0000000000..fa6695836f --- /dev/null +++ b/group/groupui/getmembers-xml.php @@ -0,0 +1,44 @@ +"; +echo ''; + +include_once("../../../config.php"); +include_once("../lib/lib.php"); + + +$groupid = required_param('groupid', PARAM_INT); +$courseid = required_param('courseid', PARAM_INT); + +require_login($courseid); + +if (confirm_sesskey() and isteacheredit($courseid)) { + + $userids = groups_get_members($groupid); + + if ($userids != false) { + // Put the groupings into a hash and sort them + foreach($userids as $userid) { + $listmembers[$userid] = groups_get_user_displayname($userid, $courseid); + } + natcasesort($listmembers); + + + // Print out the XML + + echo ""; + } +} + +echo ''; +?> diff --git a/group/groupui/getnonmembers-xml.php b/group/groupui/getnonmembers-xml.php new file mode 100644 index 0000000000..5ec6457864 --- /dev/null +++ b/group/groupui/getnonmembers-xml.php @@ -0,0 +1,49 @@ +"; +echo ''; +include_once("../../../config.php"); +include_once("../lib/lib.php"); + + +$groupid = required_param('groupid', PARAM_INT); +$groupingid = required_param('groupingid', PARAM_INT); +$courseid = required_param('courseid', PARAM_INT); +$showall = required_param('showall', PARAM_INT); + +require_login($courseid); + +if (confirm_sesskey() and isteacheredit($courseid)) { + echo "$groupingid $groupid"; + if ($showall == 0) { + $userids = groups_get_users_not_in_any_group_in_grouping($courseid,$groupingid, $groupid); + } else { + $userids = groups_get_users_not_in_group($courseid, $groupid); + } + + if ($userids != false) { + // Put the groupings into a hash and sorts them + foreach($userids as $userid) { + $listmembers[$userid] = groups_get_user_displayname($userid, $courseid); + } + natcasesort($listmembers); + + + // Print out the XML + echo ""; + } + } + +echo ''; +?> diff --git a/group/groupui/index.php b/group/groupui/index.php new file mode 100644 index 0000000000..d6d3a6e8c2 --- /dev/null +++ b/group/groupui/index.php @@ -0,0 +1,59 @@ +dirroot.'/lib/uploadlib.php'); + +$error = false; + +$courseid = required_param('id'); + +// Get the course information so we can print the header and check the course id +// is valid +$course = groups_get_course_info($courseid); +if (!$course) { + $error = true; + print_error('The course id is invalid'); +} + + +if (!$error) { + // Make sure that the user is a teacher with edit permission for this course + require_login($courseid); + if (!isteacheredit($courseid)) { + redirect(); + } + + // Set the session key so we can check this later + $sesskey = !empty($USER->id) ? $USER->sesskey : ''; + + if (!empty($CFG->gdversion) and $maxbytes) { + $printuploadpicture = true; + } else { + $printuploadpicture = false; + } + + + $maxbytes = get_max_upload_file_size($CFG->maxbytes, $course->maxbytes); + $strgroups = get_string('groups'); + $strparticipants = get_string('participants'); + // Print the page and form + print_header("$course->shortname: $strgroups", + "$course->fullname", + "wwwroot/course/view.php?id=$courseid\">$course->shortname ". + "-> wwwroot/user/index.php?id=$courseid\">$strparticipants ". + "-> $strgroups", "", "", true, '', user_login_string($course, $USER)); + + include('form.html'); + + print_footer($course); + +} + +?> diff --git a/group/groupui/main-buttons-form.js b/group/groupui/main-buttons-form.js new file mode 100644 index 0000000000..c13880bfe7 --- /dev/null +++ b/group/groupui/main-buttons-form.js @@ -0,0 +1,66 @@ + + +function onShowAddMembersForm() { + hideAllForms(); + showElement("addmembersform"); + updateNonMembers(); + groupname = getSelectedGroupName(); + replaceText('selectedgroup', groupname); + return false; +} + +function onShowAddGroupsToGroupingForm() { + hideAllForms(); + showElement("addgroupstogroupingform"); + updateGroupsNotInGrouping(); + groupingname = getSelectedGroupingName(); + replaceText('selectedgroupingforaddinggroups', groupingname); + return false; +} + +function onShowCreateGroupingForm() { + hideAllForms(); + showElement("creategroupingform"); + return false; +} + +function onShowCreateGroupForm() { + hideAllForms(); + showElement("creategroupform"); + groupingname = getSelectedGroupingName(); + replaceText('selectedgroupingforcreatinggroup', groupingname); + return false; +} + +function onShowEditGroupSettingsForm() { + hideAllForms(); + showElement("editgroupsettingsform"); + getGroupSettings(); + return false; +} + +function onShowEditGroupingPermissionsForm() { + hideAllForms(); + showElement("editgroupingpermissionsform"); + getGroupingPermissions(); + return false; +} + +function onShowEditGroupingSettingsForm() { + hideAllForms(); + showElement("editgroupingsettingsform"); + getGroupingSettings(); + return false; +} + + +function onShowAutomaticGroupingForm() { + hideAllForms(); + showElement("createautomaticgroupingform"); + return false; +} + +function onPrinterFriendly() { + document.location.href = "printgrouping.php?courseid="+courseid+"&groupingid="+selectedgroupingid; + return false; +} diff --git a/group/groupui/main-form.html b/group/groupui/main-form.html new file mode 100644 index 0000000000..af48f448a4 --- /dev/null +++ b/group/groupui/main-form.html @@ -0,0 +1,41 @@ +
+ + + + + + + + + + + + + + + + +
+ + + + + +
+

+

+

+

+

+

+
+

+

+

+

+

+
+

+

+
+
diff --git a/group/groupui/main-init-form.js b/group/groupui/main-init-form.js new file mode 100644 index 0000000000..b4914e5073 --- /dev/null +++ b/group/groupui/main-init-form.js @@ -0,0 +1,75 @@ +/* + * This file contains all the functions called when the pages loads and also all the functions that are called + * on events such as clicking buttons in the forms for the form.html page. + * + * This script requires functions from ajax.js and form-access.js + * + * This code also assumes you have a basic understanding of how Ajax works - if + * you don't, it won't make much sense! +*/ + + + +// Create XMLHttpRequest objects to use +var request = createRequest(); +var updategroupingsrequest = createRequest(); +var updateselectedgroupingsrequest = createRequest(); +var updateselectedgrouprequest = createRequest(); + +// The selectedgroupingid should always be set to the current selected groupingid and the +// selectedgroupid should always be set to the current selected groupid. We initialise them to +// be null at the start, but they'll get set when the page loads. +var selectedgroupingid = null; +var selectedgroupid = null; + +// When the page has loaded called the initPage function +window.onload = initPage; + +/** + * The initPage function updates the groupings, groups and members in all the selects appropriately + *and adds the right javascript events to all the buttons etc. + */ +function initPage() { + // Check that we're using a recent enough version of javascript + if (!document.getElementById) { + return false; + } + updateGroupings(); + + addEvent('groupings', 'change', onGroupingChange); + addEvent('groups', 'change', onGroupChange); + addEvent('deletegrouping', 'click', onDeleteGrouping); + addEvent('deletegroup', 'click', onDeleteGroup); + addEvent('removegroup', 'click', onRemoveGroup); + addEvent('removemembers', 'click', onRemoveMembers); + addEvent('showaddmembersform', 'click', onShowAddMembersForm); + addEvent('showaddgroupstogroupingform', 'click', onShowAddGroupsToGroupingForm); + addEvent('showcreategroupingform', 'click', onShowCreateGroupingForm); + addEvent('showcreategroupform', 'click', onShowCreateGroupForm); + addEvent('showeditgroupsettingsform', 'click', onShowEditGroupSettingsForm); + addEvent('showeditgroupingsettingsform', 'click', onShowEditGroupingSettingsForm); + addEvent('showeditgroupingpermissionsform', 'click', onShowEditGroupingPermissionsForm); + addEvent('showcreateautomaticgroupingform', 'click', onShowAutomaticGroupingForm); + addEvent('printerfriendly', 'click', onPrinterFriendly); + addEvent('createautomaticgrouping', 'click', onCreateAutomaticGrouping); + addEvent('cancelcreateautomaticgrouping', 'click', onCancel); + addEvent('addgroupstogrouping', 'click', onAddGroupsToGrouping); + addEvent('canceladdgroupstogrouping', 'click', onCancel); + addEvent('creategroup', 'click', onCreateGroup); + addEvent('cancelcreategroup', 'click', onCancel); + addEvent('creategrouping', 'click', onCreateGrouping); + addEvent('cancelcreategrouping', 'click', onCancel); + addEvent('addmembers', 'click', onAddMembers); + addEvent('canceladdmembers', 'click', onCancel); + addEvent('showall', 'change', onShowAll); + addEvent('editgroupsettings', 'click', onEditGroupSettingsSave); + addEvent('canceleditgroupsettings', 'click', onCancel); + addEvent('editgroupingsettings', 'click', onEditGroupingSettingsSave); + addEvent('canceleditgroupingsettings', 'click', onCancel); + addEvent('editgroupingpermissions', 'click', onEditGroupingPermissionsSave); + addEvent('canceleditgroupingpermissions', 'click', onCancel); +} + + + + diff --git a/group/groupui/main-selects-form.js b/group/groupui/main-selects-form.js new file mode 100644 index 0000000000..3b5c08ef2e --- /dev/null +++ b/group/groupui/main-selects-form.js @@ -0,0 +1,255 @@ +/** + * This file contains various utility functions, primarily to get and set information on form.html + * and to take information from XML documents and either return information from them or modifiy the + * form appropriately. + */ + + +function onGroupingChange() { + hideAllForms(); + showElement("groupeditform"); + if (!document.getElementById('groupings')) { + alert('No groupings id element'); + } else { + groupingselect = document.getElementById('groupings'); + selectedgroupingid = groupingselect.value; + selectedgroupid = null; + updateSelectedGrouping(); + } + return false; +} + +function onGroupChange() { + hideAllForms(); + showElement("groupeditform"); + selectedgroupid = getSelectedGroup(); + updateSelectedGroup(); + return false; +} + + +function getSelectedGroupingName() { + if (!document.getElementById('groupings')) { + alert('No groupings id element'); + value = null; + } else { + groupingselect = document.getElementById('groupings'); + value = groupingselect.options[groupingselect.selectedIndex].firstChild.nodeValue; + } + return value; +} + +function getSelectedGroupName() { + if (!document.getElementById('groups')) { + alert('No groups id element'); + value = null; + } else { + groupselect = document.getElementById('groups'); + value = groupselect.options[groupselect.selectedIndex].firstChild.nodeValue; + } + return value; +} + +/* + * Set the selected grouping on the form to the grouping whose id is selectedgroupingid + */ +function setSelectedGrouping() { + if (selectedgroupingid == null) { + selectedgroupingid = getFirstOption("groupings"); + } + + if (selectedgroupingid != null) { + if (!document.getElementById('groupings')) { + alert('No groupings id element'); + } else { + groupingselect = document.getElementById('groupings'); + groupingselect.value = selectedgroupingid + } + } +} + +/* + * Get the id of the group that is currently selected + */ +function getSelectedGroup() { + if (!document.getElementById('groups')) { + alert('No groups id element'); + value = null; + } else { + groupselect = document.getElementById('groups'); + value = groupselect.value; + } + return value; +} + +/* + * Set the selected group on the form to the group whose id is selectedgroupid + */ +function setSelectedGroup() { + if (selectedgroupid == null) { + selectedgroupid = getFirstOption("groups"); + } + + if (selectedgroupid != null) { + if (!document.getElementById('groups')) { + alert('No groups id element'); + } else { + groupselect = document.getElementById('groups'); + groupselect.value = selectedgroupid; + } + } +} + + +/* + * Get the selected users to delete + */ +function getSelectedUsers() { + return getMultipleSelect("members") +} + + + +/*************************************************************** + * Functions that just display information (and don't change the data in the database) + **********************************************/ + +/** + * Updates the list of groupings, setting either a specified grouping as selected or + * the first grouping as selected. + */ +function updateGroupings() { + alert("updateGroupings called"); + var url = "getgroupings-xml.php"; + requeststring = 'courseid='+courseid+'&'+'sesskey='+sesskey; + var transaction = YAHOO.util.Connect.asyncRequest('POST', url, + updateGroupingsResponseCallback, requeststring); + //sendPostRequest(updategroupingsrequest, url, requeststring, updateGroupingsResponse); +} + +var updateGroupingsResponseCallback = +{ + success:updateGroupingsResponse, + failure:responseFailure, +}; + + +/** + * The callback function for updateGroupings() + * Takes the XML containing the grouping details that has been sent back and updates the display. + */ +function updateGroupingsResponse() { + + alert("Called updateGroupingsResponse"); + if (updategroupingsrequest.readyState == 4 && updategroupingsrequest.status == 200) { + alert("updateGroupingsResponse called"); + var xmlDoc = updategroupingsrequest.responseXML; + error = getFromXML(updategroupingsrequest.responseXML, 'error'); + if (error != null) { + alert(error); + } + alert(updategroupingsrequest.responseText); + var noofoptions = addOptionsFromXML("groupings", xmlDoc); + + // If the selected grouping is not set, set it to the first grouping in the list + if(selectedgroupingid == null) { + selectedgroupingid = getFirstOption("groupings"); + selectedgroupid = null; + } + + // If there are no groupings, make sure the rest of the form is set up appropriately + // i.e. there should be any groups or members shown and various buttons should be disabled + // If there are groupings, update the one that is selected and enable any buttons that + // might have been disabled. + if (noofoptions == 0) { + removeOptions("groups"); + removeOptions("members"); + disableButton("showaddmembersform"); + disableButton("showcreategroupform"); + disableButton("showaddgroupstogroupingform"); + } else { + updateSelectedGrouping(); + enableButton("showaddmembersform"); + enableButton("showcreategroupform"); + enableButton("showaddgroupstogroupingform"); + } + } +} + +/** + * Updates the list of groups when groupingid is marked as selected + * groupid can be null or a specified group - this is the group that gets marked as + * selectedgroupingid cannot be null. + */ +function updateSelectedGrouping() { + //alert("UpdateSelectedGrouping called"); + setSelectedGrouping(); + var url = "getgroupsingrouping-xml.php"; + requeststring = "groupingid="+selectedgroupingid; + sendPostRequest(updateselectedgroupingsrequest, url, requeststring, updateSelectedGroupingResponse); +} + +/** + * The callback for the response to the request sent in updateSelectedGrouping() + */ +function updateSelectedGroupingResponse() { + if (checkAjaxResponse(updateselectedgroupingsrequest)) { + //alert("updateSelectedGroupingResponse called"); + var xmlDoc = updateselectedgroupingsrequest.responseXML; + error = getFromXML(updateselectedgroupingsrequest.responseXML, 'error'); + if (error != null) { + alert(error); + } + // alert(updateselectedgroupingsrequest.responseText); + var noofoptions = addOptionsFromXML("groups", xmlDoc); + if (selectedgroupid == null) { + selectedgroupid = getFirstOption("groups"); + } + + if (noofoptions == 0) { + removeOptions("members"); + disableButton("showaddmembersform"); + } else { + updateSelectedGroup(selectedgroupid); + enableButton("showaddmembersform"); + } + } +} + +/** + * Updates the members for the selected group - currently none marked as selected + */ +function updateSelectedGroup() { + //alert("updateSelectedGroup"); + setSelectedGroup(); + var url = "getmembers-xml.php"; + var requeststring = "groupid="+selectedgroupid; + sendPostRequest(updateselectedgrouprequest, url, requeststring, updateSelectedGroupResponse); +} + +/** + * The callback for the response to the request sent in updateSelectedGroup() + */ +function updateSelectedGroupResponse() { + if (checkAjaxResponse(updateselectedgrouprequest)) { + var xmlDoc = updateselectedgrouprequest.responseXML; + //alert("updateSelectedGroupResponse"); + error = getFromXML(xmlDoc, 'error'); + if (error != null) { + alert(error); + } + + //alert(request.responseText); + var noofoptions = addOptionsFromXML("members", xmlDoc); + } +} + + + + + + + + + + diff --git a/group/groupui/printgrouping.php b/group/groupui/printgrouping.php new file mode 100644 index 0000000000..2f1927597c --- /dev/null +++ b/group/groupui/printgrouping.php @@ -0,0 +1,64 @@ +shortname: $strgroups", "$course->fullname", + "wwwroot/course/view.php?id=$courseid\">$course->shortname ". + "-> wwwroot/user/index.php?id=$courseid\">$strparticipants ". + "-> wwwroot/course/groups/groupui/index.php?id=$courseid\">$strgroups". + "-> Display grouping", "", "", true, '', user_login_string($course, $USER)); + + $groupingsettings = groups_get_grouping_settings($groupingid); + + // Print the name of the grouping + $name = $groupingsettings->name; + print("

$name

"); + + // Get the groups and group members for the grouping + $groupids = groups_get_groups_in_grouping($groupingid); + + if ($groupids != false) { + + // Make sure the groups are in the right order + foreach($groupids as $groupid) { + $listgroups[$groupid] = groups_get_group_displayname($groupid); + } + + natcasesort($listgroups); + + // Go through each group in turn and print the group name and then the members + foreach($listgroups as $groupid=>$groupname) { + print "

$groupname

"; + $userids = groups_get_members($groupid); + if ($userids != false) { + // Make sure the users are in the right order + unset($listmembers); + foreach($userids as $userid) { + $listmembers[$userid] = groups_get_user_displayname($userid, $courseid); + } + natcasesort($listmembers); + + foreach($listmembers as $userid=>$name) { + print("$name
"); + } + } + } + } + + print_footer($course); + +} + +?> diff --git a/group/groupui/removegroupfromgrouping-xml.php b/group/groupui/removegroupfromgrouping-xml.php new file mode 100644 index 0000000000..604ed7ef6f --- /dev/null +++ b/group/groupui/removegroupfromgrouping-xml.php @@ -0,0 +1,28 @@ +"; +echo ''; + +include_once("../../../config.php"); +include("../lib/lib.php"); + +$groupid = required_param('groupid', PARAM_INT); +$groupingid = required_param('groupingid', PARAM_INT); +$courseid = required_param('courseid', PARAM_INT); + +require_login($courseid); + +if (confirm_sesskey() and isteacheredit($courseid)) { + $groupingremoved = groups_remove_group_from_grouping($groupid, $groupingid); + if (!$groupingremoved) { + echo 'Failed to remove group from grouping'; + } +} + +echo ''; +?> diff --git a/group/groupui/removegroupfromgrouping.js b/group/groupui/removegroupfromgrouping.js new file mode 100644 index 0000000000..df4b38335a --- /dev/null +++ b/group/groupui/removegroupfromgrouping.js @@ -0,0 +1,34 @@ + +function onRemoveGroup() { + hideAllForms(); + showElement("groupeditform"); + removeGroupFromGrouping(); + return false; +} + +/** + * Removes the selected group from the selected grouping, does not delete the group (so it can e.g. be added to + * another grouping + */ +function removeGroupFromGrouping() { + //alert("Called removeGroupFromGrouping"); + var url = "removegroupfromgrouping-xml.php"; + var requeststring = "groupid="+selectedgroupid+"&groupingid="+selectedgroupingid; + sendPostRequest(request, url, requeststring, removeGroupFromGroupingResponse); +} + +/** + * The callback for the response to the request sent in removeGroupFromGrouping() + */ +function removeGroupFromGroupingResponse() { + if (checkAjaxResponse(request)) { + //alert("removeGroupFromGroupingResponse called"); + var xmlDoc= request.responseXML; + // Need XML sent back with groupingid + // Really want to set this to be the grouping before + selectedgroupid = null; + updateGroupings(); + } +} + + diff --git a/group/groupui/removemembers-xml.php b/group/groupui/removemembers-xml.php new file mode 100644 index 0000000000..2da318847b --- /dev/null +++ b/group/groupui/removemembers-xml.php @@ -0,0 +1,39 @@ +"; +echo ''; + +include_once("../../../config.php"); +include("../lib/lib.php"); + +$groupid = required_param('groupid', PARAM_INT); +$users = required_param('users'); +$courseid = required_param('courseid', PARAM_INT); + +require_login($courseid); + +if (confirm_sesskey() and isteacheredit($courseid)) { + // Change the comma-separated string of the userids into an array of the userids + $userids = explode(',', $users); + if ($userids != false) { + // Remove each user in turn from the group. + foreach($userids as $userid) { + $useradded = groups_remove_member($userid, $groupid); + if (!$useradded) { + echo "Failed to adduser $userid"; + } + } + } +} + + +echo ''; + +?> diff --git a/group/groupui/removemembers.js b/group/groupui/removemembers.js new file mode 100644 index 0000000000..ef16b9b88e --- /dev/null +++ b/group/groupui/removemembers.js @@ -0,0 +1,33 @@ + + + +function onRemoveMembers() { + hideAllForms(); + showElement("groupeditform"); + removeMembers(); + return false; +} + + + +/** + * Removes the selected members from the selected group + */ +function removeMembers() { + //alert("Called removeMembers"); + users = getSelectedUsers(); + var url = "removemembers-xml.php"; + var requeststring = "groupid="+selectedgroupid+"&users="+users; + sendPostRequest(request, url, requeststring, removeMembersResponse); +} + +/** + * The callback for the response to the request sent in removeMembers() + */ +function removeMembersResponse() { + if (checkAjaxResponse(request)) { + //alert("removeMembersResponse called"); + //alert(request.responseText); + updateSelectedGroup(); + } +} diff --git a/group/groupui/util-form.js b/group/groupui/util-form.js new file mode 100644 index 0000000000..84be35edd5 --- /dev/null +++ b/group/groupui/util-form.js @@ -0,0 +1,358 @@ +/** + * This file contains various utility functions, primarily to get and set information on form.html + * and to take information from XML documents and either return information from them or modifiy the + * form appropriately. + */ + +/* + * Disable the button with the specified id + */ +function disableButton(id) { + if (!document.getElementById(id)) { + showNoElementError(id) + } else { + var node = document.getElementById(id); + node.disabled = true; + } +} + +/** + * Enable the button with the specified id + */ +function enableButton(id) { + if (!document.getElementById(id)) { + showNoElementError(id) + } else { + var node = document.getElementById(id); + node.disabled = false; + } +} + +/** + * Show the form with the specified id + */ +function showElement(id) { + if (!document.getElementById(id)) { + showNoElementError(id) + } else { + document.getElementById(id).style.visibility = "visible"; + } +} + +/** + * Hide the form with the specified id + */ +function hideElement(id) { + if (!document.getElementById(id)) { + showNoElementError(id) + } else { + var node = document.getElementById(id); + node.style.visibility = "hidden"; + } +} + + +/** + * Hides all the extra forms in form.html + */ +function hideAllForms() { + hideElement("addmembersform"); + hideElement("addgroupstogroupingform"); + hideElement("creategroupingform"); + hideElement("createautomaticgroupingform"); + hideElement("creategroupform"); + hideElement("editgroupingsettingsform"); + hideElement("editgroupingpermissionsform"); + hideElement("editgroupsettingsform"); + hideElement("groupeditform"); +} + +function onCancel() { + hideAllForms(); + showElement("groupeditform"); + return false; +} + + +function addEvent(id, eventtype, fn){ + if (!document.getElementById(id)) { + alert('No ' + id + ' element'); + return false; + } else { + obj = document.getElementById(id); + } + + if (obj.addEventListener) { + obj.addEventListener(eventtype, fn, false ); + } else if (obj.attachEvent) { + obj["e"+ eventtype +fn] = fn; + obj[eventtype+fn] = function() { obj["e"+ eventtype +fn]( window.event ); } + obj.attachEvent( "on"+ eventtype , obj[eventtype+fn] ); + } else { + obj["on"+type] = obj["e"+ eventtype +fn]; + } +} + +/** + * Gets the value of the first option in a select + */ +function getFirstOption(id) { + if (document.getElementById(id)) { + var node = document.getElementById(id); + if (node.hasChildNodes()) { + var children + firstoption = node.firstChild; + if (firstoption.value) { + value = firstoption.value; + } else { + value = null; + } + } else { + value = null; + } + } else { + value = null; + } + return value; +} + +/* + *Turn the values from a multiple select to a comma-separated list +*/ +function getMultipleSelect(id) { + if (!document.getElementById(id)) { + showNoElementError(id) + } else { + node = document.getElementById(id); + } + var selected = "" + + for (var i = 0; i < node.options.length; i++) { + if (node.options[i].selected) { + selected = selected + node.options[ i ].value + ","; + } + } + // Remove the last comma - there must be a nicer way of doing this! + // Maybe easier with regular expressions? + var length = selected.length; + if (selected.charAt(length - 1) == ',') { + selected = selected.substring(0, length -1); + } + + return selected; +} + +/* + * Creates an option in a select element with the specified id with the given name and value. +*/ +function createOption(id, value, name) { + var node = document.getElementById(id); + var option = document.createElement("option"); + option.setAttribute("value", value); + node.appendChild(option); + var namenode = document.createTextNode(name); + option.appendChild(namenode); +} + +/* + * Removes all the options from a select with a given id +*/ +function removeOptions(id) { + var node = document.getElementById(id); + + while (node.hasChildNodes()) + { + node.removeChild(node.firstChild); + } +} + +/* + * Takes an XML doc of the form + * And adds an option to the selected with the specified id + * @param id The id of the select + * @param xmlDoc The XML document + * @return The number of options added + */ +function addOptionsFromXML(id, xmlDoc) { + // Clear any options that are already there. + removeOptions(id); + + var optionelements = xmlDoc.getElementsByTagName('option'); + var nameelements = xmlDoc.getElementsByTagName('name'); + var valueelements = xmlDoc.getElementsByTagName('value'); + + if (nameelements != null) { + for (var i = 0; i < nameelements.length; i++) { + var name = nameelements[i].firstChild.nodeValue; + var value = valueelements[i].firstChild.nodeValue; + createOption(id, value, name); + } + noofoptions = nameelements.length; + } else { + noofoptions = 0; + } + return noofoptions; +} + +/* + * Gets an error from an XML doc contain a tag of the form + * If it contains more than one such tag, it only return the value from the first one. + */ +function getErrorFromXML(xmlDoc) { + alert(xmlDoc.getElementsByTagName('error')); + if (!xmlDoc.getElementsByTagName('error')) { + value = null; + } else { + var errorelement = xmlDoc.getElementsByTagName('error')[0]; + var value = errorelement.firstChild.nodeValue; + } + return value; +} + + +function addChildrenFromXML(parentnode, xmlparentnode) { + xmlChildNodes = xmlparentnode.childNodes; + length = xmlChildNodes.length; + for (i = 0; i < length; i++) { + child = parentnode.appendChild(parentnode, xmlChildNodes[i]); + addChildrenFromXML(child, xmlChildNodes[i]) + } +} + +function getTextInputValue(id) { + if (!document.getElementById(id)) { + showNoElementError(id) + value = null; + } else { + textinput = document.getElementById(id); + value = textinput.value; + } + return value; +} + +function setTextInputValue(id, value) { + if (!document.getElementById(id)) { + showNoElementError(id); + value = null; + } else { + textinput = document.getElementById(id); + textinput.value = value; + } +} + +function getCheckBoxValue(id) { + if (!document.getElementById(id)) { + showNoElementError(id); + value= null; + } else { + checkbox = document.getElementById(id); + value = checkbox.checked; + } + return boolToInt(value); +} + +function boolStringToBool(boolstring) { + if (boolstring == 'true') { + return true; + } else { + return false; + } +} + +function boolToInt(boolean) { + if (boolean) { + return '1'; + } else if (boolean == false) { + return '0'; + } else { + return boolean; + } +} + +function setCheckBoxValue(id, checked) { + if (!document.getElementById(id)) { + showNoElementError(id); + } else { + checkbox = document.getElementById(id); + checkbox.checked = checked; + } +} + +function replaceText(id, text) { + if (!document.getElementById(id)) { + showNoElementError(id) + value = null; + } else { + element = document.getElementById(id); + if (element.childNodes) { + for (var i = 0; i < element.childNodes.length; i++) { + var childNode = element.childNodes[i]; + element.removeChild(childNode); + } + } + var textnode = document.createTextNode(text); + element.appendChild(textnode); + } +} + + + function getRadioValue(radioelement) { + value = ""; + if (!radioelement) { + value = ""; + } + + + for(var i = 0; i < radioelement.length; i++) { + if(radioelement[i].checked) { + value = radioelement[i].value; + } + } + return value; +} + +/* + * Gets the groupid from an XML doc contain a tag of the form + * If it contains more than one such tag, it only return the value from the first one. + */ +function getFromXML(xmlDoc, id) { + if (!xmlDoc.getElementsByTagName(id)) { + var value = null; + } else if (xmlDoc.getElementsByTagName(id).length == 0) { + var value = null; + } else { + var element = xmlDoc.getElementsByTagName(id)[0]; + if (!element.firstChild) { + var value = ''; + } else { + var value = element.firstChild.nodeValue; + } + } + + return value; +} + +function showNoElementError(id) { + alert('Error: No ' + id +' element'); +} + +function isPositiveInt(str) { + isPosInt = true; + + var i = parseInt (str); + + if (isNaN (i)) { + isPosInt = false; + } + + if (i < 0) { + isPosInt = false; + // Check not characters at the end of the number + } + + if (i.toString() != str) { + isPosInt = false; + } + return isPosInt ; +} + diff --git a/group/groupui/yahoo.js b/group/groupui/yahoo.js new file mode 100644 index 0000000000..e285bc39a2 --- /dev/null +++ b/group/groupui/yahoo.js @@ -0,0 +1,84 @@ +/* +Copyright (c) 2006, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.net/yui/license.txt +version: 0.11.0 +*/ + +/** + * The Yahoo global namespace + * @constructor + */ +var YAHOO = window.YAHOO || {}; + +/** + * Returns the namespace specified and creates it if it doesn't exist + * + * YAHOO.namespace("property.package"); + * YAHOO.namespace("YAHOO.property.package"); + * + * Either of the above would create YAHOO.property, then + * YAHOO.property.package + * + * @param {String} ns The name of the namespace + * @return {Object} A reference to the namespace object + */ +YAHOO.namespace = function(ns) { + + if (!ns || !ns.length) { + return null; + } + + var levels = ns.split("."); + var nsobj = YAHOO; + + // YAHOO is implied, so it is ignored if it is included + for (var i=(levels[0] == "YAHOO") ? 1 : 0; idirroot.'/course/groups/lib/configlib.php'); +include_once($CFG->dirroot.'/course/groups/db/dbsetup.php'); +include_once($CFG->dirroot.'/course/groups/lib/utillib.php'); + +// Set up the database +groups_create_database_tables(); + + +// Change database tables - course table need to remove two fields add groupingid field +// Move everything over +// Course module instance need to add groupingid field +// Module table - add group support field. +// Add deletable by teacher field. + +/** + * Copies the moodle groups to a new grouping within IMS groups + * @param int $courseid The id of the course + * @return int The id of the grouping to which the groups have been copied, or false if an error occurred. + */ +function groups_copy_moodle_groups_to_groups($courseid) { + $groupingsettings->name = 'Old moodle groups'; + $groupingid = groups_create_grouping($courseid, $groupingsettings); + + $groupids = groups_get_moodle_groups($courseid); + if (!$groupids) { + $groupingid = false; + } else { + + foreach($groupids as $groupid) { + $groupcopied = groups_db_copy_moodle_group_to_imsgroup($groupid, $courseid); + if (!$groupcopied) { + $groupingid = false; + } + + $groupadded = groups_add_group_to_grouping($groupid, $groupingid); + if (!$groupadded) { + $groupingid = false; + } + } + } + + return $groupingid; +} + +?> diff --git a/group/install.sql b/group/install.sql new file mode 100644 index 0000000000..22feae978f --- /dev/null +++ b/group/install.sql @@ -0,0 +1,199 @@ +-- phpMyAdmin SQL Dump +-- version 2.8.1 +-- http://www.phpmyadmin.net +-- +-- Host: localhost +-- Generation Time: Oct 24, 2006 at 05:23 PM +-- Server version: 5.0.21 +-- PHP Version: 4.4.2-pl1 +-- +-- Database: `moodle` +-- + +-- -------------------------------------------------------- + +-- +-- Table structure for table `mdl_course` +-- + +CREATE TABLE `mdl_course` ( + `id` int(10) unsigned NOT NULL auto_increment, + `category` int(10) unsigned NOT NULL default '0', + `sortorder` int(10) unsigned NOT NULL default '0', + `password` varchar(50) collate utf8_unicode_ci NOT NULL default '', + `fullname` varchar(254) collate utf8_unicode_ci NOT NULL default '', + `shortname` varchar(100) collate utf8_unicode_ci NOT NULL default '', + `idnumber` varchar(100) collate utf8_unicode_ci NOT NULL default '', + `summary` text collate utf8_unicode_ci NOT NULL, + `format` varchar(10) collate utf8_unicode_ci NOT NULL default 'topics', + `showgrades` smallint(2) unsigned NOT NULL default '1', + `modinfo` longtext collate utf8_unicode_ci NOT NULL, + `newsitems` smallint(5) unsigned NOT NULL default '1', + `teacher` varchar(100) collate utf8_unicode_ci NOT NULL default 'Teacher', + `teachers` varchar(100) collate utf8_unicode_ci NOT NULL default 'Teachers', + `student` varchar(100) collate utf8_unicode_ci NOT NULL default 'Student', + `students` varchar(100) collate utf8_unicode_ci NOT NULL default 'Students', + `guest` tinyint(2) unsigned NOT NULL default '0', + `startdate` int(10) unsigned NOT NULL default '0', + `enrolperiod` int(10) unsigned NOT NULL default '0', + `numsections` smallint(5) unsigned NOT NULL default '1', + `marker` int(10) unsigned NOT NULL default '0', + `maxbytes` int(10) unsigned NOT NULL default '0', + `showreports` int(4) unsigned NOT NULL default '0', + `visible` int(1) unsigned NOT NULL default '1', + `hiddensections` int(2) unsigned NOT NULL default '0', + `groupmode` int(4) unsigned NOT NULL default '0', + `groupmodeforce` int(4) unsigned NOT NULL default '0', + `lang` varchar(10) collate utf8_unicode_ci NOT NULL default '', + `theme` varchar(50) collate utf8_unicode_ci NOT NULL default '', + `cost` varchar(10) collate utf8_unicode_ci NOT NULL default '', + `currency` char(3) collate utf8_unicode_ci NOT NULL default 'USD', + `timecreated` int(10) unsigned NOT NULL default '0', + `timemodified` int(10) unsigned NOT NULL default '0', + `metacourse` int(1) unsigned NOT NULL default '0', + `requested` int(1) unsigned NOT NULL default '0', + `restrictmodules` int(1) unsigned NOT NULL default '0', + `expirynotify` tinyint(1) unsigned NOT NULL default '0', + `expirythreshold` int(10) unsigned NOT NULL default '0', + `notifystudents` tinyint(1) unsigned NOT NULL default '0', + `enrollable` tinyint(1) unsigned NOT NULL default '1', + `enrolstartdate` int(10) unsigned NOT NULL default '0', + `enrolenddate` int(10) unsigned NOT NULL default '0', + `enrol` varchar(20) collate utf8_unicode_ci NOT NULL default '', + PRIMARY KEY (`id`), + KEY `category` (`category`), + KEY `idnumber` (`idnumber`), + KEY `shortname` (`shortname`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=7 ; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `mdl_course_modules` +-- + +CREATE TABLE `mdl_course_modules` ( + `id` int(10) unsigned NOT NULL auto_increment, + `course` int(10) unsigned NOT NULL default '0', + `module` int(10) unsigned NOT NULL default '0', + `instance` int(10) unsigned NOT NULL default '0', + `section` int(10) unsigned NOT NULL default '0', + `added` int(10) unsigned NOT NULL default '0', + `score` tinyint(4) NOT NULL default '0', + `indent` int(5) unsigned NOT NULL default '0', + `visible` tinyint(1) NOT NULL default '1', + `visibleold` tinyint(1) NOT NULL default '1', + `groupingid` int(10) NOT NULL default '0', + PRIMARY KEY (`id`), + UNIQUE KEY `id` (`id`), + KEY `visible` (`visible`), + KEY `course` (`course`), + KEY `module` (`module`), + KEY `instance` (`instance`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=2 ; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `mdl_groups_courses_groupings` +-- + +CREATE TABLE `mdl_groups_courses_groupings` ( + `id` int(10) unsigned NOT NULL auto_increment, + `courseid` int(10) unsigned NOT NULL default '0', + `groupingid` mediumint(9) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `id` (`id`), + KEY `courseid` (`courseid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=87 ; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `mdl_groups_courses_groups` +-- + +CREATE TABLE `mdl_groups_courses_groups` ( + `id` int(10) unsigned NOT NULL auto_increment, + `courseid` int(10) unsigned NOT NULL default '0', + `groupid` int(11) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `id` (`id`), + KEY `courseid` (`courseid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=132 ; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `mdl_groups_groupings` +-- + +CREATE TABLE `mdl_groups_groupings` ( + `id` int(10) unsigned NOT NULL auto_increment, + `name` varchar(254) character set latin1 collate latin1_general_ci NOT NULL default '', + `description` text character set latin1 collate latin1_general_ci NOT NULL, + `timecreated` int(10) unsigned NOT NULL default '0', + `viewowngroup` tinyint(1) NOT NULL, + `viewallgroupsmembers` tinyint(1) NOT NULL, + `viewallgroupsactivities` tinyint(1) NOT NULL, + `teachersgroupmark` tinyint(1) NOT NULL, + `teachersgroupview` binary(1) NOT NULL, + `teachersoverride` binary(1) NOT NULL, + `teacherdeletable` binary(1) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `id` (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=87 ; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `mdl_groups_groupings_groups` +-- + +CREATE TABLE `mdl_groups_groupings_groups` ( + `id` int(10) unsigned NOT NULL auto_increment, + `groupingid` int(10) unsigned default '0', + `groupid` int(10) NOT NULL, + `timecreated` int(10) unsigned NOT NULL default '0', + PRIMARY KEY (`id`), + UNIQUE KEY `id` (`id`), + KEY `courseid` (`groupingid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=67 ; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `mdl_groups_groups` +-- + +CREATE TABLE `mdl_groups_groups` ( + `id` int(10) unsigned NOT NULL auto_increment, + `name` varchar(254) character set latin1 collate latin1_general_ci NOT NULL default '', + `description` text character set latin1 collate latin1_general_ci NOT NULL, + `enrolmentkey` varchar(50) character set latin1 collate latin1_general_ci NOT NULL default '', + `lang` varchar(10) character set latin1 collate latin1_general_ci NOT NULL default 'en', + `theme` varchar(50) character set latin1 collate latin1_general_ci NOT NULL default '', + `picture` int(10) unsigned NOT NULL default '0', + `hidepicture` int(1) unsigned NOT NULL default '0', + `timecreated` int(10) unsigned NOT NULL default '0', + `timemodified` int(10) unsigned NOT NULL default '0', + PRIMARY KEY (`id`), + UNIQUE KEY `id` (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=132 ; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `mdl_groups_groups_users` +-- + +CREATE TABLE `mdl_groups_groups_users` ( + `id` int(10) unsigned NOT NULL auto_increment, + `groupid` int(10) unsigned NOT NULL default '0', + `userid` int(10) unsigned NOT NULL default '0', + `timeadded` int(10) unsigned NOT NULL default '0', + PRIMARY KEY (`id`), + UNIQUE KEY `id` (`id`), + KEY `groupid` (`groupid`), + KEY `userid` (`userid`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=175 ; diff --git a/group/lib/automaticgroupinglib.php b/group/lib/automaticgroupinglib.php new file mode 100644 index 0000000000..7158436680 --- /dev/null +++ b/group/lib/automaticgroupinglib.php @@ -0,0 +1,250 @@ +prefix) { + $prefix = get_string('defaultgroupprefix', 'groups'); + } else { + $prefix = $groupingsettings->prefix; + } + + if (!$groupingsettings->defaultgroupdescription) { + $defaultgroupdescription = ''; + } else { + $defaultgroupdescription = $groupingsettings->defaultgroupdescription; + } + + // Now create a group for each set of students, add the group to the + // grouping and then add the students + $i = 1; + foreach ($userarrays as $userids) { + $groupsettings->name = $prefix.' '.$i; + $groupsettings->description = $defaultgroupdescription; + $i++; + $groupid = groups_create_group($courseid, $groupsettings); + $groupadded = groups_add_group_to_grouping($groupid, + $groupingid); + if (!$groupid or !$groupadded) { + $groupingid = false; + } else { + if ($userids) { + foreach($userids as $userid) { + $usersadded = groups_add_member($userid, $groupid); + // If unsuccessful just carry on I guess + } + } + } + } + } + } + return $groupingid; +} + + +/** + * Takes an array and a set size, puts the elements of the array into an array + * of arrays of size $setsize randomly. + * @param array $array The array to distribute into random sets + * @param int $setsize The size of each set - this can be set to false, if you + * would prefer to specify the number of sets. + * @param int $nosets The number of sets - this can be set to false if you would + * prefer to specify the setsize. + * If both $setsize and $nosets are set then $setsize takes precedence. If both + * are set to false then the function does nothing and returns false. + * @param $distribevenly boolean Determines how extra elements are distributed + * if $setsize doesn't divide exactly into the number of elements if $setsize is + * specified. If it is true then extra elements will be distributed evenly + * amongst the sets, whereas if it is set to false then the remaining elements + * will be put into a separate set. + * @param boolean $randomise If this is true then the elements of array will be + * put into the arrays in a random order, otherwise they will be put into the + * array in the same order as the original array. + * @return array The array of arrays of elements generated. + */ +function groups_distribute_in_random_sets($array, $setsize, $nosets, + $distribevenly = true, + $randomise = true) { + $noelements = count($array); + + // Create a list of the numbers 1,..., $noelements, in either random order + // or in numerical order depending on whether $randomise has been set. + if ($randomise) { + $orderarray = groups_random_list($noelements); + } else { + // Just create the array (1,2,3,....) + $orderarray = array(); + for($i = 0; $i < $noelements; $i++) { + array_push($orderarray, $i); + } + } + + // Now use the ordering in $orderarray to generate the new arrays + $arrayofrandomsets = array(); // + + for ($i = 0; $i < $noelements; $i++) { + $arrayofrandomsets[$arrayno][$i] = $array[$orderarray[$i]]; + if (groups_last_element_in_set($noelements, $setsize, $nosets, + $distribevenly, $i) + and $i != $noelements - 1) { + $arrayno++; + $arrayofrandomsets[$arrayno] = array(); + } + + } + + return $arrayofrandomsets; +} + +/** + * Returns an array of the numbers 0,..,$size - 1 in random order + * @param int $size the number of numbers to return in a random order + * @return array The array of numbers in a random order + */ +function groups_random_list($size) { + $orderarray = array(); + $noelementsset = 0; + while($noelementsset != $size) { + $newelement = rand() % $size; + // If the array doesn't already contain the element, add it. + if (array_search($newelement, $orderarray) === false) { + array_push($orderarray, $newelement); + $noelementsset++; + } + } + + return $orderarray; +} + +/** + * A helper function for groups_distribute_in_random_sets(). + * When distributing elements into sets, determines if a given element is the + * last element in the set. + * @param int $totalnoelements The total number of elements being distributed. + * @param int $setsize See groups_distribute_in_random_sets() + * @param int $nosets See groups_distribute_in_random_sets() + * @param boolean $distribevenly See groups_distribute_in_random_sets() + * @param int $elementno The element number that we are considering i.e. if this + * is the 15th element then this would be 15. + * @return boolean True if the element under consideration would be the last + * element in the set, fals otherwise. + */ +function groups_last_element_in_set($totalnoelements, $setsize, $nosets, + $distribevenly, $elementno) { + $lastelement = false; + $elementno = $elementno + 1; // Counting from zero is just too confusing! + + // If $nosets has been specified, make sure $setsize is set to the right + // value, so that we can treat the two cases identically. Then work out how + // many extra elements will be left over. + if (!$setsize) { + $setsize = floor($totalnoelements / $nosets); + $noextra = $totalnoelements % $nosets; + } else { + $noextra = $totalnoelements % $setsize; + } + + if (!$distribevenly) { + // If we're putting our extra elements in a set at the end, everything + // is easy! + if ($elementno % $setsize == 0) { + $lastelement = true; + } + } else { + // Work out the number of elements that will be in the bigger sets that + // have the leftover elements in + // them. + $noinbiggersets = $noextra * ($setsize + 1); + // Work out if this element is a last element in a set or not - we need + // to separate the case where the element is one of the ones that goes + // into the bigger sets at the beginning + // and the case where it's one of the elements in the normal sized sets. + if (($elementno <= $noinbiggersets and $elementno % ($setsize + 1) == 0) + or ($elementno > $noinbiggersets and + ($elementno - $noinbiggersets ) % $setsize == 0) ) { + $lastelement = true; + } + } + + return $lastelement; +} +?> \ No newline at end of file diff --git a/group/lib/basicgrouplib.php b/group/lib/basicgrouplib.php new file mode 100644 index 0000000000..e46030da5c --- /dev/null +++ b/group/lib/basicgrouplib.php @@ -0,0 +1,312 @@ +dirroot.'/course/groups/db/dbbasicgrouplib.php'); + + +/***************************** + List functions + *****************************/ + +/** + * Gets a list of the group ids for a specified course id + * @param int $courseid The id of the course. + * @return array | false Returns an array of the userids or false if no records + * or an error occurred. + */ +function groups_get_groups($courseid) { + $groupids = groups_db_get_groups($courseid); + return $groupids; +} + + +/** + * Returns the ids of the users in the specified group. + * @param int $groupid The groupid to get the users for + * @param string $membertype Either 'student', 'teacher' or false. The function + * only returns these + * types of group members. If set to false, returns all group members. + * @return array | false Returns an array of the user ids for the specified + * group or false if no users or an error returned. + */ +function groups_get_members($groupid, $membertype = false) { + $userids = groups_db_get_members($groupid); + return $userids; +} + + +/** + * Gets the groups to which a user belongs for a specified course. + * @param int $userid The id of the specified user + * @param int $courseid The id of the course. + * @param boolean $usedatabase. If true, gets the information from + * @return array | false An array of the group ids of the groups to which the + * user belongs or false if there are no groups or an error occurred. + */ +function groups_get_groups_for_user($userid, $courseid) { + $groupids = groups_db_get_groups_for_user($userid, $courseid); + return $groupids; +} + +/** + * Gets the groups for the current user and specified course + * @param int $courseid The id of the course + * @param int $usedatabase Set to true if the information is to be obtained + * directly + * from the database, false if it is to be obtained from the $USER object. + * @return array An array of the groupids. + */ +function groups_get_groups_for_current_user($courseid) { + global $USER; + $groupids = groups_get_groups_for_user($USER->id, $courseid); + return $groupids; +} + + +/** + * Get the group settings object for a group - this contains the following + * properties: + * name, description, lang, theme, picture, hidepicture + * @param int $groupid The id of the gruop + * @return object The group settings object + */ +function groups_get_group_settings($groupid) { + return groups_db_get_group_settings($groupid); +} + +/** + * Gets the path where the image for a particular group can be found (if it + * exists) + * @param int $groupid The id of the group + * @return string The path of the image for the group + */ +function groups_get_group_image_path($groupid) { + return $CFG->dataroot.'/groups/'.$groupid.'/'.$image; +} + +/** + * Gets the name of a group with a specified id + * @param int $groupid The id of the group + * @return string The name of the group + */ +function groups_get_group_name($groupid) { + $settings = groups_get_group_settings($groupid); + return $settings->name; +} + +/** + * Gets the users for a course who are not in a specified group + * @param int $groupid The id of the group + * @return array An array of the userids of the non-group members, or false if + * an error occurred. + */ +function groups_get_users_not_in_group($courseid, $groupid) { + $users = get_course_users($courseid); + $userids = groups_users_to_userids($users); + $nongroupmembers = array(); + + foreach($userids as $userid) { + if (!groups_is_member($groupid, $userid)) { + array_push($nongroupmembers, $userid); + } + } + + return $nongroupmembers; +} + +/** + * Given two users, determines if there exists a group to which they both belong + * @param int $userid1 The id of the first user + * @param int $userid2 The id of the second user + * @return boolean True if the users are in a common group, false otherwise or + * if an error occurred. + */ +function groups_users_in_common_group($userid1, $userid2) { + return groups_db_users_in_common_group($userid1, $userid1); +} + + + + + +/***************************** + Membership functions + *****************************/ + + +/** + * Determines if a group with a given groupid exists. + * @param int $groupid The groupid to check for + * @return boolean True if the group exists, false otherwise or if an error + * occurred. + */ +function groups_group_exists($groupid) { + return groups_db_group_exists($groupid); +} + +/** + * Determines if a specified user is a member of a specified group + * @param int $groupid The group about which the request has been made + * @param int $userid The user about which the request has been made + * @return boolean True if the user is a member of the group, false otherwise + */ + function groups_is_member($groupid, $userid) { + $ismember = groups_db_is_member($groupid, $userid); + return $ismember; +} + + +/** + * Determines if a specified group is a group for a specified course + * @param int $groupid The group about which the request has been made + * @param int $courseid The course for which the request has been made + * @return boolean True if the group belongs to the course, false otherwise + */ +function groups_group_belongs_to_course($groupid, $courseid) { + $belongstocourse = groups_db_group_belongs_to_course($groupid, $courseid); + return $belongstocourse; +} + +/** + * Returns an object with the default group info values - these can of course be + * overridden if desired. + * Can also be used to set the default for any values not set + * @return object The group info object. + */ +function groups_set_default_group_settings($groupinfo = null) { + + if (!isset($groupinfo->name)) { + $groupinfo->name = 'Temporary Group Name'; + } + + if (!isset($groupinfo->description)) { + $groupinfo->description = ''; + } + + if (!isset($groupinfo->lang)) { + $groupinfo->lang = current_language(); + } + + if (!isset($groupinfo->theme)) { + $groupinfo->theme = ''; + } + + if (!isset($groupinfo->picture)) { + $groupinfo->picture = ''; + } + + if (!isset($groupinfo->hidepicture)) { + $groupinfo->hidepicture = '1'; + } + + if (isset($groupinfo->hidepicture)) { + if ($groupinfo->hidepicture != '0' and $groupinfo->hidepicture != '1') { + $groupinfo->hidepicture = '1'; + } + } + + return $groupinfo; +} + +/***************************** + Creation functions + *****************************/ + +/** + * Creates a group for a specified course + * All groups should really belong to a grouping (though there is nothing in + * this API that stops them not doing + * so, to allow plenty of flexibility) so you should be using this in + * conjunction with the function to add a group to + * a grouping. + * @param int $courseid The course to create the group for + * @return int | false The id of the group created or false if the group was + * not created successfully. + * See comment above on web service autoupdating. + */ +function groups_create_group($courseid, $groupsettings = false) { + return groups_db_create_group($courseid, $groupsettings); +} + + +/** + * Sets the information about a group + * Only sets the string for the picture - does not upload the picture! + * @param object $groupsettings An object containing some or all of the + * following properties: name, description, lang, theme, picture, hidepicture + * @return boolean True if info was added successfully, false otherwise. + */ +function groups_set_group_settings($groupid, $groupsettings) { + return groups_db_set_group_settings($groupid, $groupsettings); +} + + +/** + * Adds a specified user to a group + * @param int $groupid The group id + * @param int $userid The user id + * @return boolean True if user added successfully or the user is already a + * member of the group, false otherwise. + * See comment above on web service autoupdating. + */ +function groups_add_member($userid, $groupid) { + $useradded = false; + + $alreadymember = groups_is_member($groupid, $userid); + if (!groups_group_exists($groupid)) { + $useradded = false; + } elseif ($alreadymember) { + $useradded = true; + } else { + $useradded = groups_db_add_member($userid, $groupid); + } + + return $useradded; +} + + +/***************************** + Deletion functions + *****************************/ + + +/** + * Deletes a group best effort + * @param int $groupid The group to delete + * @return boolean True if deletion was successful, false otherwise + * See comment above on web service autoupdating. + */ +function groups_delete_group($groupid) { + $groupdeleted = groups_db_delete_group($groupid); + + return $groupdeleted; +} + + +/** + * Deletes the specified user from the specified group + * @param int $userid The user to delete + * @param int $groupid The group to delete the user from + * @return boolean True if deletion was successful, false otherwise + * See comment above on web service autoupdating. + */ +function groups_remove_member($userid, $groupid) { + return groups_db_remove_member($userid, $groupid); +} +?> \ No newline at end of file diff --git a/group/lib/courselib.php b/group/lib/courselib.php new file mode 100644 index 0000000000..b257b56e4c --- /dev/null +++ b/group/lib/courselib.php @@ -0,0 +1,12 @@ + diff --git a/group/lib/groupinglib.php b/group/lib/groupinglib.php new file mode 100644 index 0000000000..b8ebd3f977 --- /dev/null +++ b/group/lib/groupinglib.php @@ -0,0 +1,347 @@ +dirroot.'/course/groups/lib/basicgrouplib.php'); +include_once($CFG->dirroot.'/course/groups/db/dbgroupinglib.php'); + +/***************************** + Access/List functions + *****************************/ + + + +/** + * Gets a list of the groupings for a specified course + * @param int $courseid The id of the course + * @return array | false An array of the ids of the groupings, or false if there + * are none or there was an error. + */ +function groups_get_groupings($courseid) { + return groups_db_get_groupings($courseid); +} + + +/** + * Gets a list of the groups in a specified grouping + * @param int $groupingid The id of the grouping + * @return array | false. An array of the ids of the groups, or false if there + * are none or an error occurred. + */ +function groups_get_groups_in_grouping($groupingid) { + return groups_db_get_groups_in_grouping($groupingid); +} + +/** + * Gets the groupings that a group belongs to + * @param int $groupid The id of the group + * @return array An array of the ids of the groupings that the group belongs to, + * or false if there are none or if an error occurred. + */ +function groups_get_groupings_for_group($groupid) { + return groups_db_get_groupings_for_group($groupid); +} + +/** + * Gets the information about a specified grouping + * @param int $groupingid + * @return object The grouping settings object - properties are name and + * description. + */ +function groups_get_grouping_settings($groupingid) { + return groups_db_get_grouping_settings($groupingid); +} + +/** + * Set information about a grouping + * @param int $groupingid The grouping to update the info for. + * @param object $groupingsettings + */ +function groups_set_grouping_settings($groupingid, $groupingsettings) { + return groups_db_set_grouping_settings($groupingid, $groupingsettings); +} + +// TO DO +function groups_get_groups_for_user_in_grouping($userid, $groupingid) { +} + +/** + * Gets a list of the groups not a specified grouping + * @param int $groupingid The grouping specified + * @return array An array of the group ids + */ +function groups_get_groups_not_in_grouping($groupingid, $courseid) { + $allgroupids = groups_get_groups($courseid); + $groupids = array(); + foreach($allgroupids as $groupid) { + if (!groups_belongs_to_grouping($groupid, $groupingid)) { + array_push($groupids, $groupid); + } + } + return $groupids; +} + +/** + * Gets the users for the course who are not in any group of a grouping. + * @param int $courseid The id of the course + * @param int $groupingid The id of the grouping + * @param int $groupid Excludes members of a particular group + * @return array An array of the userids of the users not in any group of + * the grouping or false if an error occurred. + */ +function groups_get_users_not_in_any_group_in_grouping($courseid, $groupingid, + $groupid = false) { + $users = get_course_users($courseid); + $userids = groups_users_to_userids($users); + $nongroupmembers = array(); + if ($userids) { + foreach($userids as $userid) { + if (!groups_is_member_of_some_group_in_grouping($userid, + $groupingid)) { + // If a group has been specified don't include members of that + // group + if ($groupid and !groups_is_member($userid, $groupid)) { + array_push($nongroupmembers, $userid); + } else { + array_push($nongroupmembers, $userid); + } + } + } + } + return $nongroupmembers; +} + + +/** + * Determines if a user is in more than one group in a grouping + * @param int $userid The id of the user + * @param int $groupingid The id of the grouping + * @return boolean True if the user is in more than one group, false otherwise + * or if an error occurred. + */ +function groups_user_is_in_multiple_groups($userid, $groupingid) { + $inmultiplegroups = false; + $groupids = groups_get_groups_for_user($courseid); + if ($groupids != false) { + $groupinggroupids = array(); + foreach($groupids as $groupid) { + if (groups_belongs_to_grouping($groupid, $groupingid)) { + array_push($groupinggroupids, $groupid); + } + } + + if (count($groupinggroupids) > 1) { + $inmultiplegroups = true; + } + } + + return $inmultiplegroups; +} + + +/** + * Returns an object with the default grouping settings values - these can of + * course be overridden if desired. + * Can also be used to set the default for any values not set + * @return object The grouping settings object. + */ +function groups_set_default_grouping_settings($groupingsettings = null) { + + if (!isset($groupingsettings->name)) { + $groupingsettings->name = 'Temporary Grouping Name'; + } + + if (!isset($groupingsettings->description)) { + $groupingsettings->description = ''; + } + + if (!isset($groupsettings->viewowngroup)) { + $groupsettings->viewowngroup = 1; + } + + if (!isset($groupsettings->viewgroupsmembers)) { + $groupsettings->viewgroupsmembers = 0; + } + + if (!isset($groupsettings->viewgroupsactivities)) { + $groupsettings->viewgroupsactivities = 0; + } + + if (!isset($groupsettings->teachersgroupmark)) { + $groupsettings->teachersgroupmark = 0; + } + + if (!isset($groupsettings->teachersgroupview)) { + $groupsettings->teachersgroupview = 0; + } + + if (!isset($groupsettings->teachersoverride)) { + $groupsettings->teachersoverride = 1; + } + + return $groupingsettings; +} + + +/** + * Gets the grouping to use for a particular instance of a module in a course + * @param int $coursemoduleid The id of the instance of the module in the course + * @return int The id of the grouping or false if there is no such id recorded + * or if an error occurred. + */ +function groups_get_grouping_for_coursemodule($coursemoduleid) { + return groups_db_get_grouping_for_coursemodule($coursemoduleid); +} + +/***************************** + Membership functions + *****************************/ + + +/** + * Determines if a grouping with a specified id exists + * @param int $groupingid The grouping id. + * @return True if the grouping exists, false otherwise or if an error occurred. + */ +function groups_grouping_exists($groupingid) { + return groups_db_grouping_exists($groupingid); +} + + /** + * Determines if a group belongs to a specified grouping + * @param int $groupid The id of the group + * @param int $groupingid The id of the grouping + * @return boolean. True if the group belongs to a grouping, false otherwise or + * if an error has occurred. + */ + function groups_belongs_to_grouping($groupid, $groupingid) { + return groups_db_belongs_to_grouping($groupid, $groupingid); + } + + + /** + * Detemines if a specified user belongs to any group of a specified grouping. + * @param int $userid The id of the user + * @param int $groupingid The id of the grouping + * @return boolean True if the user belongs to some group in the grouping, + * false otherwise or if an error occurred. + */ + function groups_is_member_of_some_group_in_grouping($userid, $groupingid) { + return groups_db_is_member_of_some_group_in_grouping($userid, $groupingid); + } + + /** + * Determines if a grouping belongs to a specified course + * @param int $groupingid The id of the grouping + * @param int $courseid The id of the course + * @return boolean True if the grouping belongs to the course, false otherwise, + * or if an error occurred. + */ + function groups_grouping_belongs_to_course($groupingid, $courseid) { + return groups_db_grouping_belongs_to_course($groupingid, $courseid); + } + + + + +/***************************** + Creation functions + *****************************/ + + +/** + * Marks a set of groups as a grouping. This is a best effort operation. + * It can also be used to create an 'empty' grouping to which + * groups can be added by passing an empty array for the group ids. + * @param array $groupids An array of the ids of the groups to marks as a + * grouping. + * @param int $courseid The id of the course for which the groups should form + * a grouping + * @return int | false The id of the grouping, or false if an error occurred. + * Also returns false if any of the groups specified do not belong to the + * course. + */ +function groups_create_grouping($courseid, $groupingsettings = false) { + $groupingid = groups_db_create_grouping($courseid, $groupingsettings); + + return $groupingid; +} + + +/** + * Adds a specified group to a specified grouping. + * @param int $groupid The id of the group + * @param int $groupingid The id of the grouping + * @return boolean True if the group was added successfully or the group already + * belonged to the grouping, false otherwise. Also returns false if the group + * doesn't belong to the same course as the grouping. + */ +function groups_add_group_to_grouping($groupid, $groupingid) { + $belongstogrouping = groups_belongs_to_grouping($groupid, $groupingid); + if (!groups_grouping_exists($groupingid)) { + $groupadded = false; + } elseif (!$belongstogrouping) { + $groupadded = groups_db_add_group_to_grouping($groupid, $groupingid); + } else { + $groupadded = true; + } + + return $groupadded; +} + + +/** + * Sets the name of a grouping overwriting any current name that the grouping + * has + * @param int $groupingid The id of the grouping specified + * @param string $name The name to give the grouping + * @return boolean True if the grouping settings was added successfully, false + * otherwise. + */ +function groups_set_grouping_name($groupingid, $name) { + return groups_db_set_grouping_name($groupingid, $name); +} + + + +/** + * Sets a grouping to use for a particular instance of a module in a course + * @param int $groupingid The id of the grouping + * @param int $coursemoduleid The id of the instance of the module in the course + * @return boolean True if the operation was successful, false otherwise + */ +function groups_set_grouping_for_coursemodule($groupingid, $coursemoduleid) { + return groups_db_set_grouping_for_coursemodule($groupingid, + $coursemoduleid); +} + + +/***************************** + Deletion functions + *****************************/ + +/** + * Removes a specified group from a specified grouping. Note that this does + * not delete the group. + * @param int $groupid The id of the group. + * @param int $groupingid The id of the grouping + * @return boolean True if the deletion was successful, false otherwise. + */ +function groups_remove_group_from_grouping($groupid, $groupingid) { + return groups_db_remove_group_from_grouping($groupid, $groupingid); +} + +/** + * Removes a grouping from a course - note that this function does not delete + * any of the groups in the grouping. + * @param int $groupingid The id of the grouping + * @return boolean True if the deletion was successful, false otherwise. + */ +function groups_delete_grouping($groupingid) { + return groups_db_delete_grouping($groupingid); + +} +?> \ No newline at end of file diff --git a/group/lib/legacylib.php b/group/lib/legacylib.php new file mode 100644 index 0000000000..cb3a0358c0 --- /dev/null +++ b/group/lib/legacylib.php @@ -0,0 +1,380 @@ +prefix}user u, + {$CFG->prefix}groups_members m + WHERE m.groupid = '$groupid' + AND m.userid = u.id $except + ORDER BY $sort"); +} + + + +/** + * Returns an array of user objects + * + * @uses $CFG + * @param int $groupid The group(s) in question. + * @param string $sort How to sort the results + * @return object (changed to groupids) + */ +function get_group_students($groupids, $sort='u.lastaccess DESC') { + + global $CFG; + + if (is_array($groupids)){ + $groups = $groupids; + $groupstr = '(m.groupid = '.array_shift($groups); + foreach ($groups as $index => $value){ + $groupstr .= ' OR m.groupid = '.$value; + } + $groupstr .= ')'; + } + else { + $groupstr = 'm.groupid = '.$groupids; + } + + return get_records_sql("SELECT DISTINCT u.* + FROM {$CFG->prefix}user u, + {$CFG->prefix}groups_members m, + {$CFG->prefix}groups g, + {$CFG->prefix}user_students s + WHERE $groupstr + AND m.userid = u.id + AND m.groupid = g.id + AND g.courseid = s.course + AND s.userid = u.id + ORDER BY $sort"); +} + +/** + * Returns list of all the teachers who can access a group + * + * @uses $CFG + * @param int $courseid The course in question. + * @param int $groupid The group in question. + * @return object + */ +function get_group_teachers($courseid, $groupid) { +/// Returns a list of all the teachers who can access a group + if ($teachers = get_course_teachers($courseid)) { + foreach ($teachers as $key => $teacher) { + if ($teacher->editall) { // These can access anything + continue; + } + if (($teacher->authority > 0) and ismember($groupid, $teacher->id)) + { // Specific group teachers + continue; + } + unset($teachers[$key]); + } + } + return $teachers; +} + + +/** + * Add a user to a group, return true upon success or if user already a group + * member + * + * @param int $groupid The group id to add user to + * @param int $userid The user id to add to the group + * @return bool + */ +function add_user_to_group ($groupid, $userid) { + return groups_add_member($userid, $groupid) ; +} + + +/** + * Get the group ID of the current user in the given course + * + * @uses $USER + * @param int $courseid The course being examined - relates to id field in + * 'course' table. + * @return array An array of the groupids that the user belongs to. + */ +function mygroupid($courseid) { + // TO DO - check whether needs to be groups or groupids. + $groupids = groups_get_groups_for_user($USER, $courseid); + return $groupids[0]; +} + +/** + * This now returns either false or SEPARATEGROUPS. If you want VISIBLE GROUPS + * with legacy code, you'll need to upgrade. + */ +function groupmode($course, $cm=null) { + + if ($cm and !$course->groupingid) { + return groups_has_groups_setup_for_instance($coursemodule); + } else { + return groups_has_groups_setup($course->id); + } +} + + + + + +/** + * Sets the current group in the session variable + * When $SESSION->currentgroup[$courseid] is set to 0 it means, show all groups. + * Sets currentgroup[$courseid] in the session variable appropriately. + * Does not do any permission checking. + * @uses $SESSION + * @param int $courseid The course being examined - relates to id field in + * 'course' table. + * @param int $groupid The group being examined. + * @return int Current group id which was set by this function + */ +function set_current_group($courseid, $groupid) { + global $SESSION; + return $SESSION->currentgroup[$courseid] = $groupid; +} + + +/** + * Gets the current group - either from the session variable or from the database. + * + * @uses $USER + * @uses $SESSION + * @param int $courseid The course being examined - relates to id field in + * 'course' table. + * @param bool $full If true, the return value is a full record object. + * If false, just the id of the record. + */ +function get_current_group($courseid, $full = false) { + global $SESSION; + + if (isset($SESSION->currentgroup[$courseid])) { + $currentgroup = $SESSION->currentgroup[$courseid]; + } else { + $currentgroup = mygroupid($courseid); + } + + if ($currentgroup) { + $SESSION->currentgroup[$courseid] = mygroupid($courseid); + } + + if ($full) { + return groups_groupid_to_group($currentgroup); + } else { + return $currentgroup; + } +} + + +/** + * A combination function to make it easier for modules + * to set up groups. + * + * It will use a given "groupid" parameter and try to use + * that to reset the current group for the user. + * + * @uses VISIBLEGROUPS + * @param course $course A {@link $COURSE} object + * @param int $groupmode Either NOGROUPS, SEPARATEGROUPS or VISIBLEGROUPS + * @param int $groupid Will try to use this optional parameter to + * reset the current group for the user + * @return int|false Returns the current group id or false if error. + */ +function get_and_set_current_group($course, $groupmode, $groupid=-1) { + groups_has_permission($userid, $groupingid, $courseid, $groupid, $permissiontype); + // Sets to the specified group, provided the current user has view permission + if (!$groupmode) { // Groups don't even apply + return false; + } + + $currentgroupid = get_current_group($course->id); + + if ($groupid < 0) { // No change was specified + return $currentgroupid; + } + + if ($groupid) { // Try to change the current group to this groupid + if ($group = get_record('groups', 'id', $groupid, 'courseid', $course->id)) { // Exists + if (isteacheredit($course->id)) { // Sets current default group + $currentgroupid = set_current_group($course->id, $group->id); + + } else if ($groupmode == VISIBLEGROUPS) { + // All groups are visible + //if (ismember($group->id)){ + $currentgroupid = set_current_group($course->id, $group->id);//set this since he might post + /*)}else { + $currentgroupid = $group->id;*/ + } else if ($groupmode == SEPARATEGROUPS) { // student in separate groups switching + if (ismember($group->id)){//check if is a member + $currentgroupid = set_current_group($course->id, $group->id); //might need to set_current_group? + } + else { + echo ($group->id); + notify('you do not belong to this group!',error); + } + } + } + } else { // When groupid = 0 it means show ALL groups + //this is changed, non editting teacher needs access to group 0 as well, for viewing work in visible groups (need to set current group for multiple pages) + if (isteacheredit($course->id) OR (isteacher($course->id) AND ($groupmode == VISIBLEGROUPS))) { // Sets current default group + $currentgroupid = set_current_group($course->id, 0); + + } else if ($groupmode == VISIBLEGROUPS) { // All groups are visible + $currentgroupid = 0; + } + } + + return $currentgroupid; +} + + +/** + * A big combination function to make it easier for modules + * to set up groups. + * + * Terminates if the current user shouldn't be looking at this group + * Otherwise returns the current group if there is one + * Otherwise returns false if groups aren't relevant + * + * @uses SEPARATEGROUPS + * @uses VISIBLEGROUPS + * @param course $course A {@link $COURSE} object + * @param int $groupmode Either NOGROUPS, SEPARATEGROUPS or VISIBLEGROUPS + * @param string $urlroot ? + * @return int|false + */ +function setup_and_print_groups($course, $groupmode, $urlroot) { + + global $USER, $SESSION; //needs his id, need to hack his groups in session + + $changegroup = optional_param('group', -1, PARAM_INT); + + $currentgroup = get_and_set_current_group($course, $groupmode, $changegroup); + if ($currentgroup === false) { + return false; + } + + if ($groupmode == VISIBLEGROUPS or ($groupmode and isteacheredit($course->id))) { + groups_instance_print_grouping_selector(); + }//added code here to allow non-editting teacher to swap in-between his own groups + //added code for students in separategrous to swtich groups + else if ($groupmode == SEPARATEGROUPS and (isteacher($course->id) or isstudent($course->id))) { + groups_instance_print_group_selector(); + } + + return $currentgroup; +} + + + +function oldgroups_print_user_group_info($currentgroup, $isseparategroups, $courseid) { + global $CFG; + if ($currentgroup and (!$isseparategroups or isteacheredit($courseid))) { /// Display info about the group + if ($group = get_record('groups', 'id', $currentgroup)) { + if (!empty($group->description) or (!empty($group->picture) and empty($group->hidepicture))) { + echo '
'; + print_group_picture($group, $course->id, true, false, false); + echo ''; + echo '

'.$group->name; + if (isteacheredit($courseid)) { + echo ' '; + echo ''; + echo ''; + } + echo '

'; + echo format_text($group->description); + echo '
'; + } + } + } +} +?> diff --git a/group/lib/lib.php b/group/lib/lib.php new file mode 100644 index 0000000000..7cff57308b --- /dev/null +++ b/group/lib/lib.php @@ -0,0 +1,10 @@ +dirroot.'/course/groups/lib/basicgrouplib.php'); + +include_once($CFG->dirroot.'/course/groups/lib/groupinglib.php'); + +include_once($CFG->dirroot.'/course/groups/lib/utillib.php'); + +include_once($CFG->dirroot.'/course/groups/lib/automaticgroupinglib.php'); +?> \ No newline at end of file diff --git a/group/lib/modulelib.php b/group/lib/modulelib.php new file mode 100644 index 0000000000..22ec458748 --- /dev/null +++ b/group/lib/modulelib.php @@ -0,0 +1,400 @@ +viewowngroup; + $viewallgroupsmembers = $groupingsettings->viewallgroupmembers; + $viewallgroupsactivities = $groupingsettings->viewallgroupsactivities; + $teachersgroupsmark = $groupingsettings->teachersgroupsmark; + $teachersgroupsview = $groupingsettings->teachersgroupsview; + $teachersgroupmark = $groupingsettings->teachersgroupmark; + $teachersgroupview = $groupingsettings->teachersgroupview; + $teachersoverride = $groupingsettings->teachersoverride; + + $permission = false; + + switch ($permissiontype) { + case 'view': + if (($isstudent and $groupmember) or + ($isteacher and $groupmember) or + ($isstudent and $viewallgroupsactivities) or + ($isteacher and !$teachersgroupview) or + ($isteacher and !$memberofsomegroup and $teachersoverride)) { + $permission = true; + } + break; + + case 'studentcontribute': + if (($isstudent and $groupmember) or + ($isteacher and $groupmember) or + ($isteacher and !$memberofsomegroup and $teachersoverride)) { + $permission = true; + } + break; + case 'teachermark': + if (($isteacher and $groupmember) or + ($isteacher and !$teachersgroupmark) or + ($isteacher and !$memberofsomegroup and $teachersoverride)) { + $permission = true; + } + break; + + case 'viewmembers': + if (($isstudent and $groupmember and $viewowngroup) or + ($isstudent and $viewallgroupsmembers) or + ($isteacher and $groupmember) or + ($isteacher and !$teachersgroupview) or + ($isteacher and !$memberofsomegroup and $teachersoverride) or + $isteacheredit) { + $permission = true; + } + break; + } + return $permission; +} + +/** + * Gets an array of members of a group that have a particular permission type + * for this instance of the module and that are enrolled on the course that + * the module instance belongs to. + * + * @param int $cmid The id of the module instance. This is necessary because the + * same group can be used in different module instances with different + * permission setups. + * @param int $groupid The id of the group + * @param int $permissiontype The permission type - see note on permission types + * above + * @return array An array containing the ids of the users with the specified + * permission. + */ +function groups_m_get_members_with_permission($cmid, $groupid, + $permissiontype) { + // Get all the users as $userid + $validuserids = array(); + foreach($userids as $userid) { + $haspermission = groups_m_has_permission($cmid, $groupid, + $permissiontype, $userid); + if ($haspermission) { + array_push($validuserids, $userid); + } + } + return $validuserids; +} + +/** + * Gets the group object associated with a group id. This group object can be + * used to get information such as the name of the group and the file for the + * group icon if it exists. (Look at the groups table in the database to see + * the fields). + * @param int $groupid The id of the group + * @return group The group object + */ +function groups_m_get_group($groupid) { + return groups_db_m_get_group($groupid); +} + +/** + * Gets the groups for the module instance. In general, you should use + * groups_m_get_groups_for_user, however this function is provided for + * circumstances where this function isn't sufficient for some reason. + * @param int $cmid The id of the module instance. + * @return array An array of the ids of the groups for the module instance + */ +function groups_m_get_groups($cmid) { + $groupingid = groups_db_get_groupingid($cmid); + $groupids = groups_get_groups_in_grouping($groupingid); + return $groupids; +} + +/** + * Gets the members of group that are enrolled on the course that the specified + * module instance belongs to. + * @param int $cmid The id of the module instance + * @param int $groupid The id of the group + * @return array An array of the userids of the members. + */ +function groups_m_get_members($cmid, $groupid) { + $userids = groups_get_members($groupid, $membertype); + if (!$userids) { + $memberids = false; + } else { + // Check if each user is enrolled on the course @@@ TO DO + } +} + +/** + * Indicates if a user is a member of a particular group. In general you should + * use groups_m_has_permission, however this function is provided for + * circumstances where this function isn't sufficient for some reason. + * @param int $groupid The id of the group + * @param int $userid The id of the user + * @return boolean True if the user is a member of the group, false otherwise + */ +function groups_m_is_member($groupid, $userid) { + return groups_is_member($groupid, $userid); +} + +/** + * Determines if a user has a particular permission type for a particular group. Permissions + * are set at grouping level and are set via the grouping settings. This is the function + * to check, if somebody can't access something that you think they ought to be able to! + * This is for the current user. What about for general user? + * @param int $courseid The id of the course + * @param int $groupid The id of the group + * @param string $permissiontype The permission type: 'view', 'studentcontribute', + * 'teacherview', 'teachercontribute', 'viewmembers', 'contribute', 'all' + */ +function groups_m_has_permission($courseid, $groupid, $permissiontype) { + $userid = $USER->id; + $groupingid = groups_get_grouping_for_coursemodule($coursemoduleid); + $isstudent = isstudent($courseid, $userid); + $isteacher = isteacher($courseid, $userid); + $groupmember = groups_is_member($groupid, $userid); + $memberofsomegroup = groups_is_member_of_some_group_in_grouping($userid, $groupingid); + + $groupingsettings = groups_get_grouping_settings($groupingid); + $viewowngroup = $groupingsettings->viewowngroup; + $viewallgroupsmembers = $groupingsettings->viewallgroupmembers; + $viewallgroupsactivities = $groupingsettings->viewallgroupsactivities; + $teachersgroupsmark = $groupingsettings->teachersgroupsmark; + $teachersgroupsview = $groupingsettings->teachersgroupsview; + $teachersgroupmark = $groupingsettings->teachersgroupmark; + $teachersgroupview = $groupingsettings->teachersgroupview; + $teachersoverride = $groupingsettings->teachersoverride; + + $permission = false; + + switch ($permissiontype) { + case 'view': + if (($isstudent and $groupmember) or + ($isteacher and $groupmember) or + ($isstudent and $viewallgroupsactivities) or + ($isteacher and !$teachersgroupview) or + ($isteacher and !$memberofsomegroup and $teachersoverride)) { + $permission = true; + } + break; + + case 'studentcontribute': + if (($isstudent and $groupmember) or + ($isteacher and $groupmember) or + ($isteacher and !$memberofsomegroup and $teachersoverride)) { + $permission = true; + } + break; + case 'teachermark': + if (($isteacher and $groupmember) or + ($isteacher and !$teachersgroupmark) or + ($isteacher and !$memberofsomegroup and $teachersoverride)) { + $permission = true; + } + break; + + case 'viewmembers': + if (($isstudent and $groupmember and $viewowngroup) or + ($isstudent and $viewallgroupsmembers) or + ($isteacher and $groupmember) or + ($isteacher and !$teachersgroupview) or + ($isteacher and !$memberofsomegroup and $teachersoverride) or + $isteacheredit) { + $permission = true; + } + break; + } + return $permission; +} + +?> \ No newline at end of file diff --git a/group/lib/utillib.php b/group/lib/utillib.php new file mode 100644 index 0000000000..a79d6a3c47 --- /dev/null +++ b/group/lib/utillib.php @@ -0,0 +1,179 @@ +dirroot.'/lib/moodlelib.php'); + + +/********************************** + * Functions to get display names + ********************************** + */ + + +/** + * Gets the number of members of a group + * @param int $groupid The group specified + * @return int The number of members of the group + */ +function groups_get_no_group_members($groupid) { + $userids = groups_get_members($groupid); + if (!$userids) { + $nomembers = 0; + } else { + $nomembers = count($userids); + } + + return $nomembers; +} + + +/** + * Gets the number of groups in a specified grouping + * @param int $groupingid The grouping specified + * @return int The number of groups in the grouping + */ +function groups_get_no_groups_in_grouping($groupingid) { + $groupids = groups_get_groups_in_grouping($groupingid); + if (!$groupids) { + $nogroups = 0; + } else { + $nogroups = count($groupids); + } + return $nogroups; +} + + +/** + * Returns the display name of a user. This is the full name which if the user + * is a teacher, is prefixed by if the teacher has edit permission and - + * otherwise. + * @param int $userid The id of the user specified + * @param boolean $teacher True if the user is a teacher, false otherwise + * @return string The display name of the user + */ +function groups_get_user_displayname($userid, $courseid) { + if ($courseid == false) { + $fullname = false; + } else { + $user = groups_get_user($userid); + $fullname = fullname($user, true); + if (isteacher($courseid, $userid)) { + if (isteacheredit($courseid, $userid)) { + $prefix = '# '; + } else { + $prefix = '- '; + } + + $fullname = $prefix.$fullname; + } + } + + return $fullname; +} + + +/** + * Returns the display name of a group - this is the group name followed by the + * number of group members in brackets + * @param int $groupid The groupid + * @return string The display name of the group + */ +function groups_get_group_displayname($groupid) { + $groupsettings = groups_get_group_settings($groupid); + $groupname = $groupsettings->name; + $nogroupmembers = groups_get_no_group_members($groupid); + $displayname= "$groupname ($nogroupmembers)"; + return $displayname; +} + + +/** + * Returns the display name of a grouping - this is the grouping name followed + * by the number of groups in the + * grouping in brackets + * @param int $groupingid The grouping id + * @return string The display name of the grouping + */ +function groups_get_grouping_displayname($groupingid) { + $groupingsettings = groups_get_grouping_settings($groupingid); + $groupingname = $groupingsettings->name; + $nogroups= groups_get_no_groups_in_grouping($groupingid); + $displayname = "$groupingname ($nogroups)"; + return $displayname; +} + + +/** + * Takes an array of users (i.e of objects) and converts it in the corresponding + * array of userids. + * @param $users array The array of users + * @return array The array of user ids, or false if an error occurred + */ +function groups_users_to_userids($users) { + if (!$users) { + $userids = false; + } else { + $userids = array(); + foreach($users as $user) { + array_push($userids, $user->id); + } + } + return $userids; +} + +/** + * Takes an array of groups (i.e of objects) and converts it in the + * corresponding array of groupids. + * @param $groups array The array of group + * @return array The array of group ids, or false if an error occurred + */ +function groups_groups_to_groupids($groups) { + $groupids = array(); + foreach ($groups as $group) { + array_push($groupids, $group->id); + } + return $groupids; +} + +// @@@ TO DO +function groups_groupid_to_group($groupid) { +} + +// @@@ TO DO +function groups_groupids_to_groups($groupids) { +} + + +/** + * Gets the user object for a given userid. Can't find a function anywhere to + * do this and we need this + * for fullname() + * + * @param $userid int The userid + * @return object The corresponding user object, or false if an error occurred + */ +function groups_get_user($userid) { + return groups_db_get_user($userid); +} + + +/** + * Gets the course information object for a given course id + * @param $courseid int The course id + * @return object The course info object, or false if an error occurred. + * @@@ TO DO - need to put the database bit into a db file + */ +function groups_get_course_info($courseid){ + if (!$courseid) { + $courseinfo = false; + } else { + $courseinfo = get_record('course', 'id', $courseid); + } + return $courseinfo; +} +?> \ No newline at end of file diff --git a/group/onedaymaybe.txt b/group/onedaymaybe.txt new file mode 100644 index 0000000000..a84ff3acd2 --- /dev/null +++ b/group/onedaymaybe.txt @@ -0,0 +1,34 @@ +List of nice to haves +--------------------- + +- A way for modules to register the extent to which they support groups. Warn +people who try to set up groups with a module with legacy group support that it +might not work if more than one grouping exists. +- A proper user interface for using the same groups in more than one course +- The option of view names by last name rather than first name. +- Option of only showing students/teachers - having teachers mixed up with +students is confusing +- Maybe a nice way to see which users are in more than one group in a grouping? +- When adding users it would be nice to see the current users. +- Think about metacourses and how groups relate to these + +Global groups - I want it to be possible to set up groupings for course 1 and +for these to be visible for all course on the site, but not editable or +deletable. I think this code should actually be quite easy to write now and I +might even do it before this code is put in, just haven't done it yet. +# A nicer user interface (that doesn't break the back button :-) Ajax separates +the back and front end of the code really well, so if anyone has good ideas on +this, it should be quite easy for someone else to do without having to know how +the internals of the groups code work. +# Integration with roles and permissions +# Sign up sheets for groups +# Proper support for blocks and global features. +# A way for modules and blocks to declare whether they support groups or not. +# Putting in search_users functionality for group permissions as well as just +members of groups. +# Cool ways to set up groups automatically for particular pedagogical reasons - +things like minimising overlap with groups in another grouping, creating groups +just from the users all in another group and creating groups which merge pairs +of groups from another grouping. +# Allow settings for groupings which restrict users from being in more than one +group, number of people per group, etc. \ No newline at end of file diff --git a/group/overview.txt b/group/overview.txt new file mode 100644 index 0000000000..fcb2301629 --- /dev/null +++ b/group/overview.txt @@ -0,0 +1,54 @@ +Quick summary! + +See the wiki too - + +http://docs.moodle.org/en/How_groups_work_in_Moodle +http://docs.moodle.org/en/Groups_documentation_for_module_developers + +To install - run install.php. This create the appropriate database tables and +sets some default config for using an IMS Enterprise web service (in particular +the default setting is that such a web service is not called). + +The user interface for managing groups for a course is groupsui/index.php. +A grouping is just a set of groups - the idea is that you can have several +groupings for a course, and then choose different groupings for different +activities. + +Note that installing this code does not enable you to actually use the groupings +with activity modules - this is coming :-) + +configui - This contains the user interface for changing the IMS Enterprise web +service config + +db - all the functions that access the database, only used internally. There are +basically six tables that this code deals with groups_groups, +groups_courses_groups,groups_groups_users, groups_groupings + +groupui - the user interface for managing the groups and groupings of a course. +This uses Ajax so most of the code for the user interface is in the javascript +files - the PHP files just send back an appropriate XML response to specific +POST requests. You'll probably need to know the basics of how Ajax works to +understand the Javascript. + +lib - The main libraries for the user interface and other moodle code to user. +-- basicgrouplib.php contains the basic functions for adding users to groups, +deleting groups etc. +-- groupinglib.php contains the basic function for groupings e.g. creating +groupings, adding groups to groupings +-- extendedgrouplib.php contains other functions that are useful and use the +basic group and grouping functions +-- lib.php is just there to let you include all the libraries more easily +-- utillib.php contains functions that are handy but don't use any of the group +or grouping library function e.g. +things like getting the names of users +-- configlib.php - Contains wrapper functions for getting and setting config + +unittests - This directory needs a bit of sorting out, and I've just discovered +that I've broken one of the main +tests... + + +strings.php - This is stuff that will need to go in the language files - it's +here for convenience while I'm doing the +development. + diff --git a/group/todo.txt b/group/todo.txt new file mode 100644 index 0000000000..fec7040115 --- /dev/null +++ b/group/todo.txt @@ -0,0 +1,80 @@ +Things I know needs doing! +-------------------------- + +0) The main thing is to sort out how permissions are going to work... + +1) Write proper code for creating the database - I left this knowing there were +changes planned here. db/dbsetup.php obviously isn't what you'd want in the end. +No foreign keys at the moment either and there ought to be. I've also been +leaving this until the database structure is reasonably settled. If you've done +this sort of thing elsewhere, I suspect this will be fine. Also need to delete +the two Yahoo files and reference the ones in lib/yui instead - copied them +over when I was trying to debug stuff. + +2) Move all the Ajax over to use the Yahoo User Interface library - this +is straightforward but tedious! I've done one example - UpdateGroupings in +main-selects-form.js, everything else needs doing. You'll need +to do something sensible with errors, and eventually delete the current +functions for doing Ajax requests and responses which aren't very good anyway. + +2) Move unit tests over to simple test and improve them - we could also do with +some automated tests for the interface too - Selenium? + +3) Security - Need to do a check of this. In particular in the functions +giving the XML for the Ajax stuff, I think there was something I remember I +needed to do... + +4) Check complies with the Moodle coding standards. I think I may have +used tabs by accident because I didn't realise that the PHPEclipse settings +overrode the main Eclipse ones. Also line lengths are too long all over the +place. + +5) The CSS stuff needs to be moved to where it's supposed to be /rationalised +etc. + +6) The whole issue of permissions - talk to me about this + +7) Enrolment keys and user pics - haven't tested these out properly. + +8) The automatic grouping code could be a lot simpler I realised afterwards, +but it works so have been loathe to change it! + +9) Interesting question as to whether we should somehow record the extent to +which modules support groups... + +10) Who do we let edit/delete what? If a grouping is used by more than one +course. Maybe we need an 'owning' course in the database structure. Site-wide +groupings - making these appear in people's lists, but not editable + +11) Check I've done the bits with objects ok - need to check how PHP does OO. + +12) Check I've done the PHP docs right - just copied other people's! + +13) Check all the strings are in the lang file + +14) Make sure everything works on Postgres as well as MySQL. + +15) One thing that needs to be thought about is if it shoudl be possible to +turn a module from not using groups to using groups once students have accessed +it and if so how this should work. + +16) Make sure all references to IMS Enterprise stuff/web services are gone. + + +Other parts of the code that will need changing +------------------------------------------------ + +1) All the modules - I started doing these and then roles and permissions +happen. +2) Lots of the code in user - if we keep the group_member table the same +can we avoid modifiying some of this +3) The form where course settings are chosen. We still want it to be possible +to set a forced grouping for the whole course still and need to remove the +current options. +4) For each module, you need to be able to set a grouping. +5) Blocks, blogs and calendar also need to be dealt with +6) Backup code - there are bugs in the groups parts of this at the moment +so be careful here :-) +7) Code to delete courses etc. +8) Need to make sure grouped acitivities only display to people in the group. +