Merge branch 'MDL-22309_master' of git://github.com/dmonllao/moodle
[moodle.git] / backup / util / ui / renderer.php
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/>.
17 /**
18  * This file contains backup and restore output renderers
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  */
25 /**
26  * The primary renderer for the backup.
27  *
28  * Can be retrieved with the following code:
29  * <?php
30  * $renderer = $PAGE->get_renderer('core', 'backup');
31  * ?>
32  *
33  * @package   core_backup
34  * @copyright 2010 Sam Hemelryk
35  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
36  */
37 class core_backup_renderer extends plugin_renderer_base {
39     /**
40      * Renderers a progress bar for the backup or restore given the items that make it up.
41      *
42      * @param array $items An array of items
43      * @return string
44      */
45     public function progress_bar(array $items) {
46         foreach ($items as &$item) {
47             $text = $item['text'];
48             unset($item['text']);
49             if (array_key_exists('link', $item)) {
50                 $link = $item['link'];
51                 unset($item['link']);
52                 $item = html_writer::link($link, $text, $item);
53             } else {
54                 $item = html_writer::tag('span', $text, $item);
55             }
56         }
57         return html_writer::tag('div', join(get_separator(), $items), array('class' => 'backup_progress clearfix'));
58     }
60     /**
61      * The backup and restore pages may display a log (if any) in a scrolling box.
62      *
63      * @param string $loghtml Log content in HTML format
64      * @return string HTML content that shows the log
65      */
66     public function log_display($loghtml) {
67         global $OUTPUT;
68         $out = html_writer::start_div('backup_log');
69         $out .= $OUTPUT->heading(get_string('backuplog', 'backup'));
70         $out .= html_writer::start_div('backup_log_contents');
71         $out .= $loghtml;
72         $out .= html_writer::end_div();
73         $out .= html_writer::end_div();
74         return $out;
75     }
77     /**
78      * Prints a dependency notification
79      *
80      * @param string $message
81      * @return string
82      */
83     public function dependency_notification($message) {
84         return html_writer::tag('div', $message, array('class' => 'notification dependencies_enforced'));
85     }
87     /**
88      * Displays the details of a backup file
89      *
90      * @param stdClass $details
91      * @param moodle_url $nextstageurl
92      * @return string
93      */
94     public function backup_details($details, $nextstageurl) {
95         $yestick = $this->output->pix_icon('i/valid', get_string('yes'));
96         $notick = $this->output->pix_icon('i/invalid', get_string('no'));
98         $html  = html_writer::start_tag('div', array('class' => 'backup-restore'));
100         $html .= html_writer::start_tag('div', array('class' => 'backup-section'));
101         $html .= $this->output->heading(get_string('backupdetails', 'backup'), 2, array('class' => 'header'));
102         $html .= $this->backup_detail_pair(get_string('backuptype', 'backup'), get_string('backuptype'.$details->type, 'backup'));
103         $html .= $this->backup_detail_pair(get_string('backupformat', 'backup'), get_string('backupformat'.$details->format, 'backup'));
104         $html .= $this->backup_detail_pair(get_string('backupmode', 'backup'), get_string('backupmode'.$details->mode, 'backup'));
105         $html .= $this->backup_detail_pair(get_string('backupdate', 'backup'), userdate($details->backup_date));
106         $html .= $this->backup_detail_pair(get_string('moodleversion', 'backup'),
107                 html_writer::tag('span', $details->moodle_release, array('class' => 'moodle_release')).
108                 html_writer::tag('span', '['.$details->moodle_version.']', array('class' => 'moodle_version sub-detail')));
109         $html .= $this->backup_detail_pair(get_string('backupversion', 'backup'),
110                 html_writer::tag('span', $details->backup_release, array('class' => 'moodle_release')).
111                 html_writer::tag('span', '['.$details->backup_version.']', array('class' => 'moodle_version sub-detail')));
112         $html .= $this->backup_detail_pair(get_string('originalwwwroot', 'backup'),
113                 html_writer::tag('span', $details->original_wwwroot, array('class' => 'originalwwwroot')).
114                 html_writer::tag('span', '['.$details->original_site_identifier_hash.']', array('class' => 'sitehash sub-detail')));
115         if (!empty($details->include_file_references_to_external_content)) {
116             $message = '';
117             if (backup_general_helper::backup_is_samesite($details)) {
118                 $message = $yestick . ' ' . get_string('filereferencessamesite', 'backup');
119             } else {
120                 $message = $notick . ' ' . get_string('filereferencesnotsamesite', 'backup');
121             }
122             $html .= $this->backup_detail_pair(get_string('includefilereferences', 'backup'), $message);
123         }
125         $html .= html_writer::end_tag('div');
127         $html .= html_writer::start_tag('div', array('class' => 'backup-section settings-section'));
128         $html .= $this->output->heading(get_string('backupsettings', 'backup'), 2, array('class' => 'header'));
129         foreach ($details->root_settings as $label => $value) {
130             if ($label == 'filename' or $label == 'user_files') {
131                 continue;
132             }
133             $html .= $this->backup_detail_pair(get_string('rootsetting'.str_replace('_', '', $label), 'backup'), $value ? $yestick : $notick);
134         }
135         $html .= html_writer::end_tag('div');
137         if ($details->type === 'course') {
138             $html .= html_writer::start_tag('div', array('class' => 'backup-section'));
139             $html .= $this->output->heading(get_string('backupcoursedetails', 'backup'), 2, array('class' => 'header'));
140             $html .= $this->backup_detail_pair(get_string('coursetitle', 'backup'), $details->course->title);
141             $html .= $this->backup_detail_pair(get_string('courseid', 'backup'), $details->course->courseid);
143             // Warning users about front page backups.
144             if ($details->original_course_format === 'site') {
145                 $html .= $this->backup_detail_pair(get_string('type_format', 'plugin'), get_string('sitecourseformatwarning', 'backup'));
146             }
147             $html .= html_writer::start_tag('div', array('class' => 'backup-sub-section'));
148             $html .= $this->output->heading(get_string('backupcoursesections', 'backup'), 3, array('class' => 'subheader'));
149             foreach ($details->sections as $key => $section) {
150                 $included = $key.'_included';
151                 $userinfo = $key.'_userinfo';
152                 if ($section->settings[$included] && $section->settings[$userinfo]) {
153                     $value = get_string('sectionincanduser', 'backup');
154                 } else if ($section->settings[$included]) {
155                     $value = get_string('sectioninc', 'backup');
156                 } else {
157                     continue;
158                 }
159                 $html .= $this->backup_detail_pair(get_string('backupcoursesection', 'backup', $section->title), $value);
160                 $table = null;
161                 foreach ($details->activities as $activitykey => $activity) {
162                     if ($activity->sectionid != $section->sectionid) {
163                         continue;
164                     }
165                     if (empty($table)) {
166                         $table = new html_table();
167                         $table->head = array(get_string('module', 'backup'), get_string('title', 'backup'), get_string('userinfo', 'backup'));
168                         $table->colclasses = array('modulename', 'moduletitle', 'userinfoincluded');
169                         $table->align = array('left', 'left', 'center');
170                         $table->attributes = array('class' => 'activitytable generaltable');
171                         $table->data = array();
172                     }
173                     $name = get_string('pluginname', $activity->modulename);
174                     $icon = new pix_icon('icon', $name, $activity->modulename, array('class' => 'iconlarge icon-pre'));
175                     $table->data[] = array(
176                         $this->output->render($icon).$name,
177                         $activity->title,
178                         ($activity->settings[$activitykey.'_userinfo']) ? $yestick : $notick,
179                     );
180                 }
181                 if (!empty($table)) {
182                     $html .= $this->backup_detail_pair(get_string('sectionactivities', 'backup'), html_writer::table($table));
183                 }
185             }
186             $html .= html_writer::end_tag('div');
187             $html .= html_writer::end_tag('div');
188         }
190         $html .= $this->output->single_button($nextstageurl, get_string('continue'), 'post');
191         $html .= html_writer::end_tag('div');
193         return $html;
194     }
196     /**
197      * Displays the general information about a backup file with non-standard format
198      *
199      * @param moodle_url $nextstageurl URL to send user to
200      * @param array $details basic info about the file (format, type)
201      * @return string HTML code to display
202      */
203     public function backup_details_nonstandard($nextstageurl, array $details) {
205         $html  = html_writer::start_tag('div', array('class' => 'backup-restore nonstandardformat'));
206         $html .= html_writer::start_tag('div', array('class' => 'backup-section'));
207         $html .= $this->output->heading(get_string('backupdetails', 'backup'), 2, 'header');
208         $html .= $this->output->box(get_string('backupdetailsnonstandardinfo', 'backup'), 'noticebox');
209         $html .= $this->backup_detail_pair(
210             get_string('backupformat', 'backup'),
211             get_string('backupformat'.$details['format'], 'backup'));
212         $html .= $this->backup_detail_pair(
213             get_string('backuptype', 'backup'),
214             get_string('backuptype'.$details['type'], 'backup'));
215         $html .= html_writer::end_tag('div');
216         $html .= $this->output->single_button($nextstageurl, get_string('continue'), 'post');
217         $html .= html_writer::end_tag('div');
219         return $html;
220     }
222     /**
223      * Displays the general information about a backup file with unknown format
224      *
225      * @param moodle_url $nextstageurl URL to send user to
226      * @return string HTML code to display
227      */
228     public function backup_details_unknown(moodle_url $nextstageurl) {
230         $html  = html_writer::start_div('unknownformat');
231         $html .= $this->output->heading(get_string('errorinvalidformat', 'backup'), 2);
232         $html .= $this->output->notification(get_string('errorinvalidformatinfo', 'backup'), 'notifyproblem');
233         $html .= $this->output->single_button($nextstageurl, get_string('continue'), 'post');
234         $html .= html_writer::end_div();
236         return $html;
237     }
239     /**
240      * Displays a course selector for restore
241      *
242      * @param moodle_url $nextstageurl
243      * @param bool $wholecourse true if we are restoring whole course (as with backup::TYPE_1COURSE), false otherwise
244      * @param restore_category_search $categories
245      * @param restore_course_search $courses
246      * @param int $currentcourse
247      * @return string
248      */
249     public function course_selector(moodle_url $nextstageurl, $wholecourse = true, restore_category_search $categories = null,
250                                     restore_course_search $courses = null, $currentcourse = null) {
251         global $CFG, $PAGE;
252         require_once($CFG->dirroot.'/course/lib.php');
254         // These variables are used to check if the form using this function was submitted.
255         $target = optional_param('target', false, PARAM_INT);
256         $targetid = optional_param('targetid', null, PARAM_INT);
258         // Check if they submitted the form but did not provide all the data we need.
259         $missingdata = false;
260         if ($target and is_null($targetid)) {
261             $missingdata = true;
262         }
264         $nextstageurl->param('sesskey', sesskey());
266         $form = html_writer::start_tag('form', array('method' => 'post', 'action' => $nextstageurl->out_omit_querystring(),
267             'class' => 'mform'));
268         foreach ($nextstageurl->params() as $key => $value) {
269             $form .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => $key, 'value' => $value));
270         }
272         $hasrestoreoption = false;
274         $html  = html_writer::start_tag('div', array('class' => 'backup-course-selector backup-restore'));
275         if ($wholecourse && !empty($categories) && ($categories->get_count() > 0 || $categories->get_search())) {
276             // New course.
277             $hasrestoreoption = true;
278             $html .= $form;
279             $html .= html_writer::start_tag('div', array('class' => 'bcs-new-course backup-section'));
280             $html .= $this->output->heading(get_string('restoretonewcourse', 'backup'), 2, array('class' => 'header'));
281             $html .= $this->backup_detail_input(get_string('restoretonewcourse', 'backup'), 'radio', 'target',
282                 backup::TARGET_NEW_COURSE, array('checked' => 'checked'));
283             $selectacategoryhtml = $this->backup_detail_pair(get_string('selectacategory', 'backup'), $this->render($categories));
284             // Display the category selection as required if the form was submitted but this data was not supplied.
285             if ($missingdata && $target == backup::TARGET_NEW_COURSE) {
286                 $html .= html_writer::span(get_string('required'), 'error');
287                 $html .= html_writer::start_tag('fieldset', array('class' => 'error'));
288                 $html .= $selectacategoryhtml;
289                 $html .= html_writer::end_tag('fieldset');
290             } else {
291                 $html .= $selectacategoryhtml;
292             }
293             $html .= $this->backup_detail_pair('', html_writer::empty_tag('input', array('type' => 'submit', 'value' => get_string('continue'))));
294             $html .= html_writer::end_tag('div');
295             $html .= html_writer::end_tag('form');
296         }
298         if ($wholecourse && !empty($currentcourse)) {
299             // Current course.
300             $hasrestoreoption = true;
301             $html .= $form;
302             $html .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'targetid', 'value' => $currentcourse));
303             $html .= html_writer::start_tag('div', array('class' => 'bcs-current-course backup-section'));
304             $html .= $this->output->heading(get_string('restoretocurrentcourse', 'backup'), 2, array('class' => 'header'));
305             $html .= $this->backup_detail_input(get_string('restoretocurrentcourseadding', 'backup'), 'radio', 'target',
306                 backup::TARGET_CURRENT_ADDING, array('checked' => 'checked'));
307             $html .= $this->backup_detail_input(get_string('restoretocurrentcoursedeleting', 'backup'), 'radio', 'target',
308                 backup::TARGET_CURRENT_DELETING);
309             $html .= $this->backup_detail_pair('', html_writer::empty_tag('input', array('type' => 'submit', 'value' => get_string('continue'))));
310             $html .= html_writer::end_tag('div');
311             $html .= html_writer::end_tag('form');
312         }
314         // If we are restoring an activity, then include the current course.
315         if (!$wholecourse) {
316             $courses->invalidate_results(); // Clean list of courses.
317             $courses->set_include_currentcourse();
318         }
319         if (!empty($courses) && ($courses->get_count() > 0 || $courses->get_search())) {
320             // Existing course.
321             $hasrestoreoption = true;
322             $html .= $form;
323             $html .= html_writer::start_tag('div', array('class' => 'bcs-existing-course backup-section'));
324             $html .= $this->output->heading(get_string('restoretoexistingcourse', 'backup'), 2, array('class' => 'header'));
325             if ($wholecourse) {
326                 $html .= $this->backup_detail_input(get_string('restoretoexistingcourseadding', 'backup'), 'radio', 'target',
327                     backup::TARGET_EXISTING_ADDING, array('checked' => 'checked'));
328                 $html .= $this->backup_detail_input(get_string('restoretoexistingcoursedeleting', 'backup'), 'radio', 'target',
329                     backup::TARGET_EXISTING_DELETING);
330             } else {
331                 $html .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'target', 'value' => backup::TARGET_EXISTING_ADDING));
332             }
333             $selectacoursehtml = $this->backup_detail_pair(get_string('selectacourse', 'backup'), $this->render($courses));
334             // Display the course selection as required if the form was submitted but this data was not supplied.
335             if ($missingdata && $target == backup::TARGET_EXISTING_ADDING) {
336                 $html .= html_writer::span(get_string('required'), 'error');
337                 $html .= html_writer::start_tag('fieldset', array('class' => 'error'));
338                 $html .= $selectacoursehtml;
339                 $html .= html_writer::end_tag('fieldset');
340             } else {
341                 $html .= $selectacoursehtml;
342             }
343             $html .= $this->backup_detail_pair('', html_writer::empty_tag('input', array('type' => 'submit', 'value' => get_string('continue'))));
344             $html .= html_writer::end_tag('div');
345             $html .= html_writer::end_tag('form');
346         }
348         if (!$hasrestoreoption) {
349             echo $this->output->notification(get_string('norestoreoptions', 'backup'));
350         }
352         $html .= html_writer::end_tag('div');
353         return $html;
354     }
356     /**
357      * Displays the import course selector
358      *
359      * @param moodle_url $nextstageurl
360      * @param import_course_search $courses
361      * @return string
362      */
363     public function import_course_selector(moodle_url $nextstageurl, import_course_search $courses = null) {
364         $html  = html_writer::start_tag('div', array('class' => 'import-course-selector backup-restore'));
365         $html .= html_writer::start_tag('form', array('method' => 'post', 'action' => $nextstageurl->out_omit_querystring()));
366         foreach ($nextstageurl->params() as $key => $value) {
367             $html .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => $key, 'value' => $value));
368         }
369         // We only allow import adding for now. Enforce it here.
370         $html .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'target', 'value' => backup::TARGET_CURRENT_ADDING));
371         $html .= html_writer::start_tag('div', array('class' => 'ics-existing-course backup-section'));
372         $html .= $this->output->heading(get_string('importdatafrom'), 2, array('class' => 'header'));
373         $html .= $this->backup_detail_pair(get_string('selectacourse', 'backup'), $this->render($courses));
374         $html .= $this->backup_detail_pair('', html_writer::empty_tag('input', array('type' => 'submit', 'value' => get_string('continue'))));
375         $html .= html_writer::end_tag('div');
376         $html .= html_writer::end_tag('form');
377         $html .= html_writer::end_tag('div');
378         return $html;
379     }
381     /**
382      * Creates a detailed pairing (key + value)
383      *
384      * @staticvar int $count
385      * @param string $label
386      * @param string $value
387      * @return string
388      */
389     protected function backup_detail_pair($label, $value) {
390         static $count = 0;
391         $count ++;
392         $html  = html_writer::start_tag('div', array('class' => 'detail-pair'));
393         $html .= html_writer::tag('label', $label, array('class' => 'detail-pair-label', 'for' => 'detail-pair-value-'.$count));
394         $html .= html_writer::tag('div', $value, array('class' => 'detail-pair-value', 'name' => 'detail-pair-value-'.$count));
395         $html .= html_writer::end_tag('div');
396         return $html;
397     }
399     /**
400      * Created a detailed pairing with an input
401      *
402      * @param string $label
403      * @param string $type
404      * @param string $name
405      * @param string $value
406      * @param array $attributes
407      * @param string|null $description
408      * @return string
409      */
410     protected function backup_detail_input($label, $type, $name, $value, array $attributes = array(), $description = null) {
411         if (!empty($description)) {
412             $description = html_writer::tag('span', $description, array('class' => 'description'));
413         } else {
414             $description = '';
415         }
416         return $this->backup_detail_pair(
417             $label,
418             html_writer::empty_tag('input', $attributes + array('name' => $name, 'type' => $type, 'value' => $value)) . $description
419         );
420     }
422     /**
423      * Creates a detailed pairing with a select
424      *
425      * @param string $label
426      * @param string $name
427      * @param array $options
428      * @param string $selected
429      * @param bool $nothing
430      * @param array $attributes
431      * @param string|null $description
432      * @return string
433      */
434     protected function backup_detail_select($label, $name, $options, $selected = '', $nothing = false, array $attributes = array(), $description = null) {
435         if (!empty ($description)) {
436             $description = html_writer::tag('span', $description, array('class' => 'description'));
437         } else {
438             $description = '';
439         }
440         return $this->backup_detail_pair($label, html_writer::select($options, $name, $selected, false, $attributes).$description);
441     }
443     /**
444      * Displays precheck notices
445      *
446      * @param array $results
447      * @return string
448      */
449     public function precheck_notices($results) {
450         $output = html_writer::start_tag('div', array('class' => 'restore-precheck-notices'));
451         if (array_key_exists('errors', $results)) {
452             foreach ($results['errors'] as $error) {
453                 $output .= $this->output->notification($error);
454             }
455         }
456         if (array_key_exists('warnings', $results)) {
457             foreach ($results['warnings'] as $warning) {
458                 $output .= $this->output->notification($warning, 'notifyproblem');
459             }
460         }
461         return $output.html_writer::end_tag('div');
462     }
464     /**
465      * Displays substage buttons
466      *
467      * @param bool $haserrors
468      * @return string
469      */
470     public function substage_buttons($haserrors) {
471         $output  = html_writer::start_tag('div', array('continuebutton'));
472         if (!$haserrors) {
473             $output .= html_writer::empty_tag('input', array('type' => 'submit', 'value' => get_string('continue')));
474         }
475         $output .= html_writer::empty_tag('input', array('type' => 'submit', 'name' => 'cancel', 'value' => get_string('cancel')));
476         $output .= html_writer::end_tag('div');
477         return $output;
478     }
480     /**
481      * Displays a role mapping interface
482      *
483      * @param array $rolemappings
484      * @param array $roles
485      * @return string
486      */
487     public function role_mappings($rolemappings, $roles) {
488         $roles[0] = get_string('none');
489         $output  = html_writer::start_tag('div', array('class' => 'restore-rolemappings'));
490         $output .= $this->output->heading(get_string('restorerolemappings', 'backup'), 2);
491         foreach ($rolemappings as $id => $mapping) {
492             $label = $mapping->name;
493             $name = 'mapping'.$id;
494             $selected = $mapping->targetroleid;
495             $output .= $this->backup_detail_select($label, $name, $roles, $mapping->targetroleid, false, array(), $mapping->description);
496         }
497         $output .= html_writer::end_tag('div');
498         return $output;
499     }
501     /**
502      * Displays a continue button
503      *
504      * @param string|moodle_url $url
505      * @param string $method
506      * @return string
507      */
508     public function continue_button($url, $method = 'post') {
509         if (!($url instanceof moodle_url)) {
510             $url = new moodle_url($url);
511         }
512         if ($method != 'post') {
513             $method = 'get';
514         }
515         $url->param('sesskey', sesskey());
516         $button = new single_button($url, get_string('continue'), $method);
517         $button->class = 'continuebutton';
518         return $this->render($button);
519     }
520     /**
521      * Print a backup files tree
522      * @param array $options
523      * @return string
524      */
525     public function backup_files_viewer(array $options = null) {
526         $files = new backup_files_viewer($options);
527         return $this->render($files);
528     }
530     /**
531      * Displays a backup files viewer
532      *
533      * @global stdClass $USER
534      * @param backup_files_viewer $viewer
535      * @return string
536      */
537     public function render_backup_files_viewer(backup_files_viewer $viewer) {
538         global $CFG;
539         $files = $viewer->files;
541         $table = new html_table();
542         $table->attributes['class'] = 'backup-files-table generaltable';
543         $table->head = array(get_string('filename', 'backup'), get_string('time'), get_string('size'), get_string('download'), get_string('restore'));
544         $table->width = '100%';
545         $table->data = array();
547         foreach ($files as $file) {
548             if ($file->is_directory()) {
549                 continue;
550             }
551             $fileurl = moodle_url::make_pluginfile_url(
552                 $file->get_contextid(),
553                 $file->get_component(),
554                 $file->get_filearea(),
555                 null,
556                 $file->get_filepath(),
557                 $file->get_filename(),
558                 true
559             );
560             $params = array();
561             $params['action'] = 'choosebackupfile';
562             $params['filename'] = $file->get_filename();
563             $params['filepath'] = $file->get_filepath();
564             $params['component'] = $file->get_component();
565             $params['filearea'] = $file->get_filearea();
566             $params['filecontextid'] = $file->get_contextid();
567             $params['contextid'] = $viewer->currentcontext->id;
568             $params['itemid'] = $file->get_itemid();
569             $restoreurl = new moodle_url('/backup/restorefile.php', $params);
570             $table->data[] = array(
571                 $file->get_filename(),
572                 userdate($file->get_timemodified()),
573                 display_size($file->get_filesize()),
574                 html_writer::link($fileurl, get_string('download')),
575                 html_writer::link($restoreurl, get_string('restore')),
576                 );
577         }
579         $html = html_writer::table($table);
580         $html .= $this->output->single_button(
581             new moodle_url('/backup/backupfilesedit.php', array(
582                 'currentcontext' => $viewer->currentcontext->id,
583                 'contextid' => $viewer->filecontext->id,
584                 'filearea' => $viewer->filearea,
585                 'component' => $viewer->component,
586                 'returnurl' => $this->page->url->out())
587             ),
588             get_string('managefiles', 'backup'),
589             'post'
590         );
592         return $html;
593     }
595     /**
596      * Renders a restore course search object
597      *
598      * @param restore_course_search $component
599      * @return string
600      */
601     public function render_restore_course_search(restore_course_search $component) {
602         $url = $component->get_url();
604         $output = html_writer::start_tag('div', array('class' => 'restore-course-search'));
605         $output .= html_writer::start_tag('div', array('class' => 'rcs-results'));
607         $table = new html_table();
608         $table->head = array('', get_string('shortnamecourse'), get_string('fullnamecourse'));
609         $table->data = array();
610         if ($component->get_count() !== 0) {
611             foreach ($component->get_results() as $course) {
612                 $row = new html_table_row();
613                 $row->attributes['class'] = 'rcs-course';
614                 if (!$course->visible) {
615                     $row->attributes['class'] .= ' dimmed';
616                 }
617                 $row->cells = array(
618                     html_writer::empty_tag('input', array('type' => 'radio', 'name' => 'targetid', 'value' => $course->id)),
619                     format_string($course->shortname, true, array('context' => context_course::instance($course->id))),
620                     format_string($course->fullname, true, array('context' => context_course::instance($course->id)))
621                 );
622                 $table->data[] = $row;
623             }
624             if ($component->has_more_results()) {
625                 $cell = new html_table_cell(get_string('moreresults', 'backup'));
626                 $cell->colspan = 3;
627                 $cell->attributes['class'] = 'notifyproblem';
628                 $row = new html_table_row(array($cell));
629                 $row->attributes['class'] = 'rcs-course';
630                 $table->data[] = $row;
631             }
632         } else {
633             $cell = new html_table_cell(get_string('nomatchingcourses', 'backup'));
634             $cell->colspan = 3;
635             $cell->attributes['class'] = 'notifyproblem';
636             $row = new html_table_row(array($cell));
637             $row->attributes['class'] = 'rcs-course';
638             $table->data[] = $row;
639         }
640         $output .= html_writer::table($table);
641         $output .= html_writer::end_tag('div');
643         $output .= html_writer::start_tag('div', array('class' => 'rcs-search'));
644         $output .= html_writer::empty_tag('input', array('type' => 'text', 'name' => restore_course_search::$VAR_SEARCH, 'value' => $component->get_search()));
645         $output .= html_writer::empty_tag('input', array('type' => 'submit', 'name' => 'searchcourses', 'value' => get_string('search')));
646         $output .= html_writer::end_tag('div');
648         $output .= html_writer::end_tag('div');
649         return $output;
650     }
652     /**
653      * Renders an import course search object
654      *
655      * @param import_course_search $component
656      * @return string
657      */
658     public function render_import_course_search(import_course_search $component) {
659         $url = $component->get_url();
661         $output = html_writer::start_tag('div', array('class' => 'import-course-search'));
662         if ($component->get_count() === 0) {
663             $output .= $this->output->notification(get_string('nomatchingcourses', 'backup'));
665             $output .= html_writer::start_tag('div', array('class' => 'ics-search'));
666             $output .= html_writer::empty_tag('input', array('type' => 'text', 'name' => restore_course_search::$VAR_SEARCH, 'value' => $component->get_search()));
667             $output .= html_writer::empty_tag('input', array('type' => 'submit', 'name' => 'searchcourses', 'value' => get_string('search')));
668             $output .= html_writer::end_tag('div');
670             $output .= html_writer::end_tag('div');
671             return $output;
672         }
674         $countstr = '';
675         if ($component->has_more_results()) {
676             $countstr = get_string('morecoursesearchresults', 'backup', $component->get_count());
677         } else {
678             $countstr = get_string('totalcoursesearchresults', 'backup', $component->get_count());
679         }
681         $output .= html_writer::tag('div', $countstr, array('class' => 'ics-totalresults'));
682         $output .= html_writer::start_tag('div', array('class' => 'ics-results'));
684         $table = new html_table();
685         $table->head = array('', get_string('shortnamecourse'), get_string('fullnamecourse'));
686         $table->data = array();
687         foreach ($component->get_results() as $course) {
688             $row = new html_table_row();
689             $row->attributes['class'] = 'ics-course';
690             if (!$course->visible) {
691                 $row->attributes['class'] .= ' dimmed';
692             }
693             $row->cells = array(
694                 html_writer::empty_tag('input', array('type' => 'radio', 'name' => 'importid', 'value' => $course->id)),
695                 format_string($course->shortname, true, array('context' => context_course::instance($course->id))),
696                 format_string($course->fullname, true, array('context' => context_course::instance($course->id)))
697             );
698             $table->data[] = $row;
699         }
700         if ($component->has_more_results()) {
701             $cell = new html_table_cell(get_string('moreresults', 'backup'));
702             $cell->colspan = 3;
703             $cell->attributes['class'] = 'notifyproblem';
704             $row = new html_table_row(array($cell));
705             $row->attributes['class'] = 'rcs-course';
706             $table->data[] = $row;
707         }
708         $output .= html_writer::table($table);
709         $output .= html_writer::end_tag('div');
711         $output .= html_writer::start_tag('div', array('class' => 'ics-search'));
712         $output .= html_writer::empty_tag('input', array('type' => 'text', 'name' => restore_course_search::$VAR_SEARCH, 'value' => $component->get_search()));
713         $output .= html_writer::empty_tag('input', array('type' => 'submit', 'name' => 'searchcourses', 'value' => get_string('search')));
714         $output .= html_writer::end_tag('div');
716         $output .= html_writer::end_tag('div');
717         return $output;
718     }
720     /**
721      * Renders a restore category search object
722      *
723      * @param restore_category_search $component
724      * @return string
725      */
726     public function render_restore_category_search(restore_category_search $component) {
727         $url = $component->get_url();
729         $output = html_writer::start_tag('div', array('class' => 'restore-course-search'));
730         $output .= html_writer::start_tag('div', array('class' => 'rcs-results'));
732         $table = new html_table();
733         $table->head = array('', get_string('name'), get_string('description'));
734         $table->data = array();
736         if ($component->get_count() !== 0) {
737             foreach ($component->get_results() as $category) {
738                 $row = new html_table_row();
739                 $row->attributes['class'] = 'rcs-course';
740                 if (!$category->visible) {
741                     $row->attributes['class'] .= ' dimmed';
742                 }
743                 $row->cells = array(
744                     html_writer::empty_tag('input', array('type' => 'radio', 'name' => 'targetid', 'value' => $category->id)),
745                     format_string($category->name, true, array('context' => context_coursecat::instance($category->id))),
746                     format_text($category->description, $category->descriptionformat, array('overflowdiv' => true))
747                 );
748                 $table->data[] = $row;
749             }
750             if ($component->has_more_results()) {
751                 $cell = new html_table_cell(get_string('moreresults', 'backup'));
752                 $cell->attributes['class'] = 'notifyproblem';
753                 $cell->colspan = 3;
754                 $row = new html_table_row(array($cell));
755                 $row->attributes['class'] = 'rcs-course';
756                 $table->data[] = $row;
757             }
758         } else {
759             $cell = new html_table_cell(get_string('nomatchingcourses', 'backup'));
760             $cell->colspan = 3;
761             $cell->attributes['class'] = 'notifyproblem';
762             $row = new html_table_row(array($cell));
763             $row->attributes['class'] = 'rcs-course';
764             $table->data[] = $row;
765         }
766         $output .= html_writer::table($table);
767         $output .= html_writer::end_tag('div');
769         $output .= html_writer::start_tag('div', array('class' => 'rcs-search'));
770         $output .= html_writer::empty_tag('input', array('type' => 'text', 'name' => restore_category_search::$VAR_SEARCH, 'value' => $component->get_search()));
771         $output .= html_writer::empty_tag('input', array('type' => 'submit', 'name' => 'searchcourses', 'value' => get_string('search')));
772         $output .= html_writer::end_tag('div');
774         $output .= html_writer::end_tag('div');
775         return $output;
776     }
779 /**
780  * Data structure representing backup files viewer
781  *
782  * @copyright 2010 Dongsheng Cai
783  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
784  * @since     Moodle 2.0
785  */
786 class backup_files_viewer implements renderable {
788     /**
789      * @var array
790      */
791     public $files;
793     /**
794      * @var context
795      */
796     public $filecontext;
798     /**
799      * @var string
800      */
801     public $component;
803     /**
804      * @var string
805      */
806     public $filearea;
808     /**
809      * @var context
810      */
811     public $currentcontext;
813     /**
814      * Constructor of backup_files_viewer class
815      * @param array $options
816      */
817     public function __construct(array $options = null) {
818         global $CFG, $USER;
819         $fs = get_file_storage();
820         $this->currentcontext = $options['currentcontext'];
821         $this->filecontext    = $options['filecontext'];
822         $this->component      = $options['component'];
823         $this->filearea       = $options['filearea'];
824         $files = $fs->get_area_files($this->filecontext->id, $this->component, $this->filearea, false, 'timecreated');
825         $this->files = array_reverse($files);
826     }