# This patch file was generated by NetBeans IDE
# This patch can be applied using context Tools: Apply Diff Patch action on respective folder.
# It uses platform neutral UTF-8 encoding.
# Above lines and this line are ignored by the patching process.
Index: moodle/backup/backup.php
--- moodle/backup/backup.php Base (1.72)
+++ moodle/backup/backup.php Locally Modified (Based On 1.72)
@@ -85,6 +85,7 @@
 $backup->process();
 if ($backup->get_stage() == backup_ui::STAGE_FINAL) {
     $backup->execute();
+    redirect(new moodle_url($PAGE->url, array('backup'=>$backupid, 'stage'=>backup_ui::STAGE_COMPLETE)));
\ No newline at end of file
 } else {
     $backup->save_controller();
 }
Index: moodle/backup/util/helper/backup_progress_helper.class.php
--- moodle/backup/util/helper/backup_progress_helper.class.php No Base Revision
+++ moodle/backup/util/helper/backup_progress_helper.class.php Locally New
@@ -0,0 +1,160 @@
+<?php
+
+class backup_progress_helper {
+
+    const STAGE_WAITINGPREP = 0;
+    const STAGE_PREPARING = 1;
+    const STAGE_PREPARED = 2;
+    const STAGE_OUTPUT = 3;
+    const STAGE_UPDATING = 4;
+    const STAGE_COMPLETE = 5;
+
+
+    protected $stage = 0;
+    
+    protected $totalsteps = 0;
+    protected $totaltasks = 0;
+
+    protected $currentstep = null;
+    protected $currenttask = null;
+    protected $currenttasksteps = 0;
+
+    protected $currenttaskpercentage = null;
+
+    public static function get_instance() {
+        static $instance;
+        if (empty($instance)) {
+            $instance = new backup_progress_helper();
+        }
+        return $instance;
+    }
+
+    public static function start_task($task, $steps) {
+        $instance = backup_progress_helper::get_instance();
+        $instance->_start_task($task, $steps);
+    }
+
+    public static function complete_task() {
+        $instance = backup_progress_helper::get_instance();
+        $instance->_complete_task();
+    }
+
+    public static function complete() {
+        $instance = backup_progress_helper::get_instance();
+        $instance->_complete();
+    }
+
+    public static function increment() {
+        $instance = backup_progress_helper::get_instance();
+        $instance->_increment();
+    }
+
+    public function prepare($tasks) {
+        $this->set_stage(self::STAGE_PREPARING);
+        $this->totaltasks = $tasks;
+        $this->set_stage(self::STAGE_PREPARED);
+    }
+
+    public function set_stage($stage) {
+        switch ($stage) {
+            case self::STAGE_WAITINGPREP :
+            case self::STAGE_PREPARING :
+                $this->totaltasks = 0;
+                $this->totalsteps = 0;
+                $this->currenttask = null;
+                $this->stage = $stage;
+                break;
+            case self::STAGE_PREPARED :
+                break;
+        }
+        $this->stage = $stage;
+    }
+
+    /**
+     *
+     * @param moodle_page $currentpage
+     */
+    public function output(moodle_page $currentpage) {
+
+        $page = new moodle_page();
+        $page->set_url($currentpage->url);
+        $page->set_context($currentpage->context);
+        $page->set_course($currentpage->course);
+        $page->set_pagelayout('maintenance');
+        $page->set_title(get_string('backupprogress', 'backup'));
+        $page->set_heading($page->title);
+
+        $config = new stdClass;
+        $config->overallProgressID = 'overall-progress';
+        $config->currentTaskProgressID = 'current-task-progress';
+        $config->overallTotal = $this->totaltasks;
+        $page->requires->yui_module('moodle-backup-progressmanager', 'M.core_backup.init_progressmanager', array($config));
+
+        $output = $page->get_renderer('core');
+
+        echo $output->header();
+        if (!empty($heading)) {
+            echo $output->heading($heading);
+        }
+
+        echo html_writer::start_tag('div', array('class'=>'backup-progress'));
+
+        echo $output->heading(get_string('overallprogress', 'backup'), 3);
+        echo html_writer::start_tag('div', array('id'=>$config->overallProgressID, 'class'=>'overall-progress progress-bar'));
+        echo html_writer::tag('div', '', array('class'=>$config->overallProgressID.'-meter progress-meter'));
+        echo html_writer::tag('div', '0 %', array('class'=>'progress-percentage'));
+        echo html_writer::end_tag('div');
+
+        echo $output->heading(get_string('currenttaskprogress', 'backup'), 3);
+        echo html_writer::start_tag('div', array('id'=>$config->currentTaskProgressID, 'class'=>'current-task-progress progress-bar'));
+        echo html_writer::tag('div', '', array('class'=>$config->currentTaskProgressID.'-meter progress-meter'));
+        echo html_writer::tag('div', '0 %', array('class'=>'progress-percentage'));
+        echo html_writer::tag('div', '', array('class'=>'current-task-name'));
+        echo html_writer::end_tag('div');
+
+        echo html_writer::end_tag('div');
+
+        echo $output->footer();
+
+        flush();
+        ob_flush();
+    }
+
+    public function _start_task($task, $steps) {
+        $this->currenttask = $task;
+        $this->currentstep = 0;
+        $this->currenttasksteps = $steps;
+        $jscode = 'M.core_backup.progressmanager.startTask('.  json_encode($task).');';
+        echo html_writer::script($jscode);
+        flush();
+        ob_flush();
+    }
+
+    public function _increment() {
+        $this->currentstep++;
+        $newpercentage = round($this->currentstep / $this->currenttasksteps, 0);
+        if ($newpercentage <= $this->currenttaskpercentage) {
+            return;
+        }
+        $this->currenttaskpercentage = $newpercentage;
+        $jscode = 'M.core_backup.progressmanager.progressCurrentTask('+(float)$this->currenttaskpercentage+');';
+        echo html_writer::script($jscode);
+        flush();
+        ob_flush();
+    }
+
+    public function _complete_task() {
+        $jscode = 'M.core_backup.progressmanager.completeCurrentTask();';
+        echo html_writer::script($jscode);
+        flush();
+        ob_flush();
+    }
+
+    public function _complete() {
+        $jscode = 'M.core_backup.progressmanager.complete();';
+        echo html_writer::script($jscode);
+        flush();
+        ob_flush();
+    }
+
+}
\ No newline at end of file
Index: moodle/backup/util/includes/backup_includes.php
--- moodle/backup/util/includes/backup_includes.php Base (1.5)
+++ moodle/backup/util/includes/backup_includes.php Locally Modified (Based On 1.5)
@@ -60,6 +60,7 @@
 require_once($CFG->dirroot . '/backup/util/helper/backup_array_iterator.class.php');
 require_once($CFG->dirroot . '/backup/util/helper/backup_anonymizer_helper.class.php');
 require_once($CFG->dirroot . '/backup/util/helper/backup_file_manager.class.php');
+require_once($CFG->dirroot . '/backup/util/helper/backup_progress_helper.class.php');
 require_once($CFG->dirroot . '/backup/util/xml/xml_writer.class.php');
 require_once($CFG->dirroot . '/backup/util/xml/output/xml_output.class.php');
 require_once($CFG->dirroot . '/backup/util/xml/output/file_xml_output.class.php');
Index: moodle/backup/util/plan/base_task.class.php
--- moodle/backup/util/plan/base_task.class.php Base (1.5)
+++ moodle/backup/util/plan/base_task.class.php Locally Modified (Based On 1.5)
@@ -145,14 +145,17 @@
         if ($this->executed) {
             throw new base_task_exception('base_task_already_executed', $this->name);
         }
+        backup_progress_helper::start_task(get_class($this), count($this->steps));
         foreach ($this->steps as $step) {
             $result = $step->execute();
+            backup_progress_helper::increment();
             // If step returns array, it will be forwarded to plan
             // (TODO: shouldn't be array but proper result object)
             if (is_array($result) and !empty($result)) {
                 $this->plan->add_result($result);
             }
         }
+        backup_progress_helper::complete_task();
         // Mark as executed if any step has been executed
         if (!empty($this->steps)) {
             $this->executed = true;
Index: moodle/backup/util/ui/backup_ui.class.php
--- moodle/backup/util/ui/backup_ui.class.php Base (1.8)
+++ moodle/backup/util/ui/backup_ui.class.php Locally Modified (Based On 1.8)
@@ -75,6 +75,9 @@
             case backup_ui::STAGE_FINAL:
                 $stage = new backup_ui_stage_final($this, $params);
                 break;
+            case backup_ui::STAGE_COMPLETE:
+                $stage = new backup_ui_stage_complete($this, $params, $this->controller->get_results());
+                break;
             default:
                 $stage = false;
                 break;
@@ -100,6 +103,8 @@
      * @return bool
      */
     public function execute() {
+        global $PAGE;
+
         if ($this->progress >= self::PROGRESS_EXECUTED) {
             throw new backup_ui_exception('backupuialreadyexecuted');
         }
@@ -108,8 +113,15 @@
         }
         $this->progress = self::PROGRESS_EXECUTED;
         $this->controller->finish_ui();
+
+        $progress = backup_progress_helper::get_instance();
+        $progress->prepare(count($this->controller->get_plan()->get_tasks()));
+        $progress->output($PAGE);
+
         $this->controller->execute_plan();
-        $this->stage = new backup_ui_stage_complete($this, $this->stage->get_params(), $this->controller->get_results());
\ No newline at end of file
+
+        $progress->complete();
+
\ No newline at end of file
         return true;
     }
     /**
Index: moodle/backup/util/ui/backup_ui_stage.class.php
--- moodle/backup/util/ui/backup_ui_stage.class.php Base (1.14)
+++ moodle/backup/util/ui/backup_ui_stage.class.php Locally Modified (Based On 1.14)
@@ -473,4 +473,14 @@
         echo $OUTPUT->continue_button($restorerul);
         echo $OUTPUT->box_end();
     }
+
+    /**
+     * You can never go past complete!
+     *
+     * @param base_moodleform $form
+     * @return true
+     */
+    public function process(base_moodleform $form=null) {
+        return false;
 }
+}
Index: moodle/backup/util/ui/progress_manager.js
--- moodle/backup/util/ui/progress_manager.js No Base Revision
+++ moodle/backup/util/ui/progress_manager.js Locally New
@@ -0,0 +1,6 @@
+/* 
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+
Index: moodle/backup/util/ui/yui/progressmanager/progressmanager.js
--- moodle/backup/util/ui/yui/progressmanager/progressmanager.js No Base Revision
+++ moodle/backup/util/ui/yui/progressmanager/progressmanager.js Locally New
@@ -0,0 +1,97 @@
+YUI.add('moodle-backup-progressmanager', function(Y) {
+
+var PROGRESS = function(config) {
+    PROGRESS.superclass.constructor.apply(this, arguments);
+}
+PROGRESS.prototype = {
+    overallProgressNode : null,
+    currentTaskProgressNode : null,
+    initializer : function(config) {
+        this.set('startTime', new Date().getTime());
+        this.overallProgressNode = Y.one('#'+config.overallProgressID);
+        this.overallProgressNode.one('.progress-meter').setStyle('width', '0');
+
+        this.currentTaskProgressNode = Y.one('#'+config.currentTaskProgressID);
+        this.overallProgressNode.one('.progress-meter').setStyle('width', '0');
+
+        var progressupdate = function(e) {
+            this.one('.progress-meter').setStyle('width', e.newVal.toString()+'%');
+            this.one('.progress-percentage').setContent(Math.round(e.newVal).toString()+' %');
+        }
+
+        this.after('overallProgressChange', progressupdate, this.overallProgressNode);
+        this.after('currentTaskProgressChange', progressupdate, this.currentTaskProgressNode);
+    },
+    startTask : function(taskName) {
+        if (this.get('currentTaskProgress') < 100) {
+            this.completeCurrentTask();
+        }
+        this.currentTaskProgressNode.one('.current-task-name').setContent(taskName);
+        this.set('currentTaskProgress', 0);
+    },
+    progressCurrentTask : function(percentage) {
+        this.set('currentTaskProgress', parseFloat(percentage));
+    },
+    completeCurrentTask : function() {
+        var oc = parseFloat(this.get('overallComplete')) + 1;
+        var ot = parseFloat(this.get('overallTotal'));
+        this.set('overallComplete', oc);
+        this.set('overallProgress', (oc / ot)*100);
+        this.set('currentTaskProgress', 100);
+    },
+    complete : function() {
+        this.completeCurrentTask();
+        var ot = parseFloat(this.get('overallTotal'));
+        this.set('overallComplete', ot);
+    }
+}
+
+Y.extend(PROGRESS, Y.Base, PROGRESS.prototype, {
+    NAME : 'progress-manager',
+    ATTRS : {
+        startTime : {
+            validator : Y.Lang.isInt
+        },
+        lastUpdate : {
+            validator : Y.Lang.isInt
+        },
+        currentTaskProgress : {
+            value : 0,
+            setter : function(newval) {
+                newval = Math.round(parseInt(newval));
+                if (newval < 0) {
+                    return 0;
+                } else if (newval > 100) {
+                    return 100;
+                }
+                return newval;
+            }
+        },
+        overallTotal : {
+            value : 0
+        },
+        overallComplete : {
+            value : 0
+        },
+        overallProgress : {
+            value : 0,
+            setter : function(newval) {
+                newval = Math.round(parseInt(newval));
+                if (newval < 0) {
+                    return 0;
+                } else if (newval > 100) {
+                    return 100;
+                }
+                return newval;
+            }
+        }
+    }
+});
+
+M.core_backup = M.core_backup || {};
+M.core_backup.progressmanager = null;
+M.core_backup.init_progressmanager = function(config) {
+    M.core_backup.progressmanager = new PROGRESS(config);
+}
+
+}, '@VERSION@', {'requires':['base','node']});
\ No newline at end of file
Index: moodle/lang/en/backup.php
--- moodle/lang/en/backup.php Base (1.30)
+++ moodle/lang/en/backup.php Locally Modified (Based On 1.30)
@@ -47,6 +47,7 @@
 $string['backupmode'] = 'Mode';
 $string['backupmode10'] = 'General';
 $string['backupmode30'] = 'Hub';
+$string['backupprogress'] = 'Backup progress';
 $string['backupsection'] = 'Backup course section: {$a}';
 $string['backupsettings'] = 'Backup settings';
 $string['backupsitedetails'] = 'Site details';
@@ -93,6 +94,7 @@
 $string['currentstage4'] = 'Confirmation and review';
 $string['currentstage8'] = 'Perform backup';
 $string['currentstage16'] = 'Complete';
+$string['currenttaskprogress'] = 'Current task progress';
 $string['dependenciesenforced'] = 'Your settings have been altered due to unmet dependencies';
 $string['enterasearch'] = 'Enter a search';
 $string['errorfilenamerequired'] = 'You must enter a valid filename for this backup';
@@ -148,6 +150,7 @@
 $string['nomatchingcourses'] = 'There are no courses to display';
 $string['norestoreoptions'] = 'There are no categories or existing courses you can restore to.';
 $string['originalwwwroot'] = 'URL of backup';
+$string['overallprogress'] = 'Overall progress';
 $string['previousstage'] = 'Previous';
 $string['qcategory2coursefallback'] = 'The questions category "{$a->name}", originally at system/course category context in backup file, will be created at course context by restore';
 $string['qcategorycannotberestored'] = 'The questions category "{$a->name}" cannot be created by restore';
Index: moodle/theme/base/style/core.css
--- moodle/theme/base/style/core.css Base (1.75)
+++ moodle/theme/base/style/core.css Locally Modified (Based On 1.75)
@@ -686,3 +686,9 @@
  */
 .yui3-skin-sam .yui3-menu-horizontal .yui3-menu-label,
 .yui3-skin-sam .yui3-menu-horizontal .yui3-menu-content {background-image:none;}
+
+.path-backup .progress-bar {width:80%;margin:5px auto;border:1px solid #000;background-color:#E2ECF0;position:relative;height:24px;}
+.path-backup .progress-bar .progress-meter {background-color:#007FB9;width:0;height:24px;}
+.path-backup .progress-bar .progress-percentage {position:relative;top:-24px;height:24px;width:100%;text-align:center;font-weight:bold;}
+.path-backup .progress-bar.current-task-progress .progress-percentage {height:12px;font-size:9px;line-height:12px;}
+.path-backup .progress-bar.current-task-progress .current-task-name {position:relative;top:-24px;height:12px;width:100%;font-size:9px;line-height:12px;text-align:center;}
