Skip to content

Commit

Permalink
MDL-41922 mod_quiz: Don't report quiz due when an attempt was finished
Browse files Browse the repository at this point in the history
  • Loading branch information
Frederic Massart committed Jun 3, 2016
1 parent 4ee8ef5 commit ac032e0
Show file tree
Hide file tree
Showing 3 changed files with 370 additions and 27 deletions.
94 changes: 94 additions & 0 deletions blocks/course_overview/tests/behat/quiz_overview.feature
@@ -0,0 +1,94 @@
@block @block_course_overview @mod_quiz
Feature: View the quiz being due
In order to know what quizzes are due
As a student
I can visit my dashboard

Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname |
| Course 1 | C1 |
| Course 2 | C2 |
And the following "course enrolments" exist:
| user | course | role |
| student1 | C1 | student |
| student2 | C2 | student |
| teacher1 | C1 | editingteacher |
| teacher1 | C2 | editingteacher |
And the following "activities" exist:
| activity | course | idnumber | name | timeclose |
| quiz | C1 | Q1A | Quiz 1A No deadline | 0 |
| quiz | C1 | Q1B | Quiz 1B Past deadline | 1337 |
| quiz | C1 | Q1C | Quiz 1C Future deadline | 9000000000 |
| quiz | C1 | Q1D | Quiz 1D Future deadline | 9000000000 |
| quiz | C1 | Q1E | Quiz 1E Future deadline | 9000000000 |
| quiz | C2 | Q2A | Quiz 2A Future deadline | 9000000000 |
And the following "question categories" exist:
| contextlevel | reference | name |
| Course | C1 | Test questions |
And the following "questions" exist:
| qtype | name | questiontext | questioncategory |
| truefalse | First question | Answer the first question | Test questions |
And quiz "Quiz 1A No deadline" contains the following questions:
| question | page |
| First question | 1 |
And quiz "Quiz 1B Past deadline" contains the following questions:
| question | page |
| First question | 1 |
And quiz "Quiz 1C Future deadline" contains the following questions:
| question | page |
| First question | 1 |
And quiz "Quiz 1D Future deadline" contains the following questions:
| question | page |
| First question | 1 |
And quiz "Quiz 1E Future deadline" contains the following questions:
| question | page |
| First question | 1 |
And quiz "Quiz 2A Future deadline" contains the following questions:
| question | page |
| First question | 1 |

Scenario: View my quizzes that are due
Given I log in as "student1"
When I am on homepage
Then I should see "You have quizzes that are due" in the "Course overview" "block"
And I should see "Quiz 1C Future deadline" in the "Course overview" "block"
And I should see "Quiz 1D Future deadline" in the "Course overview" "block"
And I should see "Quiz 1E Future deadline" in the "Course overview" "block"
And I should not see "Quiz 1A No deadline" in the "Course overview" "block"
And I should not see "Quiz 1B Past deadline" in the "Course overview" "block"
And I should not see "Quiz 2A Future deadline" in the "Course overview" "block"
And I log out
And I log in as "student2"
And I should see "You have quizzes that are due" in the "Course overview" "block"
And I should not see "Quiz 1C Future deadline" in the "Course overview" "block"
And I should not see "Quiz 1D Future deadline" in the "Course overview" "block"
And I should not see "Quiz 1E Future deadline" in the "Course overview" "block"
And I should not see "Quiz 1A No deadline" in the "Course overview" "block"
And I should not see "Quiz 1B Past deadline" in the "Course overview" "block"
And I should see "Quiz 2A Future deadline" in the "Course overview" "block"

Scenario: View my quizzes that are due and never finished
Given I log in as "student1"
And I follow "Course 1"
And I follow "Quiz 1D Future deadline"
And I press "Attempt quiz now"
And I follow "Finish attempt ..."
And I press "Submit all and finish"
And I follow "Course 1"
And I follow "Quiz 1E Future deadline"
And I press "Attempt quiz now"
When I am on homepage
Then I should see "You have quizzes that are due" in the "Course overview" "block"
And I should see "Quiz 1C Future deadline" in the "Course overview" "block"
And I should see "Quiz 1E Future deadline" in the "Course overview" "block"
And I should not see "Quiz 1A No deadline" in the "Course overview" "block"
And I should not see "Quiz 1B Past deadline" in the "Course overview" "block"
And I should not see "Quiz 1D Future deadline" in the "Course overview" "block"
And I should not see "Quiz 2A Future deadline" in the "Course overview" "block"

81 changes: 54 additions & 27 deletions mod/quiz/lib.php
Expand Up @@ -544,14 +544,14 @@ function quiz_cron() {
}

/**
* @param int $quizid the quiz id.
* @param int|array $quizids A quiz ID, or an array of quiz IDs.
* @param int $userid the userid.
* @param string $status 'all', 'finished' or 'unfinished' to control
* @param bool $includepreviews
* @return an array of all the user's attempts at this quiz. Returns an empty
* array if there are none.
*/
function quiz_get_user_attempts($quizid, $userid, $status = 'finished', $includepreviews = false) {
function quiz_get_user_attempts($quizids, $userid, $status = 'finished', $includepreviews = false) {
global $DB, $CFG;
// TODO MDL-33071 it is very annoying to have to included all of locallib.php
// just to get the quiz_attempt::FINISHED constants, but I will try to sort
Expand All @@ -578,15 +578,18 @@ function quiz_get_user_attempts($quizid, $userid, $status = 'finished', $include
break;
}

$quizids = (array) $quizids;
list($insql, $inparams) = $DB->get_in_or_equal($quizids, SQL_PARAMS_NAMED);
$params += $inparams;
$params['userid'] = $userid;

$previewclause = '';
if (!$includepreviews) {
$previewclause = ' AND preview = 0';
}

$params['quizid'] = $quizid;
$params['userid'] = $userid;
return $DB->get_records_select('quiz_attempts',
'quiz = :quizid AND userid = :userid' . $previewclause . $statuscondition,
"quiz $insql AND userid = :userid" . $previewclause . $statuscondition,
$params, 'attempt ASC');
}

Expand Down Expand Up @@ -1465,6 +1468,20 @@ function quiz_print_overview($courses, &$htmlarray) {
return;
}

// Get the quizzes attempts.
$attemptsinfo = [];
$quizids = [];
foreach ($quizzes as $quiz) {
$quizids[] = $quiz->id;
$attemptsinfo[$quiz->id] = ['count' => 0, 'hasfinished' => false];
}
$attempts = quiz_get_user_attempts($quizids, $USER->id);
foreach ($attempts as $attempt) {
$attemptsinfo[$attempt->quiz]['count']++;
$attemptsinfo[$attempt->quiz]['hasfinished'] = true;
}
unset($attempts);

// Fetch some language strings outside the main loop.
$strquiz = get_string('modulename', 'quiz');
$strnoattempts = get_string('noattempts', 'quiz');
Expand All @@ -1474,46 +1491,56 @@ function quiz_print_overview($courses, &$htmlarray) {
$now = time();
foreach ($quizzes as $quiz) {
if ($quiz->timeclose >= $now && $quiz->timeopen < $now) {
// Give a link to the quiz, and the deadline.
$str = '<div class="quiz overview">' .
'<div class="name">' . $strquiz . ': <a ' .
($quiz->visible ? '' : ' class="dimmed"') .
' href="' . $CFG->wwwroot . '/mod/quiz/view.php?id=' .
$quiz->coursemodule . '">' .
$quiz->name . '</a></div>';
$str .= '<div class="info">' . get_string('quizcloseson', 'quiz',
userdate($quiz->timeclose)) . '</div>';
$str = '';

// Now provide more information depending on the uers's role.
$context = context_module::instance($quiz->coursemodule);
if (has_capability('mod/quiz:viewreports', $context)) {
// For teacher-like people, show a summary of the number of student attempts.
// The $quiz objects returned by get_all_instances_in_course have the necessary $cm
// fields set to make the following call work.
$str .= '<div class="info">' .
quiz_num_attempt_summary($quiz, $quiz, true) . '</div>';
} else if (has_any_capability(array('mod/quiz:reviewmyattempts', 'mod/quiz:attempt'),
$context)) { // Student
$str .= '<div class="info">' . quiz_num_attempt_summary($quiz, $quiz, true) . '</div>';

} else if (has_any_capability(array('mod/quiz:reviewmyattempts', 'mod/quiz:attempt'), $context)) { // Student
// For student-like people, tell them how many attempts they have made.
if (isset($USER->id) &&
($attempts = quiz_get_user_attempts($quiz->id, $USER->id))) {
$numattempts = count($attempts);
$str .= '<div class="info">' .
get_string('numattemptsmade', 'quiz', $numattempts) . '</div>';

if (isset($USER->id)) {
if ($attemptsinfo[$quiz->id]['hasfinished']) {
// The student's last attempt is finished.
continue;
}

if ($attemptsinfo[$quiz->id]['count'] > 0) {
$str .= '<div class="info">' .
get_string('numattemptsmade', 'quiz', $attemptsinfo[$quiz->id]['count']) . '</div>';
} else {
$str .= '<div class="info">' . $strnoattempts . '</div>';
}

} else {
$str .= '<div class="info">' . $strnoattempts . '</div>';
}

} else {
// For ayone else, there is no point listing this quiz, so stop processing.
continue;
}

// Add the output for this quiz to the rest.
$str .= '</div>';
// Give a link to the quiz, and the deadline.
$html = '<div class="quiz overview">' .
'<div class="name">' . $strquiz . ': <a ' .
($quiz->visible ? '' : ' class="dimmed"') .
' href="' . $CFG->wwwroot . '/mod/quiz/view.php?id=' .
$quiz->coursemodule . '">' .
$quiz->name . '</a></div>';
$html .= '<div class="info">' . get_string('quizcloseson', 'quiz',
userdate($quiz->timeclose)) . '</div>';
$html .= $str;
$html .= '</div>';
if (empty($htmlarray[$quiz->course]['quiz'])) {
$htmlarray[$quiz->course]['quiz'] = $str;
$htmlarray[$quiz->course]['quiz'] = $html;
} else {
$htmlarray[$quiz->course]['quiz'] .= $str;
$htmlarray[$quiz->course]['quiz'] .= $html;
}
}
}
Expand Down

0 comments on commit ac032e0

Please sign in to comment.