diff --git a/admin/cron.php b/admin/cron.php index 6d7608f6ed3..c0c759c403b 100644 --- a/admin/cron.php +++ b/admin/cron.php @@ -123,6 +123,8 @@ } flush(); + sync_metacourses(); + } // End of occasional clean-up tasks if (file_exists("$CFG->dataroot/cronextra.php")) { diff --git a/blocks/admin/block_admin.php b/blocks/admin/block_admin.php index 49213c8e3b9..2535fe2db33 100644 --- a/blocks/admin/block_admin.php +++ b/blocks/admin/block_admin.php @@ -103,10 +103,15 @@ class block_admin extends block_base { if (!$course->students) { $course->students = get_string('defaultcoursestudents'); + } + if (!$course->meta_course) { + $this->content->items[]=''.$course->students.'...'; + $this->content->icons[]=''; + } + else { + $this->content->items[]=''.$course->students.'...'; + $this->content->icons[]=''; } - $this->content->items[]=''.$course->students.'...'; - $this->content->icons[]=''; - $this->content->items[]=''.get_string('backup').'...'; $this->content->icons[]=''; diff --git a/course/edit.html b/course/edit.html index 6380029631f..317b5160cbe 100644 --- a/course/edit.html +++ b/course/edit.html @@ -15,6 +15,9 @@ if (!isset($form->enrolperiod)) { $form->enrolperiod = 0; } + if (!isset($form->meta_course)) { + $form->meta_course = 0; + } ?>
@@ -255,6 +258,20 @@ ?> + + + + diff --git a/course/edit.php b/course/edit.php index edfa2ccf72f..83e728cedf9 100644 --- a/course/edit.php +++ b/course/edit.php @@ -9,6 +9,8 @@ $category = (int)optional_param('category', 0); // possible default category require_login(); + + $disable_meta = false; if ($id) { if (! $course = get_record("course", "id", $id)) { @@ -18,6 +20,20 @@ if (!isteacheredit($course->id)) { error("You do not currently have editing privileges!"); } + + if (course_in_meta($course)) { + $disable_meta = get_string('metaalreadyinmeta'); + } + else if ($course->meta_course) { + if (count_records("meta_course","parent_course",$course->id) > 0) { + $disable_meta = get_string('metaalreadyhascourses'); + } + } + else { + if (count_records("user_students","course",$course->id) > 0) { + $disable_meta = get_string('metaalreadyhasenrolments'); + } + } } else { // Admin is creating a new course if (!iscreator()) { diff --git a/course/lib.php b/course/lib.php index 6b74205d1c0..2bcfa7aa359 100644 --- a/course/lib.php +++ b/course/lib.php @@ -1867,4 +1867,26 @@ function make_editing_buttons($mod, $absolute=false, $moveselect=true, $indent=- " alt=\"$str->delete\" />$hideshow$groupmode"; } +/** + * given a course object with shortname & fullname, this function will + * truncate the the number of chars allowed and add ... if it was too long + */ +function course_format_name ($course,$max=100) { + + $str = $course->shortname.': '.$course->fullname; + if (strlen($str) <= $max) { + return $str; + } + else { + return substr($str,0,$max-3).'...'; + } +} + +/** + * This function will return true if the given course is a child course at all + */ +function course_in_meta ($course) { + return record_exists("meta_course","child_course",$course->id); +} + ?> diff --git a/course/student.php b/course/student.php index 7e074998fd2..666a6406332 100644 --- a/course/student.php +++ b/course/student.php @@ -18,6 +18,10 @@ error("Course ID was incorrect (can't find it)"); } + if ($course->meta_course) { + redirect("$CFG->wwwroot/course/importstudents.php?id=$course->id"); + } + require_login($course->id); if (!isteacheredit($course->id)) { diff --git a/lang/en/help/enrolperiod.html b/lang/en/help/enrolperiod.html index c55f4aec63d..33f993f1c1b 100644 --- a/lang/en/help/enrolperiod.html +++ b/lang/en/help/enrolperiod.html @@ -11,3 +11,5 @@ in this course until they are manually unenrolled or the clean-up function to remove defunct students takes effect.

+

If you have selected to manage this course as a meta course, + your enrolment period will not be used.

\ No newline at end of file diff --git a/lang/en/moodle.php b/lang/en/moodle.php index e0589fd0336..fc20a90a6f9 100644 --- a/lang/en/moodle.php +++ b/lang/en/moodle.php @@ -590,6 +590,7 @@ $string['htmleditordisabledbrowser'] = 'The HTML editor is unavailable because y $string['htmlformat'] = 'Pretty HTML format'; $string['icqnumber'] = 'ICQ number'; $string['idnumber'] = 'ID number'; +$string['importmetacoursenote'] = 'Use this form to add courses to your meta course (this will import the enrolments)'; $string['inactive'] = 'Inactive'; $string['include'] = 'Include'; $string['includeallusers'] = 'Include All Users'; @@ -671,6 +672,9 @@ $string['makeeditable'] = 'If you make \'$a\' editable by the web server process $string['manageblocks'] = 'Blocks'; $string['managedatabase'] = 'Database'; $string['managefilters'] = 'Filters'; +$string['managemeta'] = 'Is this a meta course?'; +$string['managemetaexplan'] = '(This means that enrolments are inherited from other courses)'; +$string['managemetadisabled'] = 'This is disabled because this course is already in a meta course'; $string['managemodules'] = 'Modules'; $string['markedthistopic'] = 'This topic is highlighted as the current topic'; $string['markthistopic'] = 'Highlight this topic as the current topic'; @@ -679,6 +683,16 @@ $string['maximumgrade'] = 'Maximum grade'; $string['maximumshort'] = 'Max'; $string['maximumupload'] = 'Maximum upload size'; $string['maxsize'] = 'Max size: $a'; +$string['metaassigncourses'] = 'Assign courses'; +$string['metaalreadycourses'] = 'Courses already assigned'; +$string['metaalreadyhascourses'] = 'This meta course already has child courses.'; +$string['metaalreadyhasenrolments'] = 'This course already has normal enrolments.'; +$string['metaalreadyinmeta'] = 'This course is already part of a meta course.'; +$string['metanoalreadycourses'] = 'No courses already assigned'; +$string['metapotentialcourses'] = 'Courses available'; +$string['metanopotentialcourses'] = 'No courses available'; +$string['metaaddcourse'] = 'Add this course'; +$string['metaremovecourse'] = 'Remove this course'; $string['min'] = 'min'; $string['mins'] = 'mins'; $string['minutes'] = 'minutes'; diff --git a/lib/datalib.php b/lib/datalib.php index bcea6cc210c..ab54b3d5bbe 100644 --- a/lib/datalib.php +++ b/lib/datalib.php @@ -1297,6 +1297,34 @@ function get_creators() { ORDER BY u.id ASC"); } +function get_courses_in_metacourse($metacourseid) { + global $CFG; + + $sql = "SELECT c.id,c.shortname,c.fullname FROM {$CFG->prefix}course c, {$CFG->prefix}meta_course mc WHERE mc.parent_course = $metacourseid + AND mc.child_course = c.id"; + + return get_records_sql($sql); +} + +function get_courses_notin_metacourse($metacourseid,$count=false) { + + global $CFG; + + $site = get_site(); // we don't want the site course in here. + + if ($count) { + $sql = "SELECT COUNT(c.id)"; + } + else { + $sql = "SELECT c.id,c.shortname,c.fullname"; + } + $sql .= " FROM {$CFG->prefix}course c LEFT JOIN {$CFG->prefix}meta_course mc ON mc.child_course = c.id + WHERE (mc.parent_course IS NULL OR mc.parent_course != $metacourseid) AND c.id != $metacourseid AND c.id != $site->id"; + + return get_records_sql($sql); +} + + /** * Returns $user object of the main teacher for a course * diff --git a/lib/db/mysql.php b/lib/db/mysql.php index e6eef77ce2a..6f19eb0720a 100644 --- a/lib/db/mysql.php +++ b/lib/db/mysql.php @@ -1102,9 +1102,23 @@ function main_upgrade($oldversion=0) { } } } + + + if ($oldversion < 2005012500) { + // add new table for meta courses. + modify_database("","CREATE TABLE `prefix_meta_course` ( + `id` int(1) unsigned NOT NULL auto_increment, + `parent_course` int(10) NOT NULL default 0, + `child_course` int(10) NOT NULL default 0, + PRIMARY KEY (`id`), + KEY `parent_course` (parent_course), + KEY `child_course` (child_course) + );"); + // add flag to course field + table_column('course','','meta_course','integer','1','','0','not null'); + } return $result; - } ?> diff --git a/lib/db/mysql.sql b/lib/db/mysql.sql index dacedc61015..369c1cefd61 100644 --- a/lib/db/mysql.sql +++ b/lib/db/mysql.sql @@ -59,6 +59,7 @@ CREATE TABLE `prefix_course` ( `cost` varchar(10) NOT NULL default '', `timecreated` int(10) unsigned NOT NULL default '0', `timemodified` int(10) unsigned NOT NULL default '0', + `meta_course` int(1) unsigned NOT NULL default '0', PRIMARY KEY (`id`), KEY `category` (`category`), KEY `idnumber` (`idnumber`), @@ -549,6 +550,16 @@ CREATE TABLE `prefix_user_coursecreators` ( KEY `userid` (`userid`) ) TYPE=MyISAM COMMENT='One record per course creator'; + +CREATE TABLE `prefix_meta_course` ( + `id` int(1) unsigned NOT NULL auto_increment, + `parent_course` int(10) NOT NULL default 0, + `child_course` int(10) NOT NULL default 0, + PRIMARY KEY (`id`), + KEY `parent_course` (parent_course), + KEY `child_course` (child_course) +); + INSERT INTO prefix_log_display VALUES ('user', 'view', 'user', 'CONCAT(firstname," ",lastname)'); INSERT INTO prefix_log_display VALUES ('course', 'user report', 'user', 'CONCAT(firstname," ",lastname)'); INSERT INTO prefix_log_display VALUES ('course', 'view', 'course', 'fullname'); diff --git a/lib/db/postgres7.php b/lib/db/postgres7.php index 9367c836c71..a98b1d1f58e 100644 --- a/lib/db/postgres7.php +++ b/lib/db/postgres7.php @@ -878,6 +878,18 @@ function main_upgrade($oldversion=0) { } } + if ($oldversion < 2005012500) { // add new table for meta courses. + modify_database("","CREATE TABLE prefix_meta_course ( + id SERIAL primary key, + parent_course integer NOT NULL, + child_course integer NOT NULL + );"); + + modify_database("","CREATE INDEX prefix_meta_course_parent_idx ON prefix_meta_course (parent_course);"); + modify_database("","CREATE INDEX prefix_meta_course_child_idx ON prefix_meta_course (child_course);"); + table_column('course','','meta_course','integer','1','','0','not null'); + } + return $result; } diff --git a/lib/db/postgres7.sql b/lib/db/postgres7.sql index 25a72683d67..9cf09a459cc 100644 --- a/lib/db/postgres7.sql +++ b/lib/db/postgres7.sql @@ -36,7 +36,8 @@ CREATE TABLE prefix_course ( lang varchar(10) NOT NULL default '', cost varchar(10) NOT NULL default '', timecreated integer NOT NULL default '0', - timemodified integer NOT NULL default '0' + timemodified integer NOT NULL default '0', + meta_course integer NOT NULL default '0' ); CREATE UNIQUE INDEX prefix_course_category_sortorder_uk ON prefix_course (category,sortorder); @@ -380,6 +381,15 @@ CREATE TABLE prefix_user_coursecreators ( userid int8 NOT NULL default '0' ); +CREATE TABLE prefix_meta_course ( + id SERIAL primary key, + parent_course integer NOT NULL, + child_course integer NOT NULL +); + +CREATE INDEX prefix_meta_course_parent_idx ON prefix_meta_course (parent_course); +CREATE INDEX prefix_meta_course_child_idx ON prefix_meta_course (child_course); + INSERT INTO prefix_log_display VALUES ('user', 'view', 'user', 'firstname||\' \'||lastname'); INSERT INTO prefix_log_display VALUES ('course', 'user report', 'user', 'firstname||\' \'||lastname'); INSERT INTO prefix_log_display VALUES ('course', 'view', 'course', 'fullname'); diff --git a/lib/moodlelib.php b/lib/moodlelib.php index c99196702f1..f09dea45a55 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -1041,6 +1041,128 @@ function check_for_restricted_user($username=NULL, $redirect='') { } } +function sync_metacourses() { + + global $CFG; + + if (!$courses = get_records_sql("SELECT DISTINCT parent_course,1 FROM {$CFG->prefix}meta_course")) { + return; + } + + foreach ($courses as $course) { + sync_metacourse($course->parent_course); + } +} + + +/** + * Goes through all enrolment records for the courses inside the metacourse and sync with them. + */ + +function sync_metacourse($metacourseid) { + + global $CFG; + + if (!$metacourse = get_record("course","id",$metacourseid)) { + return false; + } + + + if (count_records('meta_course','parent_course',$metacourseid) == 0) { // if there are no child courses for this meta course, nuke the enrolments + if ($enrolments = get_records('user_students','course',$metacourseid,'','userid,1')) { + foreach ($enrolments as $enrolment) { + unenrol_student($enrolment->userid,$metacourseid); + } + } + return true; + } + + + // this will return a list of userids from user_student for enrolments in the metacourse that shouldn't be there. + $sql = "SELECT DISTINCT parent.userid,1 + FROM {$CFG->prefix}meta_course meta + JOIN {$CFG->prefix}user_students parent + ON meta.parent_course = parent.course + AND meta.parent_course = $metacourseid + LEFT JOIN {$CFG->prefix}user_students child + ON meta.child_course = child.course + WHERE child.course IS NULL"; + + if ($enrolmentstodelete = get_records_sql($sql)) { + foreach ($enrolmentstodelete as $enrolment) { + unenrol_student($enrolment->userid,$metacourseid); // doing it this way for forum subscriptions etc. + } + } + + + // this will return a list of userids that need to be enrolled in the metacourse + $sql = "SELECT DISTINCT child.userid,1 + FROM {$CFG->prefix}meta_course meta + JOIN {$CFG->prefix}user_students child + ON meta.child_course = child.course + AND meta.parent_course = $metacourseid + LEFT JOIN {$CFG->prefix}user_students parent + ON meta.parent_course = parent.course + WHERE parent.course IS NULL"; + + if ($userstoadd = get_records_sql($sql)) { + foreach ($userstoadd as $user) { + enrol_student($user->userid,$metacourseid); + } + } + + // and next make sure that we have the right start time and end time (ie max and min) for them all. + if ($enrolments = get_records('user_students','course',$metacourseid,'','id,userid')) { + foreach ($enrolments as $enrol) { + if ($maxmin = get_record_sql("SELECT min(timestart) AS timestart, max(timeend) AS timeend + FROM mdl_user_students u JOIN mdl_meta_course mc ON u.course = mc.child_course WHERE userid = $enrol->userid + AND mc.parent_course = $metacourseid")) { + $enrol->timestart = $maxmin->timestart; + $enrol->timeend = $maxmin->timeend; + update_record('user_students',$enrol); + } + } + } + return true; +} + +/** + * Adds a record to the metacourse table and calls sync_metacoures + */ +function add_to_metacourse ($metacourseid, $courseid) { + + if (!$metacourse = get_record("course","id",$metacourseid)) { + return false; + } + + if (!$course = get_record("course","id",$courseid)) { + return false; + } + + if (!$record = get_record("meta_course","parent_course",$metacourseid,"child_course",$courseid)) { + $rec->parent_course = $metacourseid; + $rec->child_course = $courseid; + if (!insert_record('meta_course',$rec)) { + return false; + } + return sync_metacourse($metacourseid); + } + return true; + +} + +/** + * Removes the record from the metacourse table and calls sync_metacourse + */ +function remove_from_metacourse($metacourseid, $courseid) { + + if (delete_records('meta_course','parent_course',$metacourseid,'child_course',$courseid)) { + return sync_metacourse($metacourseid); + } + return false; +} + + /** * Determines if a user an admin * @@ -1640,6 +1762,12 @@ function enrol_student($userid, $courseid, $timestart=0, $timeend=0, $enrol='man if (!$user = get_record('user', 'id', $userid)) { // Check user return false; } + // enrol the student in any parent meta courses... + if ($parents = get_records('meta_course','child_course',$courseid)) { + foreach ($parents as $parent) { + enrol_student($userid, $parent->parent_course,$timestart,$timeend,$enrol); + } + } if ($student = get_record('user_students', 'userid', $userid, 'course', $courseid)) { $student->timestart = $timestart; $student->timeend = $timeend; @@ -1682,6 +1810,12 @@ function unenrol_student($userid, $courseid=0) { delete_records('groups_members', 'groupid', $group->id, 'userid', $userid); } } + // enrol the student in any parent meta courses... + if ($parents = get_records('meta_course','child_course',$courseid)) { + foreach ($parents as $parent) { + unenrol_student($userid, $parent->parent_course); + } + } return delete_records('user_students', 'userid', $userid, 'course', $courseid); } else { @@ -2009,6 +2143,24 @@ function remove_course_contents($courseid, $showfeedback=true) { $result = false; } + if ($course->meta_course) { + delete_records("meta_course","parent_course",$course->id); + sync_metacourse($course->id); // have to do it here so the enrolments get nuked. sync_metacourses won't find it without the id. + if ($showfeedback) { + notify("$strdeleted meta_course"); + } + } + else { + if ($parents = get_records("meta_course","child_course",$course->id)) { + foreach ($parents as $parent) { + remove_from_metacourse($parent->parent_course,$parent->child_course); // this will do the unenrolments as well. + } + if ($showfeedback) { + notify("$strdeleted meta_course"); + } + } + } + return $result; } diff --git a/version.php b/version.php index e2a5c22d3c3..bf9a923e823 100644 --- a/version.php +++ b/version.php @@ -6,7 +6,7 @@ // This is compared against the values stored in the database to determine // whether upgrades should be performed (see lib/db/*.php) - $version = 2005011000; // YYYYMMDD = date of first major branch release 1.4 + $version = 2005012500; // YYYYMMDD = date of first major branch release 1.4 // XY = increments within a single day $release = '1.5 UNSTABLE DEVELOPMENT'; // Human-friendly version name

:

+ meta_course,"","",""); + } else { + echo ((empty($form->meta_course)) ? get_string("no") : get_string("yes")); + echo " - $disable_meta "; + } ?>  +
" />