mirror of
https://github.com/moodle/moodle.git
synced 2025-01-17 21:49:15 +01:00
MDL-80808 quiz: improve message when the student can't review
This commit is contained in:
parent
3fc907e3d8
commit
435ee33af1
@ -556,7 +556,7 @@ class access_manager {
|
||||
$this->quizobj->get_quiz(), $when);
|
||||
|
||||
if (!$reviewoptions->attempt) {
|
||||
return $output->no_review_message($this->quizobj->cannot_review_message($when, true));
|
||||
return $output->no_review_message($this->quizobj->cannot_review_message($when, true, $attempt->timefinish));
|
||||
|
||||
} else {
|
||||
return $output->review_link($this->quizobj->review_url($attempt->id),
|
||||
|
@ -61,6 +61,9 @@ class quiz_attempt {
|
||||
/** @var int maximum number of slots in the quiz for the review page to default to show all. */
|
||||
const MAX_SLOTS_FOR_DEFAULT_REVIEW_SHOW_ALL = 50;
|
||||
|
||||
/** @var int amount of time considered 'immedately after the attempt', in seconds. */
|
||||
const IMMEDIATELY_AFTER_PERIOD = 2 * MINSECS;
|
||||
|
||||
/** @var quiz_settings object containing the quiz settings. */
|
||||
protected $quizobj;
|
||||
|
||||
@ -1226,7 +1229,7 @@ class quiz_attempt {
|
||||
*/
|
||||
public function cannot_review_message($short = false) {
|
||||
return $this->quizobj->cannot_review_message(
|
||||
$this->get_attempt_state(), $short);
|
||||
$this->get_attempt_state(), $short, $this->attempt->timefinish);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -497,9 +497,15 @@ class quiz_settings {
|
||||
* @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.
|
||||
* @param int|null $attemptsubmittime time this attempt was submitted. (Optional, but should be given.)
|
||||
* @return string an appropraite message.
|
||||
*/
|
||||
public function cannot_review_message($when, $short = false) {
|
||||
public function cannot_review_message($when, $short = false, int $attemptsubmittime = null) {
|
||||
|
||||
if ($attemptsubmittime === null) {
|
||||
debugging('It is recommended that you pass $attemptsubmittime to cannot_review_message', DEBUG_DEVELOPER);
|
||||
$attemptsubmittime = time(); // This will be approximately right, which is enough for the one place were it is used.
|
||||
}
|
||||
|
||||
if ($short) {
|
||||
$langstrsuffix = 'short';
|
||||
@ -509,17 +515,30 @@ class quiz_settings {
|
||||
$dateformat = '';
|
||||
}
|
||||
|
||||
if ($when == display_options::DURING ||
|
||||
$when == display_options::IMMEDIATELY_AFTER) {
|
||||
return '';
|
||||
$reviewfrom = 0;
|
||||
switch ($when) {
|
||||
case display_options::DURING:
|
||||
return '';
|
||||
|
||||
case display_options::IMMEDIATELY_AFTER:
|
||||
if ($this->quiz->reviewattempt & display_options::LATER_WHILE_OPEN) {
|
||||
$reviewfrom = $attemptsubmittime + quiz_attempt::IMMEDIATELY_AFTER_PERIOD;
|
||||
break;
|
||||
}
|
||||
// Fall through.
|
||||
|
||||
case display_options::LATER_WHILE_OPEN:
|
||||
if ($this->quiz->timeclose && ($this->quiz->reviewattempt & display_options::AFTER_CLOSE)) {
|
||||
$reviewfrom = $this->quiz->timeclose;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($reviewfrom) {
|
||||
return get_string('noreviewuntil' . $langstrsuffix, 'quiz',
|
||||
userdate($reviewfrom, $dateformat));
|
||||
} 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 {
|
||||
return get_string('noreview' . $langstrsuffix, 'quiz');
|
||||
}
|
||||
return get_string('noreview' . $langstrsuffix, 'quiz');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1125,7 +1125,7 @@ function quiz_attempt_state($quiz, $attempt) {
|
||||
return display_options::DURING;
|
||||
} else if ($quiz->timeclose && time() >= $quiz->timeclose) {
|
||||
return display_options::AFTER_CLOSE;
|
||||
} else if (time() < $attempt->timefinish + 120) {
|
||||
} else if (time() < $attempt->timefinish + quiz_attempt::IMMEDIATELY_AFTER_PERIOD) {
|
||||
return display_options::IMMEDIATELY_AFTER;
|
||||
} else {
|
||||
return display_options::LATER_WHILE_OPEN;
|
||||
|
@ -16,8 +16,10 @@
|
||||
|
||||
namespace mod_quiz;
|
||||
|
||||
use basic_testcase;
|
||||
use mod_quiz\question\display_options;
|
||||
use mod_quiz\quiz_settings;
|
||||
use stdClass;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
@ -30,33 +32,99 @@ require_once($CFG->dirroot . '/mod/quiz/locallib.php');
|
||||
* @package mod_quiz
|
||||
* @copyright 2008 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @covers \mod_quiz\quiz_settings
|
||||
*/
|
||||
class quizobj_test extends \basic_testcase {
|
||||
public function test_cannot_review_message() {
|
||||
$quiz = new \stdClass();
|
||||
$quiz->reviewattempt = 0x10010;
|
||||
$quiz->timeclose = 0;
|
||||
$quiz->attempts = 0;
|
||||
class quizobj_test extends basic_testcase {
|
||||
/**
|
||||
* Test cases for {@see test_cannot_review_message()}.
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
public static function cannot_review_message_testcases(): array {
|
||||
return [
|
||||
// Review Time close
|
||||
// Later close quiz attempt When Expected
|
||||
// Quiz with no close date.
|
||||
[false, false, null, null, display_options::DURING, ''],
|
||||
[false, false, null, -60, display_options::IMMEDIATELY_AFTER, 'noreview'],
|
||||
[false, false, null, -180, display_options::LATER_WHILE_OPEN, 'noreview'],
|
||||
[false, false, null, -180, display_options::AFTER_CLOSE, 'noreview'],
|
||||
[false, true, null, null, display_options::DURING, ''],
|
||||
[false, true, null, -60, display_options::IMMEDIATELY_AFTER, 'noreview'],
|
||||
[false, true, null, -180, display_options::LATER_WHILE_OPEN, 'noreview'],
|
||||
[false, true, null, -180, display_options::AFTER_CLOSE, 'noreview'],
|
||||
// Quiz with a close in the future date, review only after close.
|
||||
[false, true, 300, null, display_options::DURING, ''],
|
||||
[false, true, 300, -60, display_options::IMMEDIATELY_AFTER, 300],
|
||||
[false, true, 300, -180, display_options::LATER_WHILE_OPEN, 300],
|
||||
// Quiz with a close in the future date, review later while open, or after close.
|
||||
[true, true, 300, null, display_options::DURING, ''],
|
||||
[true, true, 300, -60, display_options::IMMEDIATELY_AFTER, 60],
|
||||
[true, false, 300, -60, display_options::IMMEDIATELY_AFTER, 60],
|
||||
// Quiz with no closer date, review later while open.
|
||||
[true, false, 300, null, display_options::DURING, ''],
|
||||
[true, false, 300, -60, display_options::IMMEDIATELY_AFTER, 60],
|
||||
];
|
||||
}
|
||||
|
||||
$cm = new \stdClass();
|
||||
/**
|
||||
* Unit test for {@see quiz_settings::cannot_review_message()}.
|
||||
*
|
||||
* @dataProvider cannot_review_message_testcases
|
||||
* @param bool $reviewlater whether the quiz allows reivew 'later while the quiz is still open'.
|
||||
* @param bool $reviewafterclose whether the quiz allows rievew 'after the quiz is closed'.
|
||||
* @param int|null $quizcloseoffset quiz close date, relative to now. Null means not set.
|
||||
* @param int|null $attemptsubmitoffset quiz attempt sumbite time relative to now. Null means not submitted yet.
|
||||
* @param int $attemptstate current state of the attempt, one of the display_options constants.
|
||||
* @param string|int $expectation expected result: '' means '', 'noreview' means noreview lang string,
|
||||
* int means noreviewuntil with that time relative to now.
|
||||
*/
|
||||
public function test_cannot_review_message(
|
||||
bool $reviewlater,
|
||||
bool $reviewafterclose,
|
||||
?int $quizcloseoffset,
|
||||
?int $attemptsubmitoffset,
|
||||
int $attemptstate,
|
||||
string|int $expectation
|
||||
): void {
|
||||
$quiz = new stdClass();
|
||||
$now = time();
|
||||
|
||||
$cm = new stdClass();
|
||||
$cm->id = 123;
|
||||
|
||||
$quizobj = new quiz_settings($quiz, $cm, new \stdClass(), false);
|
||||
// Prepare quiz settings.
|
||||
$quiz->reviewattempt = display_options::DURING;
|
||||
if ($reviewlater) {
|
||||
$quiz->reviewattempt |= display_options::LATER_WHILE_OPEN;
|
||||
}
|
||||
if ($reviewafterclose) {
|
||||
$quiz->reviewattempt |= display_options::AFTER_CLOSE;
|
||||
}
|
||||
$quiz->attempts = 0;
|
||||
|
||||
$this->assertEquals('',
|
||||
$quizobj->cannot_review_message(display_options::DURING));
|
||||
$this->assertEquals('',
|
||||
$quizobj->cannot_review_message(display_options::IMMEDIATELY_AFTER));
|
||||
$this->assertEquals(get_string('noreview', 'quiz'),
|
||||
$quizobj->cannot_review_message(display_options::LATER_WHILE_OPEN));
|
||||
$this->assertEquals(get_string('noreview', 'quiz'),
|
||||
$quizobj->cannot_review_message(display_options::AFTER_CLOSE));
|
||||
if ($quizcloseoffset === null) {
|
||||
$quiz->timeclose = 0;
|
||||
} else {
|
||||
$quiz->timeclose = $now + $quizcloseoffset;
|
||||
}
|
||||
if ($attemptsubmitoffset === null) {
|
||||
$submittime = 0;
|
||||
} else {
|
||||
$submittime = $now + $attemptsubmitoffset;
|
||||
}
|
||||
|
||||
$closetime = time() + 10000;
|
||||
$quiz->timeclose = $closetime;
|
||||
$quizobj = new quiz_settings($quiz, $cm, new \stdClass(), false);
|
||||
$quizobj = new quiz_settings($quiz, $cm, new stdClass(), false);
|
||||
|
||||
$this->assertEquals(get_string('noreviewuntil', 'quiz', userdate($closetime)),
|
||||
$quizobj->cannot_review_message(display_options::LATER_WHILE_OPEN));
|
||||
// Prepare expected message.
|
||||
if ($expectation === 'noreview') {
|
||||
$expectation = get_string('noreview', 'quiz');
|
||||
} else if (is_int($expectation)) {
|
||||
$expectation = get_string('noreviewuntil', 'quiz', userdate($now + $expectation));
|
||||
}
|
||||
|
||||
// Test.
|
||||
$this->assertEquals($expectation,
|
||||
$quizobj->cannot_review_message($attemptstate, false, $submittime));
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ This files describes API changes in the quiz code.
|
||||
* A quiz_structure_modified callback has been added for quiz_ plugins, called from
|
||||
grade_calculator::recompute_quiz_sumgrades(). Plugins can implement this by creating a `quiz_structure_modified`
|
||||
class in their namespace with a static `callback` method, see quiz_statistics as an example.
|
||||
* quiz_settings::no_review_message now takes a new argument $attemptsubmittime for the time when the quiz attempt was
|
||||
submitted. It is strongly recommended that you always pass that.
|
||||
|
||||
=== 4.3 ===
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user