/** * @param string $errorstr passed by reference, if silent is true, * errorstr will be populated and this function will return false rather than calling error() or notify() * @param boolean $noredirect (optional) if this is passed, this function will not print continue, or * redirect to the next step in the restore process, instead will return $backup_unique_code */ function restore_precheck($id, $file, &$errorstr, $noredirect = false) { global $CFG, $SESSION; //Prepend dataroot to variable to have the absolute path $file = $CFG->dataroot . "/" . $file; if (!defined('RESTORE_SILENTLY')) { //Start the main table echo "<table cellpadding=\"5\">"; echo "<tr><td>"; //Start the mail ul echo "<ul>"; } //Check the file exists if (!is_file($file)) { if (!defined('RESTORE_SILENTLY')) { error("File not exists ({$file})"); } else { $errorstr = "File not exists ({$file})"; return false; } } //Check the file name ends with .zip if (!substr($file, -4) == ".zip") { if (!defined('RESTORE_SILENTLY')) { error("File has an incorrect extension"); } else { $errorstr = 'File has an incorrect extension'; return false; } } //Now calculate the unique_code for this restore $backup_unique_code = time(); //Now check and create the backup dir (if it doesn't exist) if (!defined('RESTORE_SILENTLY')) { echo "<li>" . get_string("creatingtemporarystructures") . '</li>'; } $status = check_and_create_backup_dir($backup_unique_code); //Empty dir if ($status) { $status = clear_backup_dir($backup_unique_code); } //Now delete old data and directories under dataroot/temp/backup if ($status) { if (!defined('RESTORE_SILENTLY')) { echo "<li>" . get_string("deletingolddata") . '</li>'; } $status = backup_delete_old_data(); } //Now copy he zip file to dataroot/temp/backup/backup_unique_code if ($status) { if (!defined('RESTORE_SILENTLY')) { echo "<li>" . get_string("copyingzipfile") . '</li>'; } if (!($status = backup_copy_file($file, $CFG->dataroot . "/temp/backup/" . $backup_unique_code . "/" . basename($file)))) { if (!defined('RESTORE_SILENTLY')) { notify("Error copying backup file. Invalid name or bad perms."); } else { $errorstr = "Error copying backup file. Invalid name or bad perms"; return false; } } } //Now unzip the file if ($status) { if (!defined('RESTORE_SILENTLY')) { echo "<li>" . get_string("unzippingbackup") . '</li>'; } if (!($status = restore_unzip($CFG->dataroot . "/temp/backup/" . $backup_unique_code . "/" . basename($file)))) { if (!defined('RESTORE_SILENTLY')) { notify("Error unzipping backup file. Invalid zip file."); } else { $errorstr = "Error unzipping backup file. Invalid zip file."; return false; } } } //Check for Blackboard backups and convert if ($status) { require_once "{$CFG->dirroot}/backup/bb/restore_bb.php"; if (!defined('RESTORE_SILENTLY')) { echo "<li>" . get_string("checkingforbbexport") . '</li>'; } $status = blackboard_convert($CFG->dataroot . "/temp/backup/" . $backup_unique_code); } //Now check for the moodle.xml file if ($status) { $xml_file = $CFG->dataroot . "/temp/backup/" . $backup_unique_code . "/moodle.xml"; if (!defined('RESTORE_SILENTLY')) { echo "<li>" . get_string("checkingbackup") . '</li>'; } if (!($status = restore_check_moodle_file($xml_file))) { if (!is_file($xml_file)) { $errorstr = 'Error checking backup file. moodle.xml not found at root level of zip file.'; } else { $errorstr = 'Error checking backup file. moodle.xml is incorrect or corrupted.'; } if (!defined('RESTORE_SILENTLY')) { notify($errorstr); } else { return false; } } } $info = ""; $course_header = ""; //Now read the info tag (all) if ($status) { if (!defined('RESTORE_SILENTLY')) { echo "<li>" . get_string("readinginfofrombackup") . '</li>'; } //Reading info from file $info = restore_read_xml_info($xml_file); //Reading course_header from file $course_header = restore_read_xml_course_header($xml_file); if (!is_object($course_header)) { // ensure we fail if there is no course header $course_header = false; } } if (!defined('RESTORE_SILENTLY')) { //End the main ul echo "</ul>\n"; //End the main table echo "</td></tr>"; echo "</table>"; } //We compare Moodle's versions if ($CFG->version < $info->backup_moodle_version && $status) { $message = new object(); $message->serverversion = $CFG->version; $message->serverrelease = $CFG->release; $message->backupversion = $info->backup_moodle_version; $message->backuprelease = $info->backup_moodle_release; print_simple_box(get_string('noticenewerbackup', '', $message), "center", "70%", '', "20", "noticebox"); } //Now we print in other table, the backup and the course it contains info if ($info and $course_header and $status) { //First, the course info if (!defined('RESTORE_SILENTLY')) { $status = restore_print_course_header($course_header); } //Now, the backup info if ($status) { if (!defined('RESTORE_SILENTLY')) { $status = restore_print_info($info); } } } //Save course header and info into php session if ($status) { $SESSION->info = $info; $SESSION->course_header = $course_header; } //Finally, a little form to continue //with some hidden fields if ($status) { if (!defined('RESTORE_SILENTLY')) { echo "<br /><div style='text-align:center'>"; $hidden["backup_unique_code"] = $backup_unique_code; $hidden["launch"] = "form"; $hidden["file"] = $file; $hidden["id"] = $id; print_single_button("restore.php", $hidden, get_string("continue"), "post"); echo "</div>"; } else { if (empty($noredirect)) { // in 2.0 we must not print "Continue" redirect link here, because ppl click on it and the execution gets interrupted on next page!!! // imo RESTORE_SILENTLY is an ugly hack :-P $sillystr = get_string('donotclickcontinue'); redirect($CFG->wwwroot . '/backup/restore.php?backup_unique_code=' . $backup_unique_code . '&launch=form&file=' . $file . '&id=' . $id, $sillystr, 0); } else { return $backup_unique_code; } } } if (!$status) { if (!defined('RESTORE_SILENTLY')) { error("An error has ocurred"); } else { $errorstr = "An error has occured"; // helpful! :P return false; } } return true; }
public static function restoreCourse($preferences, $session) { global $Out; // the initial set of preferences should be enough to get the restore started. // once in progress the restore will obtain the preferences from the backup file // itself if (!isset($preferences)) { return null; } // Assumes the backup file is in the course data directory and the // preferences are in the backup file itself. global $CFG; // for large files uncomment following code //@ini_set("max_execution_time","3000"); //raise_memory_limit("192M"); $file = self::createBackupFilePath($preferences->course_id); $file .= '/' . $preferences->backup_name; //path to file //Check the file exists if (!is_file($file)) { return false; } //Check the file name ends with .zip if (!substr($file, -4) == ".zip") { return false; } //Now calculate the unique_code for this restore $backup_unique_code = $preferences->backup_unique_code; //Now check and create the backup dir (if it doesn't exist) $status = check_and_create_backup_dir($backup_unique_code); //Empty dir if ($status) { $status = clear_backup_dir($backup_unique_code); } //Now delete old data and directories under dataroot/temp/backup if ($status) { $status = backup_delete_old_data(); } $tempBackupPath = synch_backup_controller::createTempBackupPath($backup_unique_code); //Now copy the zip file to dataroot/temp/backup/backup_unique_code if ($status) { if (!($status = backup_copy_file($file, $tempBackupPath . "/" . basename($file)))) { // There has been a problem. Invalid name or bad perms return false; } } //Now unzip the file if ($status) { if (!($status = restore_unzip($tempBackupPath . "/" . basename($file)))) { // error: Invalid zip file return false; } } //Check for Blackboard backups and convert if ($status) { require_once "{$CFG->dirroot}/backup/bb/restore_bb.php"; $status = blackboard_convert($tempBackupPath); } // backup file has now been unpacked. Retrieve the serialized preferences $preferencesPath = $tempBackupPath . '/' . self::getPreferencesFileName(); $preferences = FileSystem::unSerializeFromFile($preferencesPath); // Now we have the preferences from the backup we need to tailor it to our current needs // should we be updating an existing item or creating one. $dataItemId = SynchContentHierarchy::generateDataItemId($preferences->course_id, synch_view_controller::$TYPE_ID_COURSE); global $SynchManager, $SynchServerController; $itemExists = $SynchManager->getSessionItemExistsByServerId($SynchServerController->getServerId(), $session); if (isset($itemExists) && is_array($itemExists) && in_array($dataItemId, $itemExists)) { $preferences->restoreto = 1; $preferences->deleting = 1; } else { $preferences->restoreto = 2; } //Now check for the moodle.xml file if ($status) { $xml_file = $tempBackupPath . "/moodle.xml"; if (!($status = restore_check_moodle_file($xml_file))) { if (!is_file($xml_file)) { //Error checking backup file. moodle.xml not found at root level of zip file return false; } else { //Error checking backup file. moodle.xml is incorrect or corrupted. return false; } } } //unpack backup file //read contents //Reading info from file $info = restore_read_xml_info($xml_file); //Reading course_header from file $courseHeader = restore_read_xml_course_header($xml_file); //Save course header and info into php session if ($status) { //$SESSION->info = $info; //$SESSION->course_header = $course_header; } global $restore; $restore = $preferences; $message = null; $restoreSuccess = restore_execute($preferences, $info, $courseHeader, $message); return $restoreSuccess; }
protected function parseXml() { global $CFG; // moodle.xml チェック $xml_file = $this->getTempDir() . '/moodle.xml'; if (!restore_check_moodle_file($xml_file)) { throw new SharingCart_XmlException('check'); } // XML をオブジェクトに読込 $xml = new stdClass(); $xml->info = restore_read_xml_info($xml_file); if (!$xml->info) { throw new SharingCart_XmlException('read'); } // バージョンチェック if ($CFG->version < $xml->info->backup_moodle_version) { throw new SharingCart_XmlException('version'); } // 必要な変数をリストア設定オブジェクトにコピー $property_map = array('backup_moodle_version' => 'backup_version', 'original_wwwroot' => 'original_wwwroot', 'original_siteidentifier' => 'original_siteidentifier'); foreach ($property_map as $name => $prop) { $this->setParam($prop, $xml->info->{$name}); } // コースヘッダ $xml->course_header = restore_read_xml_course_header($xml_file); if (!$xml->course_header) { throw new SharingCart_XmlException('course'); } // 問題バンク $this->restoreQuestions(); // モジュール $this->prefs->mods = array(); if (!empty($xml->info->mods)) { foreach ($xml->info->mods as $name => $mod) { $this->prefs->mods[$name] = new stdClass(); $this->prefs->mods[$name]->restore = $mod->backup == 'true'; $this->prefs->mods[$name]->userinfo = $mod->userinfo == 'true'; $this->prefs->mods[$name]->instances = array(); // モジュール個別のリストアライブラリをインクルード if ($this->prefs->mods[$name]->restore) { $mod_restorelib = "{$CFG->dirroot}/mod/{$name}/restorelib.php"; if (is_file($mod_restorelib)) { require_once $mod_restorelib; } } // モジュールインスタンス if (!empty($mod->instances)) { foreach ($mod->instances as $inst) { $this->prefs->mods[$name]->instances[$inst->id] = new stdClass(); $this->prefs->mods[$name]->instances[$inst->id]->restore = $inst->backup == 'true'; $this->prefs->mods[$name]->instances[$inst->id]->userinfo = $inst->userinfo == 'true'; } } } } // モジュールをリストア if (!restore_create_modules($this->prefs, $xml_file)) { throw new SharingCart_XmlException('modules'); } if (!restore_check_instances($this->prefs)) { throw new SharingCart_XmlException('modules'); } // リンクの張り直し (Moodle 標準) if (!restore_decode_content_links($this->prefs)) { throw new SharingCart_XmlException('decode links'); } // セクションをリストア $this->restoreSection(); }
/** * This function will restore an entire backup.zip into the specified course * using standard moodle backup/restore functions, but silently. * * @see /backup/lib.php * @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 rollover_import_backup_file_silently($backup_unique_code, $destinationcourse, $emptyfirst = false, $userdata = false, $preferences = array()) { global $CFG, $SESSION, $USER; // is there such a thing on cron? I guess so.. global $restore; // ick if (empty($USER)) { $USER = get_admin(); $USER->admin = 1; // not sure why, but this doesn't get set } 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. // first check we have a valid file. /* Skip the file checking stuff, because we're not using a zip 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)) {*/ //if (!$backup_unique_code = restore_precheck(/*NOT NEEDED*/0,$pathtofile,$errorstr,true)) { // mtrace($debuginfo.'Failed restore_precheck (error was '.$errorstr.')'); // return false; //} // RL: the following few lines are normally handled by restore_precheck $xml_file = $CFG->dataroot . "/temp/backup/" . $backup_unique_code . "/moodle.xml"; //Reading info from file $info = restore_read_xml_info($xml_file); //Reading course_header from file $course_header = restore_read_xml_course_header($xml_file); if (!is_object($course_header)) { // ensure we fail if there is no course header $course_header = false; } $SESSION->info = $info; $SESSION->course_header = $course_header; $SESSION->restore = new StdClass(); // add on some extra stuff we need... $SESSION->restore->metacourse = $restore->metacourse = isset($preferences['restore_metacourse']) ? $preferences['restore_metacourse'] : 0; $SESSION->restore->users = $restore->users = $userdata; $SESSION->restore->logs = $restore->logs = isset($preferences['restore_logs']) ? $preferences['restore_logs'] : 0; $SESSION->restore->user_files = $restore->user_files = $userdata; $SESSION->restore->messages = $restore->messages = isset($preferences['restore_messages']) ? $preferences['restore_messages'] : 0; //$SESSION->restore->restoreto = 0; // Make sure we delete content and add everything from the source course. $SESSION->restore->restoreto = RESTORETO_NEW_COURSE; $SESSION->restore->course_id = $restore->course_id = $destinationcourse; $SESSION->restore->deleting = $emptyfirst; $SESSION->restore->restore_course_files = $restore->course_files = isset($preferences['restore_course_files']) ? $preferences['restore_course_files'] : 0; $SESSION->restore->restore_site_files = $restore->restore_site_files = isset($preferences['restore_site_files']) ? $preferences['restore_site_files'] : 0; $SESSION->restore->backup_version = $SESSION->info->backup_backup_version; // If a start date was specified, determine the difference between the start date of the template course // and the one specified for use in module dates. if (!empty($preferences['restore_startdate'])) { $SESSION->restore->course_startdateoffset = $preferences['restore_startdate'] - $SESSION->course_header->course_startdate; } else { $SESSION->restore->course_startdateoffset = 0; } // Set restore groups to 0 $SESSION->restore->groups = $restore->groups = RESTORE_GROUPS_NONE; // Set restore cateogry to 0, restorelib.php will look in the backup xml file $SESSION->restore->restore_restorecatto = $restore->restore_restorecatto = 0; $SESSION->restore->blogs = $restore->blogs = 0; restore_setup_for_check($SESSION->restore, $backup_unique_code); // maybe we need users (defaults to 2 in restore_setup_for_check) /* if (!empty($userdata)) { $SESSION->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($SESSION->info->mods[$modname]) && $SESSION->info->mods[$modname]->backup == "true") { $SESSION->restore->mods[$modname]->restore = true; $SESSION->restore->mods[$modname]->userinfo = $userdata; } else { // avoid warnings $SESSION->restore->mods[$modname]->restore = false; $SESSION->restore->mods[$modname]->userinfo = false; } } } $restore = clone $SESSION->restore; if (!restore_execute($restore, $SESSION->info, $SESSION->course_header, $errorstr)) { mtrace($debuginfo . 'Failed restore_execute (error was ' . $errorstr . ')'); return false; } rebuild_course_cache($SESSION->restore->course_id); return $SESSION->restore->course_id; }