MDL-74923 quiz: move mod_quiz_display_options to classes folder

This commit is contained in:
Tim Hunt
2022-12-13 16:24:57 +00:00
parent 40a89d8a9a
commit cefbf74d02
20 changed files with 313 additions and 272 deletions
+2 -1
View File
@@ -25,6 +25,7 @@
defined('MOODLE_INTERNAL') || die();
use mod_quiz\question\display_options;
/**
* This class keeps track of the various access rules that apply to a particular
@@ -528,7 +529,7 @@ class quiz_access_manager {
}
$when = quiz_attempt_state($this->quizobj->get_quiz(), $attempt);
$reviewoptions = mod_quiz_display_options::make_from_quiz(
$reviewoptions = display_options::make_from_quiz(
$this->quizobj->get_quiz(), $when);
if (!$reviewoptions->attempt) {
+13 -12
View File
@@ -28,6 +28,7 @@
defined('MOODLE_INTERNAL') || die();
use mod_quiz\question\bank\qbank_helper;
use mod_quiz\question\display_options;
/**
@@ -476,7 +477,7 @@ class quiz {
* If $reviewoptions->attempt is false, meaning that students can't review this
* attempt at the moment, return an appropriate string explaining why.
*
* @param int $when One of the mod_quiz_display_options::DURING,
* @param int $when One of the display_options::DURING,
* IMMEDIATELY_AFTER, LATER_WHILE_OPEN or AFTER_CLOSE constants.
* @param bool $short if true, return a shorter string.
* @return string an appropraite message.
@@ -491,11 +492,11 @@ class quiz {
$dateformat = '';
}
if ($when == mod_quiz_display_options::DURING ||
$when == mod_quiz_display_options::IMMEDIATELY_AFTER) {
if ($when == display_options::DURING ||
$when == display_options::IMMEDIATELY_AFTER) {
return '';
} else if ($when == mod_quiz_display_options::LATER_WHILE_OPEN && $this->quiz->timeclose &&
$this->quiz->reviewattempt & mod_quiz_display_options::AFTER_CLOSE) {
} else if ($when == display_options::LATER_WHILE_OPEN && $this->quiz->timeclose &&
$this->quiz->reviewattempt & display_options::AFTER_CLOSE) {
return get_string('noreviewuntil' . $langstrsuffix, 'quiz',
userdate($this->quiz->timeclose, $dateformat));
} else {
@@ -631,7 +632,7 @@ class quiz_attempt {
/** @var array slot => page number for this slot. */
protected $questionpages;
/** @var mod_quiz_display_options cache for the appropriate review options. */
/** @var display_options cache for the appropriate review options. */
protected $reviewoptions = null;
// Constructor =============================================================
@@ -1080,7 +1081,7 @@ class quiz_attempt {
* If not, prints an error.
*/
public function check_review_capability() {
if ($this->get_attempt_state() == mod_quiz_display_options::IMMEDIATELY_AFTER) {
if ($this->get_attempt_state() == display_options::IMMEDIATELY_AFTER) {
$capability = 'mod/quiz:attempt';
} else {
$capability = 'mod/quiz:reviewmyattempts';
@@ -1132,7 +1133,7 @@ class quiz_attempt {
}
/**
* @return int one of the mod_quiz_display_options::DURING,
* @return int one of the display_options::DURING,
* IMMEDIATELY_AFTER, LATER_WHILE_OPEN or AFTER_CLOSE constants.
*/
public function get_attempt_state() {
@@ -1140,7 +1141,7 @@ class quiz_attempt {
}
/**
* Wrapper that the correct mod_quiz_display_options for this quiz at the
* Wrapper that the correct display_options for this quiz at the
* moment.
*
* @param bool $reviewing true for options when reviewing, false for when attempting.
@@ -1160,15 +1161,15 @@ class quiz_attempt {
return $this->reviewoptions;
} else {
$options = mod_quiz_display_options::make_from_quiz($this->get_quiz(),
mod_quiz_display_options::DURING);
$options = display_options::make_from_quiz($this->get_quiz(),
display_options::DURING);
$options->flags = quiz_get_flag_option($this->attempt, $this->quizobj->get_context());
return $options;
}
}
/**
* Wrapper that the correct mod_quiz_display_options for this quiz at the
* Wrapper that the correct display_options for this quiz at the
* moment.
*
* @param bool $reviewing true for review page, else attempt page.
@@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
use mod_quiz\question\display_options;
/**
* Structure step to restore one quiz activity
*
@@ -162,70 +164,70 @@ class restore_quiz_activity_structure_step extends restore_questions_activity_st
$oldreview = $data->review;
$data->reviewattempt =
mod_quiz_display_options::DURING |
display_options::DURING |
($oldreview & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_RESPONSES ?
mod_quiz_display_options::IMMEDIATELY_AFTER : 0) |
display_options::IMMEDIATELY_AFTER : 0) |
($oldreview & QUIZ_OLD_OPEN & QUIZ_OLD_RESPONSES ?
mod_quiz_display_options::LATER_WHILE_OPEN : 0) |
display_options::LATER_WHILE_OPEN : 0) |
($oldreview & QUIZ_OLD_CLOSED & QUIZ_OLD_RESPONSES ?
mod_quiz_display_options::AFTER_CLOSE : 0);
display_options::AFTER_CLOSE : 0);
$data->reviewcorrectness =
mod_quiz_display_options::DURING |
display_options::DURING |
($oldreview & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_SCORES ?
mod_quiz_display_options::IMMEDIATELY_AFTER : 0) |
display_options::IMMEDIATELY_AFTER : 0) |
($oldreview & QUIZ_OLD_OPEN & QUIZ_OLD_SCORES ?
mod_quiz_display_options::LATER_WHILE_OPEN : 0) |
display_options::LATER_WHILE_OPEN : 0) |
($oldreview & QUIZ_OLD_CLOSED & QUIZ_OLD_SCORES ?
mod_quiz_display_options::AFTER_CLOSE : 0);
display_options::AFTER_CLOSE : 0);
$data->reviewmarks =
mod_quiz_display_options::DURING |
display_options::DURING |
($oldreview & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_SCORES ?
mod_quiz_display_options::IMMEDIATELY_AFTER : 0) |
display_options::IMMEDIATELY_AFTER : 0) |
($oldreview & QUIZ_OLD_OPEN & QUIZ_OLD_SCORES ?
mod_quiz_display_options::LATER_WHILE_OPEN : 0) |
display_options::LATER_WHILE_OPEN : 0) |
($oldreview & QUIZ_OLD_CLOSED & QUIZ_OLD_SCORES ?
mod_quiz_display_options::AFTER_CLOSE : 0);
display_options::AFTER_CLOSE : 0);
$data->reviewspecificfeedback =
($oldreview & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_FEEDBACK ?
mod_quiz_display_options::DURING : 0) |
display_options::DURING : 0) |
($oldreview & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_FEEDBACK ?
mod_quiz_display_options::IMMEDIATELY_AFTER : 0) |
display_options::IMMEDIATELY_AFTER : 0) |
($oldreview & QUIZ_OLD_OPEN & QUIZ_OLD_FEEDBACK ?
mod_quiz_display_options::LATER_WHILE_OPEN : 0) |
display_options::LATER_WHILE_OPEN : 0) |
($oldreview & QUIZ_OLD_CLOSED & QUIZ_OLD_FEEDBACK ?
mod_quiz_display_options::AFTER_CLOSE : 0);
display_options::AFTER_CLOSE : 0);
$data->reviewgeneralfeedback =
($oldreview & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_GENERALFEEDBACK ?
mod_quiz_display_options::DURING : 0) |
display_options::DURING : 0) |
($oldreview & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_GENERALFEEDBACK ?
mod_quiz_display_options::IMMEDIATELY_AFTER : 0) |
display_options::IMMEDIATELY_AFTER : 0) |
($oldreview & QUIZ_OLD_OPEN & QUIZ_OLD_GENERALFEEDBACK ?
mod_quiz_display_options::LATER_WHILE_OPEN : 0) |
display_options::LATER_WHILE_OPEN : 0) |
($oldreview & QUIZ_OLD_CLOSED & QUIZ_OLD_GENERALFEEDBACK ?
mod_quiz_display_options::AFTER_CLOSE : 0);
display_options::AFTER_CLOSE : 0);
$data->reviewrightanswer =
($oldreview & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_ANSWERS ?
mod_quiz_display_options::DURING : 0) |
display_options::DURING : 0) |
($oldreview & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_ANSWERS ?
mod_quiz_display_options::IMMEDIATELY_AFTER : 0) |
display_options::IMMEDIATELY_AFTER : 0) |
($oldreview & QUIZ_OLD_OPEN & QUIZ_OLD_ANSWERS ?
mod_quiz_display_options::LATER_WHILE_OPEN : 0) |
display_options::LATER_WHILE_OPEN : 0) |
($oldreview & QUIZ_OLD_CLOSED & QUIZ_OLD_ANSWERS ?
mod_quiz_display_options::AFTER_CLOSE : 0);
display_options::AFTER_CLOSE : 0);
$data->reviewoverallfeedback =
0 |
($oldreview & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_OVERALLFEEDBACK ?
mod_quiz_display_options::IMMEDIATELY_AFTER : 0) |
display_options::IMMEDIATELY_AFTER : 0) |
($oldreview & QUIZ_OLD_OPEN & QUIZ_OLD_OVERALLFEEDBACK ?
mod_quiz_display_options::LATER_WHILE_OPEN : 0) |
display_options::LATER_WHILE_OPEN : 0) |
($oldreview & QUIZ_OLD_CLOSED & QUIZ_OLD_OVERALLFEEDBACK ?
mod_quiz_display_options::AFTER_CLOSE : 0);
display_options::AFTER_CLOSE : 0);
}
// The old popup column from from <= 2.1 need to be mapped to
+4 -4
View File
@@ -35,25 +35,25 @@ defined('MOODLE_INTERNAL') || die();
class mod_quiz_admin_review_setting extends admin_setting {
/**
* @var integer should match the constants defined in
* {@link mod_quiz_display_options}. Copied for performance reasons.
* {@see display_options}. Copied for performance reasons.
*/
const DURING = 0x10000;
/**
* @var integer should match the constants defined in
* {@link mod_quiz_display_options}. Copied for performance reasons.
* {@see display_options}. Copied for performance reasons.
*/
const IMMEDIATELY_AFTER = 0x01000;
/**
* @var integer should match the constants defined in
* {@link mod_quiz_display_options}. Copied for performance reasons.
* {@see display_options}. Copied for performance reasons.
*/
const LATER_WHILE_OPEN = 0x00100;
/**
* @var integer should match the constants defined in
* {@link mod_quiz_display_options}. Copied for performance reasons.
* {@see display_options}. Copied for performance reasons.
*/
const AFTER_CLOSE = 0x00010;
+2 -2
View File
@@ -194,8 +194,8 @@ class mod_quiz_external extends external_api {
(-1 means use decimalpoints.)', VALUE_OPTIONAL),
'reviewattempt' => new external_value(PARAM_INT, 'Whether users are allowed to review their quiz
attempts at various times. This is a bit field, decoded by the
mod_quiz_display_options class. It is formed by ORing together
the constants defined there.', VALUE_OPTIONAL),
\mod_quiz\question\display_options class. It is formed by ORing
together the constants defined there.', VALUE_OPTIONAL),
'reviewcorrectness' => new external_value(PARAM_INT, 'Whether users are allowed to review their quiz
attempts at various times.
A bit field, like reviewattempt.', VALUE_OPTIONAL),
@@ -0,0 +1,91 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace mod_quiz\question;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/question/engine/lib.php');
/**
* An extension of question_display_options that includes the extra options used
* by the quiz.
*
* @copyright 2022 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class display_options extends \question_display_options {
/**#@+
* @var integer bits used to indicate various times in relation to a
* quiz attempt.
*/
const DURING = 0x10000;
const IMMEDIATELY_AFTER = 0x01000;
const LATER_WHILE_OPEN = 0x00100;
const AFTER_CLOSE = 0x00010;
/**#@-*/
/**
* @var boolean if this is false, then the student is not allowed to review
* anything about the attempt.
*/
public $attempt = true;
/**
* @var boolean if this is false, then the student is not allowed to review
* anything about the attempt.
*/
public $overallfeedback = self::VISIBLE;
/**
* Set up the various options from the quiz settings, and a time constant.
* @param object $quiz the quiz settings.
* @param int $one of the {@link DURING}, {@link IMMEDIATELY_AFTER},
* {@link LATER_WHILE_OPEN} or {@link AFTER_CLOSE} constants.
* @return display_options set up appropriately.
*/
public static function make_from_quiz($quiz, $when) {
$options = new self();
$options->attempt = self::extract($quiz->reviewattempt, $when, true, false);
$options->correctness = self::extract($quiz->reviewcorrectness, $when);
$options->marks = self::extract($quiz->reviewmarks, $when,
self::MARK_AND_MAX, self::MAX_ONLY);
$options->feedback = self::extract($quiz->reviewspecificfeedback, $when);
$options->generalfeedback = self::extract($quiz->reviewgeneralfeedback, $when);
$options->rightanswer = self::extract($quiz->reviewrightanswer, $when);
$options->overallfeedback = self::extract($quiz->reviewoverallfeedback, $when);
$options->numpartscorrect = $options->feedback;
$options->manualcomment = $options->feedback;
if ($quiz->questiondecimalpoints != -1) {
$options->markdp = $quiz->questiondecimalpoints;
} else {
$options->markdp = $quiz->decimalpoints;
}
return $options;
}
protected static function extract($bitmask, $bit,
$whenset = self::VISIBLE, $whennotset = self::HIDDEN) {
if ($bitmask & $bit) {
return $whenset;
} else {
return $whennotset;
}
}
}
@@ -22,7 +22,7 @@ use context_course;
use core_user;
use moodle_recordset;
use question_display_options;
use mod_quiz_display_options;
use mod_quiz\question\display_options;
use quiz_attempt;
require_once($CFG->dirroot . '/mod/quiz/locallib.php');
@@ -103,7 +103,7 @@ class quiz_notify_attempt_manual_grading_completed extends \core\task\scheduled_
$quiz = quiz_update_effective_access($quiz, $attempt->userid);
$attemptobj = new quiz_attempt($attempt, $quiz, $cm, $course, false);
$options = mod_quiz_display_options::make_from_quiz($quiz, quiz_attempt_state($quiz, $attempt));
$options = display_options::make_from_quiz($quiz, quiz_attempt_state($quiz, $attempt));
if ($options->manualcomment == question_display_options::HIDDEN) {
// User cannot currently see the feedback, so don't message them.
+1 -1
View File
@@ -23,7 +23,7 @@
<FIELD NAME="grademethod" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="1" SEQUENCE="false" COMMENT="One of the values QUIZ_GRADEHIGHEST, QUIZ_GRADEAVERAGE, QUIZ_ATTEMPTFIRST or QUIZ_ATTEMPTLAST."/>
<FIELD NAME="decimalpoints" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="2" SEQUENCE="false" COMMENT="Number of decimal points to use when displaying grades."/>
<FIELD NAME="questiondecimalpoints" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="-1" SEQUENCE="false" COMMENT="Number of decimal points to use when displaying question grades. (-1 means use decimalpoints.)"/>
<FIELD NAME="reviewattempt" TYPE="int" LENGTH="6" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Whether users are allowed to review their quiz attempts at various times. This is a bit field, decoded by the mod_quiz_display_options class. It is formed by ORing together the constants defined there."/>
<FIELD NAME="reviewattempt" TYPE="int" LENGTH="6" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Whether users are allowed to review their quiz attempts at various times. This is a bit field, decoded by the \mod_quiz\question\display_options class. It is formed by ORing together the constants defined there."/>
<FIELD NAME="reviewcorrectness" TYPE="int" LENGTH="6" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Whether users are allowed to review their quiz attempts at various times. A bit field, like reviewattempt."/>
<FIELD NAME="reviewmarks" TYPE="int" LENGTH="6" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Whether users are allowed to review their quiz attempts at various times. A bit field, like reviewattempt."/>
<FIELD NAME="reviewspecificfeedback" TYPE="int" LENGTH="6" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Whether users are allowed to review their quiz attempts at various times. A bit field, like reviewattempt."/>
+2
View File
@@ -27,4 +27,6 @@ defined('MOODLE_INTERNAL') || die();
$renamedclasses = [
// Since Moodle 4.1.
'mod_quiz\local\views\secondary' => 'mod_quiz\navigation\views\secondary',
// Since Moodle 4.2.
'mod_quiz_display_options' => 'mod_quiz\question\display_options',
];
+11 -10
View File
@@ -29,6 +29,7 @@
defined('MOODLE_INTERNAL') || die();
use mod_quiz\question\bank\custom_view;
use mod_quiz\question\display_options;
use core_question\statistics\questions\all_calculated_for_qubaid_condition;
require_once($CFG->dirroot . '/calendar/lib.php');
@@ -759,10 +760,10 @@ function quiz_grade_item_update($quiz, $grades = null) {
// 2. If the quiz is set to not show grades at either of those times,
// create the grade_item as hidden.
// 3. If the quiz is set to show grades, create the grade_item visible.
$openreviewoptions = mod_quiz_display_options::make_from_quiz($quiz,
mod_quiz_display_options::LATER_WHILE_OPEN);
$closedreviewoptions = mod_quiz_display_options::make_from_quiz($quiz,
mod_quiz_display_options::AFTER_CLOSE);
$openreviewoptions = display_options::make_from_quiz($quiz,
display_options::LATER_WHILE_OPEN);
$closedreviewoptions = display_options::make_from_quiz($quiz,
display_options::AFTER_CLOSE);
if ($openreviewoptions->marks < question_display_options::MARK_AND_MAX &&
$closedreviewoptions->marks < question_display_options::MARK_AND_MAX) {
$params['hidden'] = 1;
@@ -1115,8 +1116,8 @@ function quiz_process_options($quiz) {
$quiz->reviewgeneralfeedback = quiz_review_option_form_to_db($quiz, 'generalfeedback');
$quiz->reviewrightanswer = quiz_review_option_form_to_db($quiz, 'rightanswer');
$quiz->reviewoverallfeedback = quiz_review_option_form_to_db($quiz, 'overallfeedback');
$quiz->reviewattempt |= mod_quiz_display_options::DURING;
$quiz->reviewoverallfeedback &= ~mod_quiz_display_options::DURING;
$quiz->reviewattempt |= display_options::DURING;
$quiz->reviewoverallfeedback &= ~display_options::DURING;
// Ensure that disabled checkboxes in completion settings are set to 0.
// But only if the completion settinsg are unlocked.
@@ -1140,10 +1141,10 @@ function quiz_process_options($quiz) {
*/
function quiz_review_option_form_to_db($fromform, $field) {
static $times = array(
'during' => mod_quiz_display_options::DURING,
'immediately' => mod_quiz_display_options::IMMEDIATELY_AFTER,
'open' => mod_quiz_display_options::LATER_WHILE_OPEN,
'closed' => mod_quiz_display_options::AFTER_CLOSE,
'during' => display_options::DURING,
'immediately' => display_options::IMMEDIATELY_AFTER,
'open' => display_options::LATER_WHILE_OPEN,
'closed' => display_options::AFTER_CLOSE,
);
$review = 0;
+12 -83
View File
@@ -40,6 +40,7 @@ require_once($CFG->libdir . '/filelib.php');
require_once($CFG->libdir . '/questionlib.php');
use mod_quiz\question\bank\qbank_helper;
use mod_quiz\question\display_options;
/**
* @var int We show the countdown timer if there is less than this amount of time left before the
@@ -1450,8 +1451,8 @@ function quiz_question_edit_button($cmid, $question, $returnurl, $contentafteric
*/
function quiz_question_preview_url($quiz, $question, $variant = null) {
// Get the appropriate display options.
$displayoptions = mod_quiz_display_options::make_from_quiz($quiz,
mod_quiz_display_options::DURING);
$displayoptions = display_options::make_from_quiz($quiz,
display_options::DURING);
$maxmark = null;
if (isset($question->maxmark)) {
@@ -1500,33 +1501,32 @@ function quiz_get_flag_option($attempt, $context) {
* quiz_get_review_options, not in the sense of $attempt->state.
* @param object $quiz the quiz settings
* @param object $attempt the quiz_attempt database row.
* @return int one of the mod_quiz_display_options::DURING,
* @return int one of the display_options::DURING,
* IMMEDIATELY_AFTER, LATER_WHILE_OPEN or AFTER_CLOSE constants.
*/
function quiz_attempt_state($quiz, $attempt) {
if ($attempt->state == quiz_attempt::IN_PROGRESS) {
return mod_quiz_display_options::DURING;
return display_options::DURING;
} else if ($quiz->timeclose && time() >= $quiz->timeclose) {
return mod_quiz_display_options::AFTER_CLOSE;
return display_options::AFTER_CLOSE;
} else if (time() < $attempt->timefinish + 120) {
return mod_quiz_display_options::IMMEDIATELY_AFTER;
return display_options::IMMEDIATELY_AFTER;
} else {
return mod_quiz_display_options::LATER_WHILE_OPEN;
return display_options::LATER_WHILE_OPEN;
}
}
/**
* The the appropraite mod_quiz_display_options object for this attempt at this
* quiz right now.
* The appropriate display_options object for this attempt at this quiz right now.
*
* @param stdClass $quiz the quiz instance.
* @param stdClass $attempt the attempt in question.
* @param context $context the quiz context.
*
* @return mod_quiz_display_options
* @return display_options
*/
function quiz_get_review_options($quiz, $attempt, $context) {
$options = mod_quiz_display_options::make_from_quiz($quiz, quiz_attempt_state($quiz, $attempt));
$options = display_options::make_from_quiz($quiz, quiz_attempt_state($quiz, $attempt));
$options->readonly = true;
$options->flags = quiz_get_flag_option($attempt, $context);
@@ -1595,7 +1595,7 @@ function quiz_get_combined_reviewoptions($quiz, $attempts) {
}
foreach ($attempts as $attempt) {
$attemptoptions = mod_quiz_display_options::make_from_quiz($quiz,
$attemptoptions = display_options::make_from_quiz($quiz,
quiz_attempt_state($quiz, $attempt));
foreach ($fields as $field) {
$someoptions->$field = $someoptions->$field || $attemptoptions->$field;
@@ -2066,77 +2066,6 @@ function quiz_get_js_module() {
}
/**
* An extension of question_display_options that includes the extra options used
* by the quiz.
*
* @copyright 2010 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class mod_quiz_display_options extends question_display_options {
/**#@+
* @var integer bits used to indicate various times in relation to a
* quiz attempt.
*/
const DURING = 0x10000;
const IMMEDIATELY_AFTER = 0x01000;
const LATER_WHILE_OPEN = 0x00100;
const AFTER_CLOSE = 0x00010;
/**#@-*/
/**
* @var boolean if this is false, then the student is not allowed to review
* anything about the attempt.
*/
public $attempt = true;
/**
* @var boolean if this is false, then the student is not allowed to review
* anything about the attempt.
*/
public $overallfeedback = self::VISIBLE;
/**
* Set up the various options from the quiz settings, and a time constant.
* @param object $quiz the quiz settings.
* @param int $one of the {@link DURING}, {@link IMMEDIATELY_AFTER},
* {@link LATER_WHILE_OPEN} or {@link AFTER_CLOSE} constants.
* @return mod_quiz_display_options set up appropriately.
*/
public static function make_from_quiz($quiz, $when) {
$options = new self();
$options->attempt = self::extract($quiz->reviewattempt, $when, true, false);
$options->correctness = self::extract($quiz->reviewcorrectness, $when);
$options->marks = self::extract($quiz->reviewmarks, $when,
self::MARK_AND_MAX, self::MAX_ONLY);
$options->feedback = self::extract($quiz->reviewspecificfeedback, $when);
$options->generalfeedback = self::extract($quiz->reviewgeneralfeedback, $when);
$options->rightanswer = self::extract($quiz->reviewrightanswer, $when);
$options->overallfeedback = self::extract($quiz->reviewoverallfeedback, $when);
$options->numpartscorrect = $options->feedback;
$options->manualcomment = $options->feedback;
if ($quiz->questiondecimalpoints != -1) {
$options->markdp = $quiz->questiondecimalpoints;
} else {
$options->markdp = $quiz->decimalpoints;
}
return $options;
}
protected static function extract($bitmask, $bit,
$whenset = self::VISIBLE, $whennotset = self::HIDDEN) {
if ($bitmask & $bit) {
return $whenset;
} else {
return $whennotset;
}
}
}
/**
* A {@link qubaid_condition} for finding all the question usages belonging to
* a particular quiz.
+9 -8
View File
@@ -28,6 +28,7 @@ defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/course/moodleform_mod.php');
require_once($CFG->dirroot . '/mod/quiz/locallib.php');
use mod_quiz\question\display_options;
/**
* Settings form for the quiz module.
@@ -204,13 +205,13 @@ class mod_quiz_mod_form extends moodleform_mod {
// Review options.
$this->add_review_options_group($mform, $quizconfig, 'during',
mod_quiz_display_options::DURING, true);
display_options::DURING, true);
$this->add_review_options_group($mform, $quizconfig, 'immediately',
mod_quiz_display_options::IMMEDIATELY_AFTER);
display_options::IMMEDIATELY_AFTER);
$this->add_review_options_group($mform, $quizconfig, 'open',
mod_quiz_display_options::LATER_WHILE_OPEN);
display_options::LATER_WHILE_OPEN);
$this->add_review_options_group($mform, $quizconfig, 'closed',
mod_quiz_display_options::AFTER_CLOSE);
display_options::AFTER_CLOSE);
foreach ($behaviours as $behaviour => $notused) {
$unusedoptions = question_engine::get_behaviour_unused_display_options($behaviour);
@@ -459,13 +460,13 @@ class mod_quiz_mod_form extends moodleform_mod {
}
$this->preprocessing_review_settings($toform, 'during',
mod_quiz_display_options::DURING);
display_options::DURING);
$this->preprocessing_review_settings($toform, 'immediately',
mod_quiz_display_options::IMMEDIATELY_AFTER);
display_options::IMMEDIATELY_AFTER);
$this->preprocessing_review_settings($toform, 'open',
mod_quiz_display_options::LATER_WHILE_OPEN);
display_options::LATER_WHILE_OPEN);
$this->preprocessing_review_settings($toform, 'closed',
mod_quiz_display_options::AFTER_CLOSE);
display_options::AFTER_CLOSE);
$toform['attemptduring'] = true;
$toform['overallfeedbackduring'] = false;
+11 -9
View File
@@ -25,6 +25,8 @@
defined('MOODLE_INTERNAL') || die();
use mod_quiz\question\display_options;
/**
* The renderer for the quiz module.
@@ -41,12 +43,12 @@ class mod_quiz_renderer extends plugin_renderer_base {
* @param int $page the current page number
* @param bool $showall whether to show entire attempt on one page.
* @param bool $lastpage if true the current page is the last page.
* @param mod_quiz_display_options $displayoptions instance of mod_quiz_display_options.
* @param display_options $displayoptions instance of display_options.
* @param array $summarydata contains all table data
* @return $output containing html data.
*/
public function review_page(quiz_attempt $attemptobj, $slots, $page, $showall,
$lastpage, mod_quiz_display_options $displayoptions,
$lastpage, display_options $displayoptions,
$summarydata) {
$output = '';
@@ -67,12 +69,12 @@ class mod_quiz_renderer extends plugin_renderer_base {
* @param quiz_attempt $attemptobj an instance of quiz_attempt.
* @param int $slot which question to display.
* @param int $seq which step of the question attempt to show. null = latest.
* @param mod_quiz_display_options $displayoptions instance of mod_quiz_display_options.
* @param display_options $displayoptions instance of display_options.
* @param array $summarydata contains all table data
* @return $output containing html data.
*/
public function review_question_page(quiz_attempt $attemptobj, $slot, $seq,
mod_quiz_display_options $displayoptions, $summarydata) {
display_options $displayoptions, $summarydata) {
$output = '';
$output .= $this->header();
@@ -177,10 +179,10 @@ class mod_quiz_renderer extends plugin_renderer_base {
* @param array $slots array of intgers relating to questions
* @param int $page current page number
* @param bool $showall if true shows attempt on single page
* @param mod_quiz_display_options $displayoptions instance of mod_quiz_display_options
* @param display_options $displayoptions instance of display_options
*/
public function questions(quiz_attempt $attemptobj, $reviewing, $slots, $page, $showall,
mod_quiz_display_options $displayoptions) {
display_options $displayoptions) {
$output = '';
foreach ($slots as $slot) {
$output .= $attemptobj->render_question($slot, $reviewing, $this,
@@ -194,7 +196,7 @@ class mod_quiz_renderer extends plugin_renderer_base {
*
* @param array $summarydata contain row data for table
* @param int $page current page number
* @param mod_quiz_display_options $displayoptions instance of mod_quiz_display_options
* @param display_options $displayoptions instance of display_options
* @param $content contains each question
* @param quiz_attempt $attemptobj instance of quiz_attempt
* @param bool $showall if true display attempt on one page
@@ -662,7 +664,7 @@ class mod_quiz_renderer extends plugin_renderer_base {
* Create the summary page
*
* @param quiz_attempt $attemptobj
* @param mod_quiz_display_options $displayoptions
* @param display_options $displayoptions
*/
public function summary_page($attemptobj, $displayoptions) {
$output = '';
@@ -680,7 +682,7 @@ class mod_quiz_renderer extends plugin_renderer_base {
* Generates the table of summarydata
*
* @param quiz_attempt $attemptobj
* @param mod_quiz_display_options $displayoptions
* @param display_options $displayoptions
*/
public function summary_table($attemptobj, $displayoptions) {
// Prepare the summary table header.
+5 -3
View File
@@ -30,6 +30,8 @@ require_once($CFG->dirroot . '/mod/quiz/attemptlib.php');
require_once($CFG->libdir . '/filelib.php');
require_once($CFG->dirroot . '/mod/quiz/accessmanager.php');
use mod_quiz\question\display_options;
/**
* Takes an array of objects and constructs a multidimensional array keyed by
* the keys it finds on the object.
@@ -427,11 +429,11 @@ function quiz_no_questions_message($quiz, $cm, $context) {
*/
function quiz_report_should_show_grades($quiz, context $context) {
if ($quiz->timeclose && time() > $quiz->timeclose) {
$when = mod_quiz_display_options::AFTER_CLOSE;
$when = display_options::AFTER_CLOSE;
} else {
$when = mod_quiz_display_options::LATER_WHILE_OPEN;
$when = display_options::LATER_WHILE_OPEN;
}
$reviewoptions = mod_quiz_display_options::make_from_quiz($quiz, $when);
$reviewoptions = display_options::make_from_quiz($quiz, $when);
return quiz_has_grades($quiz) &&
($reviewoptions->marks >= question_display_options::MARK_AND_MAX ||
+3 -3
View File
@@ -28,7 +28,7 @@ namespace mod_quiz\external;
use externallib_advanced_testcase;
use mod_quiz_external;
use mod_quiz_display_options;
use mod_quiz\question\display_options;
use quiz;
use quiz_attempt;
@@ -681,7 +681,7 @@ class external_test extends externallib_advanced_testcase {
}
/**
* Test get_combined_review_options.
* This is a basic test, this is already tested in mod_quiz_display_options_testcase.
* This is a basic test, this is already tested in display_options_testcase.
*/
public function test_get_combined_review_options() {
global $DB;
@@ -1027,7 +1027,7 @@ class external_test extends externallib_advanced_testcase {
list($quiz, $context, $quizobj, $attempt, $attemptobj) = $this->create_quiz_with_questions(true);
// Set correctness mask so questions state can be fetched only after finishing the attempt.
$DB->set_field('quiz', 'reviewcorrectness', mod_quiz_display_options::IMMEDIATELY_AFTER, array('id' => $quiz->id));
$DB->set_field('quiz', 'reviewcorrectness', display_options::IMMEDIATELY_AFTER, array('id' => $quiz->id));
$quizobj = $attemptobj->get_quizobj();
$quizobj->preload_questions();
+19 -18
View File
@@ -25,7 +25,7 @@
namespace mod_quiz;
use quiz_attempt;
use mod_quiz_display_options;
use mod_quiz\question\display_options;
defined('MOODLE_INTERNAL') || die();
@@ -60,30 +60,31 @@ class locallib_test extends \advanced_testcase {
public function quiz_attempt_state_data_provider() {
return [
[quiz_attempt::IN_PROGRESS, null, null, mod_quiz_display_options::DURING],
[quiz_attempt::FINISHED, -90, null, mod_quiz_display_options::IMMEDIATELY_AFTER],
[quiz_attempt::FINISHED, -7200, null, mod_quiz_display_options::LATER_WHILE_OPEN],
[quiz_attempt::FINISHED, -7200, 3600, mod_quiz_display_options::LATER_WHILE_OPEN],
[quiz_attempt::FINISHED, -30, 30, mod_quiz_display_options::IMMEDIATELY_AFTER],
[quiz_attempt::FINISHED, -90, -30, mod_quiz_display_options::AFTER_CLOSE],
[quiz_attempt::FINISHED, -7200, -3600, mod_quiz_display_options::AFTER_CLOSE],
[quiz_attempt::FINISHED, -90, -3600, mod_quiz_display_options::AFTER_CLOSE],
[quiz_attempt::ABANDONED, -10000000, null, mod_quiz_display_options::LATER_WHILE_OPEN],
[quiz_attempt::ABANDONED, -7200, 3600, mod_quiz_display_options::LATER_WHILE_OPEN],
[quiz_attempt::ABANDONED, -7200, -3600, mod_quiz_display_options::AFTER_CLOSE],
[quiz_attempt::IN_PROGRESS, null, null, display_options::DURING],
[quiz_attempt::FINISHED, -90, null, display_options::IMMEDIATELY_AFTER],
[quiz_attempt::FINISHED, -7200, null, display_options::LATER_WHILE_OPEN],
[quiz_attempt::FINISHED, -7200, 3600, display_options::LATER_WHILE_OPEN],
[quiz_attempt::FINISHED, -30, 30, display_options::IMMEDIATELY_AFTER],
[quiz_attempt::FINISHED, -90, -30, display_options::AFTER_CLOSE],
[quiz_attempt::FINISHED, -7200, -3600, display_options::AFTER_CLOSE],
[quiz_attempt::FINISHED, -90, -3600, display_options::AFTER_CLOSE],
[quiz_attempt::ABANDONED, -10000000, null, display_options::LATER_WHILE_OPEN],
[quiz_attempt::ABANDONED, -7200, 3600, display_options::LATER_WHILE_OPEN],
[quiz_attempt::ABANDONED, -7200, -3600, display_options::AFTER_CLOSE],
];
}
/**
* @dataProvider quiz_attempt_state_data_provider
*
* @param unknown $attemptstate as in the quiz_attempts.state DB column.
* @param unknown $relativetimefinish time relative to now when the attempt finished, or null for 0.
* @param unknown $relativetimeclose time relative to now when the quiz closes, or null for 0.
* @param unknown $expectedstate expected result. One of the mod_quiz_display_options constants/
* @param string $attemptstate as in the quiz_attempts.state DB column.
* @param int|null $relativetimefinish time relative to now when the attempt finished, or null for 0.
* @param int|null $relativetimeclose time relative to now when the quiz closes, or null for 0.
* @param int $expectedstate expected result. One of the display_options constants.
* @covers ::quiz_attempt_state
*/
public function test_quiz_attempt_state($attemptstate,
$relativetimefinish, $relativetimeclose, $expectedstate) {
public function test_quiz_attempt_state(string $attemptstate,
?int $relativetimefinish, ?int $relativetimeclose, int $expectedstate) {
$attempt = new \stdClass();
$attempt->state = $attemptstate;
@@ -0,0 +1,82 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace mod_quiz\question;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/quiz/locallib.php');
/**
* Unit tests for {@see display_options}.
*
* @package mod_quiz
* @category test
* @copyright 2010 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \mod_quiz\question\display_options
*/
class display_options_test extends \basic_testcase {
public function test_num_attempts_access_rule() {
$quiz = new \stdClass();
$quiz->decimalpoints = 2;
$quiz->questiondecimalpoints = -1;
$quiz->reviewattempt = 0x11110;
$quiz->reviewcorrectness = 0x10000;
$quiz->reviewmarks = 0x01110;
$quiz->reviewspecificfeedback = 0x10000;
$quiz->reviewgeneralfeedback = 0x01000;
$quiz->reviewrightanswer = 0x00100;
$quiz->reviewoverallfeedback = 0x00010;
$options = display_options::make_from_quiz($quiz,
display_options::DURING);
$this->assertEquals(true, $options->attempt);
$this->assertEquals(display_options::VISIBLE, $options->correctness);
$this->assertEquals(display_options::MAX_ONLY, $options->marks);
$this->assertEquals(display_options::VISIBLE, $options->feedback);
// The next two should be controlled by the same settings as ->feedback.
$this->assertEquals(display_options::VISIBLE, $options->numpartscorrect);
$this->assertEquals(display_options::VISIBLE, $options->manualcomment);
$this->assertEquals(2, $options->markdp);
$quiz->questiondecimalpoints = 5;
$options = display_options::make_from_quiz($quiz,
display_options::IMMEDIATELY_AFTER);
$this->assertEquals(display_options::MARK_AND_MAX, $options->marks);
$this->assertEquals(display_options::VISIBLE, $options->generalfeedback);
$this->assertEquals(display_options::HIDDEN, $options->feedback);
// The next two should be controlled by the same settings as ->feedback.
$this->assertEquals(display_options::HIDDEN, $options->numpartscorrect);
$this->assertEquals(display_options::HIDDEN, $options->manualcomment);
$this->assertEquals(5, $options->markdp);
$options = display_options::make_from_quiz($quiz,
display_options::LATER_WHILE_OPEN);
$this->assertEquals(display_options::VISIBLE, $options->rightanswer);
$this->assertEquals(display_options::HIDDEN, $options->generalfeedback);
$options = display_options::make_from_quiz($quiz,
display_options::AFTER_CLOSE);
$this->assertEquals(display_options::VISIBLE, $options->overallfeedback);
$this->assertEquals(display_options::HIDDEN, $options->rightanswer);
}
}
@@ -1,83 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace mod_quiz;
use mod_quiz_display_options;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/quiz/locallib.php');
/**
* Unit tests for {@link mod_quiz_display_options}.
*
* @package mod_quiz
* @category test
* @copyright 2010 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class quizdisplayoptions_test extends \basic_testcase {
public function test_num_attempts_access_rule() {
$quiz = new \stdClass();
$quiz->decimalpoints = 2;
$quiz->questiondecimalpoints = -1;
$quiz->reviewattempt = 0x11110;
$quiz->reviewcorrectness = 0x10000;
$quiz->reviewmarks = 0x01110;
$quiz->reviewspecificfeedback = 0x10000;
$quiz->reviewgeneralfeedback = 0x01000;
$quiz->reviewrightanswer = 0x00100;
$quiz->reviewoverallfeedback = 0x00010;
$options = mod_quiz_display_options::make_from_quiz($quiz,
mod_quiz_display_options::DURING);
$this->assertEquals(true, $options->attempt);
$this->assertEquals(mod_quiz_display_options::VISIBLE, $options->correctness);
$this->assertEquals(mod_quiz_display_options::MAX_ONLY, $options->marks);
$this->assertEquals(mod_quiz_display_options::VISIBLE, $options->feedback);
// The next two should be controlled by the same settings as ->feedback.
$this->assertEquals(mod_quiz_display_options::VISIBLE, $options->numpartscorrect);
$this->assertEquals(mod_quiz_display_options::VISIBLE, $options->manualcomment);
$this->assertEquals(2, $options->markdp);
$quiz->questiondecimalpoints = 5;
$options = mod_quiz_display_options::make_from_quiz($quiz,
mod_quiz_display_options::IMMEDIATELY_AFTER);
$this->assertEquals(mod_quiz_display_options::MARK_AND_MAX, $options->marks);
$this->assertEquals(mod_quiz_display_options::VISIBLE, $options->generalfeedback);
$this->assertEquals(mod_quiz_display_options::HIDDEN, $options->feedback);
// The next two should be controlled by the same settings as ->feedback.
$this->assertEquals(mod_quiz_display_options::HIDDEN, $options->numpartscorrect);
$this->assertEquals(mod_quiz_display_options::HIDDEN, $options->manualcomment);
$this->assertEquals(5, $options->markdp);
$options = mod_quiz_display_options::make_from_quiz($quiz,
mod_quiz_display_options::LATER_WHILE_OPEN);
$this->assertEquals(mod_quiz_display_options::VISIBLE, $options->rightanswer);
$this->assertEquals(mod_quiz_display_options::HIDDEN, $options->generalfeedback);
$options = mod_quiz_display_options::make_from_quiz($quiz,
mod_quiz_display_options::AFTER_CLOSE);
$this->assertEquals(mod_quiz_display_options::VISIBLE, $options->overallfeedback);
$this->assertEquals(mod_quiz_display_options::HIDDEN, $options->rightanswer);
}
}
+6 -6
View File
@@ -16,7 +16,7 @@
namespace mod_quiz;
use mod_quiz_display_options;
use mod_quiz\question\display_options;
use quiz;
defined('MOODLE_INTERNAL') || die();
@@ -44,19 +44,19 @@ class quizobj_test extends \basic_testcase {
$quizobj = new quiz($quiz, $cm, new \stdClass(), false);
$this->assertEquals('',
$quizobj->cannot_review_message(mod_quiz_display_options::DURING));
$quizobj->cannot_review_message(display_options::DURING));
$this->assertEquals('',
$quizobj->cannot_review_message(mod_quiz_display_options::IMMEDIATELY_AFTER));
$quizobj->cannot_review_message(display_options::IMMEDIATELY_AFTER));
$this->assertEquals(get_string('noreview', 'quiz'),
$quizobj->cannot_review_message(mod_quiz_display_options::LATER_WHILE_OPEN));
$quizobj->cannot_review_message(display_options::LATER_WHILE_OPEN));
$this->assertEquals(get_string('noreview', 'quiz'),
$quizobj->cannot_review_message(mod_quiz_display_options::AFTER_CLOSE));
$quizobj->cannot_review_message(display_options::AFTER_CLOSE));
$closetime = time() + 10000;
$quiz->timeclose = $closetime;
$quizobj = new quiz($quiz, $cm, new \stdClass(), false);
$this->assertEquals(get_string('noreviewuntil', 'quiz', userdate($closetime)),
$quizobj->cannot_review_message(mod_quiz_display_options::LATER_WHILE_OPEN));
$quizobj->cannot_review_message(display_options::LATER_WHILE_OPEN));
}
}
+9
View File
@@ -1,5 +1,14 @@
This files describes API changes in the quiz code.
=== 4.2 ===
* The quiz has a lot of old classes in lib.php files. These have now been moved into the classes folder,
and so are now in namespaces. Because of Moodle's class renaming support, your code should continue
working, but output deprecated warnings, so you probably want to update. This should mostly be
doable by adding use statements, and a search/replace.
- mod_quiz_display_options => mod_quiz\question\display_options
=== 4.1 ===
* quiz_has_question_use is now deprecated. Use mod_quiz\structure::has_use_capability istead.