MDL-3030 quiz overdue handling: catch the overdue event and send message.

This commit is contained in:
Tim Hunt 2012-04-20 16:24:33 +01:00
parent a403bce0bd
commit fd0537ce36
4 changed files with 144 additions and 15 deletions

View File

@ -35,6 +35,14 @@ $handlers = array(
'handlerfunction' => 'quiz_attempt_submitted_handler',
'schedule' => 'cron',
),
// Handle our own quiz_attempt_overdue event, to email the student to let them
// know they forgot to submit, and that they have another chance.
'quiz_attempt_overdue' => array (
'handlerfile' => '/mod/quiz/locallib.php',
'handlerfunction' => 'quiz_attempt_overdue_handler',
'schedule' => 'cron',
),
);
/* List of events generated by the quiz module, with the fields on the event object.

View File

@ -25,14 +25,20 @@
defined('MOODLE_INTERNAL') || die();
$messageproviders = array (
// Notify teacher that a student has submitted a quiz attempt
'submission' => array (
'capability' => 'mod/quiz:emailnotifysubmission'
$messageproviders = array(
// Notify teacher that a student has submitted a quiz attempt.
'submission' => array(
'capability' => 'mod/quiz:emailnotifysubmission'
),
// Confirm a student's quiz attempt
'confirmation' => array (
'capability' => 'mod/quiz:emailconfirmsubmission'
)
// Confirm a student's quiz attempt.
'confirmation' => array(
'capability' => 'mod/quiz:emailconfirmsubmission'
),
// Warning to the student that their quiz attempt is now overdue, if the quiz
// has a grace period.
'attempt_overdue' => array(
'capability' => 'mod/quiz:emailwarnoverdue'
),
);

View File

@ -262,16 +262,27 @@ This message confirms that we have safely received your answers.
You can access this quiz at {$a->quizurl}.';
$string['emailconfirmsmall'] = 'Thank you for submitting your answers to \'{$a->quizname}\'';
$string['emailconfirmsubject'] = 'Quiz submission confirmation: {$a->quizname}';
$string['emailconfirmsubject'] = 'Submission confirmation: {$a->quizname}';
$string['emailnotifybody'] = 'Dear {$a->username},
{$a->studentname} has completed the quiz
{$a->studentname} has completed
\'{$a->quizname}\' ({$a->quizurl})
in course \'{$a->coursename}\'
You can review this attempt at {$a->quizreviewurl}.';
$string['emailnotifysmall'] = '{$a->studentname} has completed {$a->quizname}';
$string['emailnotifysubject'] = '{$a->studentname} has completed quiz {$a->quizname}';
$string['emailnotifysmall'] = '{$a->studentname} has completed {$a->quizname}. See {$a->quizreviewurl}';
$string['emailnotifysubject'] = '{$a->studentname} has completed {$a->quizname}';
$string['emailoverduebody'] = 'Dear {$a->studentname},
You started an attempt at \'{$a->quizname}\'
in course \'{$a->coursename}\', but you never submitted it.
If you would would still like to submit this attempt, please go to
{$a->attemptsummaryurl} and click the submit button.
You must do this before {$a->attemptgraceend}
otherwise you attempt will not be counted.';
$string['emailoverduesmall'] = 'You did not submit your attempt at {$a->quizname}. Please go to {$a->attemptsummaryurl} before {$a->attemptgraceend} if you would still like to submit.';
$string['emailoverduesubject'] = 'Attempt now overdue: {$a->quizname}';
$string['empty'] = 'Empty';
$string['enabled'] = 'Enabled';
$string['endtest'] = 'Finish attempt ...';

View File

@ -1255,14 +1255,14 @@ function quiz_send_notification_messages($course, $quiz, $attempt, $context, $cm
$a->quizreporturl = $CFG->wwwroot . '/mod/quiz/report.php?id=' . $cm->id;
$a->quizreportlink = '<a href="' . $a->quizreporturl . '">' .
format_string($quiz->name) . ' report</a>';
$a->quizreviewurl = $CFG->wwwroot . '/mod/quiz/review.php?attempt=' . $attempt->id;
$a->quizreviewlink = '<a href="' . $a->quizreviewurl . '">' .
format_string($quiz->name) . ' review</a>';
$a->quizurl = $CFG->wwwroot . '/mod/quiz/view.php?id=' . $cm->id;
$a->quizlink = '<a href="' . $a->quizurl . '">' . format_string($quiz->name) . '</a>';
// Attempt info
$a->submissiontime = userdate($attempt->timefinish);
$a->timetaken = format_time($attempt->timefinish - $attempt->timestart);
$a->quizreviewurl = $CFG->wwwroot . '/mod/quiz/review.php?attempt=' . $attempt->id;
$a->quizreviewlink = '<a href="' . $a->quizreviewurl . '">' .
format_string($quiz->name) . ' review</a>';
// Student who sat the quiz info
$a->studentidnumber = $submitter->idnumber;
$a->studentname = fullname($submitter);
@ -1288,6 +1288,80 @@ function quiz_send_notification_messages($course, $quiz, $attempt, $context, $cm
return $allok;
}
/**
* Send the notification message when a quiz attempt becomes overdue.
*
* @param object $course the course
* @param object $quiz the quiz
* @param object $attempt this attempt just finished
* @param object $context the quiz context
* @param object $cm the coursemodule for this quiz
*/
function quiz_send_overdue_message($course, $quiz, $attempt, $context, $cm) {
global $CFG, $DB;
// Do nothing if required objects not present
if (empty($course) or empty($quiz) or empty($attempt) or empty($context)) {
throw new coding_exception('$course, $quiz, $attempt, $context and $cm must all be set.');
}
$submitter = $DB->get_record('user', array('id' => $attempt->userid), '*', MUST_EXIST);
if (!has_capability('mod/quiz:emailwarnoverdue', $context, $submitter, false)) {
return; // Message not required.
}
// Prepare lots of useful information that admins might want to include in
// the email message.
$quizname = format_string($quiz->name);
$deadlines = array();
if ($quiz->timelimit) {
$deadlines[] = $attempt->timestart + $quiz->timelimit;
}
if ($quiz->timeclose) {
$deadlines[] = $quiz->timeclose;
}
$duedate = min($deadlines) + $quiz->graceperiod;
$a = new stdClass();
// Course info.
$a->coursename = $course->fullname;
$a->courseshortname = $course->shortname;
// Quiz info.
$a->quizname = $quizname;
$a->quizurl = $CFG->wwwroot . '/mod/quiz/view.php?id=' . $cm->id;
$a->quizlink = '<a href="' . $a->quizurl . '">' . $quizname . '</a>';
// Attempt info.
$a->attemptgraceend = format_time($duedate);
$a->attemptsummaryurl = $CFG->wwwroot . '/mod/quiz/summary.php?attempt=' . $attempt->id;
$a->attemptsummarylink = '<a href="' . $a->attemptsummaryurl . '">' . $quizname . ' review</a>';
// Student's info.
$a->studentidnumber = $submitter->idnumber;
$a->studentname = fullname($submitter);
$a->studentusername = $submitter->username;
// Prepare the message.
$eventdata = new stdClass();
$eventdata->component = 'mod_quiz';
$eventdata->name = 'attempt_overdue';
$eventdata->notification = 1;
$eventdata->userfrom = get_admin();
$eventdata->userto = $submitter;
$eventdata->subject = get_string('emailoverduesubject', 'quiz', $a);
$eventdata->fullmessage = get_string('emailoverduebody', 'quiz', $a);
$eventdata->fullmessageformat = FORMAT_PLAIN;
$eventdata->fullmessagehtml = '';
$eventdata->smallmessage = get_string('emailoverduesmall', 'quiz', $a);
$eventdata->contexturl = $a->quizurl;
$eventdata->contexturlname = $a->quizname;
// Send the message.
return message_send($eventdata);
}
/**
* Handle the quiz_attempt_submitted event.
*
@ -1313,6 +1387,36 @@ function quiz_attempt_submitted_handler($event) {
get_context_instance(CONTEXT_MODULE, $cm->id), $cm);
}
/**
* Handle the quiz_attempt_overdue event.
*
* For quizzes with applicable settings, this sends a message to the user, reminding
* them that they forgot to submit, and that they have another chance to do so.
*
* @param object $event the event object.
*/
function quiz_attempt_overdue_handler($event) {
global $DB;
$course = $DB->get_record('course', array('id' => $event->courseid));
$quiz = $DB->get_record('quiz', array('id' => $event->quizid));
$cm = get_coursemodule_from_id('quiz', $event->cmid, $event->courseid);
$attempt = $DB->get_record('quiz_attempts', array('id' => $event->attemptid));
if (!($course && $quiz && $cm && $attempt)) {
// Something has been deleted since the event was raised. Therefore, the
// event is no longer relevant.
return true;
}
return quiz_send_overdue_message($course, $quiz, $attempt,
get_context_instance(CONTEXT_MODULE, $cm->id), $cm);
}
/**
* Get the information about the standard quiz JavaScript module.
* @return array a standard jsmodule structure.
*/
function quiz_get_js_module() {
global $PAGE;