function restore_create_users($restore, $xml_file) { global $CFG, $db; require_once $CFG->dirroot . '/tag/lib.php'; $authcache = array(); // Cache to get some bits from authentication plugins $status = true; // Users have already been checked by restore_precheck_users() so they are loaded // in backup_ids table. They don't need to be loaded (parsed) from XML again. Also, note // the same function has performed the needed modifications in the $user->mnethostid field // so we don't need to do it again here at all. Just some checks. // Get users ids from backup_ids table $userids = get_fieldset_select('backup_ids', 'old_id', "backup_code = {$restore->backup_unique_code} AND table_name = 'user'"); // Have users to process, proceed with them if (!empty($userids)) { /// Get languages for quick search later $languages = get_list_of_languages(); /// Iterate over all users loaded from xml $counter = 0; /// Init trailing messages $messages = array(); foreach ($userids as $userid) { // Defaults $user_exists = false; // By default user does not exist $newid = null; // By default, there is not newid // Get record from backup_ids $useridsdbrec = backup_getid($restore->backup_unique_code, 'user', $userid); // Based in restore_precheck_users() calculations, if the user exists // new_id must contain the id of the matching user if (!empty($useridsdbrec->new_id)) { $user_exists = true; $newid = $useridsdbrec->new_id; } $user = $useridsdbrec->info; foreach (array_keys(get_object_vars($user)) as $field) { if (!is_array($user->{$field})) { $user->{$field} = backup_todb($user->{$field}, false); if (is_null($user->{$field})) { $user->{$field} = ''; } } } //Now, recode some languages (Moodle 1.5) if ($user->lang == 'ma_nt') { $user->lang = 'mi_nt'; } //Country list updates - MDL-13060 //Any user whose country code has been deleted or modified needs to be assigned a valid one. $country_update_map = array('ZR' => 'CD', 'TP' => 'TL', 'FX' => 'FR', 'KO' => 'RS', 'CS' => 'RS', 'WA' => 'GB'); if (array_key_exists($user->country, $country_update_map)) { $user->country = $country_update_map[$user->country]; } //If language does not exist here - use site default if (!array_key_exists($user->lang, $languages)) { $user->lang = $CFG->lang; } //Check if it's admin and coursecreator $is_admin = !empty($user->roles['admin']); $is_coursecreator = !empty($user->roles['coursecreator']); //Check if it's teacher and student $is_teacher = !empty($user->roles['teacher']); $is_student = !empty($user->roles['student']); //Check if it's needed $is_needed = !empty($user->roles['needed']); //Calculate if it is a course user //Has role teacher or student or needed $is_course_user = ($is_teacher or $is_student or $is_needed); // Only try to perform mnethost/auth modifications if restoring to another server // or if, while restoring to same server, the user doesn't exists yet (rebuilt site) // // So existing user data in same server *won't be modified by restore anymore*, // under any circumpstance. If somehting is wrong with existing data, it's server fault. if (!backup_is_same_site($restore) || backup_is_same_site($restore) && !$user_exists) { //Arriving here, any user with mnet auth and using $CFG->mnet_localhost_id is wrong //as own server cannot be accesed over mnet. Change auth to manual and inform about the switch if ($user->auth == 'mnet' && $user->mnethostid == $CFG->mnet_localhost_id) { // Respect registerauth if ($CFG->registerauth == 'email') { $user->auth = 'email'; } else { $user->auth = 'manual'; } // inform about the automatic switch of authentication/host if (empty($user->mnethosturl)) { $user->mnethosturl = '----'; } $messages[] = get_string('mnetrestore_extusers_switchuserauth', 'admin', $user); } } unset($user->mnethosturl); //Flags to see what parts are we going to restore $create_user = true; $create_roles = true; $create_custom_profile_fields = true; $create_tags = true; $create_preferences = true; //If we are restoring course users and it isn't a course user if ($restore->users == 1 and !$is_course_user) { //If only restoring course_users and user isn't a course_user, inform to $backup_ids $status = backup_putid($restore->backup_unique_code, "user", $userid, null, 'notincourse'); $create_user = false; $create_roles = false; $create_custom_profile_fields = false; $create_tags = false; $create_preferences = false; } if ($user_exists and $create_user) { //If user exists mark its newid in backup_ids (the same than old) $status = backup_putid($restore->backup_unique_code, "user", $userid, $newid, 'exists'); $create_user = false; $create_custom_profile_fields = false; $create_tags = false; $create_preferences = false; } //Here, if create_user, do it if ($create_user) { //Unset the id because it's going to be inserted with a new one unset($user->id); /// Disable pictures based on global setting or existing empty value (old backups can contain wrong empties) if (!empty($CFG->disableuserimages) || empty($user->picture)) { $user->picture = 0; } //We need to analyse the AUTH field to recode it: // - if the field isn't set, we are in a pre 1.4 backup and $CFG->registerauth will decide // - if the auth isn't enabled in target site, $CFG->registerauth will decide // - finally, if the auth resulting isn't enabled, default to 'manual' if (empty($user->auth) || !is_enabled_auth($user->auth)) { if ($CFG->registerauth == 'email') { $user->auth = 'email'; } else { $user->auth = 'manual'; } } if (!is_enabled_auth($user->auth)) { // Final auth check verify, default to manual if not enabled $user->auth = 'manual'; } // Now that we know the auth method, for users to be created without pass // if password handling is internal and reset password is available // we set the password to "restored" (plain text), so the login process // will know how to handle that situation in order to allow the user to // recover the password. MDL-20846 if (empty($user->password)) { // Only if restore comes without password if (!array_key_exists($user->auth, $authcache)) { // Not in cache $userauth = new stdClass(); $authplugin = get_auth_plugin($user->auth); $userauth->preventpassindb = $authplugin->prevent_local_passwords(); $userauth->isinternal = $authplugin->is_internal(); $userauth->canresetpwd = $authplugin->can_reset_password(); $authcache[$user->auth] = $userauth; } else { $userauth = $authcache[$user->auth]; // Get from cache } // Most external plugins do not store passwords locally if (!empty($userauth->preventpassindb)) { $user->password = '******'; // If Moodle is responsible for storing/validating pwd and reset functionality is available, mark } else { if ($userauth->isinternal and $userauth->canresetpwd) { $user->password = '******'; } } } //We need to process the POLICYAGREED field to recalculate it: // - if the destination site is different (by wwwroot) reset it. // - if the destination site is the same (by wwwroot), leave it unmodified if (!backup_is_same_site($restore)) { $user->policyagreed = 0; } else { //Nothing to do, we are in the same server } //Check if the theme exists in destination server $themes = get_list_of_themes(); if (!in_array($user->theme, $themes)) { $user->theme = ''; } //We are going to create the user //The structure is exactly as we need $newid = insert_record("user", addslashes_recursive($user)); //Put the new id $status = backup_putid($restore->backup_unique_code, "user", $userid, $newid, "new"); } ///TODO: This seccion is to support pre 1.7 course backups, using old roles /// teacher, coursecreator, student.... providing a basic mapping to new ones. /// Someday we'll drop support for them and this section will be safely deleted (2.0?) //Here, if create_roles, do it as necessary if ($create_roles) { //Get the newid and current info from backup_ids $data = backup_getid($restore->backup_unique_code, "user", $userid); $newid = $data->new_id; $currinfo = $data->info . ","; //Now, depending of the role, create records in user_studentes and user_teacher //and/or mark it in backup_ids if ($is_admin) { //If the record (user_admins) doesn't exists //Only put status in backup_ids $currinfo = $currinfo . "admin,"; $status = backup_putid($restore->backup_unique_code, "user", $userid, $newid, $currinfo); } if ($is_coursecreator) { //If the record (user_coursecreators) doesn't exists //Only put status in backup_ids $currinfo = $currinfo . "coursecreator,"; $status = backup_putid($restore->backup_unique_code, "user", $userid, $newid, $currinfo); } if ($is_needed) { //Only put status in backup_ids $currinfo = $currinfo . "needed,"; $status = backup_putid($restore->backup_unique_code, "user", $userid, $newid, $currinfo); } if ($is_teacher) { //If the record (teacher) doesn't exists //Put status in backup_ids $currinfo = $currinfo . "teacher,"; $status = backup_putid($restore->backup_unique_code, "user", $userid, $newid, $currinfo); //Set course and user $user->roles['teacher']->course = $restore->course_id; $user->roles['teacher']->userid = $newid; //Need to analyse the enrol field // - if it isn't set, set it to $CFG->enrol // - if we are in a different server (by wwwroot), set it to $CFG->enrol // - if we are in the same server (by wwwroot), maintain it unmodified. if (empty($user->roles['teacher']->enrol)) { $user->roles['teacher']->enrol = $CFG->enrol; } else { if (!backup_is_same_site($restore)) { $user->roles['teacher']->enrol = $CFG->enrol; } else { //Nothing to do. Leave it unmodified } } $rolesmapping = $restore->rolesmapping; $context = get_context_instance(CONTEXT_COURSE, $restore->course_id); if ($user->roles['teacher']->editall) { role_assign($rolesmapping['defaultteacheredit'], $newid, 0, $context->id, $user->roles['teacher']->timestart, $user->roles['teacher']->timeend, 0, $user->roles['teacher']->enrol); // editting teacher } else { // non editting teacher role_assign($rolesmapping['defaultteacher'], $newid, 0, $context->id, $user->roles['teacher']->timestart, $user->roles['teacher']->timeend, 0, $user->roles['teacher']->enrol); } } if ($is_student) { //Put status in backup_ids $currinfo = $currinfo . "student,"; $status = backup_putid($restore->backup_unique_code, "user", $userid, $newid, $currinfo); //Set course and user $user->roles['student']->course = $restore->course_id; $user->roles['student']->userid = $newid; //Need to analyse the enrol field // - if it isn't set, set it to $CFG->enrol // - if we are in a different server (by wwwroot), set it to $CFG->enrol // - if we are in the same server (by wwwroot), maintain it unmodified. if (empty($user->roles['student']->enrol)) { $user->roles['student']->enrol = $CFG->enrol; } else { if (!backup_is_same_site($restore)) { $user->roles['student']->enrol = $CFG->enrol; } else { //Nothing to do. Leave it unmodified } } $rolesmapping = $restore->rolesmapping; $context = get_context_instance(CONTEXT_COURSE, $restore->course_id); role_assign($rolesmapping['defaultstudent'], $newid, 0, $context->id, $user->roles['student']->timestart, $user->roles['student']->timeend, 0, $user->roles['student']->enrol); } if (!$is_course_user) { //If the record (user) doesn't exists if (!record_exists("user", "id", $newid)) { //Put status in backup_ids $currinfo = $currinfo . "user,"; $status = backup_putid($restore->backup_unique_code, "user", $userid, $newid, $currinfo); } } } /// Here, if create_custom_profile_fields, do it as necessary if ($create_custom_profile_fields) { if (isset($user->user_custom_profile_fields)) { foreach ($user->user_custom_profile_fields as $udata) { /// If the profile field has data and the profile shortname-datatype is defined in server if ($udata->field_data) { if ($field = get_record('user_info_field', 'shortname', $udata->field_name, 'datatype', $udata->field_type)) { /// Insert the user_custom_profile_field $rec = new object(); $rec->userid = $newid; $rec->fieldid = $field->id; $rec->data = $udata->field_data; insert_record('user_info_data', $rec); } } } } } /// Here, if create_tags, do it as necessary if ($create_tags) { /// if tags are enabled and there are user tags if (!empty($CFG->usetags) && isset($user->user_tags)) { $tags = array(); foreach ($user->user_tags as $user_tag) { $tags[] = $user_tag->rawname; } tag_set('user', $newid, $tags); } } //Here, if create_preferences, do it as necessary if ($create_preferences) { if (isset($user->user_preferences)) { foreach ($user->user_preferences as $user_preference) { //We check if that user_preference exists in DB if (!record_exists("user_preferences", "userid", $newid, "name", $user_preference->name)) { //Prepare the record and insert it $user_preference->userid = $newid; $status = insert_record("user_preferences", $user_preference); } } } } //Do some output $counter++; if ($counter % 10 == 0) { if (!defined('RESTORE_SILENTLY')) { echo "."; if ($counter % 200 == 0) { echo "<br />"; } } backup_flush(300); } } /// End of loop over all the users loaded from backup_ids table /// Inform about all the messages geerated while restoring users if (!defined('RESTORE_SILENTLY')) { if ($messages) { echo '<ul>'; foreach ($messages as $message) { echo '<li>' . $message . '</li>'; } echo '</ul>'; } } } return $status; }
function iterate_purge($starttime) { global $SESSION, $CFG; $userid = current($SESSION->purge_progress); $incourses = implode(',', $SESSION->bulk_courses); // delete all quiz activity $quizzessql = "SELECT DISTINCT q.* FROM {$CFG->prefix}quiz q INNER JOIN {$CFG->prefix}quiz_attempts a\n ON a.quiz=q.id AND a.userid={$userid} AND q.course IN ({$incourses})"; if ($quizzes = get_records_sql($quizzessql)) { foreach ($quizzes as $quiz) { $attemptssql = "SELECT a.* FROM {$CFG->prefix}quiz_attempts a\n \t\t\t\tWHERE a.quiz={$quiz->id} AND a.userid={$userid}"; $attempts = get_records_sql($attemptssql); foreach ($attempts as $attempt) { quiz_delete_attempt($attempt, $quiz); } } } if (is_timeout_close($starttime)) { return false; } // delete all lesson activity $lessons = get_fieldset_select('lesson', 'id', "course IN ({$incourses})"); if (!empty($lessons)) { $lessons = implode(',', $lessons); /// Clean up the timer table delete_records_select('lesson_timer', "userid={$userid} AND lessonid IN ({$lessons})"); /// Remove the grades from the grades and high_scores tables delete_records_select('lesson_grades', "userid={$userid} AND lessonid IN ({$lessons})"); delete_records_select('lesson_high_scores', "userid={$userid} AND lessonid IN ({$lessons})"); /// Remove attempts delete_records_select('lesson_attempts', "userid={$userid} AND lessonid IN ({$lessons})"); /// Remove seen branches delete_records_select('lesson_branch', "userid={$userid} AND lessonid IN ({$lessons})"); } if (is_timeout_close($starttime)) { return false; } // delete all assignment submissions $assignmentlist = array(); // delete submission files $assignmentssql = "SELECT DISTINCT a.id, a.course FROM {$CFG->prefix}assignment a INNER JOIN {$CFG->prefix}assignment_submissions s\n ON s.assignment=a.id AND s.userid={$userid} AND a.course IN ({$incourses})"; if ($assignments = get_records_sql($assignmentssql)) { foreach ($assignments as $assignment) { fulldelete($CFG->dataroot . '/' . $assignment->course . '/moddata/assignment/' . $assignment->id . '/' . $userid); $assignmentlist[] = $assignment->id; } } // delete submission records if (!empty($assignmentlist)) { $assignmentlist = implode(',', $assignmentlist); delete_records_select('assignment_submissions', "userid={$userid} AND assignment IN ({$assignmentlist})"); } if (is_timeout_close($starttime)) { return false; } // finally, delete all grade records to clean up database $sql = "SELECT g.id \n FROM {$CFG->prefix}grade_grades g INNER JOIN {$CFG->prefix}grade_items i\n ON g.itemid = i.id AND i.courseid IN ({$incourses}) AND g.userid={$userid}"; $grades = get_fieldset_sql($sql); if (!empty($grades)) { $grades = implode(',', $grades); delete_records_select('grade_grades', "id IN ({$grades})"); } // unenrol selected users from all courses foreach ($SESSION->bulk_courses as $course) { $context = get_context_instance(CONTEXT_COURSE, $course); role_unassign(0, $userid, 0, $context->id); } array_shift($SESSION->purge_progress); if (is_timeout_close($starttime)) { return false; } return true; }