MDL-23407, the advlink plugin of tinymce should use external repositories only
[moodle.git] / backup / util / ui / restore_ui_stage.class.php
CommitLineData
785d6603
SH
1<?php
2
3
4// This file is part of Moodle - http://moodle.org/
5//
6// Moodle is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10//
11// Moodle is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
18
19/**
20 * restore user interface stages
21 *
22 * This file contains the classes required to manage the stages that make up the
23 * restore user interface.
24 * These will be primarily operated a {@see restore_ui} instance.
25 *
26 * @package moodlecore
27 * @copyright 2010 Sam Hemelryk
28 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
29 */
30
31/**
32 * Abstract stage class
33 *
34 * This class should be extended by all restore stages (a requirement of many restore ui functions).
35 * Each stage must then define two abstract methods
36 * - process : To process the stage
37 * - initialise_stage_form : To get a restore_moodleform instance for the stage
38 *
39 * @copyright 2010 Sam Hemelryk
40 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
41 */
42abstract class restore_ui_stage extends base_ui_stage {
43 /**
44 *
45 * @param restore_ui $ui
46 */
47 public function __construct(restore_ui $ui, array $params=null) {
48 $this->ui = $ui;
49 $this->params = $params;
50 }
51 /**
52 * The restore id from the restore controller
53 * @return string
54 */
55 final public function get_restoreid() {
56 return $this->get_uniqueid();
57 }
58
59 final public function is_independent() {
60 return false;
61 }
62
63 public function has_sub_stages() {
64 return false;
65 }
66
67 /**
68 * The name of this stage
69 * @return string
70 */
71 final public function get_name() {
72 return get_string('restorestage'.$this->stage,'backup');
73 }
39bc4c6f
SH
74 final public function is_first_stage() {
75 return $this->stage == restore_ui::STAGE_SETTINGS;
76 }
785d6603
SH
77}
78
79abstract class restore_ui_independent_stage {
80 abstract public function __construct($contextid);
81 abstract public function process();
82 abstract public function display($renderer);
83 abstract public function get_stage();
84 /**
85 * Gets an array of progress bar items that can be displayed through the restore renderer.
86 * @return array Array of items for the progress bar
87 */
88 public function get_progress_bar() {
89 global $PAGE;
90 $stage = restore_ui::STAGE_COMPLETE;
91 $currentstage = $this->get_stage();
92 $items = array();
93 while ($stage > 0) {
94 $classes = array('backup_stage');
95 if (floor($stage/2) == $currentstage) {
96 $classes[] = 'backup_stage_next';
97 } else if ($stage == $currentstage) {
98 $classes[] = 'backup_stage_current';
99 } else if ($stage < $currentstage) {
100 $classes[] = 'backup_stage_complete';
101 }
102 $item = array('text' => strlen(decbin($stage)).'. '.get_string('restorestage'.$stage, 'backup'),'class' => join(' ', $classes));
103 if ($stage < $currentstage && $currentstage < restore_ui::STAGE_COMPLETE) {
104 //$item['link'] = new moodle_url($PAGE->url, array('restore'=>$this->get_restoreid(), 'stage'=>$stage));
105 }
106 array_unshift($items, $item);
107 $stage = floor($stage/2);
108 }
109 return $items;
110 }
111 abstract public function get_stage_name();
112 final public function is_independent() {
113 return true;
114 }
115}
116
117class restore_ui_stage_confirm extends restore_ui_independent_stage {
118 protected $contextid;
119 protected $filename = null;
120 protected $filepath = null;
121 protected $details;
122 public function __construct($contextid) {
123 $this->contextid = $contextid;
124 $this->filename = required_param('filename', PARAM_FILE);
125 }
126 public function process() {
127 global $CFG;
128 if (!file_exists("$CFG->dataroot/temp/backup/".$this->filename)) {
129 throw new restore_ui_exception('invalidrestorefile');
130 }
39bc4c6f
SH
131 $outcome = $this->extract_file_to_dir();
132 if ($outcome) {
133 fulldelete($this->filename);
134 }
135 return $outcome;
785d6603
SH
136 }
137 protected function extract_file_to_dir() {
138 global $CFG, $USER;
139
140 $this->filepath = restore_controller::get_tempdir_name($this->contextid, $USER->id);
141
142 $fb = get_file_packer();
143 return ($fb->extract_to_pathname("$CFG->dataroot/temp/backup/".$this->filename, "$CFG->dataroot/temp/backup/$this->filepath/"));
144 }
145 public function display($renderer) {
146 $this->details = backup_general_helper::get_backup_information($this->filepath);
147 return $renderer->backup_details($this->details, new moodle_url('/backup/restore.php', array('contextid'=>$this->contextid, 'filepath'=>$this->filepath, 'stage'=>restore_ui::STAGE_DESTINATION)));
148 }
149 public function get_stage_name() {
150 return get_string('restorestage'.restore_ui::STAGE_CONFIRM, 'backup');
151 }
152 public function get_stage() {
153 return restore_ui::STAGE_CONFIRM;
154 }
155}
156
157class restore_ui_stage_destination extends restore_ui_independent_stage {
158 protected $contextid;
159 protected $filepath = null;
160 protected $details;
161 protected $courseid = null;
39bc4c6f 162 protected $target = backup::TARGET_NEW_COURSE;
785d6603
SH
163 public function __construct($contextid) {
164 $this->contextid = $contextid;
165 $this->filepath = required_param('filepath', PARAM_ALPHANUM);
166 }
167 public function process() {
168 global $CFG, $DB;
169 if (!file_exists("$CFG->dataroot/temp/backup/".$this->filepath) || !is_dir("$CFG->dataroot/temp/backup/".$this->filepath)) {
170 throw new restore_ui_exception('invalidrestorepath');
171 }
39bc4c6f
SH
172 $this->target = optional_param('target', backup::TARGET_NEW_COURSE, PARAM_INT);
173 $targetid = optional_param('targetid', null, PARAM_INT);
174 if (!is_null($this->target) && !is_null($targetid) && confirm_sesskey()) {
175 if ($this->target == backup::TARGET_NEW_COURSE) {
785d6603
SH
176 list($fullname, $shortname) = restore_dbops::calculate_course_names(0, get_string('restoringcourse', 'backup'), get_string('restoringcourseshortname', 'backup'));
177 $this->courseid = restore_dbops::create_new_course($fullname, $shortname, $targetid);
178 } else {
179 $this->courseid = $targetid;
180 }
181 return ($DB->record_exists('course', array('id'=>$this->courseid)));
182 }
183 return false;
184 }
185 /**
186 *
187 * @global moodle_database $DB
188 * @param core_backup_renderer $renderer
189 * @return string
190 */
191 public function display($renderer) {
39bc4c6f 192 global $DB, $USER;
785d6603
SH
193 $this->details = backup_general_helper::get_backup_information($this->filepath);
194 $url = new moodle_url('/backup/restore.php', array('contextid'=>$this->contextid, 'filepath'=>$this->filepath, 'stage'=>restore_ui::STAGE_SETTINGS));
39bc4c6f 195
785d6603 196 $context = get_context_instance_by_id($this->contextid);
39bc4c6f
SH
197 $currentcourse = ($context->contextlevel == CONTEXT_COURSE && has_capability('moodle/restore:restorecourse', $context))?$context->instanceid:false;
198
785d6603 199 $courselist = array();
39bc4c6f 200 $courses = get_user_capability_course('moodle/restore:restorecourse', $USER->id, true, 'fullname,shortname,visible,sortorder');
785d6603
SH
201 foreach ($courses as $course) {
202 $courselist[$course->id] = $course->fullname.' ['.$course->shortname.']';
203 }
39bc4c6f
SH
204
205 $categories = make_categories_options();
206 foreach ($categories as $categoryid=>$category) {
207 if (!has_capability('moodle/course:create', get_context_instance(CONTEXT_COURSECAT, $categoryid))) {
208 unset($categories[$categoryid]);
209 }
210 }
211
212 $html = $renderer->course_selector($url, $this->details, $categories, $courselist, $currentcourse);
785d6603
SH
213 return $html;
214 }
215 public function get_stage_name() {
216 return get_string('restorestage'.restore_ui::STAGE_DESTINATION, 'backup');
217 }
218 public function get_filepath() {
219 return $this->filepath;
220 }
221 public function get_course_id() {
222 return $this->courseid;
223 }
224 public function get_stage() {
225 return restore_ui::STAGE_DESTINATION;
226 }
39bc4c6f
SH
227 public function get_target() {
228 return $this->target;
229 }
785d6603
SH
230}
231
232class restore_ui_stage_settings extends restore_ui_stage {
233 /**
234 * Initial restore stage constructor
235 * @param restore_ui $ui
236 */
237 public function __construct(restore_ui $ui, array $params=null) {
238 $this->stage = restore_ui::STAGE_SETTINGS;
239 parent::__construct($ui, $params);
240 }
241
242 public function process(base_moodleform $form=null) {
243 $form = $this->initialise_stage_form();
244
245 if ($form->is_cancelled()) {
246 $this->ui->cancel_restore();
247 }
248
249 $data = $form->get_data();
250 if ($data && confirm_sesskey()) {
251 $tasks = $this->ui->get_tasks();
252 $changes = 0;
253 foreach ($tasks as &$task) {
254 // We are only interesting in the backup root task for this stage
255 if ($task instanceof restore_root_task || $task instanceof restore_course_task) {
256 // Get all settings into a var so we can iterate by reference
257 $settings = $task->get_settings();
258 foreach ($settings as &$setting) {
259 $name = $setting->get_ui_name();
260 if (isset($data->$name) && $data->$name != $setting->get_value()) {
261 $setting->set_value($data->$name);
262 $changes++;
263 } else if (!isset($data->$name) && $setting->get_ui_type() == backup_setting::UI_HTML_CHECKBOX && $setting->get_value()) {
264 $setting->set_value(0);
265 $changes++;
266 }
267 }
268 }
269 }
270 // Return the number of changes the user made
271 return $changes;
272 } else {
273 return false;
274 }
275 }
276
277 protected function initialise_stage_form() {
278 global $PAGE;
279 if ($this->stageform === null) {
280 $form = new restore_settings_form($this, $PAGE->url);
281 // Store as a variable so we can iterate by reference
282 $tasks = $this->ui->get_tasks();
283 $headingprinted = false;
284 // Iterate all tasks by reference
285 foreach ($tasks as &$task) {
286 // For the initial stage we are only interested in the root settings
287 if ($task instanceof restore_root_task) {
288 if (!$headingprinted) {
289 $form->add_heading('rootsettings', get_string('restorerootsettings', 'backup'));
290 $headingprinted = true;
291 }
292 $settings = $task->get_settings();
293 // First add all settings except the filename setting
294 foreach ($settings as &$setting) {
295 if ($setting->get_name() == 'filename') {
296 continue;
297 }
298 $form->add_setting($setting, $task);
299 }
300 // Then add all dependencies
301 foreach ($settings as &$setting) {
302 if ($setting->get_name() == 'filename') {
303 continue;
304 }
305 $form->add_dependencies($setting);
306 }
307 }
308 }
309 $this->stageform = $form;
310 }
311 // Return the form
312 return $this->stageform;
313 }
314}
315
316/**
317 * Schema stage of backup process
318 *
319 * During the schema stage the user is required to set the settings that relate
320 * to the area that they are backing up as well as its children.
321 *
322 * @copyright 2010 Sam Hemelryk
323 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
324 */
325class restore_ui_stage_schema extends restore_ui_stage {
326 /**
327 * Schema stage constructor
328 * @param backup_moodleform $ui
329 */
330 public function __construct(restore_ui $ui, array $params=null) {
331 $this->stage = restore_ui::STAGE_SCHEMA;
332 parent::__construct($ui, $params);
333 }
334 /**
335 * Processes the schema stage
336 *
337 * @param backup_moodleform|null $form
338 * @return int The number of changes the user made
339 */
340 public function process(base_moodleform $form = null) {
341 $form = $this->initialise_stage_form();
342 // Check it wasn't cancelled
343 if ($form->is_cancelled()) {
344 $this->ui->cancel_backup();
345 }
346
347 // Check it has been submit
348 $data = $form->get_data();
349 if ($data && confirm_sesskey()) {
350 // Get the tasks into a var so we can iterate by reference
351 $tasks = $this->ui->get_tasks();
352 $changes = 0;
353 // Iterate all tasks by reference
354 foreach ($tasks as &$task) {
355 // We are only interested in schema settings
356 if (!($task instanceof restore_root_task)) {
357 // Store as a variable so we can iterate by reference
358 $settings = $task->get_settings();
359 // Iterate by reference
360 foreach ($settings as &$setting) {
361 $name = $setting->get_ui_name();
362 if (isset($data->$name) && $data->$name != $setting->get_value()) {
363 $setting->set_value($data->$name);
364 $changes++;
365 } else if (!isset($data->$name) && $setting->get_ui_type() == backup_setting::UI_HTML_CHECKBOX && $setting->get_value()) {
366 $setting->set_value(0);
367 $changes++;
368 }
369 }
370 }
371 }
372 // Return the number of changes the user made
373 return $changes;
374 } else {
375 return false;
376 }
377 }
378 /**
379 * Creates the backup_schema_form instance for this stage
380 *
381 * @return backup_schema_form
382 */
383 protected function initialise_stage_form() {
384 global $PAGE;
385 if ($this->stageform === null) {
386 $form = new restore_schema_form($this, $PAGE->url);
387 $tasks = $this->ui->get_tasks();
388 $content = '';
389 $courseheading = false;
390 foreach ($tasks as $task) {
391 if (!($task instanceof restore_root_task)) {
392 if (!$courseheading) {
393 // If we havn't already display a course heading to group nicely
394 $form->add_heading('coursesettings', get_string('coursesettings', 'backup'));
395 $courseheading = true;
396 }
397 // First add each setting
398 foreach ($task->get_settings() as $setting) {
399 $form->add_setting($setting, $task);
400 }
401 // The add all the dependencies
402 foreach ($task->get_settings() as $setting) {
403 $form->add_dependencies($setting);
404 }
405 } else if ($this->ui->enforce_changed_dependencies()) {
406 // Only show these settings if dependencies changed them.
407 // Add a root settings heading to group nicely
408 $form->add_heading('rootsettings', get_string('rootsettings', 'backup'));
409 // Iterate all settings and add them to the form as a fixed
410 // setting. We only want schema settings to be editable
411 foreach ($task->get_settings() as $setting) {
412 if ($setting->get_name() != 'filename') {
413 $form->add_fixed_setting($setting);
414 }
415 }
416 }
417 }
418 $this->stageform = $form;
419 }
420 return $this->stageform;
421 }
422}
423
424/**
425 * Confirmation stage
426 *
427 * On this stage the user reviews the setting for the backup and can change the filename
428 * of the file that will be generated.
429 *
430 * @copyright 2010 Sam Hemelryk
431 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
432 */
433class restore_ui_stage_review extends restore_ui_stage {
434 /**
435 * Constructs the stage
436 * @param backup_ui $ui
437 */
438 public function __construct($ui, array $params=null) {
439 $this->stage = restore_ui::STAGE_REVIEW;
440 parent::__construct($ui, $params);
441 }
442 /**
443 * Processes the confirmation stage
444 *
445 * @param backup_moodleform $form
446 * @return int The number of changes the user made
447 */
448 public function process(base_moodleform $form = null) {
449 $form = $this->initialise_stage_form();
450 // Check it hasn't been cancelled
451 if ($form->is_cancelled()) {
452 $this->ui->cancel_backup();
453 }
454
455 $data = $form->get_data();
456 if ($data && confirm_sesskey()) {
457 return 0;
458 } else {
459 return false;
460 }
461 }
462 /**
463 * Creates the backup_confirmation_form instance this stage requires
464 *
465 * @return backup_confirmation_form
466 */
467 protected function initialise_stage_form() {
468 global $PAGE;
469 if ($this->stageform === null) {
470 // Get the form
471 $form = new restore_review_form($this, $PAGE->url);
472 $content = '';
473 $courseheading = false;
474
475 foreach ($this->ui->get_tasks() as $task) {
476 if ($task instanceof restore_root_task) {
477 // If its a backup root add a root settings heading to group nicely
478 $form->add_heading('rootsettings', get_string('rootsettings', 'backup'));
479 } else if (!$courseheading) {
480 // we havn't already add a course heading
481 $form->add_heading('coursesettings', get_string('coursesettings', 'backup'));
482 $courseheading = true;
483 }
484 // Iterate all settings, doesnt need to happen by reference
485 foreach ($task->get_settings() as $setting) {
486 $form->add_fixed_setting($setting);
487 }
488 }
489 $this->stageform = $form;
490 }
491 return $this->stageform;
492 }
493}
494
495/**
496 * Final stage of backup
497 *
498 * This stage is special in that it is does not make use of a form. The reason for
499 * this is the order of procession of backup at this stage.
500 * The processesion is:
501 * 1. The final stage will be intialise.
502 * 2. The confirmation stage will be processed.
503 * 3. The backup will be executed
504 * 4. The complete stage will be loaded by execution
505 * 5. The complete stage will be displayed
506 *
507 * This highlights that we neither need a form nor a display method for this stage
508 * we simply need to process.
509 *
510 * @copyright 2010 Sam Hemelryk
511 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
512 */
513class restore_ui_stage_process extends restore_ui_stage {
514
515 const SUBSTAGE_NONE = 0;
516 const SUBSTAGE_CONVERT = 1;
517 const SUBSTAGE_PRECHECKS = 2;
518
519 protected $substage = 0;
520
521 /**
522 * Constructs the final stage
523 * @param backup_ui $ui
524 */
525 public function __construct(base_ui $ui, array $params=null) {
526 $this->stage = restore_ui::STAGE_PROCESS;
527 parent::__construct($ui, $params);
528 }
529 /**
530 * Processes the final stage.
531 *
532 * In this case it checks to see if there is a sub stage that we need to display
533 * before execution, if there is we gear up to display the subpage, otherwise
534 * we return true which will lead to execution of the restore and the loading
535 * of the completed stage.
536 */
537 public function process(base_moodleform $form=null) {
538 $rc = $this->ui->get_controller();
539 if ($rc->get_status() == backup::STATUS_REQUIRE_CONV) {
540 $this->substage = self::SUBSTAGE_CONVERT;
541 } else {
542 if ($rc->get_status() == backup::STATUS_SETTING_UI) {
543 $rc->finish_ui();
544 }
545 if ($rc->get_status() == backup::STATUS_NEED_PRECHECK && !$rc->execute_precheck(true)) {
546 $this->substage = self::SUBSTAGE_PRECHECKS;
547 }
548 }
549 return empty($this->substage);
550 }
551 /**
552 * should NEVER be called... throws an exception
553 */
554 protected function initialise_stage_form() {
555 throw new backup_ui_exception('backup_ui_must_execute_first');
556 }
557 /**
558 * should NEVER be called... throws an exception
559 */
560 public function display($renderer) {
561 global $PAGE;
562 switch ($this->substage) {
563 case self::SUBSTAGE_CONVERT :
564 echo '<h2>Need to show the conversion screens here</h2>';
565 break;
566 case self::SUBSTAGE_PRECHECKS :
567 $results = $this->ui->get_controller()->get_precheck_results();
568 echo $renderer->precheck_notices($results);
569 break;
570 default:
571 throw new restore_ui_exception('backup_ui_must_execute_first');
572 }
573 echo $renderer->continue_button(new moodle_url($PAGE->url, array('restore'=>$this->get_uniqueid(), 'stage'=>restore_ui::STAGE_PROCESS, 'substage'=>$this->substage)));
574 }
575
576 public function has_sub_stages() {
577 return true;
578 }
579}
580
581class restore_ui_stage_complete extends restore_ui_stage_process {
582 /**
583 * The results of the backup execution
584 * @var array
585 */
586 protected $results;
587 /**
588 * Constructs the complete backup stage
589 * @param backup_ui $ui
590 * @param array|null $params
591 * @param array $results
592 */
593 public function __construct(restore_ui $ui, array $params=null, array $results=null) {
594 $this->results = $results;
595 parent::__construct($ui, $params);
596 $this->stage = restore_ui::STAGE_COMPLETE;
597 }
598 /**
599 * Displays the completed backup stage.
600 *
601 * Currently this just envolves redirecting to the file browser with an
602 * appropriate message.
603 *
604 * @global core_renderer $OUTPUT
39bc4c6f 605 * @param core_backup_renderer $renderer
785d6603 606 */
39bc4c6f 607 public function display(core_backup_renderer $renderer) {
785d6603
SH
608 global $OUTPUT;
609 echo $OUTPUT->box_start();
610 echo $OUTPUT->notification(get_string('restoreexecutionsuccess', 'backup'), 'notifysuccess');
39bc4c6f 611 echo $renderer->continue_button(new moodle_url('/course/view.php', array('id'=>$this->get_ui()->get_controller()->get_courseid())), 'get');
785d6603
SH
612 echo $OUTPUT->box_end();
613 }
614}