Differences Between: [Versions 310 and 402] [Versions 311 and 402] [Versions 39 and 402] [Versions 400 and 402] [Versions 401 and 402]
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 ['type' => single_button::BUTTON_DANGER]); 248 249 echo $OUTPUT->footer(); 250 exit; 251 } 252 } 253 break; 254 255 256 case 'sort': // Set the default sort parameters 257 if (confirm_sesskey()) { 258 $rec = new stdClass(); 259 $rec->id = $data->id; 260 $rec->defaultsort = $defaultsort; 261 $rec->defaultsortdir = $defaultsortdir; 262 263 $DB->update_record('data', $rec); 264 redirect($CFG->wwwroot.'/mod/data/field.php?d='.$data->id, get_string('changessaved'), 2); 265 exit; 266 } 267 break; 268 269 case 'usepreset': 270 $importer = preset_importer::create_from_parameters($manager); 271 if (!$importer->needs_mapping() || $action == 'notmapping') { 272 $backurl = new moodle_url('/mod/data/field.php', ['id' => $cm->id]); 273 if ($importer->import(false)) { 274 notification::success(get_string('importsuccess', 'mod_data')); 275 } else { 276 notification::error(get_string('cannotapplypreset', 'mod_data')); 277 } 278 redirect($backurl); 279 } 280 $PAGE->navbar->add(get_string('usestandard', 'data')); 281 $fieldactionbar = $actionbar->get_fields_mapping_action_bar(); 282 data_print_header($course, $cm, $data, false, $fieldactionbar); 283 $importer = new preset_existing_importer($manager, $fullname); 284 echo $renderer->importing_preset($data, $importer); 285 echo $OUTPUT->footer(); 286 exit; 287 288 default: 289 break; 290 } 291 292 293 294 /// Print the browsing interface 295 296 ///get the list of possible fields (plugins) 297 $plugins = core_component::get_plugin_list('datafield'); 298 $menufield = array(); 299 300 foreach ($plugins as $plugin=>$fulldir){ 301 if (!is_dir($fulldir)) { 302 continue; 303 } 304 $menufield[$plugin] = get_string('pluginname', 'datafield_'.$plugin); //get from language files 305 } 306 asort($menufield); //sort in alphabetical order 307 $PAGE->force_settings_menu(true); 308 309 $PAGE->set_pagetype('mod-data-field-' . $newtype); 310 $titleparts = [ 311 format_string($data->name), 312 format_string($course->fullname), 313 ]; 314 if (($mode == 'new') && (!empty($newtype))) { // Adding a new field. 315 array_unshift($titleparts, get_string('newfield', 'data')); 316 $PAGE->set_title(implode(moodle_page::TITLE_SEPARATOR, $titleparts)); 317 data_print_header($course, $cm, $data, 'fields'); 318 echo $OUTPUT->heading(get_string('newfield', 'data')); 319 320 $field = data_get_field_new($newtype, $data); 321 $field->display_edit_field(); 322 323 } else if ($mode == 'display' && confirm_sesskey()) { /// Display/edit existing field 324 array_unshift($titleparts, get_string('editfield', 'data')); 325 $PAGE->set_title(implode(moodle_page::TITLE_SEPARATOR, $titleparts)); 326 data_print_header($course, $cm, $data, 'fields'); 327 echo $OUTPUT->heading(get_string('editfield', 'data')); 328 329 $field = data_get_field_from_id($fid, $data); 330 $field->display_edit_field(); 331 332 } else { /// Display the main listing of all fields 333 array_unshift($titleparts, get_string('managefields', 'data')); 334 $PAGE->set_title(implode(moodle_page::TITLE_SEPARATOR, $titleparts)); 335 $hasfields = $manager->has_fields(); 336 // Check if it is an empty database with no fields. 337 if (!$hasfields) { 338 echo $OUTPUT->header(); 339 echo $renderer->render_fields_zero_state($manager); 340 echo $OUTPUT->footer(); 341 // Don't check the rest of the options. There is no field, there is nothing else to work with. 342 exit; 343 } 344 $fieldactionbar = $actionbar->get_fields_action_bar(true); 345 data_print_header($course, $cm, $data, 'fields', $fieldactionbar); 346 347 echo $OUTPUT->box_start(); 348 echo get_string('fieldshelp', 'data'); 349 echo $OUTPUT->box_end(); 350 echo $OUTPUT->box_start('d-flex flex-row-reverse'); 351 echo $OUTPUT->render($actionbar->get_create_fields(true)); 352 echo $OUTPUT->box_end(); 353 $table = new html_table(); 354 $table->head = [ 355 get_string('fieldname', 'data'), 356 get_string('type', 'data'), 357 get_string('required', 'data'), 358 get_string('fielddescription', 'data'), 359 ' ', 360 ]; 361 $table->align = ['left', 'left', 'left', 'left']; 362 $table->wrap = [false,false,false,false]; 363 $table->responsive = false; 364 365 $fieldrecords = $manager->get_field_records(); 366 $missingfieldtypes = []; 367 foreach ($fieldrecords as $fieldrecord) { 368 369 $field = data_get_field($fieldrecord, $data); 370 371 $baseurl = new moodle_url('/mod/data/field.php', array( 372 'd' => $data->id, 373 'fid' => $field->field->id, 374 'sesskey' => sesskey(), 375 )); 376 377 $displayurl = new moodle_url($baseurl, array( 378 'mode' => 'display', 379 )); 380 381 $deleteurl = new moodle_url($baseurl, array( 382 'mode' => 'delete', 383 )); 384 385 $actionmenu = new action_menu(); 386 $actionmenu->set_kebab_trigger(); 387 $actionmenu->set_action_label(get_string('actions')); 388 $actionmenu->set_additional_classes('fields-actions'); 389 390 // It display a notification when the field type does not exist. 391 if ($field->type === 'unknown') { 392 $missingfieldtypes[] = $field->field->name; 393 $fieltypedata = $field->field->type; 394 } else { 395 $fieltypedata = $field->image() . ' ' . $field->name(); 396 // Edit icon, only displayed when the field type is known. 397 $actionmenu->add(new action_menu_link_secondary( 398 $displayurl, 399 null, 400 get_string('edit'), 401 )); 402 } 403 404 // Delete. 405 $actionmenu->add(new action_menu_link_secondary( 406 $deleteurl, 407 null, 408 get_string('delete'), 409 )); 410 $actionmenutemplate = $actionmenu->export_for_template($OUTPUT); 411 412 $table->data[] = [ 413 $field->field->name, 414 $fieltypedata, 415 $field->field->required ? get_string('yes') : get_string('no'), 416 shorten_text($field->field->description, 30), 417 $OUTPUT->render_from_template('core/action_menu', $actionmenutemplate) 418 ]; 419 420 if (!empty($missingfieldtypes)) { 421 echo $OUTPUT->notification(get_string('missingfieldtypes', 'data') . html_writer::alist($missingfieldtypes)); 422 } 423 } 424 echo html_writer::table($table); 425 426 echo '<div class="sortdefault">'; 427 echo '<form id="sortdefault" action="'.$CFG->wwwroot.'/mod/data/field.php" method="get">'; 428 echo '<div>'; 429 echo '<input type="hidden" name="d" value="'.$data->id.'" />'; 430 echo '<input type="hidden" name="mode" value="sort" />'; 431 echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />'; 432 echo '<label for="defaultsort">'.get_string('defaultsortfield','data').'</label>'; 433 echo '<select id="defaultsort" name="defaultsort" class="custom-select">'; 434 if ($fields = $DB->get_records('data_fields', array('dataid'=>$data->id))) { 435 echo '<optgroup label="'.get_string('fields', 'data').'">'; 436 foreach ($fields as $field) { 437 if ($data->defaultsort == $field->id) { 438 echo '<option value="'.$field->id.'" selected="selected">'.$field->name.'</option>'; 439 } else { 440 echo '<option value="'.$field->id.'">'.$field->name.'</option>'; 441 } 442 } 443 echo '</optgroup>'; 444 } 445 $options = array(); 446 $options[DATA_TIMEADDED] = get_string('timeadded', 'data'); 447 // TODO: we will need to change defaultsort db to unsinged to make these work in 2.0 448 /* $options[DATA_TIMEMODIFIED] = get_string('timemodified', 'data'); 449 $options[DATA_FIRSTNAME] = get_string('authorfirstname', 'data'); 450 $options[DATA_LASTNAME] = get_string('authorlastname', 'data'); 451 if ($data->approval and has_capability('mod/data:approve', $context)) { 452 $options[DATA_APPROVED] = get_string('approved', 'data'); 453 }*/ 454 echo '<optgroup label="'.get_string('other', 'data').'">'; 455 foreach ($options as $key => $name) { 456 if ($data->defaultsort == $key) { 457 echo '<option value="'.$key.'" selected="selected">'.$name.'</option>'; 458 } else { 459 echo '<option value="'.$key.'">'.$name.'</option>'; 460 } 461 } 462 echo '</optgroup>'; 463 echo '</select>'; 464 465 $options = array(0 => get_string('ascending', 'data'), 466 1 => get_string('descending', 'data')); 467 echo html_writer::label(get_string('sortby'), 'menudefaultsortdir', false, array('class' => 'accesshide')); 468 echo html_writer::select($options, 'defaultsortdir', $data->defaultsortdir, false, array('class' => 'custom-select')); 469 echo '<input type="submit" class="btn btn-secondary ml-1" value="'.get_string('save', 'data').'" />'; 470 echo '</div>'; 471 echo '</form>'; 472 473 // Add a sticky footer. 474 echo $renderer->render_fields_footer($manager); 475 476 echo '</div>'; 477 } 478 479 /// Finish the page 480 echo $OUTPUT->footer();
title
Description
Body
title
Description
Body
title
Description
Body
title
Body