Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.

Differences Between: [Versions 310 and 403] [Versions 311 and 403] [Versions 39 and 403] [Versions 400 and 403] [Versions 401 and 403]

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * This page handles editing and creation of quiz overrides
  19   *
  20   * @package   mod_quiz
  21   * @copyright 2010 Matt Petro
  22   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  use mod_quiz\form\edit_override_form;
  26  use mod_quiz\quiz_settings;
  27  
  28  require_once(__DIR__ . '/../../config.php');
  29  require_once($CFG->dirroot.'/mod/quiz/lib.php');
  30  require_once($CFG->dirroot.'/mod/quiz/locallib.php');
  31  
  32  $cmid = optional_param('cmid', 0, PARAM_INT);
  33  $overrideid = optional_param('id', 0, PARAM_INT);
  34  $action = optional_param('action', null, PARAM_ALPHA);
  35  $reset = optional_param('reset', false, PARAM_BOOL);
  36  
  37  $override = null;
  38  if ($overrideid) {
  39      $override = $DB->get_record('quiz_overrides', ['id' => $overrideid], '*', MUST_EXIST);
  40      $quizobj = quiz_settings::create($override->quiz);
  41  } else {
  42      $quizobj = quiz_settings::create_for_cmid($cmid);
  43  }
  44  
  45  $quiz = $quizobj->get_quiz();
  46  $cm = $quizobj->get_cm();
  47  $course = $quizobj->get_course();
  48  $context = $quizobj->get_context();
  49  
  50  $url = new moodle_url('/mod/quiz/overrideedit.php');
  51  if ($action) {
  52      $url->param('action', $action);
  53  }
  54  if ($overrideid) {
  55      $url->param('id', $overrideid);
  56  } else {
  57      $url->param('cmid', $cmid);
  58  }
  59  
  60  $PAGE->set_url($url);
  61  
  62  // Activate the secondary nav tab.
  63  $PAGE->set_secondary_active_tab("mod_quiz_useroverrides");
  64  
  65  require_login($course, false, $cm);
  66  
  67  // Add or edit an override.
  68  require_capability('mod/quiz:manageoverrides', $context);
  69  
  70  if ($overrideid) {
  71      // Editing an override.
  72      $data = clone $override;
  73  
  74      if ($override->groupid) {
  75          if (!groups_group_visible($override->groupid, $course, $cm)) {
  76              throw new \moodle_exception('invalidoverrideid', 'quiz');
  77          }
  78      } else {
  79          if (!groups_user_groups_visible($course, $override->userid, $cm)) {
  80              throw new \moodle_exception('invalidoverrideid', 'quiz');
  81          }
  82      }
  83  } else {
  84      // Creating a new override.
  85      $data = new stdClass();
  86  }
  87  
  88  // Merge quiz defaults with data.
  89  $keys = ['timeopen', 'timeclose', 'timelimit', 'attempts', 'password'];
  90  foreach ($keys as $key) {
  91      if (!isset($data->{$key}) || $reset) {
  92          $data->{$key} = $quiz->{$key};
  93      }
  94  }
  95  
  96  // If we are duplicating an override, then clear the user/group and override id
  97  // since they will change.
  98  if ($action === 'duplicate') {
  99      $override->id = null;
 100      $override->userid = null;
 101      $override->groupid = null;
 102  }
 103  
 104  // True if group-based override.
 105  $groupmode = !empty($data->groupid) || ($action === 'addgroup' && empty($overrideid));
 106  
 107  $overridelisturl = new moodle_url('/mod/quiz/overrides.php', ['cmid' => $cm->id]);
 108  if (!$groupmode) {
 109      $overridelisturl->param('mode', 'user');
 110  }
 111  
 112  // Setup the form.
 113  $mform = new edit_override_form($url, $cm, $quiz, $context, $groupmode, $override);
 114  $mform->set_data($data);
 115  
 116  if ($mform->is_cancelled()) {
 117      redirect($overridelisturl);
 118  
 119  } else if (optional_param('resetbutton', 0, PARAM_ALPHA)) {
 120      $url->param('reset', true);
 121      redirect($url);
 122  
 123  } else if ($fromform = $mform->get_data()) {
 124      // Process the data.
 125      $fromform->quiz = $quiz->id;
 126  
 127      // Replace unchanged values with null.
 128      foreach ($keys as $key) {
 129          if ($fromform->{$key} == $quiz->{$key}) {
 130              $fromform->{$key} = null;
 131          }
 132      }
 133  
 134      // See if we are replacing an existing override.
 135      $userorgroupchanged = false;
 136      if (empty($override->id)) {
 137          $userorgroupchanged = true;
 138      } else if (!empty($fromform->userid)) {
 139          $userorgroupchanged = $fromform->userid !== $override->userid;
 140      } else {
 141          $userorgroupchanged = $fromform->groupid !== $override->groupid;
 142      }
 143  
 144      if ($userorgroupchanged) {
 145          $conditions = [
 146                  'quiz' => $quiz->id,
 147                  'userid' => empty($fromform->userid) ? null : $fromform->userid,
 148                  'groupid' => empty($fromform->groupid) ? null : $fromform->groupid];
 149          if ($oldoverride = $DB->get_record('quiz_overrides', $conditions)) {
 150              // There is an old override, so we merge any new settings on top of
 151              // the older override.
 152              foreach ($keys as $key) {
 153                  if (is_null($fromform->{$key})) {
 154                      $fromform->{$key} = $oldoverride->{$key};
 155                  }
 156              }
 157              // Set the course module id before calling quiz_delete_override().
 158              $quiz->cmid = $cm->id;
 159              quiz_delete_override($quiz, $oldoverride->id);
 160          }
 161      }
 162  
 163      // Set the common parameters for one of the events we may be triggering.
 164      $params = [
 165          'context' => $context,
 166          'other' => [
 167              'quizid' => $quiz->id
 168          ]
 169      ];
 170      if (!empty($override->id)) {
 171          $fromform->id = $override->id;
 172          $DB->update_record('quiz_overrides', $fromform);
 173          $cachekey = $groupmode ? "{$fromform->quiz}_g_{$fromform->groupid}" : "{$fromform->quiz}_u_{$fromform->userid}";
 174          cache::make('mod_quiz', 'overrides')->delete($cachekey);
 175  
 176          // Determine which override updated event to fire.
 177          $params['objectid'] = $override->id;
 178          if (!$groupmode) {
 179              $params['relateduserid'] = $fromform->userid;
 180              $event = \mod_quiz\event\user_override_updated::create($params);
 181          } else {
 182              $params['other']['groupid'] = $fromform->groupid;
 183              $event = \mod_quiz\event\group_override_updated::create($params);
 184          }
 185  
 186          // Trigger the override updated event.
 187          $event->trigger();
 188      } else {
 189          unset($fromform->id);
 190          $fromform->id = $DB->insert_record('quiz_overrides', $fromform);
 191          $cachekey = $groupmode ? "{$fromform->quiz}_g_{$fromform->groupid}" : "{$fromform->quiz}_u_{$fromform->userid}";
 192          cache::make('mod_quiz', 'overrides')->delete($cachekey);
 193  
 194          // Determine which override created event to fire.
 195          $params['objectid'] = $fromform->id;
 196          if (!$groupmode) {
 197              $params['relateduserid'] = $fromform->userid;
 198              $event = \mod_quiz\event\user_override_created::create($params);
 199          } else {
 200              $params['other']['groupid'] = $fromform->groupid;
 201              $event = \mod_quiz\event\group_override_created::create($params);
 202          }
 203  
 204          // Trigger the override created event.
 205          $event->trigger();
 206      }
 207  
 208      quiz_update_open_attempts(['quizid' => $quiz->id]);
 209      if ($groupmode) {
 210          // Priorities may have shifted, so we need to update all of the calendar events for group overrides.
 211          quiz_update_events($quiz);
 212      } else {
 213          // User override. We only need to update the calendar event for this user override.
 214          quiz_update_events($quiz, $fromform);
 215      }
 216  
 217      if (!empty($fromform->submitbutton)) {
 218          redirect($overridelisturl);
 219      }
 220  
 221      // The user pressed the 'again' button, so redirect back to this page.
 222      $url->remove_params('cmid');
 223      $url->param('action', 'duplicate');
 224      $url->param('id', $fromform->id);
 225      redirect($url);
 226  
 227  }
 228  
 229  // Print the form.
 230  $pagetitle = get_string('editoverride', 'quiz');
 231  $PAGE->navbar->add($pagetitle);
 232  $PAGE->set_pagelayout('admin');
 233  $PAGE->add_body_class('limitedwidth');
 234  $PAGE->set_title($pagetitle);
 235  $PAGE->set_heading($course->fullname);
 236  $PAGE->activityheader->set_attrs([
 237      "title" => format_string($quiz->name, true, ['context' => $context]),
 238      "description" => "",
 239      "hidecompletion" => true
 240  ]);
 241  echo $OUTPUT->header();
 242  
 243  $mform->display();
 244  
 245  echo $OUTPUT->footer();