Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.
/mod/data/ -> field.php (source)

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          '&nbsp;',
 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() . '&nbsp;' . $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();