930c936d992640430ae620eab98a1d670aee8299
[moodle.git] / mod / data / preset.php
1 <?php
3 // This file is part of Moodle - http://moodle.org/
4 //
5 // Moodle is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // Moodle is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
18 /**
19  * Preset Menu
20  *
21  * This is the page that is the menu item in the config database
22  * pages.
23  *
24  * This file is part of the Database module for Moodle
25  *
26  * @copyright 2005 Martin Dougiamas  http://dougiamas.com
27  * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
28  * @package mod-data
29  */
31 require_once('../../config.php');
32 require_once('lib.php');
33 require_once($CFG->libdir.'/xmlize.php');
35 $id       = optional_param('id', 0, PARAM_INT);    // course module id
36 $d        = optional_param('d', 0, PARAM_INT);     // database activity id
37 $action   = optional_param('action', 'base', PARAM_ALPHANUM); // current action
38 $fullname = optional_param('fullname', '', PARAM_PATH); // directory the preset is in
39 $file     = optional_param('file', '', PARAM_PATH); // uploaded file
41 $url = new moodle_url('/mod/data/preset.php');
42 if ($action !== 'base') {
43     $url->param('action', $action);
44 }
45 if ($fullname !== '') {
46     $url->param('fullname', $fullname);
47 }
48 if ($file !== '') {
49     $url->param('file', $file);
50 }
52 // find out preset owner userid and shortname
53 $parts = explode('/', $fullname);
54 $userid = empty($parts[0]) ? 0 : (int)$parts[0];
55 $shortname = empty($parts[1]) ? '' : $parts[1];
56 unset($parts);
57 unset($fullname);
59 if ($id) {
60     $url->param('id', $id);
61     $PAGE->set_url($url);
62     if (! $cm = get_coursemodule_from_id('data', $id)) {
63         print_error('invalidcoursemodule');
64     }
65     if (! $course = $DB->get_record('course', array('id'=>$cm->course))) {
66         print_error('coursemisconf');
67     }
68     if (! $data = $DB->get_record('data', array('id'=>$cm->instance))) {
69         print_error('invalidid', 'data');
70     }
71 } else if ($d) {
72     $url->param('d', $d);
73     $PAGE->set_url($url);
74     if (! $data = $DB->get_record('data', array('id'=>$d))) {
75         print_error('invalidid', 'data');
76     }
77     if (! $course = $DB->get_record('course', array('id'=>$data->course))) {
78         print_error('coursemisconf');
79     }
80     if (! $cm = get_coursemodule_from_instance('data', $data->id, $course->id)) {
81         print_error('invalidcoursemodule');
82     }
83 } else {
84     print_error('missingparameter');
85 }
87 // fill in missing properties needed for updating of instance
88 $data->course     = $cm->course;
89 $data->cmidnumber = $cm->idnumber;
90 $data->instance   = $cm->instance;
92 if (!$context = get_context_instance(CONTEXT_MODULE, $cm->id)) {
93     print_error('cannotfindcontext');
94 }
96 require_login($course->id, false, $cm);
98 require_capability('mod/data:managetemplates', $context);
100 if ($userid && ($userid != $USER->id) && !has_capability('mod/data:viewalluserpresets', $context)) {
101     print_error('cannotaccesspresentsother', 'data');
104 /* Need sesskey security check here for import instruction */
105 $sesskey = sesskey();
106 $PAGE->set_title(get_string('course') . ': ' . $course->fullname);
107 $PAGE->set_heading($course->fullname);
109 /********************************************************************/
110 /* Output */
111 if ($action !== 'export') {
112     data_print_header($course, $cm, $data, 'presets');
115 switch ($action) {
116         /***************** Deleting *****************/
117     case 'confirmdelete' :
118         if (!confirm_sesskey()) { // GET request ok here
119             print_error('invalidsesskey');
120         }
122         if ($userid > 0 and ($userid == $USER->id || has_capability('mod/data:manageuserpresets', $context))) {
123            //ok can delete
124         } else {
125             print_error('invalidrequest');
126         }
128         $path = data_preset_path($course, $userid, $shortname);
130         $strwarning = get_string('deletewarning', 'data').'<br />'.
131                       data_preset_name($shortname, $path);
133         $optionsyes = array('fullname' => $userid.'/'.$shortname,
134                          'action' => 'delete',
135                          'd' => $data->id);
137         $optionsno = array('d' => $data->id);
138         echo $OUTPUT->confirm($strwarning, new moodle_url('preset.php', $optionsyes), new moodle_url('preset.php', $optionsno));
139         echo $OUTPUT->footer();
140         exit(0);
141         break;
143     case 'delete' :
144         if (!data_submitted() and !confirm_sesskey()) {
145             print_error('invalidrequest');
146         }
148         if ($userid > 0 and ($userid == $USER->id || has_capability('mod/data:manageuserpresets', $context))) {
149            //ok can delete
150         } else {
151             print_error('invalidrequest');
152         }
154         $presetpath = data_preset_path($course, $userid, $shortname);
156         if (!clean_preset($presetpath)) {
157             print_error('cannotdeletepreset', 'data');
158         }
159         @rmdir($presetpath);
161         $strdeleted = get_string('deleted', 'data');
162         echo $OUTPUT->notification("$shortname $strdeleted", 'notifysuccess');
163         break;
165         /***************** Importing *****************/
166     case 'importpreset' :
167         if (!data_submitted() or !confirm_sesskey()) {
168             print_error('invalidrequest');
169         }
171         $pimporter = new PresetImporter($course, $cm, $data, $userid, $shortname);
172         $pimporter->import_options();
174         echo $OUTPUT->footer();
175         exit(0);
176         break;
178         /* Imports a zip file. */
179     case 'importzip' :
180         if (!data_submitted() or !confirm_sesskey()) {
181             print_error('invalidrequest');
182         }
184         if (!make_upload_directory('temp/data/'.$USER->id)) {
185             print_error('nopermissiontomkdir');
186         }
188         $presetfile = $CFG->dataroot.'/temp/data/'.$USER->id;
189         clean_preset($presetfile);
191         if (!unzip_file($CFG->dataroot."/$course->id/$file", $presetfile, false)) {
192             print_error('cannotunzipfile');
193         }
195         $pimporter = new PresetImporter($course, $cm, $data, -$USER->id, $shortname);
196         $pimporter->import_options();
198         echo $OUTPUT->footer();
199         exit(0);
200         break;
202     case 'finishimport':
203         if (!data_submitted() or !confirm_sesskey()) {
204             print_error('invalidrequest');
205         }
207         $pimporter = new PresetImporter($course, $cm, $data, $userid, $shortname);
208         $pimporter->import();
210         $strimportsuccess = get_string('importsuccess', 'data');
211         $straddentries = get_string('addentries', 'data');
212         $strtodatabase = get_string('todatabase', 'data');
213         if (!$DB->get_records('data_records', array('dataid'=>$data->id))) {
214             echo $OUTPUT->notification("$strimportsuccess <a href='edit.php?d=$data->id'>$straddentries</a> $strtodatabase", 'notifysuccess');
215         } else {
216             echo $OUTPUT->notification("$strimportsuccess", 'notifysuccess');
217         }
218         break;
220         /* Exports as a zip file ready for download. */
221     case 'export':
222         if (!data_submitted() or !confirm_sesskey()) {
223             print_error('invalidrequest');
224         }
225         $exportfile = data_presets_export($course, $cm, $data);
226         $exportfilename = basename($exportfile);
227         header("Content-Type: application/download\n");
228         header("Content-Disposition: attachment; filename=$exportfilename");
229         header('Expires: 0');
230         header('Cache-Control: must-revalidate,post-check=0,pre-check=0');
231         header('Pragma: public');
232         $exportfilehandler = fopen($exportfile, 'rb');
233         print fread($exportfilehandler, filesize($exportfile));
234         fclose($exportfilehandler);
235         unlink($exportfile);
236         exit(0);
237         break;
239         /***************** Exporting *****************/
240     case 'save1':
241         if (!data_submitted() or !confirm_sesskey()) {
242             print_error('invalidrequest');
243         }
245         $strcontinue = get_string('continue');
246         $strwarning = get_string('presetinfo', 'data');
247         $strname = get_string('shortname');
249         echo '<div style="text-align:center">';
250         echo '<p>'.$strwarning.'</p>';
251         echo '<form action="preset.php" method="post">';
252         echo '<fieldset class="invisiblefieldset">';
253         echo '<label for="shorname">'.$strname.'</label> <input type="text" id="shorname" name="name" value="'.$data->name.'" />';
254         echo '<input type="hidden" name="action" value="save2" />';
255         echo '<input type="hidden" name="d" value="'.$data->id.'" />';
256         echo '<input type="hidden" name="sesskey" value="'.$sesskey.'" />';
257         echo '<input type="submit" value="'.$strcontinue.'" /></fieldset></form></div>';
258         echo $OUTPUT->footer();
259         exit(0);
260         break;
262     case 'save2':
263         if (!data_submitted() or !confirm_sesskey()) {
264             print_error('invalidrequest');
265         }
267         $strcontinue = get_string('continue');
268         $stroverwrite = get_string('overwrite', 'data');
269         $strname = get_string('shortname');
271         $name = optional_param('name', $data->name, PARAM_FILE);
273         if (is_directory_a_preset("$CFG->dataroot/data/preset/$USER->id/$name")) {
274             echo $OUTPUT->notification("Preset already exists: Pick another name or overwrite");
276             echo '<div style="text-align:center">';
277             echo '<form action="preset.php" method="post">';
278             echo '<fieldset class="invisiblefieldset">';
279             echo '<label for="shorname">'.$strname.'</label> <input type="textbox" name="name" value="'.$name.'" />';
280             echo '<input type="hidden" name="action" value="save2" />';
281             echo '<input type="hidden" name="d" value="'.$data->id.'" />';
282             echo '<input type="hidden" name="sesskey" value="'.$sesskey.'" />';
283             echo '<input type="submit" value="'.$strcontinue.'" /></fieldset></form>';
285             echo '<form action="preset.php" method="post">';
286             echo '<div>';
287             echo '<input type="hidden" name="name" value="'.$name.'" />';
288             echo '<input type="hidden" name="action" value="save3" />';
289             echo '<input type="hidden" name="d" value="'.$data->id.'" />';
290             echo '<input type="hidden" name="sesskey" value="'.$sesskey.'" />';
291             echo '<input type="submit" value="'.$stroverwrite.'" /></div></form>';
292             echo '</div>';
293             echo $OUTPUT->footer();
294             exit(0);
295             break;
296         }
298     case 'save3':
299         if (!data_submitted() or !confirm_sesskey()) {
300             print_error('invalidrequest');
301         }
303         $name = optional_param('name', $data->name, PARAM_FILE);
304         $presetdirectory = "/data/preset/$USER->id/$name";
306         make_upload_directory($presetdirectory);
307         clean_preset($CFG->dataroot.$presetdirectory);
309         $file = data_presets_export($course, $cm, $data);
310         if (!unzip_file($file, $CFG->dataroot.$presetdirectory, false)) {
311             print_error('cannotunziptopreset', 'data');
312         }
313         echo $OUTPUT->notification(get_string('savesuccess', 'data'), 'notifysuccess');
314         break;
317 $presets = data_get_available_presets($context);
319 $strimport         = get_string('import');
320 $strfromfile       = get_string('fromfile', 'data');
321 $strchooseorupload = get_string('chooseorupload', 'data');
322 $strusestandard    = get_string('usestandard', 'data');
323 $strchoose         = get_string('choose');
324 $strexport         = get_string('export', 'data');
325 $strexportaszip    = get_string('exportaszip', 'data');
326 $strsaveaspreset   = get_string('saveaspreset', 'data');
327 $strsave           = get_string('save', 'data');
328 $strdelete         = get_string('delete');
330 echo '<div style="text-align:center">';
331 echo '<table class="presets" cellpadding="5">';
332 echo '<tr><td valign="top" colspan="2" align="center"><h3>'.$strexport.'</h3></td></tr>';
334 echo '<tr><td><label>'.$strexportaszip.'</label>';
335 echo $OUTPUT->help_icon('exportaszip', 'data');
336 echo '</td><td>';
337 $options = array();
338 $options['sesskey'] = sesskey();
339 $options['action']  = 'export';
340 $options['d']       = $data->id;
341 echo $OUTPUT->single_button(new moodle_url('preset.php', $options), $strexport);
342 echo '</td></tr>';
344 echo '<tr><td><label>'.$strsaveaspreset.'</label>';
345 echo $OUTPUT->help_icon('saveaspreset', 'data');
346 echo '</td><td>';
347 $options = array();
348 $options['sesskey'] = sesskey();
349 $options['action']  = 'save1';
350 $options['d']       = $data->id;
351 echo $OUTPUT->single_button(new moodle_url('preset.php', $options), $strsave);
352 echo '</td></tr>';
353 echo '<tr><td valign="top" colspan="2" align="center"><h3>'.$strimport.'</h3></td></tr>';
354 echo '<tr><td><label for="fromfile">'.$strfromfile.'</label>';
355 echo $OUTPUT->help_icon('fromfile', 'data');
356 echo '</td><td>';
357 echo '<form id="uploadpreset" method="post" action="preset.php">';
358 echo '<fieldset class="invisiblefieldset">';
359 echo '<input type="hidden" name="d" value="'.$data->id.'" />';
360 echo '<input type="hidden" name="action" value="importzip" />';
361 echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
362 echo '<input name="file" size="20" value="" id="fromfile" type="text" /><input name="coursefiles" value="'.$strchooseorupload.'" type="button" />';
363 echo '<input type="submit" value="'.$strimport.'" />';
364 echo '</fieldset></form>';
365 echo '</td></tr>';
367 //attach the onclick event to fromfile button
368 $link = '/files/index.php?id={$course->id}&amp;choose=uploadpreset.file';
369 $action = new popup_action('click', $link, 'coursefiles', array('height'=>750,'width'=>500));
370 $OUTPUT->add_action_handler($action, 'fromfile');
372 echo '<tr valign="top"><td><label>'.$strusestandard.'</label>';
373 echo $OUTPUT->help_icon('usestandard', 'data');
374 echo '</td><td>';
376 echo '<form id="presets" method="post" action="preset.php" >';
377 echo '<fieldset class="invisiblefieldset">';
378 echo '<input type="hidden" name="d" value="'.$data->id.'" />';
379 echo '<input type="hidden" name="action" value="importpreset" />';
380 echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
382 $i = 0;
383 foreach ($presets as $id => $preset) {
384     $screenshot = '';
385     if (!empty($preset->userid)) {
386         $user = $DB->get_record('user', array('id'=>$preset->userid));
387         $desc = $preset->name.' ('.fullname($user, true).')';
388     } else {
389         $desc = $preset->name;
390     }
392     if (!empty($preset->screenshot)) {
393         $screenshot = '<img width="150" class="presetscreenshot" src="'.$preset->screenshot.'" alt="'.get_string('screenshot').' '.$desc.'" />&nbsp;';
394     }
396     $fullname = $preset->userid.'/'.$preset->shortname;
398     $dellink = '';
399     if ($preset->userid > 0 and ($preset->userid == $USER->id || has_capability('mod/data:manageuserpresets', $context))) {
400         $dellink = '&nbsp;<a href="preset.php?d='.$data->id.'&amp;action=confirmdelete&amp;fullname='.$fullname.'&amp;sesskey='.sesskey().'">'.
401                    '<img src="'.$OUTPUT->pix_url('t/delete') . '" class="iconsmall" alt="'.$strdelete.' '.$desc.'" /></a>';
402     }
404     echo '<input type="radio" name="fullname" id="usepreset'.$i.'" value="'.$fullname.'" /><label for="usepreset'.$i++.'">'.$desc.'</label>'.$dellink.'<br />';
406 echo '<br />';
407 echo '<input type="submit" value="'.$strchoose.'" />';
408 echo '</fieldset></form>';
409 echo '</td></tr>';
410 echo '</table>';
411 echo '</div>';
413 echo $OUTPUT->footer();
414 exit(0);
416 ################################################################################
419 function data_presets_export($course, $cm, $data) {
420     global $CFG, $DB;
421     $presetname = clean_filename($data->name) . '-preset-' . gmdate("Ymd_Hi");
422     $exportsubdir = "$course->id/moddata/data/$data->id/$presetname";
423     make_upload_directory($exportsubdir);
424     $exportdir = "$CFG->dataroot/$exportsubdir";
426     // Assemble "preset.xml":
427     $presetxmldata = "<preset>\n\n";
429     // Raw settings are not preprocessed during saving of presets
430     $raw_settings = array(
431         'intro',
432         'comments',
433         'requiredentries',
434         'requiredentriestoview',
435         'maxentries',
436         'rssarticles',
437         'approval',
438         'defaultsortdir'
439     );
441     $presetxmldata .= "<settings>\n";
442     // First, settings that do not require any conversion
443     foreach ($raw_settings as $setting) {
444         $presetxmldata .= "<$setting>" . htmlspecialchars($data->$setting) . "</$setting>\n";
445     }
447     // Now specific settings
448     if ($data->defaultsort > 0 && $sortfield = data_get_field_from_id($data->defaultsort, $data)) {
449         $presetxmldata .= '<defaultsort>' . htmlspecialchars($sortfield->field->name) . "</defaultsort>\n";
450     } else {
451         $presetxmldata .= "<defaultsort>0</defaultsort>\n";
452     }
453     $presetxmldata .= "</settings>\n\n";
455     // Now for the fields. Grab all that are non-empty
456     $fields = $DB->get_records('data_fields', array('dataid'=>$data->id));
457     ksort($fields);
458     if (!empty($fields)) {
459         foreach ($fields as $field) {
460             $presetxmldata .= "<field>\n";
461             foreach ($field as $key => $value) {
462                 if ($value != '' && $key != 'id' && $key != 'dataid') {
463                     $presetxmldata .= "<$key>" . htmlspecialchars($value) . "</$key>\n";
464                 }
465             }
466             $presetxmldata .= "</field>\n\n";
467         }
468     }
469     $presetxmldata .= '</preset>';
471     // After opening a file in write mode, close it asap
472     $presetxmlfile = fopen($exportdir . '/preset.xml', 'w');
473     fwrite($presetxmlfile, $presetxmldata);
474     fclose($presetxmlfile);
476     // Now write the template files
477     $singletemplate = fopen($exportdir . '/singletemplate.html', 'w');
478     fwrite($singletemplate, $data->singletemplate);
479     fclose($singletemplate);
481     $listtemplateheader = fopen($exportdir . '/listtemplateheader.html', 'w');
482     fwrite($listtemplateheader, $data->listtemplateheader);
483     fclose($listtemplateheader);
485     $listtemplate = fopen($exportdir . '/listtemplate.html', 'w');
486     fwrite($listtemplate, $data->listtemplate);
487     fclose($listtemplate);
489     $listtemplatefooter = fopen($exportdir . '/listtemplatefooter.html', 'w');
490     fwrite($listtemplatefooter, $data->listtemplatefooter);
491     fclose($listtemplatefooter);
493     $addtemplate = fopen($exportdir . '/addtemplate.html', 'w');
494     fwrite($addtemplate, $data->addtemplate);
495     fclose($addtemplate);
497     $rsstemplate = fopen($exportdir . '/rsstemplate.html', 'w');
498     fwrite($rsstemplate, $data->rsstemplate);
499     fclose($rsstemplate);
501     $rsstitletemplate = fopen($exportdir . '/rsstitletemplate.html', 'w');
502     fwrite($rsstitletemplate, $data->rsstitletemplate);
503     fclose($rsstitletemplate);
505     $csstemplate = fopen($exportdir . '/csstemplate.css', 'w');
506     fwrite($csstemplate, $data->csstemplate);
507     fclose($csstemplate);
509     $jstemplate = fopen($exportdir . '/jstemplate.js', 'w');
510     fwrite($jstemplate, $data->jstemplate);
511     fclose($jstemplate);
513     $asearchtemplate = fopen($exportdir . '/asearchtemplate.html', 'w');
514     fwrite($asearchtemplate, $data->asearchtemplate);
515     fclose($asearchtemplate);
517     // Check if all files have been generated
518     if (! is_directory_a_preset($exportdir)) {
519         print_error('generateerror', 'data');
520     }
522     $filelist = array(
523         'preset.xml',
524         'singletemplate.html',
525         'listtemplateheader.html',
526         'listtemplate.html',
527         'listtemplatefooter.html',
528         'addtemplate.html',
529         'rsstemplate.html',
530         'rsstitletemplate.html',
531         'csstemplate.css',
532         'jstemplate.js',
533         'asearchtemplate.html'
534     );
536     foreach ($filelist as $key => $file) {
537         $filelist[$key] = $exportdir . '/' . $filelist[$key];
538     }
540     $exportfile = "$CFG->dataroot/$course->id/moddata/data/$data->id/$presetname.zip";
541     file_exists($exportfile) && unlink($exportfile);
542     $status = zip_files($filelist, $exportfile);
543     // ToDo: status check
544     foreach ($filelist as $file) {
545         unlink($file);
546     }
547     rmdir($exportdir);
549     // Return the full path to the exported preset file:
550     return $exportfile;