}
/**
- * Cron function to be run periodically according to the moodle cron
- * Finds all assignment notifications that have yet to be mailed out, and mails them
+ * Finds all assignment notifications that have yet to be mailed out, and mails them.
+ *
+ * Cron function to be run periodically according to the moodle cron
*
* @return bool
*/
static function cron() {
- global $CFG, $DB;
-
- // used to cache DB lookups
- $croncache = array();
+ global $DB;
// only ever send a max of one days worth of updates
$yesterday = time() - (24 * 3600);
$timenow = time();
- // email students about new feedback
- $submissions = $DB->get_records_sql("SELECT s.*, a.course, a.name, g.*, g.id as gradeid, g.timemodified as lastmodified
- FROM {assign} a
- JOIN {assign_grades} g ON g.assignment = a.id
- LEFT JOIN {assign_submission} s ON s.assignment = a.id AND s.userid = g.userid
- WHERE g.timemodified >= :yesterday
- AND g.timemodified <= :today
- AND g.mailed = 0", array('yesterday'=>$yesterday, 'today'=>$timenow));
+ // Collect all submissions from the past 24 hours that require mailing.
+ $sql = "SELECT s.*, a.course, a.name, g.*, g.id as gradeid, g.timemodified as lastmodified
+ FROM {assign} a
+ JOIN {assign_grades} g ON g.assignment = a.id
+ LEFT JOIN {assign_submission} s ON s.assignment = a.id AND s.userid = g.userid
+ WHERE g.timemodified >= :yesterday AND
+ g.timemodified <= :today AND
+ g.mailed = 0";
+ $params = array('yesterday' => $yesterday, 'today' => $timenow);
+ $submissions = $DB->get_records_sql($sql, $params);
mtrace('Processing ' . count($submissions) . ' assignment submissions ...');
+ // Preload courses we are going to need those.
+ $courseids = array();
+ foreach ($submissions as $submission) {
+ $courseids[] = $submission->course;
+ }
+ // Filter out duplicates
+ $courseids = array_unique($courseids);
+ $ctxselect = context_helper::get_preload_record_columns_sql('ctx');
+ list($courseidsql, $params) = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED);
+ $sql = "SELECT c.*, {$ctxselect}
+ FROM {course} c
+ LEFT JOIN {context} ctx ON ctx.instanceid = c.id AND ctx.contextlevel = :contextlevel
+ WHERE c.id {$courseidsql}";
+ $params['contextlevel'] = CONTEXT_COURSE;
+ $courses = $DB->get_records_sql($sql, $params);
+ // Clean up... this could go on for a while.
+ unset($courseids);
+ unset($ctxselect);
+ unset($courseidsql);
+ unset($params);
+
+ // Simple array we'll use for caching modules.
+ $modcache = array();
+
+ // Email students about new feedback
foreach ($submissions as $submission) {
mtrace("Processing assignment submission $submission->id ...");
// do not cache user lookups - could be too many
- if (! $user = $DB->get_record("user", array("id"=>$submission->userid))) {
+ if (!$user = $DB->get_record("user", array("id"=>$submission->userid))) {
mtrace("Could not find user $submission->userid");
continue;
}
// use a cache to prevent the same DB queries happening over and over
- if (! $course = array_search('course_' . $submission->course, $croncache)) {
- if (! $course = $DB->get_record("course", array("id"=>$submission->course))) {
- mtrace("Could not find course $submission->course");
- continue;
- }
- $croncache['course_' . $submission->course] = $course;
+ if (!array_key_exists($submission->course, $courses)) {
+ mtrace("Could not find course $submission->course");
+ continue;
+ }
+ $course = $courses[$submission->course];
+ if (isset($course->ctxid)) {
+ // Context has not yet been preloaded. Do so now.
+ context_helper::preload_from_record($course);
}
- /// Override the language and timezone of the "current" user, so that
- /// mail is customised for the receiver.
+ // Override the language and timezone of the "current" user, so that
+ // mail is customised for the receiver.
cron_setup_user($user, $course);
// context lookups are already cached
- $coursecontext = context_course::instance($submission->course);
- $courseshortname = format_string($course->shortname, true, array('context' => $coursecontext));
+ $coursecontext = context_course::instance($course->id);
if (!is_enrolled($coursecontext, $user->id)) {
+ $courseshortname = format_string($course->shortname, true, array('context' => $coursecontext));
mtrace(fullname($user)." not an active participant in " . $courseshortname);
continue;
}
- if (! $grader = $DB->get_record("user", array("id"=>$submission->grader))) {
+ if (!$grader = $DB->get_record("user", array("id"=>$submission->grader))) {
mtrace("Could not find grader $submission->grader");
continue;
}
-
- if (! $mod = array_search('mod_' . $submission->assignment, $croncache)) {
+ if (!array_key_exists($submission->assignment, $modcache)) {
if (! $mod = get_coursemodule_from_instance("assign", $submission->assignment, $course->id)) {
mtrace("Could not find course module for assignment id $submission->assignment");
continue;
}
- $croncache['mod_' . $submission->assignment] = $mod;
+ $modcache[$submission->assignment] = $mod;
+ } else {
+ $mod = $modcache[$submission->assignment];
}
-
// context lookups are already cached
$contextmodule = context_module::instance($mod->id);
- if (! $mod->visible) { /// Hold mail notification for hidden assignments until later
+ if (!$mod->visible) {
+ // Hold mail notification for hidden assignments until later
continue;
}
// need to send this to the student
- self::send_assignment_notification($grader, $user, 'feedbackavailable', 'assign_student_notification', $submission->lastmodified, $mod, $contextmodule, $course, get_string('modulename', 'assign'), $submission->name);
+ $messagetype = 'feedbackavailable';
+ $eventtype = 'assign_student_notification';
+ $updatetime = $submission->lastmodified;
+ $modulename = get_string('modulename', 'assign');
+ self::send_assignment_notification($grader, $user, $messagetype, $eventtype, $updatetime, $mod, $contextmodule, $course, $modulename, $submission->name);
$grade = new stdClass();
$grade->id = $submission->gradeid;
mtrace('Done processing ' . count($submissions) . ' assignment submissions');
cron_setup_user();
- // free up memory
- unset($croncache);
+
+ // Free up memory just to be sure
+ unset($courses);
+ unset($modcache);
return true;
}
}
/**
- * Format a notification based on it's type
+ * Format a notification for plain text
*
* @param string $messagetype
* @param stdClass $info
}
/**
- * Format a notification based on it's type
+ * Format a notification for HTML
*
* @param string $messagetype
* @param stdClass $info
+ * @param stdClass $course
+ * @param stdClass $context
+ * @param string $modulename
+ * @param stdClass $coursemodule
+ * @param string $assignmentname
+ * @param stdClass $info
*/
private static function format_notification_message_html($messagetype, $info, $course, $context, $modulename, $coursemodule, $assignmentname) {
global $CFG;
/**
* email someone about something (static so it can be called from cron)
*
- * @global stdClass $CFG
- * @global moodle_database $DB
* @param stdClass $userfrom
* @param stdClass $userto
* @param string $messagetype
* @param stdClass $context
* @param stdClass $course
* @param string $modulename
- * @param string $moduleplural
* @param string $assignmentname
* @return void
*/
public static function send_assignment_notification($userfrom, $userto, $messagetype, $eventtype,
$updatetime, $coursemodule, $context, $course,
$modulename, $assignmentname) {
- global $CFG, $DB;
-
- $strnotification = get_string('notification', 'assign');
+ global $CFG;
$info = new stdClass();
$info->username = fullname($userfrom, true);
$eventdata->contexturlname = $info->assignment;
message_send($eventdata);
-
}
/**
* email someone about something
*
- * @global stdClass $CFG
- * @global moodle_database $DB
- * @param stdClass $submission
+ * @param stdClass $userfrom
+ * @param stdClass $userto
+ * @param string $messagetype
+ * @param string $eventtype
+ * @param int $updatetime
* @return void
*/
public function send_notification($userfrom, $userto, $messagetype, $eventtype, $updatetime) {
}
/**
- * email student upon successful submission
+ * Email student upon successful submission
*
- * @global stdClass $CFG
* @global moodle_database $DB
* @param stdClass $submission
* @return void
global $DB;
$adminconfig = $this->get_admin_config();
- if (!$adminconfig->submissionreceipts) { // No need to do anything
+ if (!$adminconfig->submissionreceipts) {
+ // No need to do anything
return;
}
-
$user = $DB->get_record('user', array('id'=>$submission->userid), '*', MUST_EXIST);
-
$this->send_notification($user, $user, 'submissionreceipt', 'assign_student_notification', $submission->timemodified);
}
/**
- * email graders upon student submissions
+ * Email graders upon student submissions
*
- * @global stdClass $CFG
* @global moodle_database $DB
* @param stdClass $submission
* @return void
}
$user = $DB->get_record('user', array('id'=>$submission->userid), '*', MUST_EXIST);
-
if ($teachers = $this->get_graders($user->id)) {
-
- $strassignments = $this->get_module_name_plural();
- $strassignment = $this->get_module_name();
- $strsubmitted = get_string('submitted', 'assign');
-
foreach ($teachers as $teacher) {
$this->send_notification($user, $teacher, 'gradersubmissionupdated', 'assign_grader_notification', $submission->timemodified);
}