Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.0.x will end 8 May 2023 (12 months).
  • Bug fixes for security issues in 4.0.x will end 13 November 2023 (18 months).
  • PHP version: minimum PHP 7.3.0 Note: the minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is also supported.
/mod/data/ -> field.php (source)

Differences Between: [Versions 310 and 400] [Versions 311 and 400] [Versions 39 and 400] [Versions 400 and 401] [Versions 400 and 402] [Versions 400 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  require_once('../../config.php');
  27  require_once ('lib.php');
  28  require_once($CFG->dirroot.'/mod/data/preset_form.php');
  29  
  30  $id             = optional_param('id', 0, PARAM_INT);            // course module id
  31  $d              = optional_param('d', 0, PARAM_INT);             // database id
  32  $fid            = optional_param('fid', 0 , PARAM_INT);          // update field id
  33  $newtype        = optional_param('newtype','',PARAM_ALPHA);      // type of the new field
  34  $mode           = optional_param('mode','',PARAM_ALPHA);
  35  $action         = optional_param('action', '', PARAM_ALPHA);
  36  $fullname       = optional_param('fullname', '', PARAM_PATH);    // Directory the preset is in.
  37  $defaultsort    = optional_param('defaultsort', 0, PARAM_INT);
  38  $defaultsortdir = optional_param('defaultsortdir', 0, PARAM_INT);
  39  $cancel         = optional_param('cancel', 0, PARAM_BOOL);
  40  
  41  if ($cancel) {
  42      $mode = 'list';
  43  }
  44  
  45  $url = new moodle_url('/mod/data/field.php');
  46  if ($fid !== 0) {
  47      $url->param('fid', $fid);
  48  }
  49  if ($newtype !== '') {
  50      $url->param('newtype', $newtype);
  51  }
  52  if ($mode !== '') {
  53      $url->param('mode', $mode);
  54  }
  55  if ($defaultsort !== 0) {
  56      $url->param('defaultsort', $defaultsort);
  57  }
  58  if ($defaultsortdir !== 0) {
  59      $url->param('defaultsortdir', $defaultsortdir);
  60  }
  61  if ($cancel !== 0) {
  62      $url->param('cancel', $cancel);
  63  }
  64  if ($action !== '') {
  65      $url->param('action', $action);
  66  }
  67  
  68  if ($id) {
  69      $url->param('id', $id);
  70      $PAGE->set_url($url);
  71      if (! $cm = get_coursemodule_from_id('data', $id)) {
  72          print_error('invalidcoursemodule');
  73      }
  74      if (! $course = $DB->get_record('course', array('id'=>$cm->course))) {
  75          print_error('coursemisconf');
  76      }
  77      if (! $data = $DB->get_record('data', array('id'=>$cm->instance))) {
  78          print_error('invalidcoursemodule');
  79      }
  80  
  81  } else {
  82      $url->param('d', $d);
  83      $PAGE->set_url($url);
  84      if (! $data = $DB->get_record('data', array('id'=>$d))) {
  85          print_error('invalidid', 'data');
  86      }
  87      if (! $course = $DB->get_record('course', array('id'=>$data->course))) {
  88          print_error('invalidcoursemodule');
  89      }
  90      if (! $cm = get_coursemodule_from_instance('data', $data->id, $course->id)) {
  91          print_error('invalidcoursemodule');
  92      }
  93  }
  94  
  95  require_login($course, true, $cm);
  96  
  97  $context = context_module::instance($cm->id);
  98  require_capability('mod/data:managetemplates', $context);
  99  
 100  $formimportzip = new data_import_preset_zip_form();
 101  $formimportzip->set_data(array('d' => $data->id));
 102  
 103  $actionbar = new \mod_data\output\action_bar($data->id, $PAGE->url);
 104  
 105  $PAGE->set_title(get_string('course') . ': ' . $course->fullname);
 106  $PAGE->set_heading($course->fullname);
 107  $PAGE->activityheader->disable();
 108  
 109  // Fill in missing properties needed for updating of instance.
 110  $data->course     = $cm->course;
 111  $data->cmidnumber = $cm->idnumber;
 112  $data->instance   = $cm->instance;
 113  
 114  /************************************
 115   *        Data Processing           *
 116   ***********************************/
 117  $renderer = $PAGE->get_renderer('mod_data');
 118  
 119  if ($formimportzip->is_cancelled()) {
 120      redirect(new moodle_url('/mod/data/field.php', ['d' => $data->id]));
 121  } else if ($formdata = $formimportzip->get_data()) {
 122      $fieldactionbar = $actionbar->get_fields_action_bar();
 123      data_print_header($course, $cm, $data, false, $fieldactionbar);
 124      echo $OUTPUT->heading(get_string('importpreset', 'data'), 2, 'mb-4');
 125      $file = new stdClass;
 126      $file->name = $formimportzip->get_new_filename('importfile');
 127      $file->path = $formimportzip->save_temp_file('importfile');
 128      $importer = new data_preset_upload_importer($course, $cm, $data, $file->path);
 129      echo $renderer->import_setting_mappings($data, $importer);
 130      echo $OUTPUT->footer();
 131      exit(0);
 132  }
 133  
 134  if ($action == 'finishimport' && confirm_sesskey()) {
 135      data_print_header($course, $cm, $data, false);
 136      $overwritesettings = optional_param('overwritesettings', false, PARAM_BOOL);
 137  
 138      if (!$fullname) {
 139          $presetdir = $CFG->tempdir . '/forms/' . required_param('directory', PARAM_FILE);
 140          if (!file_exists($presetdir) || !is_dir($presetdir)) {
 141              throw new moodle_exception('cannotimport', 'error');
 142          }
 143          $importer = new data_preset_upload_importer($course, $cm, $data, $presetdir);
 144      } else {
 145          $importer = new data_preset_existing_importer($course, $cm, $data, $fullname);
 146      }
 147  
 148      $importer->import($overwritesettings);
 149      $strimportsuccess = get_string('importsuccess', 'data');
 150      $straddentries = get_string('addentries', 'data');
 151      $strtodatabase = get_string('todatabase', 'data');
 152  
 153      if (!$DB->get_records('data_records', array('dataid' => $data->id))) {
 154          echo $OUTPUT->notification("$strimportsuccess <a href='edit.php?d=$data->id'>$straddentries</a> $strtodatabase",
 155              'notifysuccess');
 156      } else {
 157          echo $OUTPUT->notification("$strimportsuccess", 'notifysuccess');
 158      }
 159  
 160      echo $OUTPUT->continue_button(new moodle_url('/mod/data/field.php', ['d' => $data->id]));
 161      echo $OUTPUT->footer();
 162      exit;
 163  }
 164  
 165  switch ($mode) {
 166  
 167      case 'add':    ///add a new field
 168          if (confirm_sesskey() and $fieldinput = data_submitted()){
 169  
 170              //$fieldinput->name = data_clean_field_name($fieldinput->name);
 171  
 172          /// Only store this new field if it doesn't already exist.
 173              if (($fieldinput->name == '') or data_fieldname_exists($fieldinput->name, $data->id)) {
 174  
 175                  $displaynoticebad = get_string('invalidfieldname','data');
 176  
 177              } else {
 178  
 179              /// Check for arrays and convert to a comma-delimited string
 180                  data_convert_arrays_to_strings($fieldinput);
 181  
 182              /// Create a field object to collect and store the data safely
 183                  $type = required_param('type', PARAM_FILE);
 184                  $field = data_get_field_new($type, $data);
 185  
 186                  if (!empty($validationerrors = $field->validate($fieldinput))) {
 187                      $displaynoticebad = html_writer::alist($validationerrors);
 188                      $mode = 'new';
 189                      $newtype = $type;
 190                      break;
 191                  }
 192  
 193                  $field->define_field($fieldinput);
 194                  $field->insert_field();
 195  
 196              /// Update some templates
 197                  data_append_new_field_to_templates($data, $fieldinput->name);
 198  
 199                  $displaynoticegood = get_string('fieldadded','data');
 200              }
 201          }
 202          break;
 203  
 204  
 205      case 'update':    ///update a field
 206          if (confirm_sesskey() and $fieldinput = data_submitted()){
 207  
 208              //$fieldinput->name = data_clean_field_name($fieldinput->name);
 209  
 210              if (($fieldinput->name == '') or data_fieldname_exists($fieldinput->name, $data->id, $fieldinput->fid)) {
 211  
 212                  $displaynoticebad = get_string('invalidfieldname','data');
 213  
 214              } else {
 215              /// Check for arrays and convert to a comma-delimited string
 216                  data_convert_arrays_to_strings($fieldinput);
 217  
 218              /// Create a field object to collect and store the data safely
 219                  $field = data_get_field_from_id($fid, $data);
 220                  if (!empty($validationerrors = $field->validate($fieldinput))) {
 221                      $displaynoticebad = html_writer::alist($validationerrors);
 222                      $mode = 'display';
 223                      break;
 224                  }
 225                  $oldfieldname = $field->field->name;
 226  
 227                  $field->field->name = $fieldinput->name;
 228                  $field->field->description = $fieldinput->description;
 229                  $field->field->required = !empty($fieldinput->required) ? 1 : 0;
 230  
 231                  for ($i=1; $i<=10; $i++) {
 232                      if (isset($fieldinput->{'param'.$i})) {
 233                          $field->field->{'param'.$i} = $fieldinput->{'param'.$i};
 234                      } else {
 235                          $field->field->{'param'.$i} = '';
 236                      }
 237                  }
 238  
 239                  $field->update_field();
 240  
 241              /// Update the templates.
 242                  data_replace_field_in_templates($data, $oldfieldname, $field->field->name);
 243  
 244                  $displaynoticegood = get_string('fieldupdated','data');
 245              }
 246          }
 247          break;
 248  
 249  
 250      case 'delete':    // Delete a field
 251          if (confirm_sesskey()){
 252  
 253              if ($confirm = optional_param('confirm', 0, PARAM_INT)) {
 254  
 255  
 256                  // Delete the field completely
 257                  if ($field = data_get_field_from_id($fid, $data)) {
 258                      $field->delete_field();
 259  
 260                      // Update the templates.
 261                      data_replace_field_in_templates($data, $field->field->name, '');
 262  
 263                      // Update the default sort field
 264                      if ($fid == $data->defaultsort) {
 265                          $rec = new stdClass();
 266                          $rec->id = $data->id;
 267                          $rec->defaultsort = 0;
 268                          $rec->defaultsortdir = 0;
 269                          $DB->update_record('data', $rec);
 270                      }
 271  
 272                      $displaynoticegood = get_string('fielddeleted', 'data');
 273                  }
 274  
 275              } else {
 276  
 277                  data_print_header($course,$cm,$data, false);
 278                  echo $OUTPUT->heading(get_string('deletefield', 'data'), 2, 'mb-4');
 279  
 280                  // Print confirmation message.
 281                  $field = data_get_field_from_id($fid, $data);
 282  
 283                  if ($field->type === 'unknown') {
 284                      $fieldtypename = get_string('unknown', 'data');
 285                  } else {
 286                      $fieldtypename = $field->name();
 287                  }
 288                  echo $OUTPUT->confirm('<strong>'.$fieldtypename.': '.$field->field->name.'</strong><br /><br />'.
 289                              get_string('confirmdeletefield', 'data'),
 290                              'field.php?d='.$data->id.'&mode=delete&fid='.$fid.'&confirm=1',
 291                              'field.php?d='.$data->id);
 292  
 293                  echo $OUTPUT->footer();
 294                  exit;
 295              }
 296          }
 297          break;
 298  
 299  
 300      case 'sort':    // Set the default sort parameters
 301          if (confirm_sesskey()) {
 302              $rec = new stdClass();
 303              $rec->id = $data->id;
 304              $rec->defaultsort = $defaultsort;
 305              $rec->defaultsortdir = $defaultsortdir;
 306  
 307              $DB->update_record('data', $rec);
 308              redirect($CFG->wwwroot.'/mod/data/field.php?d='.$data->id, get_string('changessaved'), 2);
 309              exit;
 310          }
 311          break;
 312  
 313      case 'import':
 314          $PAGE->navbar->add(get_string('importpreset', 'data'));
 315          $fieldactionbar = $actionbar->get_fields_action_bar();
 316          data_print_header($course, $cm, $data, false, $fieldactionbar);
 317  
 318          echo $OUTPUT->heading(get_string('importpreset', 'data'), 2, 'mb-4');
 319          echo $formimportzip->display();
 320          echo $OUTPUT->footer();
 321          exit;
 322  
 323      case 'usepreset':
 324          $PAGE->navbar->add(get_string('usestandard', 'data'));
 325          $fieldactionbar = $actionbar->get_fields_action_bar();
 326          data_print_header($course, $cm, $data, false, $fieldactionbar);
 327  
 328          if ($action === 'select') {
 329              if (!empty($fullname)) {
 330                  echo $OUTPUT->heading(get_string('usestandard', 'data'), 2, 'mb-4');
 331                  $importer = new data_preset_existing_importer($course, $cm, $data, $fullname);
 332                  echo $renderer->import_setting_mappings($data, $importer);
 333              }
 334          } else {
 335              echo $OUTPUT->heading(get_string('presets', 'data'), 2, 'mb-4');
 336              $presets = data_get_available_presets($context);
 337              $presetstable = new \mod_data\output\presets($data->id, $presets,
 338                  new \moodle_url('/mod/data/field.php'));
 339              echo $renderer->render_presets($presetstable, false);
 340          }
 341          echo $OUTPUT->footer();
 342          exit;
 343  
 344      default:
 345          break;
 346  }
 347  
 348  
 349  
 350  /// Print the browsing interface
 351  
 352  ///get the list of possible fields (plugins)
 353  $plugins = core_component::get_plugin_list('datafield');
 354  $menufield = array();
 355  
 356  foreach ($plugins as $plugin=>$fulldir){
 357      if (!is_dir($fulldir)) {
 358          continue;
 359      }
 360      $menufield[$plugin] = get_string('pluginname', 'datafield_'.$plugin);    //get from language files
 361  }
 362  asort($menufield);    //sort in alphabetical order
 363  $PAGE->force_settings_menu(true);
 364  
 365  $PAGE->set_pagetype('mod-data-field-' . $newtype);
 366  if (($mode == 'new') && (!empty($newtype))) { // Adding a new field.
 367      data_print_header($course, $cm, $data,'fields');
 368      echo $OUTPUT->heading(get_string('newfield', 'data'));
 369  
 370      $field = data_get_field_new($newtype, $data);
 371      $field->display_edit_field();
 372  
 373  } else if ($mode == 'display' && confirm_sesskey()) { /// Display/edit existing field
 374      data_print_header($course, $cm, $data,'fields');
 375      echo $OUTPUT->heading(get_string('editfield', 'data'));
 376  
 377      $field = data_get_field_from_id($fid, $data);
 378      $field->display_edit_field();
 379  
 380  } else {                                              /// Display the main listing of all fields
 381      $fieldactionbar = $actionbar->get_fields_action_bar(true, true, true);
 382      data_print_header($course, $cm, $data, 'fields', $fieldactionbar);
 383      echo $OUTPUT->heading(get_string('managefields', 'data'), 2, 'mb-4');
 384  
 385      if (!$DB->record_exists('data_fields', array('dataid'=>$data->id))) {
 386          echo $OUTPUT->notification(get_string('nofieldindatabase','data'));  // nothing in database
 387          echo $OUTPUT->notification(get_string('pleaseaddsome','data', 'preset.php?id='.$cm->id));      // link to presets
 388  
 389      } else {    //else print quiz style list of fields
 390  
 391          $table = new html_table();
 392          $table->head = array(
 393              get_string('fieldname', 'data'),
 394              get_string('type', 'data'),
 395              get_string('required', 'data'),
 396              get_string('fielddescription', 'data'),
 397              get_string('action', 'data'),
 398          );
 399          $table->align = array('left', 'left', 'left', 'left');
 400          $table->wrap = array(false,false,false,false);
 401  
 402          if ($fff = $DB->get_records('data_fields', array('dataid'=>$data->id),'id')){
 403              $missingfieldtypes = [];
 404              foreach ($fff as $ff) {
 405  
 406                  $field = data_get_field($ff, $data);
 407  
 408                  $baseurl = new moodle_url('/mod/data/field.php', array(
 409                      'd'         => $data->id,
 410                      'fid'       => $field->field->id,
 411                      'sesskey'   => sesskey(),
 412                  ));
 413  
 414                  $displayurl = new moodle_url($baseurl, array(
 415                      'mode'      => 'display',
 416                  ));
 417  
 418                  $deleteurl = new moodle_url($baseurl, array(
 419                      'mode'      => 'delete',
 420                  ));
 421  
 422                  // It display a notification when the field type does not exist.
 423                  $deletelink = html_writer::link($deleteurl, $OUTPUT->pix_icon('t/delete', get_string('delete')));
 424                  $editlink = html_writer::link($displayurl, $OUTPUT->pix_icon('t/edit', get_string('edit')));
 425                  if ($field->type === 'unknown') {
 426                      $missingfieldtypes[] = $field->field->name;
 427                      $fieldnamedata = $field->field->name;
 428                      $fieltypedata = $field->field->type;
 429                      $fieldlinkdata = $deletelink;
 430                  } else {
 431                      $fieldnamedata = html_writer::link($displayurl, $field->field->name);
 432                      $fieltypedata = $field->image() . '&nbsp;' . $field->name();
 433                      $fieldlinkdata = $editlink . '&nbsp;' . $deletelink;
 434                  }
 435  
 436                  $table->data[] = [
 437                      $fieldnamedata,
 438                      $fieltypedata,
 439                      $field->field->required ? get_string('yes') : get_string('no'),
 440                      shorten_text($field->field->description, 30),
 441                      $fieldlinkdata
 442                  ];
 443              }
 444              if (!empty($missingfieldtypes)) {
 445                  echo $OUTPUT->notification(get_string('missingfieldtypes', 'data') . html_writer::alist($missingfieldtypes));
 446              }
 447          }
 448          echo html_writer::table($table);
 449      }
 450  
 451      echo '<div class="sortdefault">';
 452      echo '<form id="sortdefault" action="'.$CFG->wwwroot.'/mod/data/field.php" method="get">';
 453      echo '<div>';
 454      echo '<input type="hidden" name="d" value="'.$data->id.'" />';
 455      echo '<input type="hidden" name="mode" value="sort" />';
 456      echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
 457      echo '<label for="defaultsort">'.get_string('defaultsortfield','data').'</label>';
 458      echo '<select id="defaultsort" name="defaultsort" class="custom-select">';
 459      if ($fields = $DB->get_records('data_fields', array('dataid'=>$data->id))) {
 460          echo '<optgroup label="'.get_string('fields', 'data').'">';
 461          foreach ($fields as $field) {
 462              if ($data->defaultsort == $field->id) {
 463                  echo '<option value="'.$field->id.'" selected="selected">'.$field->name.'</option>';
 464              } else {
 465                  echo '<option value="'.$field->id.'">'.$field->name.'</option>';
 466              }
 467          }
 468          echo '</optgroup>';
 469      }
 470      $options = array();
 471      $options[DATA_TIMEADDED]    = get_string('timeadded', 'data');
 472  // TODO: we will need to change defaultsort db to unsinged to make these work in 2.0
 473  /*        $options[DATA_TIMEMODIFIED] = get_string('timemodified', 'data');
 474      $options[DATA_FIRSTNAME]    = get_string('authorfirstname', 'data');
 475      $options[DATA_LASTNAME]     = get_string('authorlastname', 'data');
 476      if ($data->approval and has_capability('mod/data:approve', $context)) {
 477          $options[DATA_APPROVED] = get_string('approved', 'data');
 478      }*/
 479      echo '<optgroup label="'.get_string('other', 'data').'">';
 480      foreach ($options as $key => $name) {
 481          if ($data->defaultsort == $key) {
 482              echo '<option value="'.$key.'" selected="selected">'.$name.'</option>';
 483          } else {
 484              echo '<option value="'.$key.'">'.$name.'</option>';
 485          }
 486      }
 487      echo '</optgroup>';
 488      echo '</select>';
 489  
 490      $options = array(0 => get_string('ascending', 'data'),
 491                       1 => get_string('descending', 'data'));
 492      echo html_writer::label(get_string('sortby'), 'menudefaultsortdir', false, array('class' => 'accesshide'));
 493      echo html_writer::select($options, 'defaultsortdir', $data->defaultsortdir, false, array('class' => 'custom-select'));
 494      echo '<input type="submit" class="btn btn-secondary ml-1" value="'.get_string('save', 'data').'" />';
 495      echo '</div>';
 496      echo '</form>';
 497      echo '</div>';
 498  
 499  }
 500  
 501  /// Finish the page
 502  echo $OUTPUT->footer();
 503