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 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; }
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; }