/** * This function restores all the needed roles for this course * i.e. roles with an assignment in any of the mods or blocks, * roles assigned on any user (e.g. parent role) and roles * assigned at course levle * This function should check for duplicate roles first * It isn't now, just overwriting */ function restore_create_roles($restore, $xmlfile) { if (!defined('RESTORE_SILENTLY')) { echo "<li>" . get_string("creatingrolesdefinitions") . '</li>'; } $info = restore_read_xml_roles($xmlfile); $sitecontext = get_context_instance(CONTEXT_SYSTEM); // the following code creates new roles // but we could use more intelligent detection, and role mapping // get role mapping info from $restore $rolemappings = array(); if (!empty($restore->rolesmapping)) { $rolemappings = $restore->rolesmapping; } // $info->roles will be empty for backups pre 1.7 if (isset($info->roles) && $info->roles) { foreach ($info->roles as $oldroleid => $roledata) { if (empty($restore->rolesmapping)) { // if this is empty altogether, we came from import or there's no roles used in course at all // in this case, write the same oldid as this is the same site // no need to do mapping $status = backup_putid($restore->backup_unique_code, "role", $oldroleid, $oldroleid); // adding a new id continue; // do not create additonal roles; } // first we check if the roles are in the mappings // if so, we just do a mapping i.e. update oldids table if (isset($rolemappings[$oldroleid]) && $rolemappings[$oldroleid]) { $status = backup_putid($restore->backup_unique_code, "role", $oldroleid, $rolemappings[$oldroleid]); // adding a new id } else { // code to make new role name/short name if same role name or shortname exists $fullname = $roledata->name; $shortname = $roledata->shortname; $currentfullname = ""; $currentshortname = ""; $counter = 0; do { if ($counter) { $suffixfull = " " . get_string("copyasnoun") . " " . $counter; $suffixshort = "_" . $counter; } else { $suffixfull = ""; $suffixshort = ""; } $currentfullname = $fullname . $suffixfull; // Limit the size of shortname - database column accepts <= 100 chars $currentshortname = substr($shortname, 0, 100 - strlen($suffixshort)) . $suffixshort; $coursefull = get_record("role", "name", addslashes($currentfullname)); $courseshort = get_record("role", "shortname", addslashes($currentshortname)); $counter++; } while ($coursefull || $courseshort); $roledata->name = $currentfullname; $roledata->shortname = $currentshortname; // done finding a unique name $newroleid = create_role(addslashes($roledata->name), addslashes($roledata->shortname), ''); $status = backup_putid($restore->backup_unique_code, "role", $oldroleid, $newroleid); // adding a new id foreach ($roledata->capabilities as $capability) { $roleinfo = new object(); $roleinfo = (object) $capability; $roleinfo->contextid = $sitecontext->id; $roleinfo->capability = $capability->name; $roleinfo->roleid = $newroleid; insert_record('role_capabilities', $roleinfo); } } /// Now, restore role nameincourse (only if the role had nameincourse in backup) if (!empty($roledata->nameincourse)) { $newrole = backup_getid($restore->backup_unique_code, 'role', $oldroleid); /// Look for target role $coursecontext = get_context_instance(CONTEXT_COURSE, $restore->course_id); /// Look for target context if (!empty($newrole->new_id) && !empty($coursecontext)) { /// Check the role hasn't any custom name in context if (!record_exists('role_names', 'roleid', $newrole->new_id, 'contextid', $coursecontext->id)) { $rolename = new object(); $rolename->roleid = $newrole->new_id; $rolename->contextid = $coursecontext->id; $rolename->name = addslashes($roledata->nameincourse); insert_record('role_names', $rolename); } } } } } return true; }
/** this function will restore an entire backup.zip into the specified course * using standard moodle backup/restore functions, but silently. * @param string $pathtofile the absolute path to the backup file. * @param int $destinationcourse the course id to restore to. * @param boolean $emptyfirst whether to delete all coursedata first. * @param boolean $userdata whether to include any userdata that may be in the backup file. * @param array $preferences optional, 0 will be used. Can contain: * metacourse * logs * course_files * messages */ function import_backup_file_silently($pathtofile, $destinationcourse, $emptyfirst = false, $userdata = false, $preferences = array()) { global $CFG, $SESSION, $USER; // is there such a thing on cron? I guess so.. if (!defined('RESTORE_SILENTLY')) { define('RESTORE_SILENTLY', true); // don't output all the stuff to us. } $debuginfo = 'import_backup_file_silently: '; $cleanupafter = false; $errorstr = ''; // passed by reference to restore_precheck to get errors from. $course = null; if ($destinationcourse && !($course = get_record('course', 'id', $destinationcourse))) { mtrace($debuginfo . 'Course with id $destinationcourse was not a valid course!'); return false; } // first check we have a valid file. if (!file_exists($pathtofile) || !is_readable($pathtofile)) { mtrace($debuginfo . 'File ' . $pathtofile . ' either didn\'t exist or wasn\'t readable'); return false; } // now make sure it's a zip file require_once $CFG->dirroot . '/lib/filelib.php'; $filename = substr($pathtofile, strrpos($pathtofile, '/') + 1); $mimetype = mimeinfo("type", $filename); if ($mimetype != 'application/zip') { mtrace($debuginfo . 'File ' . $pathtofile . ' was of wrong mimetype (' . $mimetype . ')'); return false; } // restore_precheck wants this within dataroot, so lets put it there if it's not already.. if (strstr($pathtofile, $CFG->dataroot) === false) { // first try and actually move it.. if (!check_dir_exists($CFG->dataroot . '/temp/backup/', true)) { mtrace($debuginfo . 'File ' . $pathtofile . ' outside of dataroot and couldn\'t move it! '); return false; } if (!copy($pathtofile, $CFG->dataroot . '/temp/backup/' . $filename)) { mtrace($debuginfo . 'File ' . $pathtofile . ' outside of dataroot and couldn\'t move it! '); return false; } else { $pathtofile = 'temp/backup/' . $filename; $cleanupafter = true; } } else { // it is within dataroot, so take it off the path for restore_precheck. $pathtofile = substr($pathtofile, strlen($CFG->dataroot . '/')); } if (!backup_required_functions()) { mtrace($debuginfo . 'Required function check failed (see backup_required_functions)'); return false; } @ini_set("max_execution_time", "3000"); if (empty($CFG->extramemorylimit)) { raise_memory_limit('128M'); } else { raise_memory_limit($CFG->extramemorylimit); } if (!($backup_unique_code = restore_precheck($destinationcourse, $pathtofile, $errorstr, true))) { mtrace($debuginfo . 'Failed restore_precheck (error was ' . $errorstr . ')'); return false; } global $restore; // ick $restore = new StdClass(); // copy back over the stuff that gets set in restore_precheck $restore->course_header = $SESSION->course_header; $restore->info = $SESSION->info; $xmlfile = "{$CFG->dataroot}/temp/backup/{$backup_unique_code}/moodle.xml"; $info = restore_read_xml_roles($xmlfile); $restore->rolesmapping = array(); if (isset($info->roles) && is_array($info->roles)) { foreach ($info->roles as $id => $info) { if ($newroleid = get_field('role', 'id', 'shortname', $info->shortname)) { $restore->rolesmapping[$id] = $newroleid; } } } // add on some extra stuff we need... $restore->metacourse = isset($preferences['restore_metacourse']) ? $preferences['restore_metacourse'] : 0; $restore->course_id = $destinationcourse; if ($destinationcourse) { $restore->restoreto = RESTORETO_CURRENT_ADDING; $restore->course_startdateoffset = $course->startdate - $restore->course_header->course_startdate; } else { $restore->restoreto = RESTORETO_NEW_COURSE; $restore->restore_restorecatto = 0; // let this be handled by the headers $restore->course_startdateoffset = 0; } $restore->users = $userdata; $restore->user_files = $userdata; $restore->deleting = $emptyfirst; $restore->groups = isset($preferences['restore_groups']) ? $preferences['restore_groups'] : RESTORE_GROUPS_NONE; $restore->logs = isset($preferences['restore_logs']) ? $preferences['restore_logs'] : 0; $restore->messages = isset($preferences['restore_messages']) ? $preferences['restore_messages'] : 0; $restore->blogs = isset($preferences['restore_blogs']) ? $preferences['restore_blogs'] : 0; $restore->course_files = isset($preferences['restore_course_files']) ? $preferences['restore_course_files'] : 0; $restore->site_files = isset($preferences['restore_site_files']) ? $preferences['restore_site_files'] : 0; $restore->backup_version = $restore->info->backup_backup_version; $restore->original_wwwroot = $restore->info->original_wwwroot; // now copy what we have over to the session // this needs to happen before restore_setup_for_check // which for some reason reads the session $SESSION->restore =& $restore; // rename the things that are called differently $SESSION->restore->restore_course_files = $restore->course_files; $SESSION->restore->restore_site_files = $restore->site_files; $SESSION->restore->backup_version = $restore->info->backup_backup_version; restore_setup_for_check($restore, $backup_unique_code); // maybe we need users (defaults to 2 (none) in restore_setup_for_check) // so set this again here if (!empty($userdata)) { $restore->users = 1; } // we also need modules... if ($allmods = get_records("modules")) { foreach ($allmods as $mod) { $modname = $mod->name; //Now check that we have that module info in the backup file if (isset($restore->info->mods[$modname]) && $restore->info->mods[$modname]->backup == "true") { $restore->mods[$modname]->restore = true; $restore->mods[$modname]->userinfo = $userdata; } else { // avoid warnings $restore->mods[$modname]->restore = false; $restore->mods[$modname]->userinfo = false; } } } if (!($status = restore_execute($restore, $restore->info, $restore->course_header, $errorstr))) { mtrace($debuginfo . 'Failed restore_execute (error was ' . $errorstr . ')'); return false; } // now get out the new courseid and return that if ($restore->restoreto = RESTORETO_NEW_COURSE) { if (!empty($SESSION->restore->course_id)) { return $SESSION->restore->course_id; } return false; } return true; }