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.

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  // 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  
  26  require_once(__DIR__ . '/../../config.php');
  27  require_once($CFG->dirroot.'/mod/quiz/lib.php');
  28  require_once($CFG->dirroot.'/mod/quiz/locallib.php');
  29  require_once($CFG->dirroot.'/mod/quiz/override_form.php');
  30  
  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  
  40      if (! $override = $DB->get_record('quiz_overrides', array('id' => $overrideid))) {
  41          throw new \moodle_exception('invalidoverrideid', 'quiz');
  42      }
  43      if (! $quiz = $DB->get_record('quiz', array('id' => $override->quiz))) {
  44          throw new \moodle_exception('invalidcoursemodule');
  45      }
  46      list($course, $cm) = get_course_and_cm_from_instance($quiz, 'quiz');
  47  
  48  } else if ($cmid) {
  49      list($course, $cm) = get_course_and_cm_from_cmid($cmid, 'quiz');
  50      $quiz = $DB->get_record('quiz', array('id' => $cm->instance), '*', MUST_EXIST);
  51  
  52  } else {
  53      throw new \moodle_exception('invalidcoursemodule');
  54  }
  55  $course = $DB->get_record('course', array('id'=>$cm->course), '*', MUST_EXIST);
  56  
  57  $url = new moodle_url('/mod/quiz/overrideedit.php');
  58  if ($action) {
  59      $url->param('action', $action);
  60  }
  61  if ($overrideid) {
  62      $url->param('id', $overrideid);
  63  } else {
  64      $url->param('cmid', $cmid);
  65  }
  66  
  67  $PAGE->set_url($url);
  68  
  69  // Activate the secondary nav tab.
  70  $PAGE->set_secondary_active_tab("mod_quiz_useroverrides");
  71  
  72  require_login($course, false, $cm);
  73  
  74  $context = context_module::instance($cm->id);
  75  
  76  // Add or edit an override.
  77  require_capability('mod/quiz:manageoverrides', $context);
  78  
  79  if ($overrideid) {
  80      // Editing an override.
  81      $data = clone $override;
  82  
  83      if ($override->groupid) {
  84          if (!groups_group_visible($override->groupid, $course, $cm)) {
  85              throw new \moodle_exception('invalidoverrideid', 'quiz');
  86          }
  87      } else {
  88          if (!groups_user_groups_visible($course, $override->userid, $cm)) {
  89              throw new \moodle_exception('invalidoverrideid', 'quiz');
  90          }
  91      }
  92  } else {
  93      // Creating a new override.
  94      $data = new stdClass();
  95  }
  96  
  97  // Merge quiz defaults with data.
  98  $keys = array('timeopen', 'timeclose', 'timelimit', 'attempts', 'password');
  99  foreach ($keys as $key) {
 100      if (!isset($data->{$key}) || $reset) {
 101          $data->{$key} = $quiz->{$key};
 102      }
 103  }
 104  
 105  // If we are duplicating an override, then clear the user/group and override id
 106  // since they will change.
 107  if ($action === 'duplicate') {
 108      $override->id = null;
 109      $override->userid = null;
 110      $override->groupid = null;
 111  }
 112  
 113  // True if group-based override.
 114  $groupmode = !empty($data->groupid) || ($action === 'addgroup' && empty($overrideid));
 115  
 116  $overridelisturl = new moodle_url('/mod/quiz/overrides.php', array('cmid'=>$cm->id));
 117  if (!$groupmode) {
 118      $overridelisturl->param('mode', 'user');
 119  }
 120  
 121  // Setup the form.
 122  $mform = new quiz_override_form($url, $cm, $quiz, $context, $groupmode, $override);
 123  $mform->set_data($data);
 124  
 125  if ($mform->is_cancelled()) {
 126      redirect($overridelisturl);
 127  
 128  } else if (optional_param('resetbutton', 0, PARAM_ALPHA)) {
 129      $url->param('reset', true);
 130      redirect($url);
 131  
 132  } else if ($fromform = $mform->get_data()) {
 133      // Process the data.
 134      $fromform->quiz = $quiz->id;
 135  
 136      // Replace unchanged values with null.
 137      foreach ($keys as $key) {
 138          if ($fromform->{$key} == $quiz->{$key}) {
 139              $fromform->{$key} = null;
 140          }
 141      }
 142  
 143      // See if we are replacing an existing override.
 144      $userorgroupchanged = false;
 145      if (empty($override->id)) {
 146          $userorgroupchanged = true;
 147      } else if (!empty($fromform->userid)) {
 148          $userorgroupchanged = $fromform->userid !== $override->userid;
 149      } else {
 150          $userorgroupchanged = $fromform->groupid !== $override->groupid;
 151      }
 152  
 153      if ($userorgroupchanged) {
 154          $conditions = array(
 155                  'quiz' => $quiz->id,
 156                  'userid' => empty($fromform->userid)? null : $fromform->userid,
 157                  'groupid' => empty($fromform->groupid)? null : $fromform->groupid);
 158          if ($oldoverride = $DB->get_record('quiz_overrides', $conditions)) {
 159              // There is an old override, so we merge any new settings on top of
 160              // the older override.
 161              foreach ($keys as $key) {
 162                  if (is_null($fromform->{$key})) {
 163                      $fromform->{$key} = $oldoverride->{$key};
 164                  }
 165              }
 166              // Set the course module id before calling quiz_delete_override().
 167              $quiz->cmid = $cm->id;
 168              quiz_delete_override($quiz, $oldoverride->id);
 169          }
 170      }
 171  
 172      // Set the common parameters for one of the events we may be triggering.
 173      $params = array(
 174          'context' => $context,
 175          'other' => array(
 176              'quizid' => $quiz->id
 177          )
 178      );
 179      if (!empty($override->id)) {
 180          $fromform->id = $override->id;
 181          $DB->update_record('quiz_overrides', $fromform);
 182          $cachekey = $groupmode ? "{$fromform->quiz}_g_{$fromform->groupid}" : "{$fromform->quiz}_u_{$fromform->userid}";
 183          cache::make('mod_quiz', 'overrides')->delete($cachekey);
 184  
 185          // Determine which override updated event to fire.
 186          $params['objectid'] = $override->id;
 187          if (!$groupmode) {
 188              $params['relateduserid'] = $fromform->userid;
 189              $event = \mod_quiz\event\user_override_updated::create($params);
 190          } else {
 191              $params['other']['groupid'] = $fromform->groupid;
 192              $event = \mod_quiz\event\group_override_updated::create($params);
 193          }
 194  
 195          // Trigger the override updated event.
 196          $event->trigger();
 197      } else {
 198          unset($fromform->id);
 199          $fromform->id = $DB->insert_record('quiz_overrides', $fromform);
 200          $cachekey = $groupmode ? "{$fromform->quiz}_g_{$fromform->groupid}" : "{$fromform->quiz}_u_{$fromform->userid}";
 201          cache::make('mod_quiz', 'overrides')->delete($cachekey);
 202  
 203          // Determine which override created event to fire.
 204          $params['objectid'] = $fromform->id;
 205          if (!$groupmode) {
 206              $params['relateduserid'] = $fromform->userid;
 207              $event = \mod_quiz\event\user_override_created::create($params);
 208          } else {
 209              $params['other']['groupid'] = $fromform->groupid;
 210              $event = \mod_quiz\event\group_override_created::create($params);
 211          }
 212  
 213          // Trigger the override created event.
 214          $event->trigger();
 215      }
 216  
 217      quiz_update_open_attempts(array('quizid'=>$quiz->id));
 218      if ($groupmode) {
 219          // Priorities may have shifted, so we need to update all of the calendar events for group overrides.
 220          quiz_update_events($quiz);
 221      } else {
 222          // User override. We only need to update the calendar event for this user override.
 223          quiz_update_events($quiz, $fromform);
 224      }
 225  
 226      if (!empty($fromform->submitbutton)) {
 227          redirect($overridelisturl);
 228      }
 229  
 230      // The user pressed the 'again' button, so redirect back to this page.
 231      $url->remove_params('cmid');
 232      $url->param('action', 'duplicate');
 233      $url->param('id', $fromform->id);
 234      redirect($url);
 235  
 236  }
 237  
 238  // Print the form.
 239  $pagetitle = get_string('editoverride', 'quiz');
 240  $PAGE->navbar->add($pagetitle);
 241  $PAGE->set_pagelayout('admin');
 242  $PAGE->add_body_class('limitedwidth');
 243  $PAGE->set_title($pagetitle);
 244  $PAGE->set_heading($course->fullname);
 245  $PAGE->activityheader->set_attrs([
 246      "title" => format_string($quiz->name, true, array('context' => $context)),
 247      "description" => "",
 248      "hidecompletion" => true
 249  ]);
 250  echo $OUTPUT->header();
 251  
 252  $mform->display();
 253  
 254  echo $OUTPUT->footer();