Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
/**
18
 * This file contains the restore user interface class
19
 *
20
 * @package   core_backup
21
 * @copyright 2010 Sam Hemelryk
22
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
 
25
/**
26
 * This is the restore user interface class
27
 *
28
 * The restore user interface class manages the user interface and restore for
29
 * Moodle.
30
 *
31
 * @package   core_backup
32
 * @copyright 2010 Sam Hemelryk
33
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
34
 */
35
class restore_ui extends base_ui {
36
    /**
37
     * The stages of the restore user interface.
38
     * Confirm the backup you are going to restore.
39
     */
40
    const STAGE_CONFIRM = 1;
41
 
42
    /**
43
     * The stages of the restore user interface.
44
     * Select the destination for the restore.
45
     */
46
    const STAGE_DESTINATION = 2;
47
 
48
    /**
49
     * The stages of the restore user interface.
50
     * Alter the setting for the restore.
51
     */
52
    const STAGE_SETTINGS = 4;
53
 
54
    /**
55
     * The stages of the restore user interface.
56
     * Alter and review the schema that you are going to restore.
57
     */
58
    const STAGE_SCHEMA = 8;
59
 
60
    /**
61
     * The stages of the restore user interface.
62
     * The final review before the restore is run.
63
     */
64
    const STAGE_REVIEW = 16;
65
 
66
    /**
67
     * The stages of the restore user interface.
68
     * The restore is in process right now.
69
     */
70
    const STAGE_PROCESS = 32;
71
 
72
    /**
73
     * The stages of the restore user interface.
74
     * The process is complete.
75
     */
76
    const STAGE_COMPLETE = 64;
77
 
78
    /**
79
     * The current UI stage.
80
     * @var restore_ui_stage
81
     */
82
    protected $stage = null;
83
 
84
    /**
85
     * @var \core\progress\base Progress indicator (where there is no controller)
86
     */
87
    protected $progressreporter = null;
88
 
89
    /**
90
     * String mappings to the above stages
91
     * @var array
92
     */
93
    public static $stages = array(
94
        restore_ui::STAGE_CONFIRM       => 'confirm',
95
        restore_ui::STAGE_DESTINATION   => 'destination',
96
        restore_ui::STAGE_SETTINGS      => 'settings',
97
        restore_ui::STAGE_SCHEMA        => 'schema',
98
        restore_ui::STAGE_REVIEW        => 'review',
99
        restore_ui::STAGE_PROCESS       => 'process',
100
        restore_ui::STAGE_COMPLETE      => 'complete'
101
    );
102
 
103
    /**
104
     * Intialises what ever stage is requested. If none are requested we check
105
     * params for 'stage' and default to initial
106
     *
107
     * @throws restore_ui_exception for an invalid stage
108
     * @param int|null $stage The desired stage to intialise or null for the default
109
     * @param array $params
110
     * @return restore_ui_stage_initial|restore_ui_stage_schema|restore_ui_stage_confirmation|restore_ui_stage_final
111
     */
112
    protected function initialise_stage($stage = null, array $params = null) {
113
        if ($stage == null) {
114
            $stage = optional_param('stage', self::STAGE_CONFIRM, PARAM_INT);
115
        }
116
        $class = 'restore_ui_stage_'.self::$stages[$stage];
117
        if (!class_exists($class)) {
118
            throw new restore_ui_exception('unknownuistage');
119
        }
120
        $stage = new $class($this, $params);
121
        return $stage;
122
    }
123
 
124
    /**
125
     * This processes the current stage of the restore
126
     * @throws restore_ui_exception if the progress is wrong.
127
     * @return bool
128
     */
129
    public function process() {
130
        if ($this->progress >= self::PROGRESS_PROCESSED) {
131
            throw new restore_ui_exception('restoreuialreadyprocessed');
132
        }
133
        $this->progress = self::PROGRESS_PROCESSED;
134
 
135
        if (optional_param('previous', false, PARAM_BOOL) && $this->stage->get_stage() > self::STAGE_CONFIRM) {
136
            $this->stage = $this->initialise_stage($this->stage->get_prev_stage(), $this->stage->get_params());
137
            return false;
138
        }
139
 
140
        // Process the stage.
141
        $processoutcome = $this->stage->process();
142
        if ($processoutcome !== false && !($this->get_stage() == self::STAGE_PROCESS && optional_param('substage', false, PARAM_BOOL))) {
143
            $this->stage = $this->initialise_stage($this->stage->get_next_stage(), $this->stage->get_params());
144
        }
145
 
146
        // Process UI event after to check changes are valid.
147
        $this->controller->process_ui_event();
148
        return $processoutcome;
149
    }
150
 
151
    /**
152
     * Returns true if the stage is independent (not requiring a restore controller)
153
     * @return bool
154
     */
155
    public function is_independent() {
156
        return false;
157
    }
158
 
159
    /**
160
     * Gets the unique ID associated with this UI
161
     * @return string
162
     */
163
    public function get_uniqueid() {
164
        return $this->get_restoreid();
165
    }
166
 
167
    /**
168
     * Gets the restore id from the controller
169
     * @return string
170
     */
171
    public function get_restoreid() {
172
        return $this->controller->get_restoreid();
173
    }
174
 
175
    /**
176
     * Gets the progress reporter object in use for this restore UI.
177
     *
178
     * IMPORTANT: This progress reporter is used only for UI progress that is
179
     * outside the restore controller. The restore controller has its own
180
     * progress reporter which is used for progress during the main restore.
181
     * Use the restore controller's progress reporter to report progress during
182
     * a restore operation, not this one.
183
     *
184
     * This extra reporter is necessary because on some restore UI screens,
185
     * there are long-running tasks even though there is no restore controller
186
     * in use.
187
     *
188
     * @return \core\progress\none
189
     */
190
    public function get_progress_reporter() {
191
        if (!$this->progressreporter) {
192
            $this->progressreporter = new \core\progress\none();
193
        }
194
        return $this->progressreporter;
195
    }
196
 
197
    /**
198
     * Sets the progress reporter that will be returned by get_progress_reporter.
199
     *
200
     * @param \core\progress\base $progressreporter Progress reporter
201
     */
202
    public function set_progress_reporter(\core\progress\base $progressreporter) {
203
        $this->progressreporter = $progressreporter;
204
    }
205
 
206
    /**
207
     * Executes the restore plan
208
     * @throws restore_ui_exception if the progress or stage is wrong.
209
     * @return bool
210
     */
211
    public function execute() {
212
        if ($this->progress >= self::PROGRESS_EXECUTED) {
213
            throw new restore_ui_exception('restoreuialreadyexecuted');
214
        }
215
        if ($this->stage->get_stage() < self::STAGE_PROCESS) {
216
            throw new restore_ui_exception('restoreuifinalisedbeforeexecute');
217
        }
218
 
219
        $this->controller->execute_plan();
220
        $this->progress = self::PROGRESS_EXECUTED;
221
        $this->stage = new restore_ui_stage_complete($this, $this->stage->get_params(), $this->controller->get_results());
222
        return true;
223
    }
224
 
225
    /**
226
     * Delete course which is created by restore process
227
     */
228
    public function cleanup() {
229
        global $DB;
230
        $courseid = $this->controller->get_courseid();
231
        if ($this->is_temporary_course_created($courseid) && $course = $DB->get_record('course', array('id' => $courseid))) {
232
            $course->deletesource = 'restore';
233
            delete_course($course, false);
234
        }
235
    }
236
 
237
    /**
238
     * Checks if the course is not restored fully and current controller has created it.
239
     * @param int $courseid id of the course which needs to be checked
240
     * @return bool
241
     */
242
    protected function is_temporary_course_created($courseid) {
243
        global $DB;
244
        // Check if current controller instance has created new course.
245
        if ($this->controller->get_target() == backup::TARGET_NEW_COURSE) {
246
            $results = $DB->record_exists_sql("SELECT bc.itemid
247
                                               FROM {backup_controllers} bc, {course} c
248
                                               WHERE bc.operation = 'restore'
249
                                                 AND bc.type = 'course'
250
                                                 AND bc.itemid = c.id
251
                                                 AND bc.itemid = ?",
252
                                               array($courseid)
253
                                             );
254
            return $results;
255
        }
256
        return false;
257
    }
258
 
259
    /**
260
     * Returns true if enforce_dependencies changed any settings
261
     * @return bool
262
     */
263
    public function enforce_changed_dependencies() {
264
        return ($this->dependencychanges > 0);
265
    }
266
 
267
    /**
268
     * Loads the restore controller if we are tracking one
269
     * @param string|bool $restoreid
270
     * @return string
271
     */
272
    final public static function load_controller($restoreid = false) {
273
        // Get the restore id optional param.
274
        if ($restoreid) {
275
            try {
276
                // Try to load the controller with it.
277
                // If it fails at this point it is likely because this is the first load.
278
                $controller = restore_controller::load_controller($restoreid);
279
                return $controller;
280
            } catch (Exception $e) {
281
                return false;
282
            }
283
        }
284
        return $restoreid;
285
    }
286
 
287
    /**
288
     * Initialised the requested independent stage
289
     *
290
     * @throws restore_ui_exception
291
     * @param int $stage One of self::STAGE_*
292
     * @param int $contextid
293
     * @return restore_ui_stage_confirm|restore_ui_stage_destination
294
     */
295
    final public static function engage_independent_stage($stage, $contextid) {
296
        if (!($stage & self::STAGE_CONFIRM + self::STAGE_DESTINATION)) {
297
            throw new restore_ui_exception('dependentstagerequested');
298
        }
299
        $class = 'restore_ui_stage_'.self::$stages[$stage];
300
        if (!class_exists($class)) {
301
            throw new restore_ui_exception('unknownuistage');
302
        }
303
        return new $class($contextid);
304
    }
305
 
306
    /**
307
     * Cancels the current restore and redirects the user back to the relevant place
308
     */
309
    public function cancel_process() {
310
        // Delete temporary restore course if exists.
311
        if ($this->controller->get_target() == backup::TARGET_NEW_COURSE) {
312
            $this->cleanup();
313
        }
314
        parent::cancel_process();
315
    }
316
 
317
    /**
318
     * Gets an array of progress bar items that can be displayed through the restore renderer.
319
     * @return array Array of items for the progress bar
320
     */
321
    public function get_progress_bar() {
322
        global $PAGE;
323
 
324
        $stage = self::STAGE_COMPLETE;
325
        $currentstage = $this->stage->get_stage();
326
        $items = array();
327
        while ($stage > 0) {
328
            $classes = array('backup_stage');
329
            if (floor($stage / 2) == $currentstage) {
330
                $classes[] = 'backup_stage_next';
331
            } else if ($stage == $currentstage) {
332
                $classes[] = 'backup_stage_current';
333
            } else if ($stage < $currentstage) {
334
                $classes[] = 'backup_stage_complete';
335
            }
336
            $item = array('text' => strlen(decbin($stage)).'. '.get_string('restorestage'.$stage, 'backup'), 'class' => join(' ', $classes));
337
            if ($stage < $currentstage && $currentstage < self::STAGE_COMPLETE && $stage > self::STAGE_DESTINATION) {
338
                $item['link'] = new moodle_url($PAGE->url, array('restore' => $this->get_restoreid(), 'stage' => $stage));
339
            }
340
            array_unshift($items, $item);
341
            $stage = floor($stage / 2);
342
        }
343
        return $items;
344
    }
345
 
346
    /**
347
     * Gets the name of this UI
348
     * @return string
349
     */
350
    public function get_name() {
351
        return 'restore';
352
    }
353
 
354
    /**
355
     * Gets the first stage for this UI
356
     * @return int STAGE_CONFIRM
357
     */
358
    public function get_first_stage_id() {
359
        return self::STAGE_CONFIRM;
360
    }
361
 
362
    /**
363
     * Returns true if this stage has substages of which at least one needs to be displayed
364
     * @return bool
365
     */
366
    public function requires_substage() {
367
        return ($this->stage->has_sub_stages() && !$this->stage->process());
368
    }
369
 
370
    /**
371
     * Displays this stage
372
     *
373
     * @throws base_ui_exception if the progress is wrong.
374
     * @param core_backup_renderer $renderer
375
     * @return string HTML code to echo
376
     */
377
    public function display(core_backup_renderer $renderer) {
378
        if ($this->progress < self::PROGRESS_SAVED) {
379
            throw new base_ui_exception('backupsavebeforedisplay');
380
        }
381
        return $this->stage->display($renderer);
382
    }
383
}
384
 
385
/**
386
 * Restore user interface exception. Modelled off the restore_exception class
387
 *
388
 * @package   core_backup
389
 * @copyright 2010 Sam Hemelryk
390
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
391
 */
392
class restore_ui_exception extends base_ui_exception {}