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;
}
Example #2
0
function restore_create_users($restore, $xml_file)
{
    global $CFG, $db;
    require_once $CFG->dirroot . '/tag/lib.php';
    $status = true;
    //Check it exists
    if (!file_exists($xml_file)) {
        $status = false;
    }
    //Get info from xml
    if ($status) {
        //info will contain the old_id of every user
        //in backup_ids->info will be the real info (serialized)
        $info = restore_read_xml_users($restore, $xml_file);
    }
    //Now, get evey user_id from $info and user data from $backup_ids
    //and create the necessary db structures
    if (!empty($info->users)) {
        /// Grab mnethosts keyed by wwwroot, to map to id
        $mnethosts = get_records('mnet_host', '', '', 'wwwroot', 'wwwroot, id');
        /// 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 ($info->users as $userid) {
            $rec = backup_getid($restore->backup_unique_code, "user", $userid);
            $user = $rec->info;
            foreach (array_keys(get_object_vars($user)) as $field) {
                if (!is_array($user->{$field})) {
                    $user->{$field} = backup_todb($user->{$field});
                    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);
            // in case we are restoring to same server, look for user by id
            // it should return record always, but in sites rebuilt from scratch
            // and being reconstructed using course backups
            $user_data = false;
            if (backup_is_same_site($restore)) {
                $user_data = get_record('user', 'id', $user->id);
            }
            // 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_data) {
                //Calculate mnethostid
                if (empty($user->mnethosturl) || $user->mnethosturl === $CFG->wwwroot) {
                    $user->mnethostid = $CFG->mnet_localhost_id;
                } else {
                    // fast url-to-id lookups
                    if (isset($mnethosts[$user->mnethosturl])) {
                        $user->mnethostid = $mnethosts[$user->mnethosturl]->id;
                    } else {
                        $user->mnethostid = $CFG->mnet_localhost_id;
                    }
                }
                //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);
            //To store user->id along all the iteration
            $newid = null;
            //check if it exists (by username) and get its id
            $user_exists = true;
            if (!backup_is_same_site($restore)) {
                /// Restoring to another server, look for existing user based on fields
                /// If restoring to same server, look has been performed some lines above (by id)
                $user_data = get_record('user', 'username', addslashes($user->username), 'mnethostid', $user->mnethostid);
            }
            if (!$user_data) {
                $user_exists = false;
            } else {
                $newid = $user_data->id;
            }
            //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);
                // relink the descriptions
                $user->description = stripslashes($user->description);
                /// 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 we'll
                //     use manual
                if (empty($user->auth)) {
                    if ($CFG->registerauth == 'email') {
                        $user->auth = 'email';
                    } else {
                        $user->auth = 'manual';
                    }
                }
                //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 xml
        /// 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;
}
Example #3
0
function restore_questions($old_category_id, $best_question_cat, $info, $restore)
{
    global $CFG, $QTYPES;
    $status = true;
    $restored_questions = array();
    //Get the questions array
    if (!empty($info['QUESTION_CATEGORY']['#']['QUESTIONS'])) {
        $questions = $info['QUESTION_CATEGORY']['#']['QUESTIONS']['0']['#']['QUESTION'];
    } else {
        $questions = array();
    }
    //Iterate over questions
    for ($i = 0; $i < sizeof($questions); $i++) {
        $que_info = $questions[$i];
        //traverse_xmlize($que_info);                                                                 //Debug
        //print_object ($GLOBALS['traverse_array']);                                                  //Debug
        //$GLOBALS['traverse_array']="";                                                              //Debug
        //We'll need this later!!
        $oldid = backup_todb($que_info['#']['ID']['0']['#']);
        //Now, build the question record structure
        $question = new object();
        $question->parent = backup_todb($que_info['#']['PARENT']['0']['#']);
        $question->name = backup_todb($que_info['#']['NAME']['0']['#']);
        $question->questiontext = backup_todb($que_info['#']['QUESTIONTEXT']['0']['#']);
        $question->questiontextformat = backup_todb($que_info['#']['QUESTIONTEXTFORMAT']['0']['#']);
        $question->image = backup_todb($que_info['#']['IMAGE']['0']['#']);
        $question->generalfeedback = backup_todb_optional_field($que_info, 'GENERALFEEDBACK', '');
        $question->defaultgrade = backup_todb($que_info['#']['DEFAULTGRADE']['0']['#']);
        $question->penalty = backup_todb($que_info['#']['PENALTY']['0']['#']);
        $question->qtype = backup_todb($que_info['#']['QTYPE']['0']['#']);
        $question->length = backup_todb($que_info['#']['LENGTH']['0']['#']);
        $question->stamp = backup_todb($que_info['#']['STAMP']['0']['#']);
        $question->version = backup_todb($que_info['#']['VERSION']['0']['#']);
        $question->hidden = backup_todb($que_info['#']['HIDDEN']['0']['#']);
        $question->timecreated = backup_todb_optional_field($que_info, 'TIMECREATED', 0);
        $question->timemodified = backup_todb_optional_field($que_info, 'TIMEMODIFIED', 0);
        // Set the createdby field, if the user was in the backup, or if we are on the same site.
        $createdby = backup_todb_optional_field($que_info, 'CREATEDBY', null);
        if (!empty($createdby)) {
            $user = backup_getid($restore->backup_unique_code, 'user', $createdby);
            if ($user) {
                $question->createdby = $user->new_id;
            } else {
                if (backup_is_same_site($restore)) {
                    $question->createdby = $createdby;
                }
            }
        }
        // Set the modifiedby field, if the user was in the backup, or if we are on the same site.
        $modifiedby = backup_todb_optional_field($que_info, 'MODIFIEDBY', null);
        if (!empty($createdby)) {
            $user = backup_getid($restore->backup_unique_code, 'user', $modifiedby);
            if ($user) {
                $question->modifiedby = $user->new_id;
            } else {
                if (backup_is_same_site($restore)) {
                    $question->modifiedby = $modifiedby;
                }
            }
        }
        if ($restore->backup_version < 2006032200) {
            // The qtype was an integer that now needs to be converted to the name
            $qtypenames = array(1 => 'shortanswer', 2 => 'truefalse', 3 => 'multichoice', 4 => 'random', 5 => 'match', 6 => 'randomsamatch', 7 => 'description', 8 => 'numerical', 9 => 'multianswer', 10 => 'calculated', 11 => 'rqp', 12 => 'essay');
            $question->qtype = $qtypenames[$question->qtype];
        }
        //Check if the question exists by category, stamp, and version
        //first check for the question in the context specified in backup
        $existingquestion = get_record("question", "category", $best_question_cat->id, "stamp", $question->stamp, "version", $question->version);
        //If the question exists, only record its id
        //always use existing question, no permissions check here
        if ($existingquestion) {
            $question = $existingquestion;
            $creatingnewquestion = false;
        } else {
            //then if context above course level check permissions and if no permission
            //to restore above course level then restore to cat in course context.
            $bestcontext = get_context_instance_by_id($best_question_cat->contextid);
            if (($bestcontext->contextlevel == CONTEXT_SYSTEM || $bestcontext->contextlevel == CONTEXT_COURSECAT) && !has_capability('moodle/question:add', $bestcontext)) {
                if (!isset($course_question_cat)) {
                    $coursecontext = get_context_instance(CONTEXT_COURSE, $restore->course_id);
                    $course_question_cat = clone $best_question_cat;
                    $course_question_cat->contextid = $coursecontext->id;
                    //create cat if it doesn't exist
                    if (!($fcat = get_record('question_categories', 'contextid', $course_question_cat->contextid, 'stamp', $course_question_cat->stamp))) {
                        $course_question_cat->id = insert_record("question_categories", $course_question_cat);
                        backup_putid($restore->backup_unique_code, "question_categories", $old_category_id, $course_question_cat->id);
                    } else {
                        $course_question_cat = $fcat;
                    }
                    //will fix category parents after all questions and categories restored. Will set parent to 0 if
                    //no parent in same context.
                }
                $question->category = $course_question_cat->id;
                //does question already exist in course cat
                $existingquestion = get_record("question", "category", $question->category, "stamp", $question->stamp, "version", $question->version);
            } else {
                //permissions ok, restore to best cat
                $question->category = $best_question_cat->id;
            }
            if (!$existingquestion) {
                //The structure is equal to the db, so insert the question
                $question->id = insert_record("question", $question);
                $creatingnewquestion = true;
            } else {
                $question = $existingquestion;
                $creatingnewquestion = false;
            }
        }
        // Fixing bug #5482: random questions have parent field set to its own id,
        //                   see: $QTYPES['random']->get_question_options()
        if ($question->qtype == 'random' && $creatingnewquestion) {
            $question->parent = $question->id;
            $status = set_field('question', 'parent', $question->parent, 'id', $question->id);
        }
        //Save newid to backup tables
        if ($question->id) {
            //We have the newid, update backup_ids
            backup_putid($restore->backup_unique_code, "question", $oldid, $question->id);
        }
        $restored_questions[$i] = new stdClass();
        $restored_questions[$i]->newid = $question->id;
        $restored_questions[$i]->oldid = $oldid;
        $restored_questions[$i]->qtype = $question->qtype;
        $restored_questions[$i]->parent = $question->parent;
        $restored_questions[$i]->is_new = $creatingnewquestion;
    }
    backup_flush(300);
    // Loop again, now all the question id mappings exist, so everything can
    // be restored.
    for ($i = 0; $i < sizeof($questions); $i++) {
        $que_info = $questions[$i];
        $newid = $restored_questions[$i]->newid;
        $oldid = $restored_questions[$i]->oldid;
        $question = new object();
        $question->qtype = $restored_questions[$i]->qtype;
        $question->parent = $restored_questions[$i]->parent;
        /// If it's a new question in the DB, restore it
        if ($restored_questions[$i]->is_new) {
            /// We have to recode the parent field
            if ($question->parent && $question->qtype != 'random') {
                /// If the parent field needs to be changed, do it here. Random questions are dealt with above.
                if ($parent = backup_getid($restore->backup_unique_code, "question", $question->parent)) {
                    $question->parent = $parent->new_id;
                    if ($question->parent != $restored_questions[$i]->parent) {
                        if (!set_field('question', 'parent', $question->parent, 'id', $newid)) {
                            echo 'Could not update parent ' . $question->parent . ' for question ' . $oldid . '<br />';
                            $status = false;
                        }
                    }
                } else {
                    echo 'Could not recode parent ' . $question->parent . ' for question ' . $oldid . '<br />';
                    $status = false;
                }
            }
            //Now, restore every question_answers in this question
            $status = question_restore_answers($oldid, $newid, $que_info, $restore);
            // Restore questiontype specific data
            if (array_key_exists($question->qtype, $QTYPES)) {
                $status = $QTYPES[$question->qtype]->restore($oldid, $newid, $que_info, $restore);
            } else {
                echo 'Unknown question type ' . $question->qtype . ' for question ' . $oldid . '<br />';
                $status = false;
            }
        } else {
            //We are NOT creating the question, but we need to know every question_answers
            //map between the XML file and the database to be able to restore the states
            //in each attempt.
            $status = question_restore_map_answers($oldid, $newid, $que_info, $restore);
            // Do the questiontype specific mapping
            if (array_key_exists($question->qtype, $QTYPES)) {
                $status = $QTYPES[$question->qtype]->restore_map($oldid, $newid, $que_info, $restore);
            } else {
                echo 'Unknown question type ' . $question->qtype . ' for question ' . $oldid . '<br />';
                $status = false;
            }
        }
        //Do some output
        if (($i + 1) % 2 == 0) {
            if (!defined('RESTORE_SILENTLY')) {
                echo ".";
                if (($i + 1) % 40 == 0) {
                    echo "<br />";
                }
            }
            backup_flush(300);
        }
    }
    return $status;
}