See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 402] [Versions 401 and 403]
1 <?php 2 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/>. 17 18 /** 19 * This file is part of the Database module for Moodle 20 * 21 * @copyright 2005 Martin Dougiamas http://dougiamas.com 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 * @package mod_data 24 */ 25 26 use core\notification; 27 use mod_data\local\importer\preset_existing_importer; 28 use mod_data\local\importer\preset_importer; 29 use mod_data\local\importer\preset_upload_importer; 30 use mod_data\manager; 31 32 require_once('../../config.php'); 33 require_once ('lib.php'); 34 require_once($CFG->dirroot.'/mod/data/preset_form.php'); 35 36 $id = optional_param('id', 0, PARAM_INT); // course module id 37 $d = optional_param('d', 0, PARAM_INT); // database id 38 $fid = optional_param('fid', 0 , PARAM_INT); // update field id 39 $newtype = optional_param('newtype','',PARAM_ALPHA); // type of the new field 40 $mode = optional_param('mode','',PARAM_ALPHA); 41 $action = optional_param('action', '', PARAM_ALPHA); 42 $fullname = optional_param('fullname', '', PARAM_PATH); // Directory the preset is in. 43 $defaultsort = optional_param('defaultsort', 0, PARAM_INT); 44 $defaultsortdir = optional_param('defaultsortdir', 0, PARAM_INT); 45 $cancel = optional_param('cancel', 0, PARAM_BOOL); 46 47 if ($cancel) { 48 $mode = 'list'; 49 } 50 51 $url = new moodle_url('/mod/data/field.php'); 52 if ($fid !== 0) { 53 $url->param('fid', $fid); 54 } 55 if ($newtype !== '') { 56 $url->param('newtype', $newtype); 57 } 58 if ($mode !== '') { 59 $url->param('mode', $mode); 60 } 61 if ($defaultsort !== 0) { 62 $url->param('defaultsort', $defaultsort); 63 } 64 if ($defaultsortdir !== 0) { 65 $url->param('defaultsortdir', $defaultsortdir); 66 } 67 if ($cancel !== 0) { 68 $url->param('cancel', $cancel); 69 } 70 if ($action !== '') { 71 $url->param('action', $action); 72 } 73 74 if ($id) { 75 list($course, $cm) = get_course_and_cm_from_cmid($id, manager::MODULE); 76 $manager = manager::create_from_coursemodule($cm); 77 $url->param('id', $cm->id); 78 } else { // We must have $d. 79 $instance = $DB->get_record('data', ['id' => $d], '*', MUST_EXIST); 80 $manager = manager::create_from_instance($instance); 81 $cm = $manager->get_coursemodule(); 82 $course = get_course($cm->course); 83 $url->param('d', $d); 84 } 85 86 $PAGE->set_url($url); 87 $data = $manager->get_instance(); 88 $context = $manager->get_context(); 89 90 require_login($course, true, $cm); 91 require_capability('mod/data:managetemplates', $context); 92 93 $actionbar = new \mod_data\output\action_bar($data->id, $PAGE->url); 94 95 $PAGE->add_body_class('mediumwidth'); 96 $PAGE->set_heading($course->fullname); 97 $PAGE->activityheader->disable(); 98 99 // Fill in missing properties needed for updating of instance. 100 $data->course = $cm->course; 101 $data->cmidnumber = $cm->idnumber; 102 $data->instance = $cm->instance; 103 104 /************************************ 105 * Data Processing * 106 ***********************************/ 107 $renderer = $manager->get_renderer(); 108 109 if ($action == 'finishimport' && confirm_sesskey()) { 110 $overwritesettings = optional_param('overwritesettings', false, PARAM_BOOL); 111 $importer = preset_importer::create_from_parameters($manager); 112 $importer->finish_import_process($overwritesettings, $data); 113 } 114 115 switch ($mode) { 116 117 case 'add': ///add a new field 118 if (confirm_sesskey() and $fieldinput = data_submitted()){ 119 120 //$fieldinput->name = data_clean_field_name($fieldinput->name); 121 122 /// Only store this new field if it doesn't already exist. 123 if (($fieldinput->name == '') or data_fieldname_exists($fieldinput->name, $data->id)) { 124 125 $displaynoticebad = get_string('invalidfieldname','data'); 126 127 } else { 128 129 /// Check for arrays and convert to a comma-delimited string 130 data_convert_arrays_to_strings($fieldinput); 131 132 /// Create a field object to collect and store the data safely 133 $type = required_param('type', PARAM_FILE); 134 $field = data_get_field_new($type, $data); 135 136 if (!empty($validationerrors = $field->validate($fieldinput))) { 137 $displaynoticebad = html_writer::alist($validationerrors); 138 $mode = 'new'; 139 $newtype = $type; 140 break; 141 } 142 143 $field->define_field($fieldinput); 144 $field->insert_field(); 145 146 /// Update some templates 147 data_append_new_field_to_templates($data, $fieldinput->name); 148 149 $displaynoticegood = get_string('fieldadded','data'); 150 } 151 } 152 break; 153 154 155 case 'update': ///update a field 156 if (confirm_sesskey() and $fieldinput = data_submitted()){ 157 158 //$fieldinput->name = data_clean_field_name($fieldinput->name); 159 160 if (($fieldinput->name == '') or data_fieldname_exists($fieldinput->name, $data->id, $fieldinput->fid)) { 161 162 $displaynoticebad = get_string('invalidfieldname','data'); 163 164 } else { 165 /// Check for arrays and convert to a comma-delimited string 166 data_convert_arrays_to_strings($fieldinput); 167 168 /// Create a field object to collect and store the data safely 169 $field = data_get_field_from_id($fid, $data); 170 if (!empty($validationerrors = $field->validate($fieldinput))) { 171 $displaynoticebad = html_writer::alist($validationerrors); 172 $mode = 'display'; 173 break; 174 } 175 $oldfieldname = $field->field->name; 176 177 $field->field->name = $fieldinput->name; 178 $field->field->description = $fieldinput->description; 179 $field->field->required = !empty($fieldinput->required) ? 1 : 0; 180 181 for ($i=1; $i<=10; $i++) { 182 if (isset($fieldinput->{'param'.$i})) { 183 $field->field->{'param'.$i} = $fieldinput->{'param'.$i}; 184 } else { 185 $field->field->{'param'.$i} = ''; 186 } 187 } 188 189 $field->update_field(); 190 191 /// Update the templates. 192 data_replace_field_in_templates($data, $oldfieldname, $field->field->name); 193 194 $displaynoticegood = get_string('fieldupdated','data'); 195 } 196 } 197 break; 198 199 200 case 'delete': // Delete a field 201 if (confirm_sesskey()){ 202 203 if ($confirm = optional_param('confirm', 0, PARAM_INT)) { 204 205 206 // Delete the field completely 207 if ($field = data_get_field_from_id($fid, $data)) { 208 $field->delete_field(); 209 210 // Update the templates. 211 data_replace_field_in_templates($data, $field->field->name, ''); 212 213 // Update the default sort field 214 if ($fid == $data->defaultsort) { 215 $rec = new stdClass(); 216 $rec->id = $data->id; 217 $rec->defaultsort = 0; 218 $rec->defaultsortdir = 0; 219 $DB->update_record('data', $rec); 220 } 221 222 $displaynoticegood = get_string('fielddeleted', 'data'); 223 } 224 225 } else { 226 $titleparts = [ 227 get_string('deletefield', 'data'), 228 format_string($data->name), 229 format_string($course->fullname), 230 ]; 231 $PAGE->set_title(implode(moodle_page::TITLE_SEPARATOR, $titleparts)); 232 data_print_header($course,$cm,$data, false); 233 echo $OUTPUT->heading(get_string('deletefield', 'data'), 2, 'mb-4'); 234 235 // Print confirmation message. 236 $field = data_get_field_from_id($fid, $data); 237 238 if ($field->type === 'unknown') { 239 $fieldtypename = get_string('unknown', 'data'); 240 } else { 241 $fieldtypename = $field->name(); 242 } 243 echo $OUTPUT->confirm('<strong>'.$fieldtypename.': '.$field->field->name.'</strong><br /><br />'. 244 get_string('confirmdeletefield', 'data'), 245 'field.php?d='.$data->id.'&mode=delete&fid='.$fid.'&confirm=1', 246 'field.php?d='.$data->id); 247 248 echo $OUTPUT->footer(); 249 exit; 250 } 251 } 252 break; 253 254 255 case 'sort': // Set the default sort parameters 256 if (confirm_sesskey()) { 257 $rec = new stdClass(); 258 $rec->id = $data->id; 259 $rec->defaultsort = $defaultsort; 260 $rec->defaultsortdir = $defaultsortdir; 261 262 $DB->update_record('data', $rec); 263 redirect($CFG->wwwroot.'/mod/data/field.php?d='.$data->id, get_string('changessaved'), 2); 264 exit; 265 } 266 break; 267 268 case 'usepreset': 269 $importer = preset_importer::create_from_parameters($manager); 270 if (!$importer->needs_mapping() || $action == 'notmapping') { 271 $backurl = new moodle_url('/mod/data/field.php', ['id' => $cm->id]); 272 if ($importer->import(false)) { 273 notification::success(get_string('importsuccess', 'mod_data')); 274 } else { 275 notification::error(get_string('cannotapplypreset', 'mod_data')); 276 } 277 redirect($backurl); 278 } 279 $PAGE->navbar->add(get_string('usestandard', 'data')); 280 $fieldactionbar = $actionbar->get_fields_mapping_action_bar(); 281 data_print_header($course, $cm, $data, false, $fieldactionbar); 282 $importer = new preset_existing_importer($manager, $fullname); 283 echo $renderer->importing_preset($data, $importer); 284 echo $OUTPUT->footer(); 285 exit; 286 287 default: 288 break; 289 } 290 291 292 293 /// Print the browsing interface 294 295 ///get the list of possible fields (plugins) 296 $plugins = core_component::get_plugin_list('datafield'); 297 $menufield = array(); 298 299 foreach ($plugins as $plugin=>$fulldir){ 300 if (!is_dir($fulldir)) { 301 continue; 302 } 303 $menufield[$plugin] = get_string('pluginname', 'datafield_'.$plugin); //get from language files 304 } 305 asort($menufield); //sort in alphabetical order 306 $PAGE->force_settings_menu(true); 307 308 $PAGE->set_pagetype('mod-data-field-' . $newtype); 309 $titleparts = [ 310 format_string($data->name), 311 format_string($course->fullname), 312 ]; 313 if (($mode == 'new') && (!empty($newtype))) { // Adding a new field. 314 array_unshift($titleparts, get_string('newfield', 'data')); 315 $PAGE->set_title(implode(moodle_page::TITLE_SEPARATOR, $titleparts)); 316 data_print_header($course, $cm, $data, 'fields'); 317 echo $OUTPUT->heading(get_string('newfield', 'data')); 318 319 $field = data_get_field_new($newtype, $data); 320 $field->display_edit_field(); 321 322 } else if ($mode == 'display' && confirm_sesskey()) { /// Display/edit existing field 323 array_unshift($titleparts, get_string('editfield', 'data')); 324 $PAGE->set_title(implode(moodle_page::TITLE_SEPARATOR, $titleparts)); 325 data_print_header($course, $cm, $data, 'fields'); 326 echo $OUTPUT->heading(get_string('editfield', 'data')); 327 328 $field = data_get_field_from_id($fid, $data); 329 $field->display_edit_field(); 330 331 } else { /// Display the main listing of all fields 332 array_unshift($titleparts, get_string('managefields', 'data')); 333 $PAGE->set_title(implode(moodle_page::TITLE_SEPARATOR, $titleparts)); 334 $hasfields = $manager->has_fields(); 335 // Check if it is an empty database with no fields. 336 if (!$hasfields) { 337 echo $OUTPUT->header(); 338 echo $renderer->render_fields_zero_state($manager); 339 echo $OUTPUT->footer(); 340 // Don't check the rest of the options. There is no field, there is nothing else to work with. 341 exit; 342 } 343 $fieldactionbar = $actionbar->get_fields_action_bar(true); 344 data_print_header($course, $cm, $data, 'fields', $fieldactionbar); 345 346 echo $OUTPUT->box_start('mb-4'); 347 echo get_string('fieldshelp', 'data'); 348 echo $OUTPUT->box_end(); 349 $table = new html_table(); 350 $table->head = [ 351 get_string('fieldname', 'data'), 352 get_string('type', 'data'), 353 get_string('required', 'data'), 354 get_string('fielddescription', 'data'), 355 ' ', 356 ]; 357 $table->align = ['left', 'left', 'left', 'left']; 358 $table->wrap = [false,false,false,false]; 359 $table->responsive = false; 360 361 $fieldrecords = $manager->get_field_records(); 362 $missingfieldtypes = []; 363 foreach ($fieldrecords as $fieldrecord) { 364 365 $field = data_get_field($fieldrecord, $data); 366 367 $baseurl = new moodle_url('/mod/data/field.php', array( 368 'd' => $data->id, 369 'fid' => $field->field->id, 370 'sesskey' => sesskey(), 371 )); 372 373 $displayurl = new moodle_url($baseurl, array( 374 'mode' => 'display', 375 )); 376 377 $deleteurl = new moodle_url($baseurl, array( 378 'mode' => 'delete', 379 )); 380 381 $actionmenu = new action_menu(); 382 $icon = $OUTPUT->pix_icon('i/menu', get_string('actions')); 383 $actionmenu->set_menu_trigger($icon, 'btn btn-icon d-flex align-items-center justify-content-center'); 384 $actionmenu->set_action_label(get_string('actions')); 385 $actionmenu->attributes['class'] .= ' fields-actions'; 386 387 // It display a notification when the field type does not exist. 388 if ($field->type === 'unknown') { 389 $missingfieldtypes[] = $field->field->name; 390 $fieltypedata = $field->field->type; 391 } else { 392 $fieltypedata = $field->image() . ' ' . $field->name(); 393 // Edit icon, only displayed when the field type is known. 394 $actionmenu->add(new action_menu_link_secondary( 395 $displayurl, 396 null, 397 get_string('edit'), 398 )); 399 } 400 401 // Delete. 402 $actionmenu->add(new action_menu_link_secondary( 403 $deleteurl, 404 null, 405 get_string('delete'), 406 )); 407 $actionmenutemplate = $actionmenu->export_for_template($OUTPUT); 408 409 $table->data[] = [ 410 $field->field->name, 411 $fieltypedata, 412 $field->field->required ? get_string('yes') : get_string('no'), 413 shorten_text($field->field->description, 30), 414 $OUTPUT->render_from_template('core/action_menu', $actionmenutemplate) 415 ]; 416 417 if (!empty($missingfieldtypes)) { 418 echo $OUTPUT->notification(get_string('missingfieldtypes', 'data') . html_writer::alist($missingfieldtypes)); 419 } 420 } 421 echo html_writer::table($table); 422 423 echo '<div class="sortdefault">'; 424 echo '<form id="sortdefault" action="'.$CFG->wwwroot.'/mod/data/field.php" method="get">'; 425 echo '<div>'; 426 echo '<input type="hidden" name="d" value="'.$data->id.'" />'; 427 echo '<input type="hidden" name="mode" value="sort" />'; 428 echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />'; 429 echo '<label for="defaultsort">'.get_string('defaultsortfield','data').'</label>'; 430 echo '<select id="defaultsort" name="defaultsort" class="custom-select">'; 431 if ($fields = $DB->get_records('data_fields', array('dataid'=>$data->id))) { 432 echo '<optgroup label="'.get_string('fields', 'data').'">'; 433 foreach ($fields as $field) { 434 if ($data->defaultsort == $field->id) { 435 echo '<option value="'.$field->id.'" selected="selected">'.$field->name.'</option>'; 436 } else { 437 echo '<option value="'.$field->id.'">'.$field->name.'</option>'; 438 } 439 } 440 echo '</optgroup>'; 441 } 442 $options = array(); 443 $options[DATA_TIMEADDED] = get_string('timeadded', 'data'); 444 // TODO: we will need to change defaultsort db to unsinged to make these work in 2.0 445 /* $options[DATA_TIMEMODIFIED] = get_string('timemodified', 'data'); 446 $options[DATA_FIRSTNAME] = get_string('authorfirstname', 'data'); 447 $options[DATA_LASTNAME] = get_string('authorlastname', 'data'); 448 if ($data->approval and has_capability('mod/data:approve', $context)) { 449 $options[DATA_APPROVED] = get_string('approved', 'data'); 450 }*/ 451 echo '<optgroup label="'.get_string('other', 'data').'">'; 452 foreach ($options as $key => $name) { 453 if ($data->defaultsort == $key) { 454 echo '<option value="'.$key.'" selected="selected">'.$name.'</option>'; 455 } else { 456 echo '<option value="'.$key.'">'.$name.'</option>'; 457 } 458 } 459 echo '</optgroup>'; 460 echo '</select>'; 461 462 $options = array(0 => get_string('ascending', 'data'), 463 1 => get_string('descending', 'data')); 464 echo html_writer::label(get_string('sortby'), 'menudefaultsortdir', false, array('class' => 'accesshide')); 465 echo html_writer::select($options, 'defaultsortdir', $data->defaultsortdir, false, array('class' => 'custom-select')); 466 echo '<input type="submit" class="btn btn-secondary ml-1" value="'.get_string('save', 'data').'" />'; 467 echo '</div>'; 468 echo '</form>'; 469 470 // Add a sticky footer. 471 echo $renderer->render_fields_footer($manager); 472 473 echo '</div>'; 474 } 475 476 /// Finish the page 477 echo $OUTPUT->footer();
title
Description
Body
title
Description
Body
title
Description
Body
title
Body