From 72f38ce75163fc77c2efecb1c34384491d9d5637 Mon Sep 17 00:00:00 2001 From: Dongsheng Cai Date: Thu, 22 Jul 2010 03:14:41 +0000 Subject: [PATCH] MDL-22915, restore pre-ui --- backup/restorefile.php | 106 ++++++++++++++++++++++++ backup/restorefile_form.php | 35 ++++++++ backup/util/ui/module.js | 156 ++++++++++++++++++++++++++++++++++++ backup/util/ui/renderer.php | 122 +++++++++++++++++++++++++++- lang/en/backup.php | 5 ++ 5 files changed, 423 insertions(+), 1 deletion(-) create mode 100755 backup/restorefile.php create mode 100755 backup/restorefile_form.php create mode 100644 backup/util/ui/module.js diff --git a/backup/restorefile.php b/backup/restorefile.php new file mode 100755 index 00000000000..286a9bbdb5a --- /dev/null +++ b/backup/restorefile.php @@ -0,0 +1,106 @@ +. + +/** + * Import backup file or select existing backup file from moodle + * @package moodlecore + * @copyright 2010 Dongsheng Cai + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once('../config.php'); +require_once(dirname(__FILE__) . '/restorefile_form.php'); +require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php'); + +$contextid = required_param('contextid', PARAM_INT); +// action +$action = optional_param('action', '', PARAM_ALPHA); +// file parameters +// non js interface may require these parameters +$component = optional_param('component', null, PARAM_ALPHAEXT); +$filearea = optional_param('filearea', null, PARAM_ALPHAEXT); +$itemid = optional_param('itemid', null, PARAM_INT); +$filepath = optional_param('filepath', null, PARAM_PATH); +$filename = optional_param('filename', null, PARAM_FILE); + +list($context, $course, $cm) = get_context_info_array($contextid); + +$url = new moodle_url('/backup/restorefile.php', array('contextid'=>$contextid)); + +switch ($context->contextlevel) { + case CONTEXT_COURSE: + $heading = get_string('restorecourse', 'backup'); + break; + case CONTEXT_MODULE: + $heading = get_string('restoreactivity', 'backup'); + break; + // TODO +} + + +require_login($course); +require_capability('moodle/restore:restorecourse', $context); + +$PAGE->set_url($url); +$PAGE->set_context($context); +$PAGE->set_title(get_string('course') . ': ' . $course->fullname); +$PAGE->set_heading($heading); +$PAGE->set_pagelayout('admin'); + +// choose the backup file from backup files tree +if ($action == 'choosebackupfile') { + $browser = get_file_browser(); + if ($fileinfo = $browser->get_file_info($context, $component, $filearea, $itemid, $filepath, $filename)) { + $filename = restore_controller::get_tempdir_name($course->id, $USER->id); + $pathname = "$CFG->dataroot/temp/backup/".$filename; + $fileinfo->copy_to_pathname($pathname); + $restore_url = new moodle_url('/backup/restore.php', array('contextid'=>$contextid, 'filename'=>$filename)); + redirect($restore_url); + } else { + redirect($url, get_string('filenotfound', 'error')); + } + die; +} + +$form = new course_restore_form(null, array('contextid'=>$contextid)); +$data = $form->get_data(); +if ($data) { + $filename = restore_controller::get_tempdir_name($course->id, $USER->id); + $pathname = "$CFG->dataroot/temp/backup/".$filename; + $form->save_file('backupfile', $pathname); + $restore_url = new moodle_url('/backup/restore.php', array('contextid'=>$contextid, 'filename'=>$filename)); + redirect($restore_url); + die; +} + +$browser = get_file_browser(); +$fileinfo = $browser->get_file_info($context, $component, $filearea, $itemid, $filepath, $filename); + +echo $OUTPUT->header(); + +echo $OUTPUT->heading(get_string('choosefile', 'backup')); +echo $OUTPUT->container_start(); +$renderer = $PAGE->get_renderer('core', 'backup'); +echo $renderer->backup_files_viewer($fileinfo, array()); +echo $OUTPUT->container_end(); + +echo $OUTPUT->heading(get_string('importfile', 'backup')); +echo $OUTPUT->container_start(); +$form->display(); +echo $OUTPUT->container_end(); + +echo $OUTPUT->footer(); diff --git a/backup/restorefile_form.php b/backup/restorefile_form.php new file mode 100755 index 00000000000..f83ee22e78d --- /dev/null +++ b/backup/restorefile_form.php @@ -0,0 +1,35 @@ +. + +/** + * Import backup file form + * @package moodlecore + * @copyright 2010 Dongsheng Cai + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +require_once($CFG->libdir.'/formslib.php'); + +class course_restore_form extends moodleform { + function definition() { + $mform =& $this->_form; + $contextid = $this->_customdata['contextid']; + $mform->addElement('hidden', 'contextid', $contextid); + $mform->addElement('filepicker', 'backupfile', get_string('files')); + $submit_string = get_string('restore'); + $this->add_action_buttons(false, $submit_string); + } +} diff --git a/backup/util/ui/module.js b/backup/util/ui/module.js new file mode 100644 index 00000000000..512c5b43406 --- /dev/null +++ b/backup/util/ui/module.js @@ -0,0 +1,156 @@ +// backup files tree +// Author: Dongsheng Cai +M.core_backup_files_tree = { + y3: null, + api: M.cfg.wwwroot+'/files/filebrowser_ajax.php', + request: function(url, node, cb) { + var api = this.api + '?action=getfiletree'; + var params = []; + params['contextid'] = this.get_param(url, 'contextid', -1); + params['component'] = this.get_param(url, 'component', null); + params['filearea'] = this.get_param(url, 'filearea', null); + params['itemid'] = this.get_param(url, 'itemid', -1); + params['filepath'] = this.get_param(url, 'filepath', null); + params['filename'] = this.get_param(url, 'filename', null); + var scope = this; + params['sesskey']=M.cfg.sesskey; + var cfg = { + method: 'POST', + on: { + complete: function(id,o,p) { + try { + var data = this.y3.JSON.parse(o.responseText); + } catch(e) { + alert(e.toString()); + return; + } + if (data && data.length==0) { + node.isLeaf = true; + } else { + for (i in data) { + if (data[i].isdir) { + var info = {label: data[i].filename, href: data[i].url}; + var n = new YAHOO.widget.TextNode(info, node, false); + YAHOO.util.Event.addListener(n.labelElId, "click", function(e) { + YAHOO.util.Event.preventDefault(e); + }); + n.isLeaf = false; + } else { + var params = data[i].params; + params.action = 'choosebackupfile'; + var restoreurl = M.cfg.wwwroot+'/backup/restorefile.php?'+build_querystring(params); + var info = {label: data[i].filename, 'href': data[i].url, 'restoreurl': restoreurl}; + params['filename'] = data[i].filename; + var n = new YAHOO.widget.RestoreNode(info, node, false); + n.isLeaf = true; + } + } + } + cb(); + } + }, + arguments: { + scope: scope + }, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', + }, + data: build_querystring(params), + context: this + }; + this.y3.io(api, cfg); + }, + init : function(Y, htmlid){ + var tree = new YAHOO.widget.TreeView(htmlid); + tree.setDynamicLoad(this.dynload); + var root = tree.getRoot(); + var children = root.children; + tree.subscribe("clickEvent", function(e) { + if(!e.node.isLeaf){ + e.node.toggle(); + } + }); + for (i in children) { + var node = children[i]; + if (node.className == 'file-tree-folder') { + node.isLeaf = false; + // prevent link + YAHOO.util.Event.addListener(node.labelElId, "click", function(e) { + YAHOO.util.Event.preventDefault(e); + }); + } else { + node.isLeaf = true; + } + } + tree.render(); + this.y3 = Y; + }, + dynload: function(node, oncompletecb) { + M.core_backup_files_tree.request(node.href, node, oncompletecb); + }, + get_param: function(url, name, val) { + name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]"); + var regexS = "[\\?&]"+name+"=([^&#]*)"; + var regex = new RegExp( regexS ); + var results = regex.exec(url); + if( results == null ) { + return val; + } else { + return unescape(results[1]); + } + } +} + +YAHOO.widget.RestoreNode = function(oData, oParent, expanded) { + + if (oData) { + if (YAHOO.lang.isString(oData)) { + oData = { label: oData }; + } + this.init(oData, oParent, expanded); + this.setUpLabel(oData); + } + +}; +YAHOO.extend(YAHOO.widget.RestoreNode, YAHOO.widget.TextNode, { + labelStyle: "ygtvlabel", + labelElId: null, + label: null, + title: null, + href: null, + target: "_blank", + _type: "RestoreNode", + setUpLabel: function(oData) { + if (YAHOO.lang.isString(oData)) { + oData = { + label: oData + }; + } else { + if (oData.style) { + this.labelStyle = oData.style; + } + } + + this.label = oData.label; + this.restoreurl = oData.restoreurl; + this.labelElId = "ygtvlabelel" + this.index; + }, + getContentHtml: function() { + var sb = []; + sb[sb.length] = ''+M.str.moodle.restore+''; + return sb.join(""); + } +}); diff --git a/backup/util/ui/renderer.php b/backup/util/ui/renderer.php index eebcfd61124..28702a42528 100644 --- a/backup/util/ui/renderer.php +++ b/backup/util/ui/renderer.php @@ -63,4 +63,124 @@ class core_backup_renderer extends plugin_renderer_base { public function dependency_notification($message) { return html_writer::tag('div', $message, array('class'=>'notification dependencies_enforced')); } -} \ No newline at end of file + /** + * Print a backup files tree + * @param file_info $fileinfo + * @param array $options + * @return string + */ + public function backup_files_viewer(file_info $fileinfo, array $options = null) { + $tree = new backup_files_viewer($fileinfo, $options); + return $this->render($tree); + } + + public function render_backup_files_viewer(backup_files_viewer $tree) { + $module = array('name'=>'backup_files_tree', 'fullpath'=>'/backup/util/ui/module.js', 'requires'=>array('yui2-treeview', 'yui2-json'), 'strings'=>array(array('restore', 'moodle'))); + $htmlid = 'backup-treeview-'.uniqid(); + $this->page->requires->js_init_call('M.core_backup_files_tree.init', array($htmlid), false, $module); + + $html = '
'; + foreach($tree->path as $path) { + $html .= $path; + $html .= ' / '; + } + $html .= '
'; + + $html .= '
'; + if (empty($tree->tree)) { + $html .= get_string('nofilesavailable', 'repository'); + } else { + $html .= '
    '; + foreach($tree->tree as $node) { + $link_attributes = array(); + if (!empty($node['isdir'])) { + $class = ' class="file-tree-folder"'; + $restore_link = ''; + } else { + $class = ' class="file-tree-file"'; + $link_attributes['target'] = '_blank'; + $restore_link = html_writer::link($node['restoreurl'], get_string('restore', 'moodle'), $link_attributes); + } + $html .= '
  • '; + $html .= html_writer::link($node['url'], $node['filename'], $link_attributes); + // when js is off, use this restore link + // otherwise, yui treeview will generate a restore link in js + $html .= ' '.$restore_link; + $html .= '
  • '; + } + $html .= '
'; + } + $html .= '
'; + return $html; + } +} +/** + * Data structure representing backup files viewer + * + * @copyright 2010 Dongsheng Cai + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @since Moodle 2.0 + */ +class backup_files_viewer implements renderable { + public $tree; + public $path; + + /** + * Constructor of backup_files_viewer class + * @param file_info $file_info + * @param array $options + */ + public function __construct(file_info $file_info, array $options = null) { + global $CFG; + $this->options = (array)$options; + + $this->tree = array(); + $children = $file_info->get_children(); + $parent_info = $file_info->get_parent(); + + $level = $parent_info; + $this->path = array(); + while ($level) { + $params = $level->get_params(); + $context = get_context_instance_by_id($params['contextid']); + // lock user in course level + if ($context->contextlevel == CONTEXT_COURSECAT or $context->contextlevel == CONTEXT_SYSTEM) { + break; + } + $url = new moodle_url('/backup/restorefile.php', $params); + $this->path[] = html_writer::link($url->out(false), $level->get_visible_name()); + $level = $level->get_parent(); + } + $this->path = array_reverse($this->path); + $this->path[] = $file_info->get_visible_name(); + + foreach ($children as $child) { + $filedate = $child->get_timemodified(); + $filesize = $child->get_filesize(); + $mimetype = $child->get_mimetype(); + $params = $child->get_params(); + $fileitem = array( + 'params' => $params, + 'filename' => $child->get_visible_name(), + 'filedate' => $filedate ? userdate($filedate) : '', + 'filesize' => $filesize ? display_size($filesize) : '' + ); + if ($child->is_directory()) { + // ignore all other fileares except backup_course backup_section and backup_activity + if ($params['component'] != 'backup' or !in_array($params['filearea'], array('course', 'section', 'activity'))) { + continue; + } + $fileitem['isdir'] = true; + // link to this folder + $folderurl = new moodle_url('/backup/restorefile.php', $params); + $fileitem['url'] = $folderurl->out(false); + } else { + $restoreurl = new moodle_url('/backup/restorefile.php', array_merge($params, array('action'=>'choosebackupfile'))); + // link to this file + $fileitem['url'] = $child->get_url(); + $fileitem['restoreurl'] = $restoreurl->out(false); + } + $this->tree[] = $fileitem; + } + } +} diff --git a/lang/en/backup.php b/lang/en/backup.php index 3e6713af6b8..7ebd8160f64 100644 --- a/lang/en/backup.php +++ b/lang/en/backup.php @@ -27,6 +27,7 @@ $string['backupcourse'] = 'Backup course: {$a}'; $string['backupsection'] = 'Backup course section: {$a}'; $string['backupactivity'] = 'Backup activity: {$a}'; $string['cannotfindassignablerole'] = 'The {$a} role in the backup file cannot be mapped to any of the roles that you are allowed to assign.'; +$string['choosefile'] = 'Choose an existing backup file'; $string['configgeneralactivities'] = 'Sets the default for including activities in a backup.'; $string['configgeneralanonymize'] = 'If enabled all information pertaining to users will be anonymised by default.'; $string['configgeneralblocks'] = 'Sets the default for including blocks in a backup.'; @@ -63,6 +64,7 @@ $string['generalroleassignments'] = 'Include role assignments'; $string['generaluserscompletion'] = 'Include user completion information'; $string['generaluserfiles'] = 'Include user files'; $string['generalusers'] = 'Include users'; +$string['importfile'] = 'Import a backup file'; $string['includesection'] = 'Include section {$a}'; $string['includeother'] = 'Include {$a}'; $string['includeuserinfo'] = 'Include user information'; @@ -76,5 +78,8 @@ $string['onstage4action'] = 'Perform backup'; $string['onstage8action'] = 'Continue'; $string['onstage16action'] = 'Continue'; $string['previousstage'] = 'Previous'; +$string['restoreactivity'] = 'Restore activity'; +$string['restorecourse'] = 'Restore course'; +$string['restoresection'] = 'Restore section'; $string['rootsettings'] = 'Backup settings'; $string['scheduledsettings'] = 'Scheduled backup settings';