예제 #1
0
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;
}