function restore_create_metacourse($restore, $xml_file) { global $CFG, $db; $status = true; //Check it exists if (!file_exists($xml_file)) { $status = false; } //Get info from xml if ($status) { //Load data from XML to info $info = restore_read_xml_metacourse($xml_file); } //Process info about metacourse if ($status and $info) { //Process child records if (!empty($info->childs)) { foreach ($info->childs as $child) { $dbcourse = false; $dbmetacourse = false; //Check if child course exists in destination server //(by id in the same server or by idnumber and shortname in other server) if (backup_is_same_site($restore)) { //Same server, lets see by id $dbcourse = get_record('course', 'id', $child->id); } else { //Different server, lets see by idnumber and shortname, and only ONE record $dbcount = count_records('course', 'idnumber', $child->idnumber, 'shortname', $child->shortname); if ($dbcount == 1) { $dbcourse = get_record('course', 'idnumber', $child->idnumber, 'shortname', $child->shortname); } } //If child course has been found, insert data if ($dbcourse) { $dbmetacourse->child_course = $dbcourse->id; $dbmetacourse->parent_course = $restore->course_id; $status = insert_record('course_meta', $dbmetacourse); } else { //Child course not found, notice! if (!defined('RESTORE_SILENTLY')) { echo '<ul><li>' . get_string('childcoursenotfound') . ' (' . $child->id . '/' . $child->idnumber . '/' . $child->shortname . ')</li></ul>'; } } } //Now, recreate student enrolments... sync_metacourse($restore->course_id); } //Process parent records if (!empty($info->parents)) { foreach ($info->parents as $parent) { $dbcourse = false; $dbmetacourse = false; //Check if parent course exists in destination server //(by id in the same server or by idnumber and shortname in other server) if (backup_is_same_site($restore)) { //Same server, lets see by id $dbcourse = get_record('course', 'id', $parent->id); } else { //Different server, lets see by idnumber and shortname, and only ONE record $dbcount = count_records('course', 'idnumber', $parent->idnumber, 'shortname', $parent->shortname); if ($dbcount == 1) { $dbcourse = get_record('course', 'idnumber', $parent->idnumber, 'shortname', $parent->shortname); } } //If parent course has been found, insert data if it is a metacourse if ($dbcourse) { if ($dbcourse->metacourse) { $dbmetacourse->parent_course = $dbcourse->id; $dbmetacourse->child_course = $restore->course_id; $status = insert_record('course_meta', $dbmetacourse); //Now, recreate student enrolments in parent course sync_metacourse($dbcourse->id); } else { //Parent course isn't metacourse, notice! if (!defined('RESTORE_SILENTLY')) { echo '<ul><li>' . get_string('parentcoursenotmetacourse') . ' (' . $parent->id . '/' . $parent->idnumber . '/' . $parent->shortname . ')</li></ul>'; } } } else { //Parent course not found, notice! if (!defined('RESTORE_SILENTLY')) { echo '<ul><li>' . get_string('parentcoursenotfound') . ' (' . $parent->id . '/' . $parent->idnumber . '/' . $parent->shortname . ')</li></ul>'; } } } } } return $status; }
} $msg .= '</p>'; print_simple_box_start('center'); notify($msg); print_simple_box_end(); } //Back to Assign Roles button echo "<br/>"; echo "<div class='continuebutton'>"; print_single_button('assign.php', array('contextid' => $contextid), get_string('assignrolesin', 'role', print_context_name($context))); echo "</div>"; } else { // Print overview table // sync metacourse enrolments if needed if ($inmeta) { sync_metacourse($course); } // Get the names of role holders for roles with between 1 and MAX_USERS_TO_LIST_PER_ROLE users, // and so determine whether to show the extra column. $rolehodlercount = array(); $rolehodlernames = array(); $strmorethanten = get_string('morethan', 'role', MAX_USERS_TO_LIST_PER_ROLE); $showroleholders = false; foreach ($assignableroles as $roleid => $rolename) { $countusers = count_role_users($roleid, $context); $rolehodlercount[$roleid] = $countusers; $roleusers = ''; if (0 < $countusers && $countusers <= MAX_USERS_TO_LIST_PER_ROLE) { $roleusers = get_role_users($roleid, $context, false, 'u.id, u.lastname, u.firstname'); if (!empty($roleusers)) { $strroleusers = array();
/** * Clear a course out completely, deleting all content * but don't delete the course itself * * @uses $CFG * @param int $courseid The id of the course that is being deleted * @param bool $showfeedback Whether to display notifications of each action the function performs. * @return bool true if all the removals succeeded. false if there were any failures. If this * method returns false, some of the removals will probably have succeeded, and others * failed, but you have no way of knowing which. */ function remove_course_contents($courseid, $showfeedback = true) { global $CFG; require_once $CFG->libdir . '/questionlib.php'; require_once $CFG->libdir . '/gradelib.php'; $result = true; if (!($course = get_record('course', 'id', $courseid))) { error('Course ID was incorrect (can\'t find it)'); } $strdeleted = get_string('deleted'); /// Clean up course formats (iterate through all formats in the even the course format was ever changed) $formats = get_list_of_plugins('course/format'); foreach ($formats as $format) { $formatdelete = $format . '_course_format_delete_course'; $formatlib = "{$CFG->dirroot}/course/format/{$format}/lib.php"; if (file_exists($formatlib)) { include_once $formatlib; if (function_exists($formatdelete)) { if ($showfeedback) { notify($strdeleted . ' ' . $format); } $formatdelete($course->id); } } } /// Delete every instance of every module if ($allmods = get_records('modules')) { foreach ($allmods as $mod) { $modname = $mod->name; $modfile = $CFG->dirroot . '/mod/' . $modname . '/lib.php'; $moddelete = $modname . '_delete_instance'; // Delete everything connected to an instance $moddeletecourse = $modname . '_delete_course'; // Delete other stray stuff (uncommon) $count = 0; if (file_exists($modfile)) { include_once $modfile; if (function_exists($moddelete)) { if ($instances = get_records($modname, 'course', $course->id)) { foreach ($instances as $instance) { if ($cm = get_coursemodule_from_instance($modname, $instance->id, $course->id)) { /// Delete activity context questions and question categories question_delete_activity($cm, $showfeedback); } if ($moddelete($instance->id)) { $count++; } else { notify('Could not delete ' . $modname . ' instance ' . $instance->id . ' (' . format_string($instance->name) . ')'); $result = false; } if ($cm) { // delete cm and its context in correct order delete_records('course_modules', 'id', $cm->id); delete_context(CONTEXT_MODULE, $cm->id); } } } } else { notify('Function ' . $moddelete . '() doesn\'t exist!'); $result = false; } if (function_exists($moddeletecourse)) { $moddeletecourse($course, $showfeedback); } } if ($showfeedback) { notify($strdeleted . ' ' . $count . ' x ' . $modname); } } } else { error('No modules are installed!'); } /// Give local code a chance to delete its references to this course. require_once $CFG->libdir . '/locallib.php'; notify_local_delete_course($courseid, $showfeedback); /// Delete course blocks if ($blocks = get_records_sql("SELECT *\n FROM {$CFG->prefix}block_instance\n WHERE pagetype = '" . PAGE_COURSE_VIEW . "'\n AND pageid = {$course->id}")) { if (delete_records('block_instance', 'pagetype', PAGE_COURSE_VIEW, 'pageid', $course->id)) { if ($showfeedback) { notify($strdeleted . ' block_instance'); } require_once $CFG->libdir . '/blocklib.php'; foreach ($blocks as $block) { /// Delete any associated contexts for this block delete_context(CONTEXT_BLOCK, $block->id); // fix for MDL-7164 // Get the block object and call instance_delete() if (!($record = blocks_get_record($block->blockid))) { $result = false; continue; } if (!($obj = block_instance($record->name, $block))) { $result = false; continue; } // Return value ignored, in core mods this does not do anything, but just in case // third party blocks might have stuff to clean up // we execute this anyway $obj->instance_delete(); } } else { $result = false; } } /// Delete any groups, removing members and grouping/course links first. require_once $CFG->dirroot . '/group/lib.php'; groups_delete_groupings($courseid, $showfeedback); groups_delete_groups($courseid, $showfeedback); /// Delete all related records in other tables that may have a courseid /// This array stores the tables that need to be cleared, as /// table_name => column_name that contains the course id. $tablestoclear = array('event' => 'courseid', 'log' => 'course', 'course_sections' => 'course', 'course_modules' => 'course', 'backup_courses' => 'courseid', 'user_lastaccess' => 'courseid', 'backup_log' => 'courseid'); foreach ($tablestoclear as $table => $col) { if (delete_records($table, $col, $course->id)) { if ($showfeedback) { notify($strdeleted . ' ' . $table); } } else { $result = false; } } /// Clean up metacourse stuff if ($course->metacourse) { delete_records("course_meta", "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} course_meta"); } } else { if ($parents = get_records("course_meta", "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} course_meta"); } } } /// Delete questions and question categories question_delete_course($course, $showfeedback); /// Remove all data from gradebook $context = get_context_instance(CONTEXT_COURSE, $courseid); remove_course_grades($courseid, $showfeedback); remove_grade_letters($context, $showfeedback); return $result; }
/** * Deletes one or more role assignments. You must specify at least one parameter. * @param $roleid * @param $userid * @param $groupid * @param $contextid * @param $enrol unassign only if enrolment type matches, NULL means anything * @return boolean - success or failure */ function role_unassign($roleid = 0, $userid = 0, $groupid = 0, $contextid = 0, $enrol = NULL) { global $USER, $CFG, $DB; require_once $CFG->dirroot . '/group/lib.php'; $success = true; $args = array('roleid', 'userid', 'groupid', 'contextid'); $select = array(); $params = array(); foreach ($args as $arg) { if (${$arg}) { $select[] = "{$arg} = ?"; $params[] = ${$arg}; } } if (!empty($enrol)) { $select[] = "enrol=?"; $params[] = $enrol; } if ($select) { if ($ras = $DB->get_records_select('role_assignments', implode(' AND ', $select), $params)) { $mods = get_list_of_plugins('mod'); foreach ($ras as $ra) { $fireevent = false; /// infinite loop protection when deleting recursively if (!($ra = $DB->get_record('role_assignments', array('id' => $ra->id)))) { continue; } if ($DB->delete_records('role_assignments', array('id' => $ra->id))) { $fireevent = true; } else { $success = false; } if (!($context = get_context_instance_by_id($ra->contextid))) { // strange error, not much to do continue; } /* mark contexts as dirty here, because we need the refreshed * caps bellow to delete group membership and user_lastaccess! * and yes, this is very expensive for bulk operations :-( */ mark_context_dirty($context->path); /// If the user is the current user, then do full reload of capabilities too. if (!empty($USER->id) && $USER->id == $ra->userid) { load_all_capabilities(); } /// Ask all the modules if anything needs to be done for this user foreach ($mods as $mod) { include_once $CFG->dirroot . '/mod/' . $mod . '/lib.php'; $functionname = $mod . '_role_unassign'; if (function_exists($functionname)) { $functionname($ra->userid, $context); // watch out, $context might be NULL if something goes wrong } } /// now handle metacourse role unassigment and removing from goups if in course context if ($context->contextlevel == CONTEXT_COURSE) { // cleanup leftover course groups/subscriptions etc when user has // no capability to view course // this may be slow, but this is the proper way of doing it if (!has_capability('moodle/course:view', $context, $ra->userid)) { // remove from groups groups_delete_group_members($context->instanceid, $ra->userid); // delete lastaccess records $DB->delete_records('user_lastaccess', array('userid' => $ra->userid, 'courseid' => $context->instanceid)); } //unassign roles in metacourses if needed if ($parents = $DB->get_records('course_meta', array('child_course' => $context->instanceid))) { foreach ($parents as $parent) { sync_metacourse($parent->parent_course); } } } if ($fireevent) { events_trigger('role_unassigned', $ra); } } } } return $success; }
/** * Clear a course out completely, deleting all content * but don't delete the course itself * * @global object * @global object * @param int $courseid The id of the course that is being deleted * @param bool $showfeedback Whether to display notifications of each action the function performs. * @return bool true if all the removals succeeded. false if there were any failures. If this * method returns false, some of the removals will probably have succeeded, and others * failed, but you have no way of knowing which. */ function remove_course_contents($courseid, $showfeedback = true) { global $CFG, $DB, $OUTPUT; require_once $CFG->libdir . '/questionlib.php'; require_once $CFG->libdir . '/gradelib.php'; $result = true; if (!($course = $DB->get_record('course', array('id' => $courseid)))) { print_error('invalidcourseid'); } $context = get_context_instance(CONTEXT_COURSE, $courseid); $strdeleted = get_string('deleted'); /// Clean up course formats (iterate through all formats in the even the course format was ever changed) $formats = get_plugin_list('format'); foreach ($formats as $format => $formatdir) { $formatdelete = $format . '_course_format_delete_course'; $formatlib = "{$formatdir}/lib.php"; if (file_exists($formatlib)) { include_once $formatlib; if (function_exists($formatdelete)) { if ($showfeedback) { echo $OUTPUT->notification($strdeleted . ' ' . $format); } $formatdelete($course->id); } } } /// Delete every instance of every module if ($allmods = $DB->get_records('modules')) { foreach ($allmods as $mod) { $modname = $mod->name; $modfile = $CFG->dirroot . '/mod/' . $modname . '/lib.php'; $moddelete = $modname . '_delete_instance'; // Delete everything connected to an instance $moddeletecourse = $modname . '_delete_course'; // Delete other stray stuff (uncommon) $count = 0; if (file_exists($modfile)) { include_once $modfile; if (function_exists($moddelete)) { if ($instances = $DB->get_records($modname, array('course' => $course->id))) { foreach ($instances as $instance) { if ($cm = get_coursemodule_from_instance($modname, $instance->id, $course->id)) { /// Delete activity context questions and question categories question_delete_activity($cm, $showfeedback); } if ($moddelete($instance->id)) { $count++; } else { echo $OUTPUT->notification('Could not delete ' . $modname . ' instance ' . $instance->id . ' (' . format_string($instance->name) . ')'); $result = false; } if ($cm) { // delete cm and its context in correct order $DB->delete_records('course_modules', array('id' => $cm->id)); delete_context(CONTEXT_MODULE, $cm->id); } } } } else { echo $OUTPUT->notification('Function ' . $moddelete . '() doesn\'t exist!'); $result = false; } if (function_exists($moddeletecourse)) { $moddeletecourse($course, $showfeedback); } } if ($showfeedback) { echo $OUTPUT->notification($strdeleted . ' ' . $count . ' x ' . $modname); } } } else { print_error('nomodules', 'debug'); } /// Delete course blocks blocks_delete_all_for_context($context->id); /// Delete any groups, removing members and grouping/course links first. require_once $CFG->dirroot . '/group/lib.php'; groups_delete_groupings($courseid, $showfeedback); groups_delete_groups($courseid, $showfeedback); /// Delete all related records in other tables that may have a courseid /// This array stores the tables that need to be cleared, as /// table_name => column_name that contains the course id. $tablestoclear = array('event' => 'courseid', 'log' => 'course', 'course_sections' => 'course', 'course_modules' => 'course', 'backup_courses' => 'courseid', 'user_lastaccess' => 'courseid', 'backup_log' => 'courseid'); foreach ($tablestoclear as $table => $col) { if ($DB->delete_records($table, array($col => $course->id))) { if ($showfeedback) { echo $OUTPUT->notification($strdeleted . ' ' . $table); } } else { $result = false; } } /// Clean up metacourse stuff if ($course->metacourse) { $DB->delete_records("course_meta", array("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) { echo $OUTPUT->notification("{$strdeleted} course_meta"); } } else { if ($parents = $DB->get_records("course_meta", array("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) { echo $OUTPUT->notification("{$strdeleted} course_meta"); } } } /// Delete questions and question categories question_delete_course($course, $showfeedback); /// Remove all data from gradebook remove_course_grades($courseid, $showfeedback); remove_grade_letters($context, $showfeedback); /// Delete course tags require_once $CFG->dirroot . '/tag/coursetagslib.php'; coursetag_delete_course_tags($course->id, $showfeedback); return $result; }
/** * Deletes one or more role assignments. You must specify at least one parameter. * @param $roleid * @param $userid * @param $groupid * @param $contextid * @param $enrol unassign only if enrolment type matches, NULL means anything * @return boolean - success or failure */ function role_unassign($roleid = 0, $userid = 0, $groupid = 0, $contextid = 0, $enrol = NULL) { global $USER, $CFG; $success = true; $args = array('roleid', 'userid', 'groupid', 'contextid'); $select = array(); foreach ($args as $arg) { if (${$arg}) { $select[] = $arg . ' = ' . ${$arg}; } } if (!empty($enrol)) { $select[] = "enrol='{$enrol}'"; } if ($select) { if ($ras = get_records_select('role_assignments', implode(' AND ', $select))) { $mods = get_list_of_plugins('mod'); foreach ($ras as $ra) { /// infinite loop protection when deleting recursively if (!($ra = get_record('role_assignments', 'id', $ra->id))) { continue; } $success = delete_records('role_assignments', 'id', $ra->id) and $success; /// If the user is the current user, then reload the capabilities too. if (!empty($USER->id) && $USER->id == $ra->userid) { load_all_capabilities(); } $context = get_record('context', 'id', $ra->contextid); /// Ask all the modules if anything needs to be done for this user foreach ($mods as $mod) { include_once $CFG->dirroot . '/mod/' . $mod . '/lib.php'; $functionname = $mod . '_role_unassign'; if (function_exists($functionname)) { $functionname($ra->userid, $context); // watch out, $context might be NULL if something goes wrong } } /// now handle metacourse role unassigment and removing from goups if in course context if (!empty($context) and $context->contextlevel == CONTEXT_COURSE) { // cleanup leftover course groups/subscriptions etc when user has // no capability to view course // this may be slow, but this is the proper way of doing it if (!has_capability('moodle/course:view', $context, $ra->userid)) { // remove from groups if ($groups = groups_get_all_groups($context->instanceid)) { foreach ($groups as $group) { delete_records('groups_members', 'groupid', $group->id, 'userid', $ra->userid); } } // delete lastaccess records delete_records('user_lastaccess', 'userid', $ra->userid, 'courseid', $context->instanceid); } //unassign roles in metacourses if needed if ($parents = get_records('course_meta', 'child_course', $context->instanceid)) { foreach ($parents as $parent) { sync_metacourse($parent->parent_course); } } } } } } return $success; }
/** * Clear a course out completely, deleting all content * but don't delete the course itself * * @uses $CFG * @param int $courseid The id of the course that is being deleted * @param bool $showfeedback Whether to display notifications of each action the function performs. * @return bool true if all the removals succeeded. false if there were any failures. If this * method returns false, some of the removals will probably have succeeded, and others * failed, but you have no way of knowing which. */ function remove_course_contents($courseid, $showfeedback = true) { global $CFG; $result = true; if (!($course = get_record('course', 'id', $courseid))) { error('Course ID was incorrect (can\'t find it)'); } $strdeleted = get_string('deleted'); /// First delete every instance of every module if ($allmods = get_records('modules')) { foreach ($allmods as $mod) { $modname = $mod->name; $modfile = $CFG->dirroot . '/mod/' . $modname . '/lib.php'; $moddelete = $modname . '_delete_instance'; // Delete everything connected to an instance $moddeletecourse = $modname . '_delete_course'; // Delete other stray stuff (uncommon) $count = 0; if (file_exists($modfile)) { include_once $modfile; if (function_exists($moddelete)) { if ($instances = get_records($modname, 'course', $course->id)) { foreach ($instances as $instance) { if ($cm = get_coursemodule_from_instance($modname, $instance->id, $course->id)) { delete_context(CONTEXT_MODULE, $cm->id); } if ($moddelete($instance->id)) { $count++; } else { notify('Could not delete ' . $modname . ' instance ' . $instance->id . ' (' . format_string($instance->name) . ')'); $result = false; } } } } else { notify('Function ' . $moddelete . '() doesn\'t exist!'); $result = false; } if (function_exists($moddeletecourse)) { $moddeletecourse($course, $showfeedback); } } if ($showfeedback) { notify($strdeleted . ' ' . $count . ' x ' . $modname); } } } else { error('No modules are installed!'); } /// Give local code a chance to delete its references to this course. require_once 'locallib.php'; notify_local_delete_course($courseid, $showfeedback); /// Delete course blocks if ($blocks = get_records_sql("SELECT *\n FROM {$CFG->prefix}block_instance\n WHERE pagetype = '" . PAGE_COURSE_VIEW . "'\n AND pageid = {$course->id}")) { if (delete_records('block_instance', 'pagetype', PAGE_COURSE_VIEW, 'pageid', $course->id)) { if ($showfeedback) { notify($strdeleted . ' block_instance'); } require_once $CFG->libdir . '/blocklib.php'; foreach ($blocks as $block) { /// Delete any associated contexts for this block // Block instances are rarely created. Since the block instance is gone from the above delete // statement, calling delete_context() will generate a warning as get_context_instance could // no longer create the context as the block is already gone. if (record_exists('context', 'contextlevel', CONTEXT_BLOCK, 'instanceid', $block->id)) { delete_context(CONTEXT_BLOCK, $block->id); } // fix for MDL-7164 // Get the block object and call instance_delete() if (!($record = blocks_get_record($block->blockid))) { $result = false; continue; } if (!($obj = block_instance($record->name, $block))) { $result = false; continue; } // Return value ignored, in core mods this does not do anything, but just in case // third party blocks might have stuff to clean up // we execute this anyway $obj->instance_delete(); } } else { $result = false; } } /// Delete any groups, removing members and grouping/course links first. //TODO: If groups or groupings are to be shared between courses, think again! if ($groupids = groups_get_groups($course->id)) { foreach ($groupids as $groupid) { if (groups_remove_all_members($groupid)) { if ($showfeedback) { notify($strdeleted . ' groups_members'); } } else { $result = false; } /// Delete any associated context for this group ?? delete_context(CONTEXT_GROUP, $groupid); if (groups_delete_group($groupid)) { if ($showfeedback) { notify($strdeleted . ' groups'); } } else { $result = false; } } } /// Delete any groupings. $result = groups_delete_all_groupings($course->id); if ($result && $showfeedback) { notify($strdeleted . ' groupings'); } /// Delete all related records in other tables that may have a courseid /// This array stores the tables that need to be cleared, as /// table_name => column_name that contains the course id. $tablestoclear = array('event' => 'courseid', 'log' => 'course', 'course_sections' => 'course', 'course_modules' => 'course', 'grade_category' => 'courseid', 'grade_exceptions' => 'courseid', 'grade_item' => 'courseid', 'grade_letter' => 'courseid', 'grade_preferences' => 'courseid', 'backup_courses' => 'courseid', 'backup_log' => 'courseid'); foreach ($tablestoclear as $table => $col) { if (delete_records($table, $col, $course->id)) { if ($showfeedback) { notify($strdeleted . ' ' . $table); } } else { $result = false; } } /// Clean up metacourse stuff if ($course->metacourse) { delete_records("course_meta", "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} course_meta"); } } else { if ($parents = get_records("course_meta", "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} course_meta"); } } } /// Delete questions and question categories include_once $CFG->libdir . '/questionlib.php'; question_delete_course($course, $showfeedback); /// Delete all roles and overiddes in the course context (but keep the course context) if ($courseid != SITEID) { delete_context(CONTEXT_COURSE, $course->id); } // fix for MDL-9016 // clear the cache because the course context is deleted, and // we don't want to write assignment, overrides and context_rel table // with this old context id! get_context_instance('clearcache'); return $result; }