backup MDL-23109 Implemented base restore UI within Moodle and linked through the...
authorSam Hemelryk <sam@moodle.com>
Thu, 22 Jul 2010 07:48:02 +0000 (07:48 +0000)
committerSam Hemelryk <sam@moodle.com>
Thu, 22 Jul 2010 07:48:02 +0000 (07:48 +0000)
25 files changed:
backup/controller/restore_controller.class.php
backup/moodle2/restore_course_task.class.php
backup/moodle2/restore_settingslib.php
backup/moodle2/restore_stepslib.php
backup/restore.php
backup/util/dbops/restore_dbops.class.php
backup/util/includes/backup_includes.php
backup/util/includes/restore_includes.php
backup/util/plan/base_step.class.php
backup/util/plan/restore_plan.class.php
backup/util/settings/base_setting.class.php
backup/util/ui/backup_moodleform.class.php
backup/util/ui/backup_ui.class.php
backup/util/ui/backup_ui_setting.class.php
backup/util/ui/backup_ui_stage.class.php
backup/util/ui/base_moodleform.class.php [new file with mode: 0644]
backup/util/ui/base_ui.class.php [new file with mode: 0644]
backup/util/ui/base_ui_stage.class.php [new file with mode: 0644]
backup/util/ui/renderer.php
backup/util/ui/restore_moodleform.class.php [new file with mode: 0644]
backup/util/ui/restore_ui.class.php [new file with mode: 0644]
backup/util/ui/restore_ui_stage.class.php [new file with mode: 0644]
lang/en/backup.php
lib/navigationlib.php
theme/base/style/core.css

index aaecc85..9c7e96b 100644 (file)
@@ -59,6 +59,15 @@ class restore_controller extends backup implements loggable {
 
     protected $checksum; // Cache @checksumable results for lighter @is_checksum_correct() uses
 
+    /**
+     *
+     * @param string $tempdir Directory under dataroot/temp/backup awaiting restore
+     * @param int $courseid Course id where restore is going to happen
+     * @param bool $interactive backup::INTERACTIVE_YES[true] or backup::INTERACTIVE_NO[false]
+     * @param int $mode backup::MODE_[ GENERAL | HUB | IMPORT | SAMESITE ]
+     * @param int $userid
+     * @param int $target backup::TARGET_[ NEW_COURSE | CURRENT_ADDING | CURRENT_DELETING | EXISTING_ADDING | EXISTING_DELETING ]
+     */
     public function __construct($tempdir, $courseid, $interactive, $mode, $userid, $target){
         $this->tempdir = $tempdir;
         $this->courseid = $courseid;
@@ -128,7 +137,7 @@ class restore_controller extends backup implements loggable {
 
     public function finish_ui() {
         if ($this->status != backup::STATUS_SETTING_UI) {
-            throw new backup_controller_exception('cannot_finish_ui_if_not_setting_ui');
+            throw new restore_controller_exception('cannot_finish_ui_if_not_setting_ui');
         }
         $this->set_status(backup::STATUS_NEED_PRECHECK);
     }
@@ -249,6 +258,10 @@ class restore_controller extends backup implements loggable {
         return $this->executiontime;
     }
 
+    /**
+     * Returns the restore plan
+     * @return restore_plan
+     */
     public function get_plan() {
         return $this->plan;
     }
index e65c869..e5f3706 100644 (file)
@@ -109,9 +109,23 @@ class restore_course_task extends restore_task {
      */
     protected function define_settings() {
 
+        //$name, $vtype, $value = null, $visibility = self::VISIBLE, $status = self::NOT_LOCKED
+        $fullname = new restore_course_generic_text_setting('course_fullname', base_setting::IS_TEXT, $this->get_info()->original_course_fullname);
+        $fullname->get_ui()->set_label(get_string('setting_course_fullname', 'backup'));
+        $this->add_setting($fullname);
+
+        $shortname = new restore_course_generic_text_setting('course_shortname', base_setting::IS_TEXT, $this->get_info()->original_course_shortname);
+        $shortname->get_ui()->set_label(get_string('setting_course_shortname', 'backup'));
+        $this->add_setting($shortname);
+
+        $startdate = new restore_course_generic_text_setting('course_startdate', base_setting::IS_INTEGER, $this->get_info()->original_course_startdate);
+        $startdate->set_ui(new backup_setting_ui_dateselector($startdate, get_string('setting_course_startdate', 'backup')));
+        $this->add_setting($startdate);
+
         // Define overwrite_conf to decide if course configuration will be restored over existing one
         $overwrite = new restore_course_overwrite_conf_setting('overwrite_conf', base_setting::IS_BOOLEAN, false);
         $overwrite->set_ui(new backup_setting_ui_select($overwrite, $overwrite->get_name(), array(1=>get_string('yes'), 0=>get_string('no'))));
+        $overwrite->get_ui()->set_label(get_string('setting_overwriteconf', 'backup'));
         $this->add_setting($overwrite);
 
     }
index df8c369..6d8b162 100644 (file)
@@ -100,6 +100,15 @@ class restore_course_generic_setting extends course_backup_setting {}
 class restore_course_overwrite_conf_setting extends restore_course_generic_setting {}
 
 
+class restore_course_generic_text_setting extends restore_course_generic_setting {
+
+    public function __construct($name, $vtype, $value = null, $visibility = self::VISIBLE, $status = self::NOT_LOCKED) {
+        parent::__construct($name, $vtype, $value, $visibility, $status);
+        $this->set_ui(new backup_setting_ui_text($this, $name));
+    }
+
+}
+
 // Section restore settings
 
 /**
index e8b5eeb..9dcb7cc 100644 (file)
@@ -543,17 +543,10 @@ class restore_course_structure_step extends restore_structure_step {
         $coursetags = isset($data->tags['tag']) ? $data->tags['tag'] : array();
         $coursemodules = isset($data->allowed_modules['module']) ? $data->allowed_modules['module'] : array();
         $oldid = $data->id; // We'll need this later
-        debugging ('review the these lines of process_course() to change to settings once available', DEBUG_DEVELOPER);
-        // TODO: Get fullname, shortname, startdate and category from settings
-        // $fullname  = $this->get_setting_value('course_fullname');
-        // $shortname = $this->get_setting_value('course_shortname');
-        // $category  = $this->get_setting_value('course_category');
-        // $startdate = $this->get_setting_value('course_startdate');
-        // TODO: Delete this lines once we are getting the vars above from settings
-        $fullname = $this->task->get_info()->original_course_fullname;
-        $shortname= $this->task->get_info()->original_course_shortname;
-        $startdate= $this->task->get_info()->original_course_startdate;
-        $category = get_course_category()->id;
+
+        $fullname  = $this->get_setting_value('course_fullname');
+        $shortname = $this->get_setting_value('course_shortname');
+        $startdate  = $this->get_setting_value('course_startdate');
 
         // Calculate final course names, to avoid dupes
         list($fullname, $shortname) = restore_dbops::calculate_course_names($this->get_courseid(), $fullname, $shortname);
@@ -563,7 +556,8 @@ class restore_course_structure_step extends restore_structure_step {
         $data->fullname = $fullname;
         $data->shortname= $shortname;
         $data->idnumber = '';
-        $data->category = $category;
+        // TODO: Set category from the UI, its not a setting just a param
+        $data->category = get_course_category()->id;
         $data->startdate= $this->apply_date_offset($data->startdate);
         if ($data->defaultgroupingid) {
             $data->defaultgroupingid = $this->get_mappingid('grouping', $data->defaultgroupingid);
index 9bbe150..a273423 100644 (file)
 <?php
     //This script is used to configure and execute the restore proccess.
 
-    //Define some globals for all the script
+require_once('../config.php');
+require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php');
+require_once($CFG->dirroot . '/backup/moodle2/restore_plan_builder.class.php');
 
-    //Units used
-    require_once("../config.php");
-    require_once("../lib/xmlize.php");
-    require_once("../course/lib.php");
-    require_once("lib.php");
-    require_once("restorelib.php");
-    require_once("bb/restore_bb.php");
-    require_once("$CFG->libdir/wiki_to_markdown.php" );
-    require_once("$CFG->libdir/adminlib.php");
+$contextid   = required_param('contextid', PARAM_INT);
+$stage      = optional_param('stage', restore_ui::STAGE_CONFIRM, PARAM_INT);
 
-    //Optional
-    $id = optional_param('id', 0, PARAM_INT);
-    $file = optional_param( 'file', 0, PARAM_PATH);
-    $cancel = optional_param('cancel', '', PARAM_RAW);
-    $launch = optional_param( 'launch', '', PARAM_ACTION);
-    $to = optional_param('to', '', PARAM_INT);
-    $method = optional_param('method', '', PARAM_ACTION);
-    $backup_unique_code = optional_param('backup_unique_code',0,PARAM_INT);
+list($context, $course, $cm) = get_context_info_array($contextid);
 
-    $url = new moodle_url('/backup/restore.php');
-    if ($id !== 0) {
-        $url->param('id', $id);
-    }
-    if ($file !== 0) {
-        $url->param('file', $file);
-    }
-    if ($cancel !== '') {
-        $url->param('cancel', $cancel);
-    }
-    if ($launch !== '') {
-        $url->param('launch', $launch);
-    }
-    if ($to !== '') {
-        $url->param('to', $to);
-    }
-    if ($method !== '') {
-        $url->param('method', $method);
-    }
-    if ($backup_unique_code !== 0) {
-        $url->param('backup_unique_code', $backup_unique_code);
-    }
-    $PAGE->set_url($url);
-
-    $site = get_site();
-
-/// With method=manual, we come from the FileManager so we delete all the backup/restore/import session structures
-    if ($method == 'manual') {
-        if (isset($SESSION->course_header)) {
-            unset ($SESSION->course_header);
-        }
-        if (isset($SESSION->info)) {
-            unset ($SESSION->info);
-        }
-        if (isset($SESSION->backupprefs)) {
-            unset ($SESSION->backupprefs);
-        }
-        if (isset($SESSION->restore)) {
-            unset ($SESSION->restore);
-        }
-        if (isset($SESSION->import_preferences)) {
-            unset ($SESSION->import_preferences);
-        }
-    }
+$PAGE->set_url(new moodle_url('/backup/restore.php', array('contextid'=>$contextid)));
+$PAGE->set_context($context);
+$PAGE->set_pagelayout('standard');
 
-    if (!$to && isset($SESSION->restore->restoreto) && isset($SESSION->restore->importing) && isset($SESSION->restore->course_id)) {
-        $to = $SESSION->restore->course_id;
-    }
+require_login($course, null, $cm);
 
-    $loginurl = get_login_url();
+$isfrontpage = ($course->id == SITEID);
 
-    if (!empty($id)) {
-        require_login($id);
-        if (!has_capability('moodle/restore:restorecourse', get_context_instance(CONTEXT_COURSE, $id))) {
-            if (empty($to)) {
-                print_error("cannotuseadminadminorteacher", '', $loginurl);
-            } else {
-                if (!has_capability('moodle/restore:restorecourse', get_context_instance(CONTEXT_COURSE, $to))
-                    && !has_capability('moodle/restore:restoretargetimport',  get_context_instance(CONTEXT_COURSE, $to))) {
-                    print_error("cannotuseadminadminorteacher", '', $loginurl);
-                }
-            }
-        }
-    } else {
-        if (!has_capability('moodle/restore:restorecourse', get_context_instance(CONTEXT_SYSTEM))) {
-            print_error("cannotuseadmin", '', $loginurl);
+if ($stage & restore_ui::STAGE_CONFIRM + restore_ui::STAGE_DESTINATION) {
+    $restore = restore_ui::engage_independent_stage($stage, $contextid);
+} else {
+    $restoreid = optional_param('restore', false, PARAM_ALPHANUM);
+    $rc = restore_ui::load_controller($restoreid);
+    if (!$rc) {
+        $restore = restore_ui::engage_independent_stage($stage/2, $contextid);
+        if ($restore->process()) {
+            $rc = new restore_controller($restore->get_filepath(), $restore->get_course_id(), backup::INTERACTIVE_YES,
+                                backup::MODE_GENERAL, $USER->id, backup::TARGET_NEW_COURSE);
         }
     }
-
-    //Check site
-    $site = get_site();
-
-    //Check necessary functions exists. Thanks to gregb@crowncollege.edu
-    backup_required_functions();
-
-    //Get strings
-    if (empty($to)) {
-        $strcourserestore = get_string("courserestore");
-    } else {
-        $strcourserestore = get_string("importdata");
-    }
-    $stradministration = get_string("administration");
-
-    //If no file has been selected from the FileManager, inform and end
-    $PAGE->set_title("$site->shortname: $strcourserestore");
-    $PAGE->set_heading($site->fullname);
-    if (!$file) {
-        $PAGE->navbar->add($stradministration, new moodle_url('/admin/index.php'));
-        $PAGE->navbar->add($strcourserestore);
-        echo $OUTPUT->header();
-        echo $OUTPUT->heading(get_string("nofilesselected"));
-        echo $OUTPUT->continue_button("$CFG->wwwroot/$CFG->admin/index.php");
-        echo $OUTPUT->footer();
-        exit;
-    }
-
-    //If cancel has been selected, inform and end
-    if ($cancel) {
-        $PAGE->navbar->add($stradministration, new moodle_url('/admin/index.php'));
-        $PAGE->navbar->add($strcourserestore);
-        echo $OUTPUT->header();
-        echo $OUTPUT->heading(get_string("restorecancelled"));
-        echo $OUTPUT->continue_button("$CFG->wwwroot/course/view.php?id=".$id);
-        echo $OUTPUT->footer();
-        exit;
-    }
-
-    //We are here, so we have a file.
-
-    //Get and check course
-    if (! $course = $DB->get_record('course', array('id'=>$id))) {
-        error("Course ID was incorrect (can't find it)");
-    }
-
-    //Print header
-    if (has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM))) {
-        $PAGE->navbar->add(basename($file));
-        echo $OUTPUT->header();
-    } else {
-        $PAGE->navbar->add($course->shortname, new moodle_url('/course/view.php', array('id'=>$course->id)));
-        $PAGE->navbar->add($strcourserestore);
-        echo $OUTPUT->header();
+    if ($rc) {
+        $restore = new restore_ui($rc, array('contextid'=>$context->id));
     }
-    //Print form
-    echo $OUTPUT->heading("$strcourserestore".((empty($to) ? ': '.basename($file) : '')));
-    echo $OUTPUT->box_start();
-
-    //Adjust some php variables to the execution of this script
-    @ini_set("max_execution_time","3000");
-    if (empty($CFG->extramemorylimit)) {
-        raise_memory_limit('128M');
+}
+$outcome = $restore->process();
+if (!$restore->is_independent()) {
+    if ($restore->get_stage() == restore_ui::STAGE_PROCESS && !$restore->requires_substage()) {
+        $restore->execute();
     } else {
-        raise_memory_limit($CFG->extramemorylimit);
-    }
-
-    //Call the form, depending the step we are
-
-    if (!$launch) {
-        include_once("restore_precheck.html");
-    } else if ($launch == "form") {
-        if (!empty($SESSION->restore->importing)) {
-            // set up all the config stuff and skip asking the user about it.
-            restore_setup_for_check($SESSION->restore,$backup_unique_code);
-            require_sesskey();
-            include_once("restore_execute.html");
-        } else {
-            include_once("restore_form.html");
-        }
-    } else if ($launch == "check") {
-        include_once("restore_check.html");
-        //To avoid multiple restore executions...
-        $SESSION->cancontinue = true;
-    } else if ($launch == "execute") {
-        //Prevent multiple restore executions...
-        if (empty($SESSION->cancontinue)) {
-            print_error('multiplerestorenotallow');
-        }
-        //Unset this for the future
-        unset($SESSION->cancontinue);
-        require_sesskey();
-        include_once("restore_execute.html");
-    }
-    echo $OUTPUT->box_end();
-
-    //Print footer
-    echo $OUTPUT->footer();
+        $restore->save_controller();
+    }
+}
+$heading = $course->fullname;
+
+$PAGE->set_title($heading.': '.$restore->get_stage_name());
+$PAGE->set_heading($heading);
+$PAGE->settingsnav->get('courseadmin')->find('restore', navigation_node::TYPE_SETTING)->make_active();
+$PAGE->navbar->add($restore->get_stage_name());
+
+$renderer = $PAGE->get_renderer('core','backup');
+echo $OUTPUT->header();
+if (!$restore->is_independent() && $restore->enforce_changed_dependencies()) {
+    echo $renderer->dependency_notification(get_string('dependenciesenforced','backup'));
+}
+echo $renderer->progress_bar($restore->get_progress_bar());
+echo $restore->display($renderer);
+echo $OUTPUT->footer();
\ No newline at end of file
index cc67e2d..977d9a6 100644 (file)
@@ -887,6 +887,26 @@ abstract class restore_dbops {
         }
         $rs->close();
     }
+
+    public static function create_new_course($fullname, $shortname, $categoryid) {
+        global $DB;
+        $category = $DB->get_record('course_categories', array('id'=>$categoryid), '*', MUST_EXIST);
+
+        $course = new stdClass;
+        $course->fullname = $fullname;
+        $course->shortname = $shortname;
+        $course->category = $category->id;
+        $course->sortorder = 0;
+        $course->timecreated  = time();
+        $course->timemodified = $course->timecreated;
+        $course->visible = $category->visible;
+
+        return $DB->insert_record('course', $course);   
+    }
+
+    public static function delete_course_content($courseid) {
+        return remove_course_contents($courseid);
+    }
 }
 
 /*
index edc7772..c775020 100644 (file)
@@ -84,6 +84,9 @@ require_once($CFG->dirroot . '/backup/util/plan/backup_step.class.php');
 require_once($CFG->dirroot . '/backup/util/plan/backup_structure_step.class.php');
 require_once($CFG->dirroot . '/backup/util/plan/backup_execution_step.class.php');
 require_once($CFG->dirroot . '/backup/controller/backup_controller.class.php');
+require_once($CFG->dirroot . '/backup/util/ui/base_moodleform.class.php');
+require_once($CFG->dirroot . '/backup/util/ui/base_ui.class.php');
+require_once($CFG->dirroot . '/backup/util/ui/base_ui_stage.class.php');
 require_once($CFG->dirroot . '/backup/util/ui/backup_moodleform.class.php');
 require_once($CFG->dirroot . '/backup/util/ui/backup_ui.class.php');
 require_once($CFG->dirroot . '/backup/util/ui/backup_ui_stage.class.php');
index d211bf9..f7abc76 100644 (file)
@@ -73,9 +73,13 @@ require_once($CFG->dirroot . '/backup/util/plan/restore_structure_step.class.php
 require_once($CFG->dirroot . '/backup/util/plan/restore_execution_step.class.php');
 require_once($CFG->dirroot . '/backup/moodle2/restore_plan_builder.class.php');
 require_once($CFG->dirroot . '/backup/controller/restore_controller.class.php');
-//require_once($CFG->dirroot . '/backup/util/ui/backup_ui.class.php');
-//require_once($CFG->dirroot . '/backup/util/ui/backup_ui_stage.class.php');
+require_once($CFG->dirroot . '/backup/util/ui/base_moodleform.class.php');
+require_once($CFG->dirroot . '/backup/util/ui/base_ui.class.php');
+require_once($CFG->dirroot . '/backup/util/ui/base_ui_stage.class.php');
 require_once($CFG->dirroot . '/backup/util/ui/backup_ui_setting.class.php');
+require_once($CFG->dirroot . '/backup/util/ui/restore_ui_stage.class.php');
+require_once($CFG->dirroot . '/backup/util/ui/restore_ui.class.php');
+require_once($CFG->dirroot . '/backup/util/ui/restore_moodleform.class.php');
 
 // And some moodle stuff too
 require_once ($CFG->dirroot . '/tag/lib.php');
index 96db85f..602381c 100644 (file)
@@ -94,6 +94,13 @@ abstract class base_step implements executable, loggable {
         return $this->task->get_courseid();
     }
 
+    protected function get_userid() {
+        if (is_null($this->task)) {
+            throw new base_step_exception('not_specified_base_task');
+        }
+        return $this->task->get_userid();
+    }
+
     protected function get_basepath() {
         return $this->task->get_basepath();
     }
index 6e2bab5..3909a1f 100644 (file)
  */
 class restore_plan extends base_plan implements loggable {
 
+    /**
+     *
+     * @var restore_controller
+     */
     protected $controller; // The restore controller building/executing this plan
     protected $basepath;   // Fullpath to dir where backup is available
     protected $preloaded;  // When executing the plan, do we have preloaded (from checks) info
index 557f536..7cad068 100644 (file)
@@ -46,6 +46,7 @@ abstract class base_setting {
     const IS_INTEGER = 'int';
     const IS_FILENAME= 'file';
     const IS_PATH    = 'path';
+    const IS_TEXT    = 'text';
 
     // Visible/hidden
     const VISIBLE = 1;
@@ -88,7 +89,8 @@ abstract class base_setting {
     public function __construct($name, $vtype, $value = null, $visibility = self::VISIBLE, $status = self::NOT_LOCKED) {
         // Check vtype
         if ($vtype !== self::IS_BOOLEAN && $vtype !== self::IS_INTEGER &&
-            $vtype !== self::IS_FILENAME && $vtype !== self::IS_PATH) {
+            $vtype !== self::IS_FILENAME && $vtype !== self::IS_PATH &&
+            $vtype !== self::IS_TEXT) {
             throw new base_setting_exception('setting_invalid_type');
         }
 
@@ -402,6 +404,12 @@ abstract class base_setting {
                     throw new base_setting_exception('setting_invalid_path', $oldvalue);
                 }
                 break;
+            case self::IS_TEXT:
+                $value = clean_param($oldvalue, PARAM_TEXT);
+                if ($value != $oldvalue) {
+                    throw new base_setting_exception('setting_invalid_text', $oldvalue);
+                }
+                break;
         }
         return $value;
     }
index df3c243..ebf5387 100644 (file)
@@ -27,8 +27,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-require_once($CFG->libdir . '/formslib.php');
-
 /**
  * Backup moodleform bridge
  *
@@ -39,27 +37,7 @@ require_once($CFG->libdir . '/formslib.php');
  * @copyright 2010 Sam Hemelryk
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
-abstract class backup_moodleform extends moodleform {
-    /**
-     * The stage this form belongs to
-     * @var backup_ui_stage
-     */
-    protected $uistage = null;
-    /**
-     * True if we have a course div open, false otherwise
-     * @var bool
-     */
-    protected $coursediv = false;
-    /**
-     * True if we have a section div open, false otherwise
-     * @var bool
-     */
-    protected $sectiondiv = false;
-    /**
-     * True if we have an activity div open, false otherwise
-     * @var bool
-     */
-    protected $activitydiv = false;
+abstract class backup_moodleform extends base_moodleform {
     /**
      * Creates the form
      *
@@ -71,189 +49,8 @@ abstract class backup_moodleform extends moodleform {
      * @param array $attributes
      * @param bool $editable
      */
-    function __construct(backup_ui_stage $uistage, $action=null, $customdata=null, $method='post', $target='', $attributes=null, $editable=true) {
-        $this->uistage = $uistage;
-        parent::__construct($action, $customdata, $method, $target, $attributes, $editable);
-    }
-    /**
-     * The standard form definition... obviously not much here
-     */
-    function definition() {
-        $mform = $this->_form;
-        $stage = $mform->addElement('hidden', 'stage', $this->uistage->get_stage());
-        $stage = $mform->addElement('hidden', 'backup', $this->uistage->get_backupid());
-        $params = $this->uistage->get_params();
-        if (is_array($params) && count($params) > 0) {
-            foreach ($params as $name=>$value) {
-                $stage = $mform->addElement('hidden', $name, $value);
-    }
-        }
-    }
-    /**
-     * Definition applied after the data is organised.. why's it here? because I want
-     * to add elements on the fly.
-     */
-    function definition_after_data() {
-        $buttonarray=array();
-        if ($this->uistage->get_stage() > backup_ui::STAGE_INITIAL) {
-            $buttonarray[] = $this->_form->createElement('submit', 'previous', get_string('previousstage','backup'));
-        }
-        $buttonarray[] = $this->_form->createElement('submit', 'submitbutton', get_string('onstage'.$this->uistage->get_stage().'action', 'backup'));
-        $buttonarray[] = $this->_form->createElement('cancel');
-        $this->_form->addGroup($buttonarray, 'buttonar', '', array(' '), false);
-        $this->_form->closeHeaderBefore('buttonar');
-    }
-    /**
-     * Closes any open divs
-     */
-    function close_task_divs() {
-        if ($this->activitydiv) {
-            $this->_form->addElement('html', html_writer::end_tag('div'));
-            $this->activitydiv = false;
-        }
-        if ($this->sectiondiv) {
-            $this->_form->addElement('html', html_writer::end_tag('div'));
-            $this->sectiondiv = false;
-        }
-        if ($this->coursediv) {
-            $this->_form->addElement('html', html_writer::end_tag('div'));
-            $this->coursediv = false;
-        }
-    }
-    /**
-     * Adds the backup_setting as a element to the form
-     * @param backup_setting $setting
-     * @return bool
-     */
-    function add_setting(backup_setting $setting, backup_task $task=null) {
-
-        // If the setting cant be changed then add it as a fixed setting.
-        if (!$setting->get_ui()->is_changeable()) {
-            return $this->add_fixed_setting($setting);
-        }
-
-        // First add the formatting for this setting
-        $this->add_html_formatting($setting);
-        // The call the add method with the get_element_properties array
-        call_user_method_array('addElement', $this->_form, $setting->get_ui()->get_element_properties($task));
-        $this->_form->setDefault($setting->get_ui_name(), $setting->get_value());
-        if ($setting->has_help()) {
-            list($identifier, $component) = $setting->get_help();
-            $this->_form->addHelpButton($setting->get_ui_name(), $identifier, $component);
-        }
-        $this->_form->addElement('html', html_writer::end_tag('div'));
-        return true;
-    }
-    /**
-     * Adds a heading to the form
-     * @param string $name
-     * @param string $text
-     */
-    function add_heading($name , $text) {
-        $this->_form->addElement('header', $name, $text);
-    }
-    /**
-     * Adds HTML formatting for the given backup setting, needed to group/segment
-     * correctly.
-     * @param backup_setting $setting
-     */
-    protected function add_html_formatting(backup_setting $setting) {
-        $mform = $this->_form;
-        $isincludesetting = (strpos($setting->get_name(), '_include')!==false);
-        if ($isincludesetting && $setting->get_level() != backup_setting::ROOT_LEVEL)  {
-            switch ($setting->get_level()) {
-                case backup_setting::COURSE_LEVEL:
-                    if ($this->activitydiv) {
-                        $this->_form->addElement('html', html_writer::end_tag('div'));
-                        $this->activitydiv = false;
-                    }
-                    if ($this->sectiondiv) {
-                        $this->_form->addElement('html', html_writer::end_tag('div'));
-                        $this->sectiondiv = false;
-                    }
-                    if ($this->coursediv) {
-                        $this->_form->addElement('html', html_writer::end_tag('div'));
-                    }
-                    $mform->addElement('html', html_writer::start_tag('div', array('class'=>'grouped_settings course_level')));
-                    $mform->addElement('html', html_writer::start_tag('div', array('class'=>'include_setting course_level')));
-                    $this->coursediv = true;
-                    break;
-                case backup_setting::SECTION_LEVEL:
-                    if ($this->activitydiv) {
-                        $this->_form->addElement('html', html_writer::end_tag('div'));
-                        $this->activitydiv = false;
-                    }
-                    if ($this->sectiondiv) {
-                        $this->_form->addElement('html', html_writer::end_tag('div'));
-                    }
-                    $mform->addElement('html', html_writer::start_tag('div', array('class'=>'grouped_settings section_level')));
-                    $mform->addElement('html', html_writer::start_tag('div', array('class'=>'include_setting section_level')));
-                    $this->sectiondiv = true;
-                    break;
-                case backup_setting::ACTIVITY_LEVEL:
-                    if ($this->activitydiv) {
-                        $this->_form->addElement('html', html_writer::end_tag('div'));
-                    }
-                    $mform->addElement('html', html_writer::start_tag('div', array('class'=>'grouped_settings activity_level')));
-                    $mform->addElement('html', html_writer::start_tag('div', array('class'=>'include_setting activity_level')));
-                    $this->activitydiv = true;
-                    break;
-                default:
-                    $mform->addElement('html', html_writer::start_tag('div', array('class'=>'normal_setting')));
-                    break;
-            }
-        } else if ($setting->get_level() == backup_setting::ROOT_LEVEL) {
-            $mform->addElement('html', html_writer::start_tag('div', array('class'=>'root_setting')));
-        } else {
-            $mform->addElement('html', html_writer::start_tag('div', array('class'=>'normal_setting')));
-        }
-    }
-    /**
-     * Adds a fixed or static setting to the form
-     * @param backup_setting $setting
-     */
-    function add_fixed_setting(backup_setting $setting) {
-        global $OUTPUT;
-        $settingui = $setting->get_ui();
-        if ($setting->get_visibility() == backup_setting::VISIBLE) {
-            $this->add_html_formatting($setting);
-            switch ($setting->get_status()) {
-                case backup_setting::LOCKED_BY_PERMISSION:
-                    $icon = ' '.$OUTPUT->pix_icon('i/permissionlock', get_string('lockedbypermission', 'backup'), 'moodle', array('class'=>'smallicon lockedicon permissionlock'));
-                    break;
-                case backup_setting::LOCKED_BY_CONFIG:
-                    $icon = ' '.$OUTPUT->pix_icon('i/configlock', get_string('lockedbyconfig', 'backup'), 'moodle', array('class'=>'smallicon lockedicon configlock'));
-                    break;
-                case backup_setting::LOCKED_BY_HIERARCHY:
-                    $icon = ' '.$OUTPUT->pix_icon('i/hierarchylock', get_string('lockedbyhierarchy', 'backup'), 'moodle', array('class'=>'smallicon lockedicon configlock'));
-                    break;
-                default:
-                    $icon = '';
-                    break;
-            }
-            $this->_form->addElement('static', 'static_'.$settingui->get_name(), $settingui->get_label(), $settingui->get_static_value().$icon);
-            $this->_form->addElement('html', html_writer::end_tag('div'));
-        }
-        $this->_form->addElement('hidden', $settingui->get_name(), $settingui->get_value());
-    }
-    /**
-     * Adds dependencies to the form recursively
-     * 
-     * @param backup_setting $setting
-     */
-    function add_dependencies(backup_setting $setting) {
-        $mform = $this->_form;
-        // Apply all dependencies for backup
-        foreach ($setting->get_my_dependency_properties() as $key=>$dependency) {
-            call_user_method_array('disabledIf', $this->_form, $dependency);
-        }
-    }
-    /**
-     * Returns true if the form was cancelled, false otherwise
-     * @return bool
-     */
-    public function is_cancelled() {
-        return (optional_param('cancel', false, PARAM_BOOL) || parent::is_cancelled());
+    public function __construct(backup_ui_stage $uistage, $action = null, $customdata = null, $method = 'post', $target = '', $attributes = null, $editable = true) {
+        parent::__construct($uistage, $action, $customdata, $method, $target, $attributes, $editable);
     }
 }
 /**
index c2dab59..01435df 100644 (file)
@@ -32,7 +32,7 @@
  * @copyright 2010 Sam Hemelryk
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
-class backup_ui {
+class backup_ui extends base_ui {
     /**
      * The stages of the backup user interface.
      */
@@ -41,45 +41,7 @@ class backup_ui {
     const STAGE_CONFIRMATION = 4;
     const STAGE_FINAL = 8;
     const STAGE_COMPLETE = 16;
-    /**
-     * The progress of this instance of the backup ui class
-     */
-    const PROGRESS_INTIAL = 0;
-    const PROGRESS_PROCESSED = 1;
-    const PROGRESS_SAVED = 2;
-    const PROGRESS_EXECUTED = 3;
-    /**
-     * The backup controller
-     * @var backup_controller
-     */
-    protected $controller;
-    /**
-     * The current stage
-     * @var backup_ui_stage
-     */
-    protected $stage;
-    /**
-     * The current progress of the UI
-     * @var int One of self::PROGRESS_*
-     */
-    protected $progress;
-    /**
-     * The number of changes made by dependency enforcement
-     * @var int
-     */
-    protected $dependencychanges = 0;
 
-    /**
-     * Yay for constructors
-     * @param backup_controller $controller
-     */
-    public function __construct(backup_controller $controller, array $params=null) {
-        $this->controller = $controller;
-        $this->progress = self::PROGRESS_INTIAL;
-        $this->stage = $this->initialise_stage(null, $params);
-        // Process UI event before to be safe
-        $this->controller->process_ui_event();
-    }
     /**
      * Intialises what ever stage is requested. If none are requested we check
      * params for 'stage' and default to initial
@@ -110,88 +72,8 @@ class backup_ui {
         }
         return $stage;
     }
-    /**
-     * This processes the current stage of the backup
-     * @return bool
-     */
-    public function process() {
-        if ($this->progress >= self::PROGRESS_PROCESSED) {
-            throw new backup_ui_exception('backupuialreadyprocessed');
-        }
-        $this->progress = self::PROGRESS_PROCESSED;
-
-        if (optional_param('previous', false, PARAM_BOOL) && $this->stage->get_stage() > self::STAGE_INITIAL) {
-            $this->stage = $this->initialise_stage($this->stage->get_prev_stage(), $this->stage->get_params());
-            return false;
-        }
-
-        // Process the stage
-        $processoutcome = $this->stage->process();
-
-        if ($processoutcome !== false) {
-            $this->stage = $this->initialise_stage($this->stage->get_next_stage(), $this->stage->get_params());
-        }
-
-        // Process UI event after to check changes are valid
-        $this->controller->process_ui_event();
-        return $processoutcome;
-    }
-    /**
-     * Saves the backup controller.
-     *
-     * Once this has been called nothing else can be changed in the controller.
-     *
-     * @return bool
-     */
-    public function save_controller() {
-        if ($this->progress >= self::PROGRESS_SAVED) {
-            throw new backup_ui_exception('backupuialreadysaved');
-        }
-        $this->progress = self::PROGRESS_SAVED;
-        // First enforce dependencies
-        $this->enforce_dependencies();
-        // Process UI event after to check any changes are valid
-        $this->controller->process_ui_event();
-        // Save the controller
-        $this->controller->save_controller();
-        return true;
-    }
-    /**
-     * Displays the UI for the backup!
-     *
-     * Note: The UI makes use of mforms (ewww!) thus it will automatically print
-     * out the result rather than returning a string of HTML like other parts of Moodle
-     *
-     * @return bool
-     */
-    public function display() {
-        if ($this->progress < self::PROGRESS_SAVED) {
-            throw new backup_ui_exception('backupsavebeforedisplay');
-        }
-        $this->stage->display();
-    }
-    /**
-     * Gets all backup tasks from the controller
-     * @return array Array of backup_task
-     */
-    public function get_backup_tasks() {
-        $plan = $this->controller->get_plan();
-        $tasks = $plan->get_tasks();
-        return $tasks;
-    }
-    /**
-     * Gets the stage we are on
-     * @return backup_ui_stage
-     */
-    public function get_stage() {
-        return $this->stage->get_stage();
-    }
-    /**
-     * Gets the name of the stage we are on
-     * @return string
-     */
-    public function get_stage_name() {
-        return $this->stage->get_name();
+    public function get_uniqueid() {
+        return $this->get_backupid();
     }
     /**
      * Gets the backup id from the controller
@@ -217,41 +99,6 @@ class backup_ui {
         $this->stage = new backup_ui_stage_complete($this, $this->stage->get_params(), $this->controller->get_results());
         return true;
     }
-    /**
-     * Enforces dependencies on all settings. Call before save
-     * @return bool True if dependencies were enforced and changes were made
-     */
-    protected function enforce_dependencies() {
-        // Get the plan
-        $plan = $this->controller->get_plan();
-        // Get the tasks as a var so we can iterate by reference
-        $tasks = $plan->get_tasks();
-        $changes = 0;
-        foreach ($tasks as &$task) {
-            // Store as a var so we can iterate by reference
-            $settings = $task->get_settings();
-            foreach ($settings as &$setting) {
-                // Get all dependencies for iteration by reference
-                $dependencies = $setting->get_dependencies();
-                foreach ($dependencies as &$dependency) {
-                    // Enforce each dependency
-                    if ($dependency->enforce()) {
-                        $changes++;
-                    }
-                }
-            }
-        }
-        // Store the number of settings that changed through enforcement
-        $this->dependencychanges = $changes;
-        return ($changes>0);
-    }
-    /**
-     * Returns true if enforce_dependencies changed any settings
-     * @return bool
-     */
-    public function enforce_changed_dependencies() {
-        return ($this->dependencychanges > 0);
-    }
     /**
      * Loads the backup controller if we are tracking one
      * @return backup_controller|false
@@ -311,57 +158,17 @@ class backup_ui {
         }
         return $items;
     }
-    /**
-     * Gets the format for the backup
-     * @return int
-     */
-    public function get_backup_format() {
-        return $this->controller->get_format();
-    }
-    /**
-     * Gets the type of the backup
-     * @return int
-     */
-    public function get_backup_type() {
-        return $this->controller->get_type();
-    }
-    /**
-     * Gets the ID used in creating the controller. Relates to course/section/cm
-     * @return int
-     */
-    public function get_controller_id() {
-        return $this->controller->get_id();
-    }
-    /**
-     * Gets the requested setting
-     * @param string $name
-     * @return mixed
-     */
-    public function get_setting($name, $default = false) {
-        try {
-            return $this->controller->get_plan()->get_setting($name);
-        } catch (Exception $e) {
-            debugging('Failed to find the setting: '.$name, DEBUG_DEVELOPER);
-            return $default;
-        }
+
+    public function get_name() {
+        return 'backup';
     }
-    /**
-     * Gets the value for the requested setting
-     *
-     * @param string $name
-     * @return mixed
-     */
-    public function get_setting_value($name, $default = false) {
-        try {
-            return $this->controller->get_plan()->get_setting($name)->get_value();
-        } catch (Exception $e) {
-            debugging('Failed to find the setting: '.$name, DEBUG_DEVELOPER);
-            return $default;
-        }
+
+    public function get_first_stage_id() {
+        return self::STAGE_INITIAL;
     }
 }
 
 /**
  * Backup user interface exception. Modelled off the backup_exception class
  */
-class backup_ui_exception extends backup_exception {}
\ No newline at end of file
+class backup_ui_exception extends base_ui_exception {}
\ No newline at end of file
index d3c3e11..fac5f77 100644 (file)
@@ -199,7 +199,7 @@ abstract class backup_setting_ui extends base_setting_ui {
      * Get element properties that can be used to make a quickform element
      * @return array
      */
-    abstract public function get_element_properties(backup_task $task=null);
+    abstract public function get_element_properties(base_task $task=null);
     /**
      * Applies config options to a given properties array and then returns it
      * @param array $properties
@@ -217,7 +217,7 @@ abstract class backup_setting_ui extends base_setting_ui {
      *          $task is used to set the setting label
      * @return string
      */
-    public function get_label(backup_task $task=null) {
+    public function get_label(base_task $task=null) {
         // If a task has been provided and the label is not already set meaniningfully
         // we will attempt to improve it.
         if (!is_null($task) && $this->label == $this->setting->get_name() && strpos($this->setting->get_name(), '_include')!==false) {
@@ -282,7 +282,7 @@ class backup_setting_ui_text extends backup_setting_ui {
      * @param backup_task|null $task
      * @return array (element, name, label, attributes)
      */
-    public function get_element_properties(backup_task $task=null) {
+    public function get_element_properties(base_task $task=null) {
         // name, label, attributes
         return $this->apply_options(array('element'=>'text','name'=>self::NAME_PREFIX.$this->name, 'label'=>$this->get_label($task), 'attributes'=>$this->attributes));
     }
@@ -322,7 +322,7 @@ class backup_setting_ui_checkbox extends backup_setting_ui {
      * @param backup_task|null $task
      * @return array (element, name, label, text, attributes);
      */
-    public function get_element_properties(backup_task $task=null) {
+    public function get_element_properties(base_task $task=null) {
         // name, label, text, attributes
         return $this->apply_options(array('element'=>'checkbox','name'=>self::NAME_PREFIX.$this->name, 'label'=>$this->get_label($task), 'text'=>$this->text, 'attributes'=>$this->attributes));
     }
@@ -387,7 +387,7 @@ class backup_setting_ui_radio extends backup_setting_ui {
      * @param backup_task|null $task
      * @return array (element, name, label, text, value, attributes)
      */
-    public function get_element_properties(backup_task $task=null) {
+    public function get_element_properties(base_task $task=null) {
         // name, label, text, value, attributes
         return $this->apply_options(array('element'=>'radio','name'=>self::NAME_PREFIX.$this->name, 'label'=>$this->get_label($task), 'text'=>$this->text, 'value'=>$this->value, 'attributes'=>$this->attributes));
     }
@@ -446,7 +446,7 @@ class backup_setting_ui_select extends backup_setting_ui {
      * @param backup_task|null $task
      * @return array (element, name, label, options, attributes)
      */
-    public function get_element_properties(backup_task $task = null) {
+    public function get_element_properties(base_task $task = null) {
         // name, label, options, attributes
         return $this->apply_options(array('element'=>'select','name'=>self::NAME_PREFIX.$this->name, 'label'=>$this->get_label($task), 'options'=>$this->values, 'attributes'=>$this->attributes));
     }
@@ -464,4 +464,30 @@ class backup_setting_ui_select extends backup_setting_ui {
     public function get_static_value() {
         return $this->values[$this->get_value()];
     }
+
+    public function is_changeable() {
+        if (count($this->values) == 1) {
+            return false;
+        } else {
+            return parent::is_changeable();
+        }
+    }
+}
+
+class backup_setting_ui_dateselector extends backup_setting_ui_text {
+    public function get_element_properties(base_task $task = null) {
+        if (!array_key_exists('optional', $this->attributes)) {
+            $this->attributes['optional'] = false;
+        }
+        $properties = parent::get_element_properties($task);
+        $properties['element'] = 'date_selector';
+        return $properties;
+    }
+    public function get_static_value() {
+        $value = $this->get_value();
+        if (!empty($value)) {
+            return userdate($value);
+        }
+        return parent::get_static_value();
+    }
 }
\ No newline at end of file
index ed49c1a..c93e054 100644 (file)
  * @copyright 2010 Sam Hemelryk
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
-abstract class backup_ui_stage {
-    /**
-     * The current stage
-     * @var int
-     */
-    protected $stage = backup_ui::STAGE_INITIAL;
-    /**
-     * The backuck UI object
-     * @var backup_ui
-     */
-    protected $ui;
-    /**
-     * The moodleform for this stage
-     * @var backup_moodleform
-     */
-    protected $stageform = null;
-    /**
-     * Custom form params that will be added as hidden inputs
-     */
-    protected $params = null;
-    /**
-     *
-     * @param backup_ui $ui
-     */
-    public function __construct(backup_ui $ui, array $params=null) {
-        $this->ui = $ui;
-        $this->params = $params;
-    }
-    /**
-     * Returns the custom params for this stage
-     * @return array|null
-     */
-    final public function get_params() {
-        return $this->params;
-    }
-    /**
-     * The current stage
-     * @return int
-     */
-    final public function get_stage() {
-        return $this->stage;
-    }
-    /**
-     * The next stage
-     * @return int
-     */
-    final public function get_next_stage() {
-        return floor($this->stage*2);
-    }
-    /**
-     * The previous stage
-     * @return int
-     */
-    final public function get_prev_stage() {
-        return floor($this->stage/2);
-    }
-    /**
-     * The name of this stage
-     * @return string
-     */
-    final public function get_name() {
-        return get_string('currentstage'.$this->stage,'backup');
+abstract class backup_ui_stage extends base_ui_stage {
+
+    public function __construct(backup_ui $ui, array $params = null) {
+       parent::__construct($ui, $params);
     }
     /**
      * The backup id from the backup controller
      * @return string
      */
     final public function get_backupid() {
-        return $this->ui->get_backupid();
-    }
-    /**
-     * Displays the stage.
-     *
-     * By default this involves instantiating the form for the stage and the calling
-     * it to display. Remember this is a moodleform instance so it will print
-     * rather than return.
-     */
-    public function display() {
-        $form = $this->initialise_stage_form();
-        $form->display();
+        return $this->get_uniqueid();
     }
-    /**
-     * Processes the stage.
-     *
-     * This must be overridden by every stage as it will be different for every stage
-     *
-     * @abstract
-     * @param backup_moodleform|null $form
-     */
-    abstract public function process(backup_moodleform $form=null);
-    /**
-     * Creates an instance of the correct moodleform properly populated and all
-     * dependencies instantiated
-     *
-     * @abstract
-     * @return backup_moodleform
-     */
-    abstract protected function initialise_stage_form();
 }
 
 /**
@@ -162,7 +76,7 @@ class backup_ui_stage_initial extends backup_ui_stage {
      * @param backup_moodleform $form
      * @return int The number of changes
      */
-    public function process(backup_moodleform $m = null) {
+    public function process(base_moodleform $m = null) {
 
         $form = $this->initialise_stage_form();
 
@@ -172,7 +86,7 @@ class backup_ui_stage_initial extends backup_ui_stage {
 
         $data = $form->get_data();
         if ($data && confirm_sesskey()) {
-            $tasks = $this->ui->get_backup_tasks();
+            $tasks = $this->ui->get_tasks();
             $changes = 0;
             foreach ($tasks as &$task) {
                 // We are only interesting in the backup root task for this stage
@@ -208,7 +122,7 @@ class backup_ui_stage_initial extends backup_ui_stage {
         if ($this->stageform === null) {
             $form = new backup_initial_form($this, $PAGE->url);
             // Store as a variable so we can iterate by reference
-            $tasks = $this->ui->get_backup_tasks();
+            $tasks = $this->ui->get_tasks();
             // Iterate all tasks by reference
             foreach ($tasks as &$task) {
                 // For the initial stage we are only interested in the root settings
@@ -262,7 +176,7 @@ class backup_ui_stage_schema extends backup_ui_stage {
      * @param backup_moodleform|null $form
      * @return int The number of changes the user made
      */
-    public function process(backup_moodleform $form = null) {
+    public function process(base_moodleform $form = null) {
         $form = $this->initialise_stage_form();
         // Check it wasn't cancelled
         if ($form->is_cancelled()) {
@@ -273,7 +187,7 @@ class backup_ui_stage_schema extends backup_ui_stage {
         $data = $form->get_data();
         if ($data && confirm_sesskey()) {
             // Get the tasks into a var so we can iterate by reference
-            $tasks = $this->ui->get_backup_tasks();
+            $tasks = $this->ui->get_tasks();
             $changes = 0;
             // Iterate all tasks by reference
             foreach ($tasks as &$task) {
@@ -309,7 +223,7 @@ class backup_ui_stage_schema extends backup_ui_stage {
         global $PAGE;
         if ($this->stageform === null) {
             $form = new backup_schema_form($this, $PAGE->url);
-            $tasks = $this->ui->get_backup_tasks();
+            $tasks = $this->ui->get_tasks();
             $content = '';
             $courseheading = false;
             foreach ($tasks as $task) {
@@ -370,7 +284,7 @@ class backup_ui_stage_confirmation extends backup_ui_stage {
      * @param backup_moodleform $form
      * @return int The number of changes the user made
      */
-    public function process(backup_moodleform $form = null) {
+    public function process(base_moodleform $form = null) {
         $form = $this->initialise_stage_form();
         // Check it hasn't been cancelled
         if ($form->is_cancelled()) {
@@ -380,7 +294,7 @@ class backup_ui_stage_confirmation extends backup_ui_stage {
         $data = $form->get_data();
         if ($data && confirm_sesskey()) {
             // Collect into a variable so we can iterate by reference
-            $tasks = $this->ui->get_backup_tasks();
+            $tasks = $this->ui->get_tasks();
             $changes = 0;
             // Iterate each task by reference
             foreach ($tasks as &$task) {
@@ -416,8 +330,8 @@ class backup_ui_stage_confirmation extends backup_ui_stage {
             if ($setting = $this->ui->get_setting('filename')) {
                 $form->add_heading('filenamesetting', get_string('filename', 'backup'));
                 if ($setting->get_value() == 'backup.zip') {
-                    $format = $this->ui->get_backup_format();
-                    $type = $this->ui->get_backup_type();
+                    $format = $this->ui->get_format();
+                    $type = $this->ui->get_type();
                     $id = $this->ui->get_controller_id();
                     $users = $this->ui->get_setting_value('users');
                     $anonymised = $this->ui->get_setting_value('anonymize');
@@ -426,7 +340,7 @@ class backup_ui_stage_confirmation extends backup_ui_stage {
                 $form->add_setting($setting);
             }
 
-            foreach ($this->ui->get_backup_tasks() as $task) {
+            foreach ($this->ui->get_tasks() as $task) {
                 if ($task instanceof backup_root_task) {
                     // If its a backup root add a root settings heading to group nicely
                     $form->add_heading('rootsettings', get_string('rootsettings', 'backup'));
@@ -481,7 +395,7 @@ class backup_ui_stage_final extends backup_ui_stage {
      *
      * In this case it ALWAYS passes processing to the previous stage (confirmation)
      */
-    public function process(backup_moodleform $form=null) {
+    public function process(base_moodleform $form=null) {
         return true;
     }
     /**
diff --git a/backup/util/ui/base_moodleform.class.php b/backup/util/ui/base_moodleform.class.php
new file mode 100644 (file)
index 0000000..47a141a
--- /dev/null
@@ -0,0 +1,260 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This file contains the generic moodleform bridge for the backup user interface
+ * as well as the individual forms that relate to the different stages the user
+ * interface can exist within.
+ *
+ * @package   moodlecore
+ * @copyright 2010 Sam Hemelryk
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once($CFG->libdir . '/formslib.php');
+
+/**
+ * Backup moodleform bridge
+ *
+ * Ahhh the mighty moodleform bridge! Strong enough to take the weight of 682 full
+ * grown african swallows all of whom have been carring coconuts for several days.
+ * EWWWWW!!!!!!!!!!!!!!!!!!!!!!!!
+ *
+ * @copyright 2010 Sam Hemelryk
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+abstract class base_moodleform extends moodleform {
+    /**
+     * The stage this form belongs to
+     * @var base_ui_stage
+     */
+    protected $uistage = null;
+    /**
+     * True if we have a course div open, false otherwise
+     * @var bool
+     */
+    protected $coursediv = false;
+    /**
+     * True if we have a section div open, false otherwise
+     * @var bool
+     */
+    protected $sectiondiv = false;
+    /**
+     * True if we have an activity div open, false otherwise
+     * @var bool
+     */
+    protected $activitydiv = false;
+    /**
+     * Creates the form
+     *
+     * @param backup_ui_stage $uistage
+     * @param moodle_url|string $action
+     * @param mixed $customdata
+     * @param string $method get|post
+     * @param string $target
+     * @param array $attributes
+     * @param bool $editable
+     */
+    function __construct(base_ui_stage $uistage, $action=null, $customdata=null, $method='post', $target='', $attributes=null, $editable=true) {
+        $this->uistage = $uistage;
+        parent::__construct($action, $customdata, $method, $target, $attributes, $editable);
+    }
+    /**
+     * The standard form definition... obviously not much here
+     */
+    function definition() {
+        $ui = $this->uistage->get_ui();
+        $mform = $this->_form;
+        $stage = $mform->addElement('hidden', 'stage', $this->uistage->get_stage());
+        $stage = $mform->addElement('hidden', $ui->get_name(), $ui->get_uniqueid());
+        $params = $this->uistage->get_params();
+        if (is_array($params) && count($params) > 0) {
+            foreach ($params as $name=>$value) {
+                $stage = $mform->addElement('hidden', $name, $value);
+            }
+        }
+    }
+    /**
+     * Definition applied after the data is organised.. why's it here? because I want
+     * to add elements on the fly.
+     */
+    function definition_after_data() {
+        $buttonarray=array();
+        if (!$this->uistage->is_first_stage()) {
+            $buttonarray[] = $this->_form->createElement('submit', 'previous', get_string('previousstage','backup'));
+        }
+        $buttonarray[] = $this->_form->createElement('submit', 'submitbutton', get_string($this->uistage->get_ui()->get_name().'stage'.$this->uistage->get_stage().'action', 'backup'));
+        $buttonarray[] = $this->_form->createElement('cancel');
+        $this->_form->addGroup($buttonarray, 'buttonar', '', array(' '), false);
+        $this->_form->closeHeaderBefore('buttonar');
+    }
+    /**
+     * Closes any open divs
+     */
+    function close_task_divs() {
+        if ($this->activitydiv) {
+            $this->_form->addElement('html', html_writer::end_tag('div'));
+            $this->activitydiv = false;
+        }
+        if ($this->sectiondiv) {
+            $this->_form->addElement('html', html_writer::end_tag('div'));
+            $this->sectiondiv = false;
+        }
+        if ($this->coursediv) {
+            $this->_form->addElement('html', html_writer::end_tag('div'));
+            $this->coursediv = false;
+        }
+    }
+    /**
+     * Adds the backup_setting as a element to the form
+     * @param backup_setting $setting
+     * @return bool
+     */
+    function add_setting(backup_setting $setting, base_task $task=null) {
+
+        // If the setting cant be changed then add it as a fixed setting.
+        if (!$setting->get_ui()->is_changeable()) {
+            return $this->add_fixed_setting($setting);
+        }
+
+        // First add the formatting for this setting
+        $this->add_html_formatting($setting);
+
+        // The call the add method with the get_element_properties array
+        call_user_method_array('addElement', $this->_form, $setting->get_ui()->get_element_properties($task));
+        $this->_form->setDefault($setting->get_ui_name(), $setting->get_value());
+        if ($setting->has_help()) {
+            list($identifier, $component) = $setting->get_help();
+            $this->_form->addHelpButton($setting->get_ui_name(), $identifier, $component);
+        }
+        $this->_form->addElement('html', html_writer::end_tag('div'));
+        return true;
+    }
+    /**
+     * Adds a heading to the form
+     * @param string $name
+     * @param string $text
+     */
+    function add_heading($name , $text) {
+        $this->_form->addElement('header', $name, $text);
+    }
+    /**
+     * Adds HTML formatting for the given backup setting, needed to group/segment
+     * correctly.
+     * @param backup_setting $setting
+     */
+    protected function add_html_formatting(backup_setting $setting) {
+        $mform = $this->_form;
+        $isincludesetting = (strpos($setting->get_name(), '_include')!==false);
+        if ($isincludesetting && $setting->get_level() != backup_setting::ROOT_LEVEL)  {
+            switch ($setting->get_level()) {
+                case backup_setting::COURSE_LEVEL:
+                    if ($this->activitydiv) {
+                        $this->_form->addElement('html', html_writer::end_tag('div'));
+                        $this->activitydiv = false;
+                    }
+                    if ($this->sectiondiv) {
+                        $this->_form->addElement('html', html_writer::end_tag('div'));
+                        $this->sectiondiv = false;
+                    }
+                    if ($this->coursediv) {
+                        $this->_form->addElement('html', html_writer::end_tag('div'));
+                    }
+                    $mform->addElement('html', html_writer::start_tag('div', array('class'=>'grouped_settings course_level')));
+                    $mform->addElement('html', html_writer::start_tag('div', array('class'=>'include_setting course_level')));
+                    $this->coursediv = true;
+                    break;
+                case backup_setting::SECTION_LEVEL:
+                    if ($this->activitydiv) {
+                        $this->_form->addElement('html', html_writer::end_tag('div'));
+                        $this->activitydiv = false;
+                    }
+                    if ($this->sectiondiv) {
+                        $this->_form->addElement('html', html_writer::end_tag('div'));
+                    }
+                    $mform->addElement('html', html_writer::start_tag('div', array('class'=>'grouped_settings section_level')));
+                    $mform->addElement('html', html_writer::start_tag('div', array('class'=>'include_setting section_level')));
+                    $this->sectiondiv = true;
+                    break;
+                case backup_setting::ACTIVITY_LEVEL:
+                    if ($this->activitydiv) {
+                        $this->_form->addElement('html', html_writer::end_tag('div'));
+                    }
+                    $mform->addElement('html', html_writer::start_tag('div', array('class'=>'grouped_settings activity_level')));
+                    $mform->addElement('html', html_writer::start_tag('div', array('class'=>'include_setting activity_level')));
+                    $this->activitydiv = true;
+                    break;
+                default:
+                    $mform->addElement('html', html_writer::start_tag('div', array('class'=>'normal_setting')));
+                    break;
+            }
+        } else if ($setting->get_level() == backup_setting::ROOT_LEVEL) {
+            $mform->addElement('html', html_writer::start_tag('div', array('class'=>'root_setting')));
+        } else {
+            $mform->addElement('html', html_writer::start_tag('div', array('class'=>'normal_setting')));
+        }
+    }
+    /**
+     * Adds a fixed or static setting to the form
+     * @param backup_setting $setting
+     */
+    function add_fixed_setting(backup_setting $setting) {
+        global $OUTPUT;
+        $settingui = $setting->get_ui();
+        if ($setting->get_visibility() == backup_setting::VISIBLE) {
+            $this->add_html_formatting($setting);
+            switch ($setting->get_status()) {
+                case backup_setting::LOCKED_BY_PERMISSION:
+                    $icon = ' '.$OUTPUT->pix_icon('i/permissionlock', get_string('lockedbypermission', 'backup'), 'moodle', array('class'=>'smallicon lockedicon permissionlock'));
+                    break;
+                case backup_setting::LOCKED_BY_CONFIG:
+                    $icon = ' '.$OUTPUT->pix_icon('i/configlock', get_string('lockedbyconfig', 'backup'), 'moodle', array('class'=>'smallicon lockedicon configlock'));
+                    break;
+                case backup_setting::LOCKED_BY_HIERARCHY:
+                    $icon = ' '.$OUTPUT->pix_icon('i/hierarchylock', get_string('lockedbyhierarchy', 'backup'), 'moodle', array('class'=>'smallicon lockedicon configlock'));
+                    break;
+                default:
+                    $icon = '';
+                    break;
+            }
+            $this->_form->addElement('static', 'static_'.$settingui->get_name(), $settingui->get_label(), $settingui->get_static_value().$icon);
+            $this->_form->addElement('html', html_writer::end_tag('div'));
+        }
+        $this->_form->addElement('hidden', $settingui->get_name(), $settingui->get_value());
+    }
+    /**
+     * Adds dependencies to the form recursively
+     *
+     * @param backup_setting $setting
+     */
+    function add_dependencies(backup_setting $setting) {
+        $mform = $this->_form;
+        // Apply all dependencies for backup
+        foreach ($setting->get_my_dependency_properties() as $key=>$dependency) {
+            call_user_method_array('disabledIf', $this->_form, $dependency);
+        }
+    }
+    /**
+     * Returns true if the form was cancelled, false otherwise
+     * @return bool
+     */
+    public function is_cancelled() {
+        return (optional_param('cancel', false, PARAM_BOOL) || parent::is_cancelled());
+    }
+}
\ No newline at end of file
diff --git a/backup/util/ui/base_ui.class.php b/backup/util/ui/base_ui.class.php
new file mode 100644 (file)
index 0000000..c8ff218
--- /dev/null
@@ -0,0 +1,281 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This file contains the backup user interface class
+ *
+ * @package   moodlecore
+ * @copyright 2010 Sam Hemelryk
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+/**
+ * This is the backup user interface class
+ *
+ * The backup user interface class manages the user interface and backup for
+ * Moodle.
+ *
+ * @copyright 2010 Sam Hemelryk
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+abstract class base_ui {
+    /**
+     * The progress of this instance of the backup ui class
+     */
+    const PROGRESS_INTIAL = 0;
+    const PROGRESS_PROCESSED = 1;
+    const PROGRESS_SAVED = 2;
+    const PROGRESS_EXECUTED = 3;
+    /**
+     * The controller
+     * @var backup_controller|restore_controller
+     */
+    protected $controller;
+    /**
+     * The current stage
+     * @var base_ui_stage
+     */
+    protected $stage;
+    /**
+     * The current progress of the UI
+     * @var int One of self::PROGRESS_*
+     */
+    protected $progress;
+    /**
+     * The number of changes made by dependency enforcement
+     * @var int
+     */
+    protected $dependencychanges = 0;
+
+    /**
+     * Yay for constructors
+     * @param backup_controller $controller
+     */
+    public function __construct($controller, array $params=null) {
+        $this->controller = $controller;
+        $this->progress = self::PROGRESS_INTIAL;
+        $this->stage = $this->initialise_stage(null, $params);
+        // Process UI event before to be safe
+        $this->controller->process_ui_event();
+    }
+    /**
+     * Intialises what ever stage is requested. If none are requested we check
+     * params for 'stage' and default to initial
+     *
+     * @param int|null $stage The desired stage to intialise or null for the default
+     * @return base_ui_stage
+     */
+    abstract protected function initialise_stage($stage = null, array $params=null);
+    /**
+     * This processes the current stage of the backup
+     * @return bool
+     */
+    public function process() {
+        if ($this->progress >= self::PROGRESS_PROCESSED) {
+            throw new backup_ui_exception('backupuialreadyprocessed');
+        }
+        $this->progress = self::PROGRESS_PROCESSED;
+
+        if (optional_param('previous', false, PARAM_BOOL) && $this->stage->get_stage() > self::STAGE_INITIAL) {
+            $this->stage = $this->initialise_stage($this->stage->get_prev_stage(), $this->stage->get_params());
+            return false;
+        }
+
+        // Process the stage
+        $processoutcome = $this->stage->process();
+
+        if ($processoutcome !== false) {
+            $this->stage = $this->initialise_stage($this->stage->get_next_stage(), $this->stage->get_params());
+        }
+
+        // Process UI event after to check changes are valid
+        $this->controller->process_ui_event();
+        return $processoutcome;
+    }
+    /**
+     * Saves the backup controller.
+     *
+     * Once this has been called nothing else can be changed in the controller.
+     *
+     * @return bool
+     */
+    public function save_controller() {
+        if ($this->progress >= self::PROGRESS_SAVED) {
+            throw new base_ui_exception('backupuialreadysaved');
+        }
+        $this->progress = self::PROGRESS_SAVED;
+        // First enforce dependencies
+        $this->enforce_dependencies();
+        // Process UI event after to check any changes are valid
+        $this->controller->process_ui_event();
+        // Save the controller
+        $this->controller->save_controller();
+        return true;
+    }
+    /**
+     * Displays the UI for the backup!
+     *
+     * Note: The UI makes use of mforms (ewww!) thus it will automatically print
+     * out the result rather than returning a string of HTML like other parts of Moodle
+     *
+     * @return bool
+     */
+    public function display() {
+        if ($this->progress < self::PROGRESS_SAVED) {
+            throw new base_ui_exception('backupsavebeforedisplay');
+        }
+        $this->stage->display();
+    }
+    /**
+     * Gets all backup tasks from the controller
+     * @return array Array of backup_task
+     */
+    public function get_tasks() {
+        $plan = $this->controller->get_plan();
+        $tasks = $plan->get_tasks();
+        return $tasks;
+    }
+    /**
+     * Gets the stage we are on
+     * @return int
+     */
+    public function get_stage() {
+        return $this->stage->get_stage();
+    }
+    /**
+     * Gets the name of the stage we are on
+     * @return string
+     */
+    public function get_stage_name() {
+        return $this->stage->get_name();
+    }
+    /**
+     * Gets the backup id from the controller
+     * @return string
+     */
+    abstract public function get_uniqueid();
+    /**
+     * Executes the backup plan
+     * @return bool
+     */
+    abstract public function execute();
+    /**
+     * Enforces dependencies on all settings. Call before save
+     * @return bool True if dependencies were enforced and changes were made
+     */
+    protected function enforce_dependencies() {
+        // Get the plan
+        $plan = $this->controller->get_plan();
+        // Get the tasks as a var so we can iterate by reference
+        $tasks = $plan->get_tasks();
+        $changes = 0;
+        foreach ($tasks as &$task) {
+            // Store as a var so we can iterate by reference
+            $settings = $task->get_settings();
+            foreach ($settings as &$setting) {
+                // Get all dependencies for iteration by reference
+                $dependencies = $setting->get_dependencies();
+                foreach ($dependencies as &$dependency) {
+                    // Enforce each dependency
+                    if ($dependency->enforce()) {
+                        $changes++;
+                    }
+                }
+            }
+        }
+        // Store the number of settings that changed through enforcement
+        $this->dependencychanges = $changes;
+        return ($changes>0);
+    }
+    /**
+     * Returns true if enforce_dependencies changed any settings
+     * @return bool
+     */
+    public function enforce_changed_dependencies() {
+        return ($this->dependencychanges > 0);
+    }
+    /**
+     * Loads the backup controller if we are tracking one
+     * @return backup_controller|false
+     */
+    abstract public static function load_controller($uniqueid=false);
+    /**
+     * Gets an array of progress bar items that can be displayed through the backup renderer.
+     * @return array Array of items for the progress bar
+     */
+    abstract public function get_progress_bar();
+    /**
+     * Gets the format for the backup
+     * @return int
+     */
+    public function get_format() {
+        return $this->controller->get_format();
+    }
+    /**
+     * Gets the type of the backup
+     * @return int
+     */
+    public function get_type() {
+        return $this->controller->get_type();
+    }
+    public function get_controller() {
+        return $this->controller;
+    }
+    /**
+     * Gets the ID used in creating the controller. Relates to course/section/cm
+     * @return int
+     */
+    public function get_controller_id() {
+        return $this->controller->get_id();
+    }
+    /**
+     * Gets the requested setting
+     * @param string $name
+     * @return mixed
+     */
+    public function get_setting($name, $default = false) {
+        try {
+            return $this->controller->get_plan()->get_setting($name);
+        } catch (Exception $e) {
+            debugging('Failed to find the setting: '.$name, DEBUG_DEVELOPER);
+            return $default;
+        }
+    }
+    /**
+     * Gets the value for the requested setting
+     *
+     * @param string $name
+     * @return mixed
+     */
+    public function get_setting_value($name, $default = false) {
+        try {
+            return $this->controller->get_plan()->get_setting($name)->get_value();
+        } catch (Exception $e) {
+            debugging('Failed to find the setting: '.$name, DEBUG_DEVELOPER);
+            return $default;
+        }
+    }
+
+    abstract public function get_name();
+
+    abstract public function get_first_stage_id();
+}
+
+/**
+ * Backup user interface exception. Modelled off the backup_exception class
+ */
+class base_ui_exception extends backup_exception {}
\ No newline at end of file
diff --git a/backup/util/ui/base_ui_stage.class.php b/backup/util/ui/base_ui_stage.class.php
new file mode 100644 (file)
index 0000000..011ff8d
--- /dev/null
@@ -0,0 +1,147 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Backup user interface stages
+ *
+ * This file contains the classes required to manage the stages that make up the
+ * backup user interface.
+ * These will be primarily operated a {@see backup_ui} instance.
+ *
+ * @package   moodlecore
+ * @copyright 2010 Sam Hemelryk
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+/**
+ * Abstract stage class
+ *
+ * This class should be extended by all backup stages (a requirement of many backup ui functions).
+ * Each stage must then define two abstract methods
+ *  - process : To process the stage
+ *  - initialise_stage_form : To get a backup_moodleform instance for the stage
+ *
+ * @copyright 2010 Sam Hemelryk
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+abstract class base_ui_stage {
+    /**
+     * The current stage
+     * @var int
+     */
+    protected $stage = 1;
+    /**
+     * The backuck UI object
+     * @var base_ui
+     */
+    protected $ui;
+    /**
+     * The moodleform for this stage
+     * @var base_moodleform
+     */
+    protected $stageform = null;
+    /**
+     * Custom form params that will be added as hidden inputs
+     */
+    protected $params = null;
+    /**
+     *
+     * @param base_ui $ui
+     */
+    public function __construct(base_ui $ui, array $params=null) {
+        $this->ui = $ui;
+        $this->params = $params;
+    }
+    /**
+     * Returns the custom params for this stage
+     * @return array|null
+     */
+    final public function get_params() {
+        return $this->params;
+    }
+    /**
+     * The current stage
+     * @return int
+     */
+    final public function get_stage() {
+        return $this->stage;
+    }
+    /**
+     * The next stage
+     * @return int
+     */
+    final public function get_next_stage() {
+        return floor($this->stage*2);
+    }
+    /**
+     * The previous stage
+     * @return int
+     */
+    final public function get_prev_stage() {
+        return floor($this->stage/2);
+    }
+    /**
+     * The name of this stage
+     * @return string
+     */
+    public function get_name() {
+        return get_string('currentstage'.$this->stage,'backup');
+    }
+    /**
+     * The backup id from the backup controller
+     * @return string
+     */
+    final public function get_uniqueid() {
+        return $this->ui->get_uniqueid();
+    }
+    /**
+     * Displays the stage.
+     *
+     * By default this involves instantiating the form for the stage and the calling
+     * it to display. Remember this is a moodleform instance so it will print
+     * rather than return.
+     */
+    public function display() {
+        $form = $this->initialise_stage_form();
+        $form->display();
+    }
+    /**
+     * Processes the stage.
+     *
+     * This must be overridden by every stage as it will be different for every stage
+     *
+     * @abstract
+     * @param backup_moodleform|null $form
+     */
+    abstract public function process(base_moodleform $form=null);
+    /**
+     * Creates an instance of the correct moodleform properly populated and all
+     * dependencies instantiated
+     *
+     * @abstract
+     * @return backup_moodleform
+     */
+    abstract protected function initialise_stage_form();
+
+    final public function get_ui() {
+        return $this->ui;
+    }
+
+    final public function is_first_stage() {
+        return $this->stage == 1;
+    }
+}
\ No newline at end of file
index 28702a4..c36f4ee 100644 (file)
@@ -63,6 +63,182 @@ class core_backup_renderer extends plugin_renderer_base {
     public function dependency_notification($message) {
         return html_writer::tag('div', $message, array('class'=>'notification dependencies_enforced'));
     }
+
+    public function backup_details($details, $nextstageurl) {
+        $yestick = $this->output->pix_icon('i/tick_green_big', get_string('yes'));
+        $notick = $this->output->pix_icon('i/cross_red_big', get_string('no'));
+
+        $html  = html_writer::start_tag('div', array('class'=>'backup-restore'));
+
+        $html .= html_writer::start_tag('div', array('class'=>'backup-section'));
+        $html .= $this->output->heading(get_string('backupdetails', 'backup'), 2, array('class'=>'header'));
+        $html .= $this->backup_detail_pair(get_string('backuptype', 'backup'), get_string('backuptype'.$details->type, 'backup'));
+        $html .= $this->backup_detail_pair(get_string('backupformat', 'backup'), get_string('backupformat'.$details->format, 'backup'));
+        $html .= $this->backup_detail_pair(get_string('backupmode', 'backup'), get_string('backupmode'.$details->mode, 'backup'));
+        $html .= $this->backup_detail_pair(get_string('backupdate', 'backup'), userdate($details->backup_date));
+        $html .= $this->backup_detail_pair(get_string('moodleversion', 'backup'), 
+                html_writer::tag('span', $details->moodle_release, array('class'=>'moodle_release')).
+                html_writer::tag('span', '['.$details->moodle_version.']', array('class'=>'moodle_version sub-detail')));
+        $html .= $this->backup_detail_pair(get_string('backupversion', 'backup'),
+                html_writer::tag('span', $details->backup_release, array('class'=>'moodle_release')).
+                html_writer::tag('span', '['.$details->backup_version.']', array('class'=>'moodle_version sub-detail')));
+        $html .= $this->backup_detail_pair(get_string('originalwwwroot', 'backup'),
+                html_writer::tag('span', $details->original_wwwroot, array('class'=>'originalwwwroot')).
+                html_writer::tag('span', '['.$details->original_site_identifier_hash.']', array('class'=>'sitehash sub-detail')));
+        $html .= html_writer::end_tag('div');
+
+        $html .= html_writer::start_tag('div', array('class'=>'backup-section settings-section'));
+        $html .= $this->output->heading(get_string('backupsettings', 'backup'), 2, array('class'=>'header'));
+        foreach ($details->root_settings as $label=>$value) {
+            if ($label == 'filename') continue;
+            $html .= $this->backup_detail_pair(get_string('general'.str_replace('_','',$label), 'backup'), $value?$yestick:$notick);
+        }
+        $html .= html_writer::end_tag('div');
+
+        $html .= html_writer::start_tag('div', array('class'=>'backup-section'));
+        $html .= $this->output->heading(get_string('backupcoursedetails', 'backup'), 2, array('class'=>'header'));
+        $html .= $this->backup_detail_pair(get_string('coursetitle', 'backup'), $details->course->title);
+        $html .= $this->backup_detail_pair(get_string('courseid', 'backup'), $details->course->courseid);
+
+        $html .= html_writer::start_tag('div', array('class'=>'backup-sub-section'));
+        $html .= $this->output->heading(get_string('backupcoursesections', 'backup'), 3, array('class'=>'subheader'));
+        foreach ($details->sections as $key=>$section) {
+            $included = $key.'_included';
+            $userinfo = $key.'_userinfo';
+            if ($section->settings[$included] && $section->settings[$userinfo]) {
+                $value = get_string('sectionincanduser','backup');
+            } else if ($section->settings[$included]) {
+                $value = get_string('sectioninc','backup');
+            } else {
+                continue;
+            }
+            $html .= $this->backup_detail_pair(get_string('backupcoursesection', 'backup', $section->title), $value);
+            $table = null;
+            foreach ($details->activities as $activitykey=>$activity) {
+                if ($activity->sectionid != $section->sectionid) {
+                    continue;
+                }
+                if (empty($table)) {
+                    $table = new html_table();
+                    $table->head = array('Module', 'Title', 'Userinfo');
+                    $table->colclasses = array('modulename', 'moduletitle', 'userinfoincluded');
+                    $table->align = array('left','left', 'center');
+                    $table->attributes = array('class'=>'activitytable generaltable');
+                    $table->data = array();
+                }
+                $table->data[] = array(
+                    get_string('pluginname', $activity->modulename),
+                    $activity->title,
+                    ($activity->settings[$activitykey.'_userinfo'])?$yestick:$notick,
+                );
+            }
+            if (!empty($table)) {
+                $html .= $this->backup_detail_pair(get_string('sectionactivities','backup'), html_writer::table($table));
+            }
+            
+        }
+        $html .= html_writer::end_tag('div');
+        $html .= html_writer::end_tag('div');
+        $html .= html_writer::end_tag('div');
+
+        $html .= $this->output->single_button($nextstageurl, get_string('continue'), 'post');
+
+        return $html;
+    }
+
+    public function course_selector(moodle_url $nextstageurl, $details, $categories, $courses, $currentcourse = null) {
+        global $CFG;
+        require_once($CFG->dirroot.'/course/lib.php');
+
+        $nextstageurl->param('sesskey', sesskey());
+
+        $form = html_writer::start_tag('form', array('method'=>'post', 'action'=>$nextstageurl->out_omit_querystring()));
+        foreach ($nextstageurl->params() as $key=>$value) {
+            $form .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>$key, 'value'=>$value));
+        }
+
+        $html  = html_writer::start_tag('div', array('class'=>'backup-course-selector backup-restore'));
+
+        // Current course
+        if (!empty($currentcourse)) {
+            $html .= $form;
+            $form .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'targetid', 'value'=>$currentcourse));
+            $html .= html_writer::start_tag('div', array('class'=>'bcs-current-course backup-section'));
+            $html .= $this->output->heading(get_string('restoretocurrentcourse', 'backup'), 2, array('class'=>'header'));
+            $html .= $this->backup_detail_input(get_string('restoretocurrentcourseadding', 'backup'), 'radio', 'target', backup::TARGET_CURRENT_ADDING);
+            $html .= $this->backup_detail_input(get_string('restoretocurrentcoursedeleting', 'backup'), 'radio', 'target', backup::TARGET_CURRENT_DELETING);
+            $html .= $this->backup_detail_pair('', html_writer::empty_tag('input', array('type'=>'submit', 'value'=>get_string('continue'))));
+            $html .= html_writer::end_tag('div');
+            $html .= html_writer::end_tag('form');
+        }
+
+        // New course
+        $html .= $form;
+        $html .= html_writer::start_tag('div', array('class'=>'bcs-new-course backup-section'));
+        $html .= $this->output->heading(get_string('restoretonewcourse', 'backup'), 2, array('class'=>'header'));
+        $html .= $this->backup_detail_input(get_string('restoretonewcourse', 'backup'), 'radio', 'target', backup::TARGET_NEW_COURSE, array('checked'=>'checked'));
+        $html .= $this->backup_detail_select(get_string('coursecategory', 'backup'), 'targetid', $categories);
+        $html .= $this->backup_detail_pair('', html_writer::empty_tag('input', array('type'=>'submit', 'value'=>get_string('continue'))));
+        $html .= html_writer::end_tag('div');
+        $html .= html_writer::end_tag('form');
+
+        // Existing course
+        $html .= $form;
+        $html .= html_writer::start_tag('div', array('class'=>'bcs-existing-course backup-section'));
+        $html .= $this->output->heading(get_string('restoretoexistingcourse', 'backup'), 2, array('class'=>'header'));
+        $html .= $this->backup_detail_input(get_string('restoretoexistingcourseadding', 'backup'), 'radio', 'target', backup::TARGET_EXISTING_ADDING);
+        $html .= $this->backup_detail_input(get_string('restoretoexistingcoursedeleting', 'backup'), 'radio', 'target', backup::TARGET_EXISTING_DELETING);
+        $html .= $this->backup_detail_select(get_string('restoretocourse', 'backup'), 'targetid', $courses);
+        $html .= $this->backup_detail_pair('', html_writer::empty_tag('input', array('type'=>'submit', 'value'=>get_string('continue'))));
+        $html .= html_writer::end_tag('div');
+        $html .= html_writer::end_tag('form');
+
+        $html .= html_writer::end_tag('div');
+        return $html;
+    }
+
+    protected function backup_detail_pair($label, $value) {
+        static $count= 0;
+        $count++;
+        $html  = html_writer::start_tag('div', array('class'=>'detail-pair'));
+        $html .= html_writer::tag('label', $label, array('class'=>'detail-pair-label', 'for'=>'detail-pair-value-'.$count));
+        $html .= html_writer::tag('div', $value, array('class'=>'detail-pair-value', 'name'=>'detail-pair-value-'.$count));
+        $html .= html_writer::end_tag('div');
+        return $html;
+    }
+
+    protected function backup_detail_input($label, $type, $name, $value, array $attributes=array()) {
+        return $this->backup_detail_pair($label, html_writer::empty_tag('input', $attributes+array('name'=>$name, 'type'=>$type, 'value'=>$value)));
+    }
+
+    protected function backup_detail_select($label, $name, $options, $selected='', $nothing=false, array $attributes=array()) {
+        return $this->backup_detail_pair($label, html_writer::select($options, 'targetid', '', false, $attributes));
+    }
+
+    public function precheck_notices($results) {
+        $output = html_writer::start_tag('div', array('class'=>'restore-precheck-notices'));
+        if (array_key_exists('errors', $results)) {
+            foreach ($results['errors'] as $error) {
+                $output .= $this->output->notification($error);
+            }
+        }
+        if (array_key_exists('warnings', $results)) {
+            foreach ($results['warnings'] as $warning) {
+                $output .= $this->output->notification($warning, 'notifywarning notifyproblem');
+            }
+        }
+        return $output.html_writer::end_tag('div');
+    }
+
+    public function continue_button($url) {
+        if (!($url instanceof moodle_url)) {
+            $url = new moodle_url($url);
+        }
+        $url->param('sesskey', sesskey());
+        $button = new single_button($url, get_string('continue'), 'post');
+        $button->class = 'continuebutton';
+        return $this->render($button);
+    }
     /**
      * Print a backup files tree
      * @param file_info $fileinfo
@@ -113,6 +289,7 @@ class core_backup_renderer extends plugin_renderer_base {
         $html .= '</div>';
         return $html;
     }
+    
 }
 /**
  * Data structure representing backup files viewer
@@ -183,4 +360,4 @@ class backup_files_viewer implements renderable {
             $this->tree[] = $fileitem;
         }
     }
-}
+}
\ No newline at end of file
diff --git a/backup/util/ui/restore_moodleform.class.php b/backup/util/ui/restore_moodleform.class.php
new file mode 100644 (file)
index 0000000..760da5f
--- /dev/null
@@ -0,0 +1,13 @@
+<?php
+
+require_once($CFG->dirroot.'/backup/util/ui/backup_moodleform.class.php');
+
+class restore_moodleform extends base_moodleform {
+    public function __construct(restore_ui_stage $uistage, $action = null, $customdata = null, $method = 'post', $target = '', $attributes = null, $editable = true) {
+        parent::__construct($uistage, $action, $customdata, $method, $target, $attributes, $editable);
+    }
+}
+
+class restore_settings_form extends restore_moodleform {}
+class restore_schema_form extends restore_moodleform {}
+class restore_review_form extends restore_moodleform {};
\ No newline at end of file
diff --git a/backup/util/ui/restore_ui.class.php b/backup/util/ui/restore_ui.class.php
new file mode 100644 (file)
index 0000000..056a0c3
--- /dev/null
@@ -0,0 +1,241 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This file contains the restore user interface class
+ *
+ * @package   moodlecore
+ * @copyright 2010 Sam Hemelryk
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+/**
+ * This is the restore user interface class
+ *
+ * The restore user interface class manages the user interface and restore for
+ * Moodle.
+ *
+ * @copyright 2010 Sam Hemelryk
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class restore_ui extends base_ui {
+    /**
+     * The stages of the restore user interface.
+     */
+    const STAGE_CONFIRM = 1;
+    const STAGE_DESTINATION = 2;
+    const STAGE_SETTINGS = 4;
+    const STAGE_SCHEMA = 8;
+    const STAGE_REVIEW = 16;
+    const STAGE_PROCESS = 32;
+    const STAGE_COMPLETE = 64;
+
+    /**
+     *
+     * @var restore_ui_stage
+     */
+    protected $stage = null;
+
+    public static $stages = array(
+        restore_ui::STAGE_CONFIRM       => 'confirm',
+        restore_ui::STAGE_DESTINATION   => 'destination',
+        restore_ui::STAGE_SETTINGS      => 'settings',
+        restore_ui::STAGE_SCHEMA        => 'schema',
+        restore_ui::STAGE_REVIEW        => 'review',
+        restore_ui::STAGE_PROCESS       => 'process',
+        restore_ui::STAGE_COMPLETE      => 'complete'
+    );
+    /**
+     * Intialises what ever stage is requested. If none are requested we check
+     * params for 'stage' and default to initial
+     *
+     * @param int|null $stage The desired stage to intialise or null for the default
+     * @return restore_ui_stage_initial|restore_ui_stage_schema|restore_ui_stage_confirmation|restore_ui_stage_final
+     */
+    protected function initialise_stage($stage = null, array $params=null) {
+        if ($stage == null) {
+            $stage = optional_param('stage', self::STAGE_CONFIRM, PARAM_INT);
+        }
+        $class = 'restore_ui_stage_'.self::$stages[$stage];
+        if (!class_exists($class)) {
+            throw new restore_ui_exception('unknownuistage');
+        }
+        $stage = new $class($this, $params);
+        return $stage;
+    }
+    /**
+     * This processes the current stage of the restore
+     * @return bool
+     */
+    public function process() {
+        if ($this->progress >= self::PROGRESS_PROCESSED) {
+            throw new restore_ui_exception('restoreuialreadyprocessed');
+        }
+        $this->progress = self::PROGRESS_PROCESSED;
+
+        if (optional_param('previous', false, PARAM_BOOL) && $this->stage->get_stage() > self::STAGE_CONFIRM) {
+            $this->stage = $this->initialise_stage($this->stage->get_prev_stage(), $this->stage->get_params());
+            return false;
+        }
+
+        // Process the stage
+        $processoutcome = $this->stage->process();
+        if ($processoutcome !== false && !($this->get_stage()==self::STAGE_PROCESS && optional_param('substage', false, PARAM_BOOL))) {
+            $this->stage = $this->initialise_stage($this->stage->get_next_stage(), $this->stage->get_params());
+        }
+
+        // Process UI event after to check changes are valid
+        $this->controller->process_ui_event();
+        return $processoutcome;
+    }
+
+    public function is_independent() {
+        return false;
+    }
+    /**
+     * @return string
+     */
+    public function get_uniqueid() {
+        return $this->get_restoreid();
+    }
+    /**
+     * Gets the restore id from the controller
+     * @return string
+     */
+    public function get_restoreid() {
+        return $this->controller->get_restoreid();
+    }
+    /**
+     * Executes the restore plan
+     * @return bool
+     */
+    public function execute() {
+        if ($this->progress >= self::PROGRESS_EXECUTED) {
+            throw new restore_ui_exception('restoreuialreadyexecuted');
+        }
+        if ($this->stage->get_stage() < self::STAGE_PROCESS) {
+            throw new restore_ui_exception('restoreuifinalisedbeforeexecute');
+        }
+        if ($this->controller->get_target() == backup::TARGET_CURRENT_DELETING || $this->controller->get_target() == backup::TARGET_EXISTING_DELETING) {
+            restore_dbops::delete_course_content($this->controller->get_courseid());
+        }
+        $this->controller->execute_plan();
+        $this->progress = self::PROGRESS_EXECUTED;
+        $this->stage = new restore_ui_stage_complete($this, $this->stage->get_params(), $this->controller->get_results());
+        return true;
+    }
+    /**
+     * Returns true if enforce_dependencies changed any settings
+     * @return bool
+     */
+    public function enforce_changed_dependencies() {
+        return ($this->dependencychanges > 0);
+    }
+    /**
+     * Loads the restore controller if we are tracking one
+     * @return restore_controller|false
+     */
+    final public static function load_controller($restoreid=false) {
+        // Get the restore id optional param
+        if ($restoreid) {
+            try {
+                // Try to load the controller with it.
+                // If it fails at this point it is likely because this is the first load
+                $controller = restore_controller::load_controller($restoreid);
+                return $controller;
+            } catch (Exception $e) {
+                return false;
+            }
+        }
+        return $restoreid;
+    }
+    final public static function engage_independent_stage($stage, $contextid) {
+        if (!($stage & self::STAGE_CONFIRM + self::STAGE_DESTINATION)) {
+            throw new restore_ui_exception('dependentstagerequested');
+        }
+        $class = 'restore_ui_stage_'.self::$stages[$stage];
+        if (!class_exists($class)) {
+            throw new restore_ui_exception('unknownuistage');
+        }
+        return new $class($contextid);
+    }
+    /**
+     * Cancels the current restore and redirects the user back to the relevant place
+     */
+    public function cancel_restore() {
+        global $PAGE;
+        // Determine the approriate URL to redirect the user to
+        if ($PAGE->context->contextlevel == CONTEXT_MODULE && $PAGE->cm !== null) {
+            $relevanturl = new moodle_url('/mod/'.$PAGE->cm->modname.'/view.php', array('id'=>$PAGE->cm->id));
+        } else {
+            $relevanturl = new moodle_url('/course/view.php', array('id'=>$PAGE->course->id));
+        }
+        redirect($relevanturl);
+    }
+    /**
+     * Gets an array of progress bar items that can be displayed through the restore renderer.
+     * @return array Array of items for the progress bar
+     */
+    public function get_progress_bar() {
+        global $PAGE;
+
+        $stage = self::STAGE_COMPLETE;
+        $currentstage = $this->stage->get_stage();
+        $items = array();
+        while ($stage > 0) {
+            $classes = array('backup_stage');
+            if (floor($stage/2) == $currentstage) {
+                $classes[] = 'backup_stage_next';
+            } else if ($stage == $currentstage) {
+                $classes[] = 'backup_stage_current';
+            } else if ($stage < $currentstage) {
+                $classes[] = 'backup_stage_complete';
+            }
+            $item = array('text' => strlen(decbin($stage)).'. '.get_string('restorestage'.$stage, 'backup'),'class' => join(' ', $classes));
+            if ($stage < $currentstage && $currentstage < self::STAGE_COMPLETE && $stage > self::STAGE_DESTINATION) {
+                $item['link'] = new moodle_url($PAGE->url, array('restore'=>$this->get_restoreid(), 'stage'=>$stage));
+            }
+            array_unshift($items, $item);
+            $stage = floor($stage/2);
+        }
+        return $items;
+    }
+
+    public function get_name() {
+        return 'restore';
+    }
+
+    public function get_first_stage_id() {
+        return self::STAGE_CONFIRM;
+    }
+
+    public function requires_substage() {
+        return ($this->stage->has_sub_stages() && !$this->stage->process());
+    }
+
+    public function display($renderer) {
+        if ($this->progress < self::PROGRESS_SAVED) {
+            throw new base_ui_exception('backupsavebeforedisplay');
+        }
+        $this->stage->display($renderer);
+    }
+}
+
+/**
+ * restore user interface exception. Modelled off the restore_exception class
+ */
+class restore_ui_exception extends base_ui_exception {}
\ No newline at end of file
diff --git a/backup/util/ui/restore_ui_stage.class.php b/backup/util/ui/restore_ui_stage.class.php
new file mode 100644 (file)
index 0000000..fc4e06c
--- /dev/null
@@ -0,0 +1,593 @@
+<?php
+
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * restore user interface stages
+ *
+ * This file contains the classes required to manage the stages that make up the
+ * restore user interface.
+ * These will be primarily operated a {@see restore_ui} instance.
+ *
+ * @package   moodlecore
+ * @copyright 2010 Sam Hemelryk
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+/**
+ * Abstract stage class
+ *
+ * This class should be extended by all restore stages (a requirement of many restore ui functions).
+ * Each stage must then define two abstract methods
+ *  - process : To process the stage
+ *  - initialise_stage_form : To get a restore_moodleform instance for the stage
+ *
+ * @copyright 2010 Sam Hemelryk
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+abstract class restore_ui_stage extends base_ui_stage {
+    /**
+     *
+     * @param restore_ui $ui
+     */
+    public function __construct(restore_ui $ui, array $params=null) {
+        $this->ui = $ui;
+        $this->params = $params;
+    }
+    /**
+     * The restore id from the restore controller
+     * @return string
+     */
+    final public function get_restoreid() {
+        return $this->get_uniqueid();
+    }
+
+    final public function is_independent() {
+        return false;
+    }
+
+    public function has_sub_stages() {
+        return false;
+    }
+
+    /**
+     * The name of this stage
+     * @return string
+     */
+    final public function get_name() {
+        return get_string('restorestage'.$this->stage,'backup');
+    }
+}
+
+abstract class restore_ui_independent_stage {
+    abstract public function __construct($contextid);
+    abstract public function process();
+    abstract public function display($renderer);
+    abstract public function get_stage();
+    /**
+     * Gets an array of progress bar items that can be displayed through the restore renderer.
+     * @return array Array of items for the progress bar
+     */
+    public function get_progress_bar() {
+        global $PAGE;
+        $stage = restore_ui::STAGE_COMPLETE;
+        $currentstage = $this->get_stage();
+        $items = array();
+        while ($stage > 0) {
+            $classes = array('backup_stage');
+            if (floor($stage/2) == $currentstage) {
+                $classes[] = 'backup_stage_next';
+            } else if ($stage == $currentstage) {
+                $classes[] = 'backup_stage_current';
+            } else if ($stage < $currentstage) {
+                $classes[] = 'backup_stage_complete';
+            }
+            $item = array('text' => strlen(decbin($stage)).'. '.get_string('restorestage'.$stage, 'backup'),'class' => join(' ', $classes));
+            if ($stage < $currentstage && $currentstage < restore_ui::STAGE_COMPLETE) {
+                //$item['link'] = new moodle_url($PAGE->url, array('restore'=>$this->get_restoreid(), 'stage'=>$stage));
+            }
+            array_unshift($items, $item);
+            $stage = floor($stage/2);
+        }
+        return $items;
+    }
+    abstract public function get_stage_name();
+    final public function is_independent() {
+        return true;
+    }
+}
+
+class restore_ui_stage_confirm extends restore_ui_independent_stage {
+    protected $contextid;
+    protected $filename = null;
+    protected $filepath = null;
+    protected $details;
+    public function __construct($contextid) {
+        $this->contextid = $contextid;
+        $this->filename = required_param('filename', PARAM_FILE);
+    }
+    public function process() {
+        global $CFG;
+        if (!file_exists("$CFG->dataroot/temp/backup/".$this->filename)) {
+            throw new restore_ui_exception('invalidrestorefile');
+        }
+        return $this->extract_file_to_dir();
+    }
+    protected function extract_file_to_dir() {
+        global $CFG, $USER;
+
+        $this->filepath = restore_controller::get_tempdir_name($this->contextid, $USER->id);
+
+        $fb = get_file_packer();
+        return ($fb->extract_to_pathname("$CFG->dataroot/temp/backup/".$this->filename, "$CFG->dataroot/temp/backup/$this->filepath/"));
+    }
+    public function display($renderer) {
+        $this->details = backup_general_helper::get_backup_information($this->filepath);
+        return $renderer->backup_details($this->details, new moodle_url('/backup/restore.php', array('contextid'=>$this->contextid, 'filepath'=>$this->filepath, 'stage'=>restore_ui::STAGE_DESTINATION)));
+    }
+    public function get_stage_name() {
+        return get_string('restorestage'.restore_ui::STAGE_CONFIRM, 'backup');
+    }
+    public function get_stage() {
+        return restore_ui::STAGE_CONFIRM;
+    }
+}
+
+class restore_ui_stage_destination extends restore_ui_independent_stage {
+    protected $contextid;
+    protected $filepath = null;
+    protected $details;
+    protected $courseid = null;
+    public function __construct($contextid) {
+        $this->contextid = $contextid;
+        $this->filepath = required_param('filepath', PARAM_ALPHANUM);
+    }
+    public function process() {
+        global $CFG, $DB;
+        if (!file_exists("$CFG->dataroot/temp/backup/".$this->filepath) || !is_dir("$CFG->dataroot/temp/backup/".$this->filepath)) {
+            throw new restore_ui_exception('invalidrestorepath');
+        }
+        $target = optional_param('target', null, PARAM_INT);
+        if (!is_null($target) && confirm_sesskey()) {
+            $targetid = required_param('targetid', PARAM_INT);
+            if ($target == backup::TARGET_NEW_COURSE) {
+                list($fullname, $shortname) = restore_dbops::calculate_course_names(0, get_string('restoringcourse', 'backup'), get_string('restoringcourseshortname', 'backup'));
+                $this->courseid = restore_dbops::create_new_course($fullname, $shortname, $targetid);
+            } else {
+                $this->courseid = $targetid;
+            }
+            return ($DB->record_exists('course', array('id'=>$this->courseid)));
+        }
+        return false;
+    }
+    /**
+     *
+     * @global moodle_database $DB
+     * @param core_backup_renderer $renderer
+     * @return string
+     */
+    public function display($renderer) {
+        global $DB;
+        $this->details = backup_general_helper::get_backup_information($this->filepath);
+        $url = new moodle_url('/backup/restore.php', array('contextid'=>$this->contextid, 'filepath'=>$this->filepath, 'stage'=>restore_ui::STAGE_SETTINGS));
+        $context = get_context_instance_by_id($this->contextid);
+        $currentcourse = ($context->contextlevel == CONTEXT_COURSE)?$context->instanceid:false;
+        $courselist = array();
+        $courses = $DB->get_recordset('course', array(), 'id,fullname,shortname');
+        foreach ($courses as $course) {
+            $courselist[$course->id] = $course->fullname.' ['.$course->shortname.']';
+        }
+        $courses->close();
+        $html = $renderer->course_selector($url, $this->details, make_categories_options(), $courselist, $currentcourse);
+        return $html;
+    }
+    public function get_stage_name() {
+        return get_string('restorestage'.restore_ui::STAGE_DESTINATION, 'backup');
+    }
+    public function get_filepath() {
+        return $this->filepath;
+    }
+    public function get_course_id() {
+        return $this->courseid;
+    }
+    public function get_stage() {
+        return restore_ui::STAGE_DESTINATION;
+    }
+}
+
+class restore_ui_stage_settings extends restore_ui_stage {
+    /**
+     * Initial restore stage constructor
+     * @param restore_ui $ui
+     */
+    public function __construct(restore_ui $ui, array $params=null) {
+        $this->stage = restore_ui::STAGE_SETTINGS;
+        parent::__construct($ui, $params);
+    }
+
+    public function process(base_moodleform $form=null) {
+        $form = $this->initialise_stage_form();
+
+        if ($form->is_cancelled()) {
+            $this->ui->cancel_restore();
+        }
+
+        $data = $form->get_data();
+        if ($data && confirm_sesskey()) {
+            $tasks = $this->ui->get_tasks();
+            $changes = 0;
+            foreach ($tasks as &$task) {
+                // We are only interesting in the backup root task for this stage
+                if ($task instanceof restore_root_task || $task instanceof restore_course_task) {
+                    // Get all settings into a var so we can iterate by reference
+                    $settings = $task->get_settings();
+                    foreach ($settings as &$setting) {
+                        $name = $setting->get_ui_name();
+                        if (isset($data->$name) &&  $data->$name != $setting->get_value()) {
+                            $setting->set_value($data->$name);
+                            $changes++;
+                        } else if (!isset($data->$name) && $setting->get_ui_type() == backup_setting::UI_HTML_CHECKBOX && $setting->get_value()) {
+                            $setting->set_value(0);
+                            $changes++;
+                        }
+                    }
+                }
+            }
+            // Return the number of changes the user made
+            return $changes;
+        } else {
+            return false;
+        }
+    }
+
+    protected function initialise_stage_form() {
+        global $PAGE;
+        if ($this->stageform === null) {
+            $form = new restore_settings_form($this, $PAGE->url);
+            // Store as a variable so we can iterate by reference
+            $tasks = $this->ui->get_tasks();
+            $headingprinted = false;
+            // Iterate all tasks by reference
+            foreach ($tasks as &$task) {
+                // For the initial stage we are only interested in the root settings
+                if ($task instanceof restore_root_task) {
+                    if (!$headingprinted) {
+                        $form->add_heading('rootsettings', get_string('restorerootsettings', 'backup'));
+                        $headingprinted = true;
+                    }
+                    $settings = $task->get_settings();
+                    // First add all settings except the filename setting
+                    foreach ($settings as &$setting) {
+                        if ($setting->get_name() == 'filename') {
+                            continue;
+                        }
+                        $form->add_setting($setting, $task);
+                    }
+                    // Then add all dependencies
+                    foreach ($settings as &$setting) {
+                        if ($setting->get_name() == 'filename') {
+                            continue;
+                        }
+                        $form->add_dependencies($setting);
+                    }
+                }
+            }
+            $this->stageform = $form;
+        }
+        // Return the form
+        return $this->stageform;
+    }
+}
+
+/**
+ * Schema stage of backup process
+ *
+ * During the schema stage the user is required to set the settings that relate
+ * to the area that they are backing up as well as its children.
+ *
+ * @copyright 2010 Sam Hemelryk
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class restore_ui_stage_schema extends restore_ui_stage {
+    /**
+     * Schema stage constructor
+     * @param backup_moodleform $ui
+     */
+    public function __construct(restore_ui $ui, array $params=null) {
+        $this->stage = restore_ui::STAGE_SCHEMA;
+        parent::__construct($ui, $params);
+    }
+    /**
+     * Processes the schema stage
+     *
+     * @param backup_moodleform|null $form
+     * @return int The number of changes the user made
+     */
+    public function process(base_moodleform $form = null) {
+        $form = $this->initialise_stage_form();
+        // Check it wasn't cancelled
+        if ($form->is_cancelled()) {
+            $this->ui->cancel_backup();
+        }
+
+        // Check it has been submit
+        $data = $form->get_data();
+        if ($data && confirm_sesskey()) {
+            // Get the tasks into a var so we can iterate by reference
+            $tasks = $this->ui->get_tasks();
+            $changes = 0;
+            // Iterate all tasks by reference
+            foreach ($tasks as &$task) {
+                // We are only interested in schema settings
+                if (!($task instanceof restore_root_task)) {
+                    // Store as a variable so we can iterate by reference
+                    $settings = $task->get_settings();
+                    // Iterate by reference
+                    foreach ($settings as &$setting) {
+                        $name = $setting->get_ui_name();
+                        if (isset($data->$name) &&  $data->$name != $setting->get_value()) {
+                            $setting->set_value($data->$name);
+                            $changes++;
+                        } else if (!isset($data->$name) && $setting->get_ui_type() == backup_setting::UI_HTML_CHECKBOX && $setting->get_value()) {
+                            $setting->set_value(0);
+                            $changes++;
+                        }
+                    }
+                }
+            }
+            // Return the number of changes the user made
+            return $changes;
+        } else {
+            return false;
+        }
+    }
+    /**
+     * Creates the backup_schema_form instance for this stage
+     *
+     * @return backup_schema_form
+     */
+    protected function initialise_stage_form() {
+        global $PAGE;
+        if ($this->stageform === null) {
+            $form = new restore_schema_form($this, $PAGE->url);
+            $tasks = $this->ui->get_tasks();
+            $content = '';
+            $courseheading = false;
+            foreach ($tasks as $task) {
+                if (!($task instanceof restore_root_task)) {
+                    if (!$courseheading) {
+                        // If we havn't already display a course heading to group nicely
+                        $form->add_heading('coursesettings', get_string('coursesettings', 'backup'));
+                        $courseheading = true;
+                    }
+                    // First add each setting
+                    foreach ($task->get_settings() as $setting) {
+                        $form->add_setting($setting, $task);
+                    }
+                    // The add all the dependencies
+                    foreach ($task->get_settings() as $setting) {
+                        $form->add_dependencies($setting);
+                    }
+                } else if ($this->ui->enforce_changed_dependencies()) {
+                    // Only show these settings if dependencies changed them.
+                    // Add a root settings heading to group nicely
+                    $form->add_heading('rootsettings', get_string('rootsettings', 'backup'));
+                    // Iterate all settings and add them to the form as a fixed
+                    // setting. We only want schema settings to be editable
+                    foreach ($task->get_settings() as $setting) {
+                        if ($setting->get_name() != 'filename') {
+                            $form->add_fixed_setting($setting);
+                        }
+                    }
+                }
+            }
+            $this->stageform = $form;
+        }
+        return $this->stageform;
+    }
+}
+
+/**
+ * Confirmation stage
+ *
+ * On this stage the user reviews the setting for the backup and can change the filename
+ * of the file that will be generated.
+ *
+ * @copyright 2010 Sam Hemelryk
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class restore_ui_stage_review extends restore_ui_stage {
+    /**
+     * Constructs the stage
+     * @param backup_ui $ui
+     */
+    public function __construct($ui, array $params=null) {
+        $this->stage = restore_ui::STAGE_REVIEW;
+        parent::__construct($ui, $params);
+    }
+    /**
+     * Processes the confirmation stage
+     *
+     * @param backup_moodleform $form
+     * @return int The number of changes the user made
+     */
+    public function process(base_moodleform $form = null) {
+        $form = $this->initialise_stage_form();
+        // Check it hasn't been cancelled
+        if ($form->is_cancelled()) {
+            $this->ui->cancel_backup();
+        }
+
+        $data = $form->get_data();
+        if ($data && confirm_sesskey()) {
+            return 0;
+        } else {
+            return false;
+        }
+    }
+    /**
+     * Creates the backup_confirmation_form instance this stage requires
+     *
+     * @return backup_confirmation_form
+     */
+    protected function initialise_stage_form() {
+        global $PAGE;
+        if ($this->stageform === null) {
+            // Get the form
+            $form = new restore_review_form($this, $PAGE->url);
+            $content = '';
+            $courseheading = false;
+
+            foreach ($this->ui->get_tasks() as $task) {
+                if ($task instanceof restore_root_task) {
+                    // If its a backup root add a root settings heading to group nicely
+                    $form->add_heading('rootsettings', get_string('rootsettings', 'backup'));
+                } else if (!$courseheading) {
+                    // we havn't already add a course heading
+                    $form->add_heading('coursesettings', get_string('coursesettings', 'backup'));
+                    $courseheading = true;
+                }
+                // Iterate all settings, doesnt need to happen by reference
+                foreach ($task->get_settings() as $setting) {
+                    $form->add_fixed_setting($setting);
+                }
+            }
+            $this->stageform = $form;
+        }
+        return $this->stageform;
+    }
+}
+
+/**
+ * Final stage of backup
+ *
+ * This stage is special in that it is does not make use of a form. The reason for
+ * this is the order of procession of backup at this stage.
+ * The processesion is:
+ * 1. The final stage will be intialise.
+ * 2. The confirmation stage will be processed.
+ * 3. The backup will be executed
+ * 4. The complete stage will be loaded by execution
+ * 5. The complete stage will be displayed
+ *
+ * This highlights that we neither need a form nor a display method for this stage
+ * we simply need to process.
+ *
+ * @copyright 2010 Sam Hemelryk
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class restore_ui_stage_process extends restore_ui_stage {
+
+    const SUBSTAGE_NONE = 0;
+    const SUBSTAGE_CONVERT = 1;
+    const SUBSTAGE_PRECHECKS = 2;
+
+    protected $substage = 0;
+
+    /**
+     * Constructs the final stage
+     * @param backup_ui $ui
+     */
+    public function __construct(base_ui $ui, array $params=null) {
+        $this->stage = restore_ui::STAGE_PROCESS;
+        parent::__construct($ui, $params);
+    }
+    /**
+     * Processes the final stage.
+     *
+     * In this case it checks to see if there is a sub stage that we need to display
+     * before execution, if there is we gear up to display the subpage, otherwise
+     * we return true which will lead to execution of the restore and the loading
+     * of the completed stage.
+     */
+    public function process(base_moodleform $form=null) {
+        $rc = $this->ui->get_controller();
+        if ($rc->get_status() == backup::STATUS_REQUIRE_CONV) {
+            $this->substage = self::SUBSTAGE_CONVERT;
+        } else {
+            if ($rc->get_status() == backup::STATUS_SETTING_UI) {
+                $rc->finish_ui();
+            }
+            if ($rc->get_status() == backup::STATUS_NEED_PRECHECK && !$rc->execute_precheck(true)) {
+                $this->substage = self::SUBSTAGE_PRECHECKS;
+            }
+        }
+        return empty($this->substage);
+    }
+    /**
+     * should NEVER be called... throws an exception
+     */
+    protected function initialise_stage_form() {
+        throw new backup_ui_exception('backup_ui_must_execute_first');
+    }
+    /**
+     * should NEVER be called... throws an exception
+     */
+    public function display($renderer) {
+        global $PAGE;
+        switch ($this->substage) {
+            case self::SUBSTAGE_CONVERT :
+                echo '<h2>Need to show the conversion screens here</h2>';
+                break;
+            case self::SUBSTAGE_PRECHECKS :
+                $results = $this->ui->get_controller()->get_precheck_results();
+                echo $renderer->precheck_notices($results);
+                break;
+            default:
+                throw new restore_ui_exception('backup_ui_must_execute_first');
+        }
+        echo $renderer->continue_button(new moodle_url($PAGE->url, array('restore'=>$this->get_uniqueid(), 'stage'=>restore_ui::STAGE_PROCESS, 'substage'=>$this->substage)));
+    }
+
+    public function has_sub_stages() {
+        return true;
+    }
+}
+
+class restore_ui_stage_complete extends restore_ui_stage_process {
+    /**
+     * The results of the backup execution
+     * @var array
+     */
+    protected $results;
+    /**
+     * Constructs the complete backup stage
+     * @param backup_ui $ui
+     * @param array|null $params
+     * @param array $results
+     */
+    public function __construct(restore_ui $ui, array $params=null, array $results=null) {
+        $this->results = $results;
+        parent::__construct($ui, $params);
+        $this->stage = restore_ui::STAGE_COMPLETE;
+    }
+    /**
+     * Displays the completed backup stage.
+     *
+     * Currently this just envolves redirecting to the file browser with an
+     * appropriate message.
+     *
+     * @global core_renderer $OUTPUT
+     */
+    public function display($renderer) {
+        global $OUTPUT;
+        echo $OUTPUT->box_start();
+        echo $OUTPUT->notification(get_string('restoreexecutionsuccess', 'backup'), 'notifysuccess');
+        echo $renderer->continue_button(new moodle_url('/course/view.php', array('id'=>$this->get_ui()->get_controller()->get_courseid())));
+        echo $OUTPUT->box_end();
+    }
+}
\ No newline at end of file
index 7ebd816..f70b10d 100644 (file)
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
+$string['backupactivity'] = 'Backup activity: {$a}';
 $string['backupcourse'] = 'Backup course: {$a}';
+$string['backupcoursedetails'] = 'Course details';
+$string['backupcoursesection'] = 'Section: {$a}';
+$string['backupcoursesections'] = 'Course sections';
+$string['backupdate'] = 'Date taken';
+$string['backupdetails'] = 'Backup details';
+$string['backupformat'] = 'Format';
+$string['backupformatmoodle2'] = 'Moodle 2';
+$string['backupmode'] = 'Mode';
+$string['backupmode10'] = 'General';
 $string['backupsection'] = 'Backup course section: {$a}';
-$string['backupactivity'] = 'Backup activity: {$a}';
+$string['backupsettings'] = 'Backup settings';
+$string['backupsitedetails'] = 'Site details';
+$string['backupstage1action'] = 'Next';
+$string['backupstage2action'] = 'Next';
+$string['backupstage4action'] = 'Perform backup';
+$string['backupstage8action'] = 'Continue';
+$string['backupstage16action'] = 'Continue';
+$string['backuptype'] = 'Type';
+$string['backuptypecourse'] = 'Course';
+$string['backupversion'] = 'Backup version';
 $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.';
@@ -39,7 +58,10 @@ $string['configgeneralroleassignments'] = 'If enabled by default roles assignmen
 $string['configgeneraluserscompletion'] = 'If enabled user completion information will be included in backups by default.';
 $string['configgeneraluserfiles'] = 'Sets the default for whether user files will be included in backups.';
 $string['configgeneralusers'] = 'Sets the default for whether to include users in backups.';
+$string['coursecategory'] = 'Category the course will be restored into';
+$string['courseid'] = 'Original ID';
 $string['coursesettings'] = 'Course settings';
+$string['coursetitle'] = 'Title';
 $string['currentstage1'] = 'Initial settings';
 $string['currentstage2'] = 'Schema settings';
 $string['currentstage4'] = 'Confirmation and review';
@@ -59,6 +81,7 @@ $string['generalblocks'] = 'Include blocks';
 $string['generalcomments'] = 'Include comments';
 $string['generalfilters'] = 'Include filters';
 $string['generalhistories'] = 'Include histories';
+$string['generalgradehistories'] = 'Include histories';
 $string['generallogs'] = 'Include logs';
 $string['generalroleassignments'] = 'Include role assignments';
 $string['generaluserscompletion'] = 'Include user completion information';
@@ -72,14 +95,49 @@ $string['locked'] = 'Locked';
 $string['lockedbypermission'] = 'You don\'t have sufficient permissions to change this setting';
 $string['lockedbyconfig'] = 'This setting has been locked by the default backup settings';
 $string['lockedbyhierarchy'] = 'Locked by dependencies';
-$string['onstage1action'] = 'Next';
-$string['onstage2action'] = 'Next';
-$string['onstage4action'] = 'Perform backup';
-$string['onstage8action'] = 'Continue';
-$string['onstage16action'] = 'Continue';
+$string['moodleversion'] = 'Moodle version';
+$string['originalwwwroot'] = 'URL of backup';
 $string['previousstage'] = 'Previous';
 $string['restoreactivity'] = 'Restore activity';
 $string['restorecourse'] = 'Restore course';
+$string['restorecoursesettings'] = 'Course settings';
+$string['restoreexecutionsuccess'] = 'The course was restored successfully, clicking the continue button below will take you to view the course you restored.';
+$string['restorenewcoursefullname'] = 'New course name';
+$string['restorenewcourseshortname'] = 'New course short name';
+$string['restorenewcoursestartdate'] = 'New start date';
+$string['restorerootsettings'] = 'Restore settings';
 $string['restoresection'] = 'Restore section';
+$string['restorestage1'] = 'Confirm';
+$string['restorestage1action'] = 'Next';
+$string['restorestage2'] = 'Destination';
+$string['restorestage2action'] = 'Next';
+$string['restorestage4'] = 'Settings';
+$string['restorestage4action'] = 'Next';
+$string['restorestage8'] = 'Schema';
+$string['restorestage8action'] = 'Next';
+$string['restorestage16'] = 'Review';
+$string['restorestage16action'] = 'Perform restore';
+$string['restorestage32'] = 'Process';
+$string['restorestage32action'] = 'Continue';
+$string['restorestage64'] = 'Complete';
+$string['restorestage64action'] = 'Continue';
+$string['restoretarget'] = 'Restore target';
+$string['restoretocourse'] = 'Restore to course: ';
+$string['restoretocurrentcourse'] = 'Restore into this course';
+$string['restoretocurrentcourseadding'] = 'Merge the backup course into this course';
+$string['restoretocurrentcoursedeleting'] = 'Delete the contents of this course and then restore';
+$string['restoretoexistingcourse'] = 'Restore into an existing course';
+$string['restoretoexistingcourseadding'] = 'Merge the backup course into the existing course';
+$string['restoretoexistingcoursedeleting'] = 'Delete the contents of the existing course and then restore';
+$string['restoretonewcourse'] = 'Restore as a new course';
+$string['restoringcourse'] = 'Course restoration in progress';
+$string['restoringcourseshortname'] = 'restoring';
 $string['rootsettings'] = 'Backup settings';
 $string['scheduledsettings'] = 'Scheduled backup settings';
+$string['sectionincanduser'] = 'Included in backup along with user information';
+$string['sectioninc'] = 'Included in backup (no user information)';
+$string['sectionactivities'] = 'Activities';
+$string['setting_overwriteconf'] = 'Overwrite course configuration';
+$string['setting_course_fullname'] = 'Course name';
+$string['setting_course_shortname'] = 'Course short name';
+$string['setting_course_startdate'] = 'Course startdate';
index 5ab75bb..59ce7b1 100644 (file)
@@ -2678,8 +2678,7 @@ class settings_navigation extends navigation_node {
 
         // Restore to this course
         if (has_capability('moodle/restore:restorecourse', $coursecontext)) {
-            $url = new moodle_url('/files/index.php', array('contextid'=>$coursecontext->id, 'itemid'=>0, 'component' => 'backup', 'filearea'=>'course'));
-            $url = null; // Disabled until restore is implemented. MDL-21432
+            $url = new moodle_url('/backup/restorefile.php', array('contextid'=>$coursecontext->id));
             $coursenode->add(get_string('restore'), $url, self::TYPE_SETTING, null, 'restore', new pix_icon('i/restore', ''));
         }
 
index b0e2a38..3129fbb 100644 (file)
@@ -634,5 +634,21 @@ body.tag .managelink {padding: 5px;}
 .dir-rtl .loginbox .loginform .form-label {float:right;text-align:left;}
 .dir-rtl .loginbox .loginform .form-input {text-align: right;}
 
+.backup-restore .backup-section {clear:both;border:1px solid #ddd;background-color:#f6f6f6;margin-bottom:1em;}
+.backup-restore .backup-section > h2.header {padding:5px 6px;margin:0;border-bottom:1px solid #ddd;}
+.backup-restore .backup-section .backup-sub-section {margin:0 25px;background-color:#f9f9f9;border:1px solid #f3f3f3;margin-bottom:1em;}
+.backup-restore .backup-section .backup-sub-section h3 {text-align:right;border-bottom:1px solid #DDD;padding:5px 86% 5px 6px;margin:0;background-color:#e9e9e9;}
+.backup-restore .backup-section.settings-section .detail-pair {margin:0;padding:0;width:50%;display:inline-block;}
+.backup-restore .backup-section.settings-section .detail-pair .detail-pair-label {width:65%;}
+.backup-restore .backup-section.settings-section .detail-pair .detail-pair-value {width:25%;}
+.backup-restore .activitytable {width:60%;min-width:500px;}
+.backup-restore .activitytable .modulename {width:100px;}
+.backup-restore .activitytable .moduleincluded {width:50px;}
+.backup-restore .activitytable .userinfoincluded {width:50px;}
+.backup-restore .detail-pair {}
+.backup-restore .detail-pair-label {display:inline-block;width:25%;padding:8px;margin:0;text-align:right;font-weight:bold;color:#444;vertical-align:top;}
+.backup-restore .detail-pair-value {display:inline-block;width:65%;padding:8px;margin:0;}
+.backup-restore .detail-pair-value > .sub-detail {display:block;color:#1580B6;margin-left:2em;font-size:90%;font-style: italic;}
+
 .corelightbox {background-color:#CCC;position:absolute;top:0;left:0;width:100%;height:100%;text-align:center;}
-.corelightbox img {position:fixed;top:50%;}
\ No newline at end of file
+.corelightbox img {position:fixed;top:50%;}