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.

Differences Between: [Versions 400 and 402] [Versions 400 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   * Base class for rules that restrict the ability to attempt a quiz.
  19   *
  20   * @package   mod_quiz
  21   * @copyright 2011 The Open University
  22   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  
  26  defined('MOODLE_INTERNAL') || die();
  27  
  28  require_once($CFG->dirroot . '/mod/quiz/locallib.php');
  29  
  30  
  31  /**
  32   * A base class that defines the interface for the various quiz access rules.
  33   * Most of the methods are defined in a slightly unnatural way because we either
  34   * want to say that access is allowed, or explain the reason why it is block.
  35   * Therefore instead of is_access_allowed(...) we have prevent_access(...) that
  36   * return false if access is permitted, or a string explanation (which is treated
  37   * as true) if access should be blocked. Slighly unnatural, but actually the easiest
  38   * way to implement this.
  39   *
  40   * @copyright 2009 Tim Hunt
  41   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  42   * @since     Moodle 2.2
  43   */
  44  abstract class quiz_access_rule_base {
  45      /** @var stdClass the quiz settings. */
  46      protected $quiz;
  47      /** @var quiz the quiz object. */
  48      protected $quizobj;
  49      /** @var int the time to use as 'now'. */
  50      protected $timenow;
  51  
  52      /**
  53       * Create an instance of this rule for a particular quiz.
  54       * @param quiz $quizobj information about the quiz in question.
  55       * @param int $timenow the time that should be considered as 'now'.
  56       */
  57      public function __construct($quizobj, $timenow) {
  58          $this->quizobj = $quizobj;
  59          $this->quiz = $quizobj->get_quiz();
  60          $this->timenow = $timenow;
  61      }
  62  
  63      /**
  64       * Return an appropriately configured instance of this rule, if it is applicable
  65       * to the given quiz, otherwise return null.
  66       * @param quiz $quizobj information about the quiz in question.
  67       * @param int $timenow the time that should be considered as 'now'.
  68       * @param bool $canignoretimelimits whether the current user is exempt from
  69       *      time limits by the mod/quiz:ignoretimelimits capability.
  70       * @return quiz_access_rule_base|null the rule, if applicable, else null.
  71       */
  72      public static function make(quiz $quizobj, $timenow, $canignoretimelimits) {
  73          return null;
  74      }
  75  
  76      /**
  77       * Whether or not a user should be allowed to start a new attempt at this quiz now.
  78       * @param int $numattempts the number of previous attempts this user has made.
  79       * @param object $lastattempt information about the user's last completed attempt.
  80       * @return string false if access should be allowed, a message explaining the
  81       *      reason if access should be prevented.
  82       */
  83      public function prevent_new_attempt($numprevattempts, $lastattempt) {
  84          return false;
  85      }
  86  
  87      /**
  88       * Whether the user should be blocked from starting a new attempt or continuing
  89       * an attempt now.
  90       * @return string false if access should be allowed, a message explaining the
  91       *      reason if access should be prevented.
  92       */
  93      public function prevent_access() {
  94          return false;
  95      }
  96  
  97      /**
  98       * @param int|null $attemptid the id of the current attempt, if there is one,
  99       *      otherwise null.
 100       * @return bool whether a check is required before the user starts/continues
 101       *      their attempt.
 102       */
 103      public function is_preflight_check_required($attemptid) {
 104          return false;
 105      }
 106  
 107      /**
 108       * Add any field you want to pre-flight check form. You should only do
 109       * something here if {@link is_preflight_check_required()} returned true.
 110       *
 111       * @param mod_quiz_preflight_check_form $quizform the form being built.
 112       * @param MoodleQuickForm $mform The wrapped MoodleQuickForm.
 113       * @param int|null $attemptid the id of the current attempt, if there is one,
 114       *      otherwise null.
 115       */
 116      public function add_preflight_check_form_fields(mod_quiz_preflight_check_form $quizform,
 117              MoodleQuickForm $mform, $attemptid) {
 118          // Do nothing by default.
 119      }
 120  
 121      /**
 122       * Validate the pre-flight check form submission. You should only do
 123       * something here if {@link is_preflight_check_required()} returned true.
 124       *
 125       * If the form validates, the user will be allowed to continue.
 126       *
 127       * @param array $data the submitted form data.
 128       * @param array $files any files in the submission.
 129       * @param array $errors the list of validation errors that is being built up.
 130       * @param int|null $attemptid the id of the current attempt, if there is one,
 131       *      otherwise null.
 132       * @return array the update $errors array;
 133       */
 134      public function validate_preflight_check($data, $files, $errors, $attemptid) {
 135          return $errors;
 136      }
 137  
 138      /**
 139       * The pre-flight check has passed. This is a chance to record that fact in
 140       * some way.
 141       * @param int|null $attemptid the id of the current attempt, if there is one,
 142       *      otherwise null.
 143       */
 144      public function notify_preflight_check_passed($attemptid) {
 145          // Do nothing by default.
 146      }
 147  
 148      /**
 149       * This is called when the current attempt at the quiz is finished. This is
 150       * used, for example by the password rule, to clear the flag in the session.
 151       */
 152      public function current_attempt_finished() {
 153          // Do nothing by default.
 154      }
 155  
 156      /**
 157       * Information, such as might be shown on the quiz view page, relating to this restriction.
 158       * There is no obligation to return anything. If it is not appropriate to tell students
 159       * about this rule, then just return ''.
 160       * @return mixed a message, or array of messages, explaining the restriction
 161       *         (may be '' if no message is appropriate).
 162       */
 163      public function description() {
 164          return '';
 165      }
 166  
 167      /**
 168       * If this rule can determine that this user will never be allowed another attempt at
 169       * this quiz, then return true. This is used so we can know whether to display a
 170       * final grade on the view page. This will only be called if there is not a currently
 171       * active attempt for this user.
 172       * @param int $numattempts the number of previous attempts this user has made.
 173       * @param object $lastattempt information about the user's last completed attempt.
 174       * @return bool true if this rule means that this user will never be allowed another
 175       * attempt at this quiz.
 176       */
 177      public function is_finished($numprevattempts, $lastattempt) {
 178          return false;
 179      }
 180  
 181      /**
 182       * If, because of this rule, the user has to finish their attempt by a certain time,
 183       * you should override this method to return the attempt end time.
 184       * @param object $attempt the current attempt
 185       * @return mixed the attempt close time, or false if there is no close time.
 186       */
 187      public function end_time($attempt) {
 188          return false;
 189      }
 190  
 191      /**
 192       * If the user should be shown a different amount of time than $timenow - $this->end_time(), then
 193       * override this method.  This is useful if the time remaining is large enough to be omitted.
 194       * @param object $attempt the current attempt
 195       * @param int $timenow the time now. We don't use $this->timenow, so we can
 196       * give the user a more accurate indication of how much time is left.
 197       * @return mixed the time left in seconds (can be negative) or false if there is no limit.
 198       */
 199      public function time_left_display($attempt, $timenow) {
 200          $endtime = $this->end_time($attempt);
 201          if ($endtime === false) {
 202              return false;
 203          }
 204          return $endtime - $timenow;
 205      }
 206  
 207      /**
 208       * @return boolean whether this rule requires that the attemp (and review)
 209       *      pages must be displayed in a pop-up window.
 210       */
 211      public function attempt_must_be_in_popup() {
 212          return false;
 213      }
 214  
 215      /**
 216       * @return array any options that are required for showing the attempt page
 217       *      in a popup window.
 218       */
 219      public function get_popup_options() {
 220          return array();
 221      }
 222  
 223      /**
 224       * Sets up the attempt (review or summary) page with any special extra
 225       * properties required by this rule. securewindow rule is an example of where
 226       * this is used.
 227       *
 228       * @param moodle_page $page the page object to initialise.
 229       */
 230      public function setup_attempt_page($page) {
 231          // Do nothing by default.
 232      }
 233  
 234      /**
 235       * It is possible for one rule to override other rules.
 236       *
 237       * The aim is that third-party rules should be able to replace sandard rules
 238       * if they want. See, for example MDL-13592.
 239       *
 240       * @return array plugin names of other rules that this one replaces.
 241       *      For example array('ipaddress', 'password').
 242       */
 243      public function get_superceded_rules() {
 244          return array();
 245      }
 246  
 247      /**
 248       * Add any fields that this rule requires to the quiz settings form. This
 249       * method is called from {@link mod_quiz_mod_form::definition()}, while the
 250       * security seciton is being built.
 251       * @param mod_quiz_mod_form $quizform the quiz settings form that is being built.
 252       * @param MoodleQuickForm $mform the wrapped MoodleQuickForm.
 253       */
 254      public static function add_settings_form_fields(
 255              mod_quiz_mod_form $quizform, MoodleQuickForm $mform) {
 256          // By default do nothing.
 257      }
 258  
 259      /**
 260       * Validate the data from any form fields added using {@link add_settings_form_fields()}.
 261       * @param array $errors the errors found so far.
 262       * @param array $data the submitted form data.
 263       * @param array $files information about any uploaded files.
 264       * @param mod_quiz_mod_form $quizform the quiz form object.
 265       * @return array $errors the updated $errors array.
 266       */
 267      public static function validate_settings_form_fields(array $errors,
 268              array $data, $files, mod_quiz_mod_form $quizform) {
 269  
 270          return $errors;
 271      }
 272  
 273      /**
 274       * @return array key => lang string any choices to add to the quiz Browser
 275       *      security settings menu.
 276       */
 277      public static function get_browser_security_choices() {
 278          return array();
 279      }
 280  
 281      /**
 282       * Save any submitted settings when the quiz settings form is submitted. This
 283       * is called from {@link quiz_after_add_or_update()} in lib.php.
 284       * @param object $quiz the data from the quiz form, including $quiz->id
 285       *      which is the id of the quiz being saved.
 286       */
 287      public static function save_settings($quiz) {
 288          // By default do nothing.
 289      }
 290  
 291      /**
 292       * Delete any rule-specific settings when the quiz is deleted. This is called
 293       * from {@link quiz_delete_instance()} in lib.php.
 294       * @param object $quiz the data from the database, including $quiz->id
 295       *      which is the id of the quiz being deleted.
 296       * @since Moodle 2.7.1, 2.6.4, 2.5.7
 297       */
 298      public static function delete_settings($quiz) {
 299          // By default do nothing.
 300      }
 301  
 302      /**
 303       * Return the bits of SQL needed to load all the settings from all the access
 304       * plugins in one DB query. The easiest way to understand what you need to do
 305       * here is probalby to read the code of {@link quiz_access_manager::load_settings()}.
 306       *
 307       * If you have some settings that cannot be loaded in this way, then you can
 308       * use the {@link get_extra_settings()} method instead, but that has
 309       * performance implications.
 310       *
 311       * @param int $quizid the id of the quiz we are loading settings for. This
 312       *     can also be accessed as quiz.id in the SQL. (quiz is a table alisas for {quiz}.)
 313       * @return array with three elements:
 314       *     1. fields: any fields to add to the select list. These should be alised
 315       *        if neccessary so that the field name starts the name of the plugin.
 316       *     2. joins: any joins (should probably be LEFT JOINS) with other tables that
 317       *        are needed.
 318       *     3. params: array of placeholder values that are needed by the SQL. You must
 319       *        used named placeholders, and the placeholder names should start with the
 320       *        plugin name, to avoid collisions.
 321       */
 322      public static function get_settings_sql($quizid) {
 323          return array('', '', array());
 324      }
 325  
 326      /**
 327       * You can use this method to load any extra settings your plugin has that
 328       * cannot be loaded efficiently with get_settings_sql().
 329       * @param int $quizid the quiz id.
 330       * @return array setting value name => value. The value names should all
 331       *      start with the name of your plugin to avoid collisions.
 332       */
 333      public static function get_extra_settings($quizid) {
 334          return array();
 335      }
 336  }